diff --git a/Gopkg.lock b/Gopkg.lock index 5e1b60bcfaebdf070f218e220d52774004bf7738..8cd1b1b6e2656491b324096f3cd57f52eb06d455 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -13,10 +13,26 @@ revision = "c95af922eae69f190717a0b7148960af8c55a072" [[projects]] - branch = "master" name = "github.com/golang/protobuf" - packages = ["jsonpb","proto","protoc-gen-go/descriptor","ptypes","ptypes/any","ptypes/duration","ptypes/empty","ptypes/struct","ptypes/timestamp","ptypes/wrappers"] - revision = "c65a0412e71e8b9b3bfd22925720d23c0f054237" + packages = [ + "jsonpb", + "proto", + "protoc-gen-go/descriptor", + "ptypes", + "ptypes/any", + "ptypes/duration", + "ptypes/empty", + "ptypes/struct", + "ptypes/timestamp", + "ptypes/wrappers" + ] + revision = "925541529c1fa6821df4e44ce2723319eb2be768" + version = "v1.0.0" + +[[projects]] + name = "github.com/gorhill/cronexpr" + packages = ["."] + revision = "d520615e531a6bf3fb69406b9eba718261285ec8" [[projects]] name = "github.com/gorilla/context" @@ -43,18 +59,29 @@ [[projects]] name = "github.com/grpc-ecosystem/grpc-gateway" - packages = ["runtime","runtime/internal","utilities"] + packages = [ + "protoc-gen-swagger/options", + "runtime", + "runtime/internal", + "utilities" + ] revision = "07f5e79768022f9a3265235f0db4ac8c3f675fec" version = "v1.3.1" [[projects]] name = "github.com/lib/pq" - packages = [".","oid"] + packages = [ + ".", + "oid" + ] revision = "83612a56d3dd153a94a629cd64925371c9adad78" [[projects]] name = "github.com/rubenv/sql-migrate" - packages = [".","sqlparse"] + packages = [ + ".", + "sqlparse" + ] revision = "6edbfbd6a369ee82463312ec67b2c92f97a1d4dc" [[projects]] @@ -62,6 +89,16 @@ packages = ["."] revision = "063359185d32c6b045fa171ad7033ea545864fa1" +[[projects]] + name = "github.com/yuin/gopher-lua" + packages = [ + ".", + "ast", + "parse", + "pm" + ] + revision = "7d7bc8747e3f614c5c587729a341fe7d8903cdb8" + [[projects]] name = "go.uber.org/atomic" packages = ["."] @@ -76,31 +113,96 @@ [[projects]] name = "go.uber.org/zap" - packages = [".","buffer","internal/bufferpool","internal/color","internal/exit","zapcore"] + packages = [ + ".", + "buffer", + "internal/bufferpool", + "internal/color", + "internal/exit", + "zapcore" + ] revision = "35aad584952c3e7020db7b839f6b102de6271f89" version = "v1.7.1" +[[projects]] + branch = "master" + name = "golang.org/x/crypto" + packages = [ + "bcrypt", + "blowfish" + ] + revision = "1875d0a70c90e57f11972aefd42276df65e895b9" + [[projects]] branch = "master" name = "golang.org/x/net" - packages = ["context","http2","http2/hpack","idna","internal/timeseries","lex/httplex","trace"] - revision = "5ccada7d0a7ba9aeb5d3aca8d3501b4c2a509fec" + packages = [ + "context", + "http2", + "http2/hpack", + "idna", + "internal/timeseries", + "lex/httplex", + "trace" + ] + revision = "2fb46b16b8dda405028c50f7c7f0f9dd1fa6bfb1" [[projects]] branch = "master" name = "golang.org/x/text" - packages = ["collate","collate/build","internal/colltab","internal/gen","internal/tag","internal/triegen","internal/ucd","language","secure/bidirule","transform","unicode/bidi","unicode/cldr","unicode/norm","unicode/rangetable"] + packages = [ + "collate", + "collate/build", + "internal/colltab", + "internal/gen", + "internal/tag", + "internal/triegen", + "internal/ucd", + "language", + "secure/bidirule", + "transform", + "unicode/bidi", + "unicode/cldr", + "unicode/norm", + "unicode/rangetable" + ] revision = "e19ae1496984b1c655b8044a65c0300a3c878dd3" [[projects]] branch = "master" name = "google.golang.org/genproto" - packages = ["googleapis/api/annotations","googleapis/rpc/status"] - revision = "a8101f21cf983e773d0c1133ebc5424792003214" + packages = [ + "googleapis/api/annotations", + "googleapis/rpc/status" + ] + revision = "4eb30f4778eed4c258ba66527a0d4f9ec8a36c45" [[projects]] name = "google.golang.org/grpc" - packages = [".","balancer","balancer/base","balancer/roundrobin","codes","connectivity","credentials","encoding","grpclb/grpc_lb_v1/messages","grpclog","internal","keepalive","metadata","naming","peer","resolver","resolver/dns","resolver/passthrough","stats","status","tap","transport"] + packages = [ + ".", + "balancer", + "balancer/base", + "balancer/roundrobin", + "codes", + "connectivity", + "credentials", + "encoding", + "grpclb/grpc_lb_v1/messages", + "grpclog", + "internal", + "keepalive", + "metadata", + "naming", + "peer", + "resolver", + "resolver/dns", + "resolver/passthrough", + "stats", + "status", + "tap", + "transport" + ] revision = "6b51017f791ae1cfbec89c52efdf444b13b550ef" version = "v1.9.2" @@ -113,6 +215,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "01db32151b4b5b577d58fd0dd63d472814ddd331fefa1b105dc12fba3d724f99" + inputs-digest = "bd27c78031b478645517c097fe42bdb946de0a2a3fdbecf6c56718b8e2ba9492" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 7b69e2436dfbfaad74dc692ce0c7be558e09c87f..226aa9331a6652272313b788d8e27c8100d67dc0 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -37,3 +37,14 @@ [[constraint]] name = "github.com/gorilla/websocket" revision = "292fd08b2560ad524ee37396253d71570339a821" + +[[constraint]] + name = "github.com/yuin/gopher-lua" + revision = "7d7bc8747e3f614c5c587729a341fe7d8903cdb8" + +[[constraint]] + name = "github.com/gorhill/cronexpr" + revision = "d520615e531a6bf3fb69406b9eba718261285ec8" + +[[constraint]] + name = "golang.org/x/crypto" diff --git a/main.go b/main.go index 73e3f313f467323e6e1233b58bb76ec583860e9f..fd8bebac9a26f354b2f59871adf272412a33f6a4 100644 --- a/main.go +++ b/main.go @@ -85,8 +85,12 @@ func main() { registry := server.NewSessionRegistry() tracker := server.StartLocalTracker(jsonLogger, registry, jsonpbMarshaler, config.GetName()) router := server.NewLocalMessageRouter(registry, tracker, jsonpbMarshaler) - pipeline := server.NewPipeline(config, db, tracker, router, registry) - apiServer := server.StartApiServer(jsonLogger, db, config, tracker, registry, pipeline, jsonpbMarshaler, jsonpbUnmarshaler) + runtimePool, err := server.NewRuntimePool(jsonLogger, multiLogger, db, config, registry, tracker, router) + if err != nil { + multiLogger.Fatal("Failed initializing runtime modules", zap.Error(err)) + } + pipeline := server.NewPipeline(config, db, registry, tracker, router, runtimePool) + apiServer := server.StartApiServer(jsonLogger, db, config, registry, tracker, pipeline, runtimePool, jsonpbMarshaler, jsonpbUnmarshaler) // Respect OS stop signals. c := make(chan os.Signal, 2) diff --git a/server/api.go b/server/api.go index fc29a0db884762ebab6478d96e27fa5e0418b4c6..da5dd0667cf40ece236d9e64c8231c12af35e6ab 100644 --- a/server/api.go +++ b/server/api.go @@ -49,12 +49,13 @@ type ApiServer struct { logger *zap.Logger db *sql.DB config Config + runtimePool *RuntimePool random *rand.Rand grpcServer *grpc.Server grpcGatewayServer *http.Server } -func StartApiServer(logger *zap.Logger, db *sql.DB, config Config, tracker Tracker, registry *SessionRegistry, pipeline *pipeline, jsonpbMarshaler *jsonpb.Marshaler, jsonpbUnmarshaler *jsonpb.Unmarshaler) *ApiServer { +func StartApiServer(logger *zap.Logger, db *sql.DB, config Config, registry *SessionRegistry, tracker Tracker, pipeline *pipeline, runtimePool *RuntimePool, jsonpbMarshaler *jsonpb.Marshaler, jsonpbUnmarshaler *jsonpb.Unmarshaler) *ApiServer { grpcServer := grpc.NewServer( grpc.UnaryInterceptor(SecurityInterceptorFunc(logger, config)), ) @@ -63,6 +64,7 @@ func StartApiServer(logger *zap.Logger, db *sql.DB, config Config, tracker Track logger: logger, db: db, config: config, + runtimePool: runtimePool, random: rand.New(rand.NewSource(time.Now().UnixNano())), grpcServer: grpcServer, } @@ -94,7 +96,7 @@ func StartApiServer(logger *zap.Logger, db *sql.DB, config Config, tracker Track CORSOrigins := handlers.AllowedOrigins([]string{"*"}) grpcGatewayRouter := mux.NewRouter() - grpcGatewayRouter.HandleFunc("/ws", NewSocketWsAcceptor(logger, config, tracker, registry, jsonpbMarshaler, jsonpbUnmarshaler, pipeline.processRequest)) + grpcGatewayRouter.HandleFunc("/ws", NewSocketWsAcceptor(logger, config, registry, tracker, jsonpbMarshaler, jsonpbUnmarshaler, pipeline.processRequest)) grpcGatewayRouter.NewRoute().Handler(grpcGateway) handlerWithCORS := handlers.CORS(CORSHeaders, CORSOrigins)(grpcGatewayRouter) diff --git a/server/api_authenticate.go b/server/api_authenticate.go index 81d290093ee50bf47b5fa2825a186976b3b0a6d4..272ae178896ecdd241476fa38b508779b18e5042 100644 --- a/server/api_authenticate.go +++ b/server/api_authenticate.go @@ -142,6 +142,10 @@ func (s *ApiServer) AuthenticateSteamFunc(ctx context.Context, in *api.Authentic func generateToken(config Config, userID, username string) string { exp := time.Now().UTC().Add(time.Duration(config.GetSession().TokenExpiryMs) * time.Millisecond).Unix() + return generateTokenWithExpiry(config, userID, username, exp) +} + +func generateTokenWithExpiry(config Config, userID, username string, exp int64) string { token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ "uid": userID, "exp": exp, diff --git a/server/api_rpc.go b/server/api_rpc.go index cc56dc40c34ad54087f8d580bad6aa521cdeaee4..9883686feca729b28a61273d87afb4ec3035226d 100644 --- a/server/api_rpc.go +++ b/server/api_rpc.go @@ -18,9 +18,65 @@ import ( "golang.org/x/net/context" "github.com/heroiclabs/nakama/api" "go.uber.org/zap" + "strings" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "github.com/yuin/gopher-lua" + "github.com/satori/go.uuid" + "github.com/golang/protobuf/ptypes/wrappers" ) func (s *ApiServer) RpcFunc(ctx context.Context, in *api.Rpc) (*api.Rpc, error) { - s.logger.Info("RPC called", zap.Any("userID", ctx.Value(ctxUserIDKey{})), zap.Any("username", ctx.Value(ctxUsernameKey{})), zap.Any("expiry", ctx.Value(ctxExpiryKey{}))) - return &api.Rpc{Id: in.Id, Payload: in.Payload, HttpKey: in.HttpKey}, nil + if in.Id == "" { + return nil, status.Error(codes.InvalidArgument, "RPC ID must be set") + } + + id := strings.ToLower(in.Id) + + if !s.runtimePool.HasRPC(id) { + return nil, status.Error(codes.NotFound, "RPC function not found") + } + + runtime := s.runtimePool.Get() + lf := runtime.GetRuntimeCallback(RPC, id) + if lf == nil { + s.runtimePool.Put(runtime) + return nil, status.Error(codes.NotFound, "RPC function not found") + } + + uid := "" + username := "" + expiry := int64(0) + if u := ctx.Value(ctxUserIDKey{}); u != nil { + uid = u.(uuid.UUID).String() + } + if u := ctx.Value(ctxUsernameKey{}); u != nil { + username = u.(string) + } + if e := ctx.Value(ctxExpiryKey{}); e != nil { + expiry = e.(int64) + } + + result, fnErr := runtime.InvokeFunctionRPC(lf, uid, username, expiry, "", in.Payload.Value) + s.runtimePool.Put(runtime) + if fnErr != nil { + s.logger.Error("Runtime RPC function caused an error", zap.String("id", in.Id), zap.Error(fnErr)) + if apiErr, ok := fnErr.(*lua.ApiError); ok && !s.config.GetLog().Verbose { + msg := apiErr.Object.String() + if strings.HasPrefix(msg, lf.Proto.SourceName) { + msg = msg[len(lf.Proto.SourceName):] + msgParts := strings.SplitN(msg, ": ", 2) + if len(msgParts) == 2 { + msg = msgParts[1] + } else { + msg = msgParts[0] + } + } + return nil, status.Error(codes.Aborted, msg) + } else { + return nil, status.Error(codes.Aborted, fnErr.Error()) + } + } + + return &api.Rpc{Payload: &wrappers.StringValue{Value: result}}, nil } diff --git a/server/pipeline.go b/server/pipeline.go index bed1314a879dbb5016bfe3b2b9adefb45103fae4..b6aebecc7958854be7b98f137e0902e99aed8f31 100644 --- a/server/pipeline.go +++ b/server/pipeline.go @@ -21,24 +21,34 @@ import ( ) type pipeline struct { - config Config - db *sql.DB - tracker Tracker - router MessageRouter - registry *SessionRegistry + config Config + db *sql.DB + registry *SessionRegistry + tracker Tracker + router MessageRouter + runtimePool *RuntimePool } -func NewPipeline(config Config, db *sql.DB, tracker Tracker, router MessageRouter, registry *SessionRegistry) *pipeline { +func NewPipeline(config Config, db *sql.DB, registry *SessionRegistry, tracker Tracker, router MessageRouter, runtimePool *RuntimePool) *pipeline { return &pipeline{ - config: config, - db: db, - tracker: tracker, - router: router, - registry: registry, + config: config, + db: db, + registry: registry, + tracker: tracker, + router: router, + runtimePool: runtimePool, } } func (p *pipeline) processRequest(logger *zap.Logger, session session, envelope *rtapi.Envelope) { - // FIXME test by echoing back message. - session.Send(envelope) + switch envelope.Message.(type) { + case *rtapi.Envelope_Rpc: + p.rpc(logger, session, envelope) + default: + session.Send(&rtapi.Envelope{Cid: envelope.Cid, Message: &rtapi.Envelope_Error{Error: &rtapi.Error{ + Code: int32(rtapi.Error_UNRECOGNIZED_PAYLOAD), + Message: "Unrecognized payload", + }}}) + return + } } diff --git a/server/pipeline_rpc.go b/server/pipeline_rpc.go new file mode 100644 index 0000000000000000000000000000000000000000..5e23fc9a7ec83830dc8f5ab9674efc5a5c2bda82 --- /dev/null +++ b/server/pipeline_rpc.go @@ -0,0 +1,90 @@ +// Copyright 2017 The Nakama Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package server + +import ( + "strings" + + "github.com/yuin/gopher-lua" + "go.uber.org/zap" + "github.com/heroiclabs/nakama/rtapi" + "github.com/heroiclabs/nakama/api" + "github.com/golang/protobuf/ptypes/wrappers" +) + +func (p *pipeline) rpc(logger *zap.Logger, session session, envelope *rtapi.Envelope) { + rpcMessage := envelope.GetRpc() + if rpcMessage.Id == "" { + session.Send(&rtapi.Envelope{Cid: envelope.Cid, Message: &rtapi.Envelope_Error{Error: &rtapi.Error{ + Code: int32(rtapi.Error_BAD_INPUT), + Message: "RPC ID must be set", + }}}) + return + } + + id := strings.ToLower(rpcMessage.Id) + + if !p.runtimePool.HasRPC(id) { + session.Send(&rtapi.Envelope{Cid: envelope.Cid, Message: &rtapi.Envelope_Error{Error: &rtapi.Error{ + Code: int32(rtapi.Error_RUNTIME_FUNCTION_NOT_FOUND), + Message: "RPC function not found", + }}}) + return + } + + runtime := p.runtimePool.Get() + lf := runtime.GetRuntimeCallback(RPC, id) + if lf == nil { + p.runtimePool.Put(runtime) + session.Send(&rtapi.Envelope{Cid: envelope.Cid, Message: &rtapi.Envelope_Error{Error: &rtapi.Error{ + Code: int32(rtapi.Error_RUNTIME_FUNCTION_NOT_FOUND), + Message: "RPC function not found", + }}}) + return + } + + result, fnErr := runtime.InvokeFunctionRPC(lf, session.UserID().String(), session.Username(), session.Expiry(), session.ID().String(), rpcMessage.Payload.Value) + p.runtimePool.Put(runtime) + if fnErr != nil { + logger.Error("Runtime RPC function caused an error", zap.String("id", rpcMessage.Id), zap.Error(fnErr)) + if apiErr, ok := fnErr.(*lua.ApiError); ok && !p.config.GetLog().Verbose { + msg := apiErr.Object.String() + if strings.HasPrefix(msg, lf.Proto.SourceName) { + msg = msg[len(lf.Proto.SourceName):] + msgParts := strings.SplitN(msg, ": ", 2) + if len(msgParts) == 2 { + msg = msgParts[1] + } else { + msg = msgParts[0] + } + } + session.Send(&rtapi.Envelope{Cid: envelope.Cid, Message: &rtapi.Envelope_Error{Error: &rtapi.Error{ + Code: int32(rtapi.Error_RUNTIME_FUNCTION_EXCEPTION), + Message: msg, + }}}) + } else { + session.Send(&rtapi.Envelope{Cid: envelope.Cid, Message: &rtapi.Envelope_Error{Error: &rtapi.Error{ + Code: int32(rtapi.Error_RUNTIME_FUNCTION_EXCEPTION), + Message: fnErr.Error(), + }}}) + } + return + } + + session.Send(&rtapi.Envelope{Cid: envelope.Cid, Message: &rtapi.Envelope_Rpc{Rpc: &api.Rpc{ + Id: rpcMessage.Id, + Payload: &wrappers.StringValue{Value: result}, + }}}) +} diff --git a/server/runtime.go b/server/runtime.go new file mode 100644 index 0000000000000000000000000000000000000000..3d6a76e0b265a9db6425c870c3a36cecc5ba14e6 --- /dev/null +++ b/server/runtime.go @@ -0,0 +1,331 @@ +// Copyright 2018 The Nakama Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package server + +import ( + "os" + "path/filepath" + + "errors" + + "strings" + + "database/sql" + + "bytes" + "github.com/yuin/gopher-lua" + "go.uber.org/zap" + "golang.org/x/net/context" + "io/ioutil" + "sync" +) + +const ( + __nakamaReturnValue = "__nakama_return_flag__" +) + +type RuntimeModule struct { + name string + path string + content []byte +} + +type RuntimePool struct { + regRPC map[string]struct{} + pool *sync.Pool +} + +func NewRuntimePool(logger *zap.Logger, multiLogger *zap.Logger, db *sql.DB, config Config, registry *SessionRegistry, tracker Tracker, router MessageRouter) (*RuntimePool, error) { + runtimeConfig := config.GetRuntime() + if err := os.MkdirAll(runtimeConfig.Path, os.ModePerm); err != nil { + return nil, err + } + + // Override before Package library is invoked. + lua.LuaLDir = runtimeConfig.Path + lua.LuaPathDefault = lua.LuaLDir + "/?.lua;" + lua.LuaLDir + "/?/init.lua" + os.Setenv(lua.LuaPath, lua.LuaPathDefault) + + stdLibs := map[string]lua.LGFunction{ + lua.LoadLibName: lua.OpenPackage, + lua.BaseLibName: lua.OpenBase, + lua.TabLibName: lua.OpenTable, + lua.OsLibName: OpenOs, + lua.StringLibName: lua.OpenString, + lua.MathLibName: lua.OpenMath, + } + + logger.Info("Initialising modules", zap.String("path", lua.LuaLDir)) + modules := make([]*RuntimeModule, 0) + err := filepath.Walk(lua.LuaLDir, func(path string, f os.FileInfo, err error) error { + if err != nil { + logger.Error("Could not read module", zap.Error(err)) + return err + } else if !f.IsDir() { + if strings.ToLower(filepath.Ext(path)) == ".lua" { + var content []byte + if content, err = ioutil.ReadFile(path); err != nil { + logger.Error("Could not read module", zap.String("path", path), zap.Error(err)) + return err + } + relPath, _ := filepath.Rel(lua.LuaLDir, path) + name := strings.TrimSuffix(relPath, filepath.Ext(relPath)) + // Make paths Lua friendly. + name = strings.Replace(name, "/", ".", -1) + modules = append(modules, &RuntimeModule{ + name: name, + path: path, + content: content, + }) + } + } + return nil + }) + if err != nil { + logger.Error("Failed to list modules", zap.Error(err)) + return nil, err + } + + regRPC := make(map[string]struct{}) + + // Initialize a one-off runtime to ensure startup code runs and modules are valid. + vm := lua.NewState(lua.Options{ + CallStackSize: 1024, + RegistrySize: 1024, + SkipOpenLibs: true, + IncludeGoStackTrace: true, + }) + for name, lib := range stdLibs { + vm.Push(vm.NewFunction(lib)) + vm.Push(lua.LString(name)) + vm.Call(1, 0) + } + + // Used to govern once-per-server-start executions. + once := &sync.Once{} + + nakamaModule := NewNakamaModule(logger, db, config, vm, registry, tracker, router, once, + func(id string) { + regRPC[id] = struct{}{} + logger.Info("Registered RPC function invocation", zap.String("id", id)) + }) + vm.PreloadModule("nakama", nakamaModule.Loader) + r := &Runtime{ + logger: logger, + vm: vm, + luaEnv: ConvertMap(vm, runtimeConfig.Environment), + } + moduleStrings := make([]string, len(modules)) + for i, module := range modules { + moduleStrings[i] = module.path + } + multiLogger.Info("Evaluating modules", zap.Int("count", len(moduleStrings)), zap.Strings("modules", moduleStrings)) + if err = r.loadModules(modules); err != nil { + return nil, err + } + multiLogger.Info("Modules loaded") + r.Stop() + + return &RuntimePool{ + regRPC: regRPC, + pool: &sync.Pool{ + New: func() interface{} { + vm := lua.NewState(lua.Options{ + CallStackSize: 1024, + RegistrySize: 1024, + SkipOpenLibs: true, + IncludeGoStackTrace: true, + }) + + for name, lib := range stdLibs { + vm.Push(vm.NewFunction(lib)) + vm.Push(lua.LString(name)) + vm.Call(1, 0) + } + + nakamaModule := NewNakamaModule(logger, db, config, vm, registry, tracker, router, once, nil) + vm.PreloadModule("nakama", nakamaModule.Loader) + + r := &Runtime{ + logger: logger, + vm: vm, + luaEnv: ConvertMap(vm, runtimeConfig.Environment), + } + + if err = r.loadModules(modules); err != nil { + multiLogger.Fatal("Failed initializing runtime modules", zap.Error(err)) + } + return r + + // TODO find a way to run r.Stop() when the pool discards this runtime. + }, + }, + }, nil +} + +func (rp *RuntimePool) HasRPC(id string) bool { + _, ok := rp.regRPC[id] + return ok +} + +func (rp *RuntimePool) Get() *Runtime { + return rp.pool.Get().(*Runtime) +} + +func (rp *RuntimePool) Put(r *Runtime) { + rp.pool.Put(r) +} + +type BuiltinModule interface { + Loader(l *lua.LState) int +} + +type Runtime struct { + logger *zap.Logger + vm *lua.LState + luaEnv *lua.LTable +} + +func (r *Runtime) loadModules(modules []*RuntimeModule) error { + // `DoFile(..)` only parses and evaluates modules. Calling it multiple times, will load and eval the file multiple times. + // So to make sure that we only load and evaluate modules once, regardless of whether there is dependency between files, we load them all into `preload`. + // This is to make sure that modules are only loaded and evaluated once as `doFile()` does not (always) update _LOADED table. + // Bear in mind two separate thoughts around the script runtime design choice: + // + // 1) This is only a problem if one module is dependent on another module. + // This means that the global functions are evaluated once at system startup and then later on when the module is required through `require`. + // We circumvent this by checking the _LOADED table to check if `require` had evaluated the module and avoiding double-eval. + // + // 2) Second item is that modules must be pre-loaded into the state for callback-func eval to work properly (in case of HTTP/RPC/etc invokes) + // So we need to always load the modules into the system via `preload` so that they are always available in the LState. + // We can't rely on `require` to have seen the module in case there is no dependency between the modules. + + //for _, mod := range r.modules { + // relPath, _ := filepath.Rel(r.luaPath, mod) + // moduleName := strings.TrimSuffix(relPath, filepath.Ext(relPath)) + // + // // check to see if this module was loaded by `require` before executing it + // loaded := l.GetField(l.Get(lua.RegistryIndex), "_LOADED") + // lv := l.GetField(loaded, moduleName) + // if lua.LVAsBool(lv) { + // // Already evaluated module via `require(..)` + // continue + // } + // + // if err = l.DoFile(mod); err != nil { + // failedModules++ + // r.logger.Error("Failed to evaluate module - skipping", zap.String("path", mod), zap.Error(err)) + // } + //} + + preload := r.vm.GetField(r.vm.GetField(r.vm.Get(lua.EnvironIndex), "package"), "preload") + fns := make(map[string]*lua.LFunction) + for _, module := range modules { + f, err := r.vm.Load(bytes.NewReader(module.content), module.path) + if err != nil { + r.logger.Error("Could not load module", zap.String("name", module.path), zap.Error(err)) + return err + } else { + r.vm.SetField(preload, module.name, f) + fns[module.name] = f + } + } + + for name, fn := range fns { + loaded := r.vm.GetField(r.vm.Get(lua.RegistryIndex), "_LOADED") + lv := r.vm.GetField(loaded, name) + if lua.LVAsBool(lv) { + // Already evaluated module via `require(..)` + continue + } + + r.vm.Push(fn) + fnErr := r.vm.PCall(0, -1, nil) + if fnErr != nil { + r.logger.Error("Could not complete runtime invocation", zap.Error(fnErr)) + return fnErr + } + } + + return nil +} + +func (r *Runtime) NewStateThread() (*lua.LState, context.CancelFunc) { + return r.vm.NewThread() +} + +func (r *Runtime) GetRuntimeCallback(e ExecutionMode, key string) *lua.LFunction { + cp := r.vm.Context().Value(CALLBACKS).(*Callbacks) + switch e { + case RPC: + return cp.RPC[key] + } + + return nil +} + +func (r *Runtime) InvokeFunctionRPC(fn *lua.LFunction, uid string, username string, sessionExpiry int64, sid string, payload string) (string, error) { + l, _ := r.NewStateThread() + defer l.Close() + + ctx := NewLuaContext(l, r.luaEnv, RPC, uid, username, sessionExpiry, sid) + var lv lua.LValue + if payload != "" { + lv = lua.LString(payload) + } + + retValue, err := r.invokeFunction(l, fn, ctx, lv) + if err != nil { + return "", err + } + + if retValue == nil || retValue == lua.LNil { + return "", nil + } else if retValue.Type() == lua.LTString { + return retValue.String(), nil + } + + return "", errors.New("Runtime function returned invalid data. Only allowed one return value of type String/Byte") +} + +func (r *Runtime) invokeFunction(l *lua.LState, fn *lua.LFunction, ctx *lua.LTable, payload lua.LValue) (lua.LValue, error) { + l.Push(lua.LString(__nakamaReturnValue)) + l.Push(fn) + + nargs := 1 + l.Push(ctx) + + if payload != nil { + nargs = 2 + l.Push(payload) + } + + err := l.PCall(nargs, lua.MultRet, nil) + if err != nil { + return nil, err + } + + retValue := l.Get(-1) + if retValue.Type() == lua.LTString && lua.LVAsString(retValue) == __nakamaReturnValue { + return nil, nil + } + + return retValue, nil +} + +func (r *Runtime) Stop() { + // Not necessarily required as it only does OS temp files cleanup, which we don't expose in the runtime. + r.vm.Close() +} diff --git a/server/runtime_lua_context.go b/server/runtime_lua_context.go new file mode 100644 index 0000000000000000000000000000000000000000..a28986f5cc486d9c7ccb1442a6803a49d15e9501 --- /dev/null +++ b/server/runtime_lua_context.go @@ -0,0 +1,153 @@ +// Copyright 2017 The Nakama Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package server + +import ( + "fmt" + + "github.com/yuin/gopher-lua" +) + +type ExecutionMode int + +const ( + RPC ExecutionMode = iota +) + +func (e ExecutionMode) String() string { + switch e { + case RPC: + return "rpc" + } + + return "" +} + +const ( + __CTX_ENV = "Env" + __CTX_MODE = "ExecutionMode" + __CTX_USER_ID = "UserId" + __CTX_USERNAME = "Username" + __CTX_USER_SESSION_EXP = "UserSessionExp" + __CTX_SESSION_ID = "SessionId" +) + +func NewLuaContext(l *lua.LState, env *lua.LTable, mode ExecutionMode, uid string, username string, sessionExpiry int64, sid string) *lua.LTable { + lt := l.NewTable() + lt.RawSetString(__CTX_ENV, env) + lt.RawSetString(__CTX_MODE, lua.LString(mode.String())) + + if uid != "" { + lt.RawSetString(__CTX_USER_ID, lua.LString(uid)) + lt.RawSetString(__CTX_USERNAME, lua.LString(username)) + lt.RawSetString(__CTX_USER_SESSION_EXP, lua.LNumber(sessionExpiry)) + } + if sid != "" { + lt.RawSetString(__CTX_SESSION_ID, lua.LString(sid)) + } + + return lt +} + +func ConvertMap(l *lua.LState, data map[string]interface{}) *lua.LTable { + lt := l.NewTable() + + for k, v := range data { + lt.RawSetString(k, convertValue(l, v)) + } + + return lt +} + +func ConvertLuaTable(lv *lua.LTable) map[string]interface{} { + returnData, _ := convertLuaValue(lv).(map[string]interface{}) + return returnData +} + +func convertValue(l *lua.LState, val interface{}) lua.LValue { + if val == nil { + return lua.LNil + } + + // Types looked up from: + // https://golang.org/pkg/encoding/json/#Unmarshal + // https://developers.google.com/protocol-buffers/docs/proto3#scalar + switch v := val.(type) { + case bool: + return lua.LBool(v) + case string: + return lua.LString(v) + case []byte: + return lua.LString(v) + case float32: + return lua.LNumber(v) + case float64: + return lua.LNumber(v) + case int: + return lua.LNumber(v) + case int32: + return lua.LNumber(v) + case int64: + return lua.LNumber(v) + case uint32: + return lua.LNumber(v) + case uint64: + return lua.LNumber(v) + case map[string]interface{}: + return ConvertMap(l, v) + case []interface{}: + lt := l.NewTable() + for k, v := range v { + lt.RawSetInt(k+1, convertValue(l, v)) + } + return lt + default: + return nil + } +} + +func convertLuaValue(lv lua.LValue) interface{} { + // Taken from: https://github.com/yuin/gluamapper/blob/master/gluamapper.go#L79 + switch v := lv.(type) { + case *lua.LNilType: + return nil + case lua.LBool: + return bool(v) + case lua.LString: + return string(v) + case lua.LNumber: + return float64(v) + case *lua.LTable: + maxn := v.MaxN() + if maxn == 0 { + // Table. + ret := make(map[string]interface{}) + v.ForEach(func(key, value lua.LValue) { + keystr := fmt.Sprint(convertLuaValue(key)) + ret[keystr] = convertLuaValue(value) + }) + return ret + } else { + // Array. + ret := make([]interface{}, 0, maxn) + for i := 1; i <= maxn; i++ { + ret = append(ret, convertLuaValue(v.RawGetInt(i))) + } + return ret + } + default: + return v + } +} diff --git a/server/runtime_nakama_module.go b/server/runtime_nakama_module.go new file mode 100644 index 0000000000000000000000000000000000000000..a91c262e15d52d2d007d1e11ee0a675e1e1c1f26 --- /dev/null +++ b/server/runtime_nakama_module.go @@ -0,0 +1,1108 @@ +// Copyright 2018 The Nakama Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package server + +import ( + "context" + "io" + "net/http" + "time" + + "strings" + + "database/sql" + + "encoding/json" + + "encoding/base64" + + "encoding/hex" + "io/ioutil" + + "github.com/gorhill/cronexpr" + "github.com/satori/go.uuid" + "github.com/yuin/gopher-lua" + "go.uber.org/zap" + "github.com/heroiclabs/nakama/rtapi" + "golang.org/x/crypto/bcrypt" + "sync" + "crypto/aes" + "crypto/rand" + "crypto/cipher" +) + +const CALLBACKS = "runtime_callbacks" + +type Callbacks struct { + RPC map[string]*lua.LFunction +} + +type NakamaModule struct { + logger *zap.Logger + db *sql.DB + config Config + registry *SessionRegistry + tracker Tracker + router MessageRouter + once *sync.Once + announceRPC func(string) + client *http.Client +} + +func NewNakamaModule(logger *zap.Logger, db *sql.DB, config Config, l *lua.LState, registry *SessionRegistry, tracker Tracker, router MessageRouter, once *sync.Once, announceRPC func(string)) *NakamaModule { + l.SetContext(context.WithValue(context.Background(), CALLBACKS, &Callbacks{ + RPC: make(map[string]*lua.LFunction), + })) + return &NakamaModule{ + logger: logger, + db: db, + config: config, + registry: registry, + tracker: tracker, + router: router, + once: once, + announceRPC: announceRPC, + client: &http.Client{ + Timeout: 5 * time.Second, + }, + } +} + +func (n *NakamaModule) Loader(l *lua.LState) int { + mod := l.SetFuncs(l.NewTable(), map[string]lua.LGFunction{ + "sql_exec": n.sqlExec, + "sql_query": n.sqlQuery, + "uuid_v4": n.uuidV4, + "uuid_bytes_to_string": n.uuidBytesToString, + "uuid_string_to_bytes": n.uuidStringToBytes, + "http_request": n.httpRequest, + "json_encode": n.jsonEncode, + "json_decode": n.jsonDecode, + "base64_encode": n.base64Encode, + "base64_decode": n.base64Decode, + "base16_encode": n.base16Encode, + "base16_decode": n.base16decode, + "aes128_encrypt": n.aes128encrypt, + "aes128_decrypt": n.aes128decrypt, + "bcrypt_hash": n.bcryptHash, + "bcrypt_compare": n.bcryptCompare, + "auth_token_generate": n.authTokenGenerate, + "cron_next": n.cronNext, + "logger_info": n.loggerInfo, + "logger_warn": n.loggerWarn, + "logger_error": n.loggerError, + "stream_user_get": n.streamUserGet, + "stream_user_join": n.streamUserJoin, + "stream_user_leave": n.streamUserLeave, + "stream_count": n.streamCount, + "stream_close": n.streamClose, + "stream_send": n.streamSend, + "register_rpc": n.registerRPC, + // "run_once": n.runOnce, + }) + + l.Push(mod) + return 1 +} + +func (n *NakamaModule) sqlExec(l *lua.LState) int { + query := l.CheckString(1) + if query == "" { + l.ArgError(1, "expects query string") + return 0 + } + paramsTable := l.OptTable(2, l.NewTable()) + if paramsTable == nil { + l.ArgError(2, "expects params table") + return 0 + } + var params []interface{} + if paramsTable.Len() != 0 { + var ok bool + params, ok = convertLuaValue(paramsTable).([]interface{}) + if !ok { + l.ArgError(2, "expects a list of params as a table") + return 0 + } + } + + result, err := n.db.Exec(query, params...) + if err != nil { + l.RaiseError("sql exec error: %v", err.Error()) + return 0 + } + count, err := result.RowsAffected() + if err != nil { + l.RaiseError("sql exec rows affected error: %v", err.Error()) + return 0 + } + + l.Push(lua.LNumber(count)) + return 1 +} + +func (n *NakamaModule) sqlQuery(l *lua.LState) int { + query := l.CheckString(1) + if query == "" { + l.ArgError(1, "expects query string") + return 0 + } + paramsTable := l.OptTable(2, l.NewTable()) + if paramsTable == nil { + l.ArgError(2, "expects params table") + return 0 + } + var params []interface{} + if paramsTable.Len() != 0 { + var ok bool + params, ok = convertLuaValue(paramsTable).([]interface{}) + if !ok { + l.ArgError(2, "expects a list of params as a table") + return 0 + } + } + + rows, err := n.db.Query(query, params...) + if err != nil { + l.RaiseError("sql query error: %v", err.Error()) + return 0 + } + defer rows.Close() + + resultColumns, err := rows.Columns() + if err != nil { + l.RaiseError("sql query column lookup error: %v", err.Error()) + return 0 + } + resultColumnCount := len(resultColumns) + resultRows := make([][]interface{}, 0) + for rows.Next() { + resultRowValues := make([]interface{}, resultColumnCount) + resultRowPointers := make([]interface{}, resultColumnCount) + for i, _ := range resultRowValues { + resultRowPointers[i] = &resultRowValues[i] + } + if err = rows.Scan(resultRowPointers...); err != nil { + l.RaiseError("sql query scan error: %v", err.Error()) + return 0 + } + resultRows = append(resultRows, resultRowValues) + } + if err = rows.Err(); err != nil { + l.RaiseError("sql query row scan error: %v", err.Error()) + return 0 + } + + rt := l.NewTable() + for i, r := range resultRows { + rowTable := l.NewTable() + for j, col := range resultColumns { + rowTable.RawSetString(col, convertValue(l, r[j])) + } + rt.RawSetInt(i+1, rowTable) + } + l.Push(rt) + return 1 +} + +func (n *NakamaModule) uuidV4(l *lua.LState) int { + l.Push(lua.LString(uuid.NewV4().String())) + return 1 +} + +func (n *NakamaModule) uuidBytesToString(l *lua.LState) int { + uuidBytes := l.CheckString(1) + if uuidBytes == "" { + l.ArgError(1, "expects a UUID byte string") + return 0 + } + u, err := uuid.FromBytes([]byte(uuidBytes)) + if err != nil { + l.ArgError(1, "not a valid UUID byte string") + return 0 + } + l.Push(lua.LString(u.String())) + return 1 +} + +func (n *NakamaModule) uuidStringToBytes(l *lua.LState) int { + uuidString := l.CheckString(1) + if uuidString == "" { + l.ArgError(1, "expects a UUID string") + return 0 + } + u, err := uuid.FromString(uuidString) + if err != nil { + l.ArgError(1, "not a valid UUID string") + return 0 + } + l.Push(lua.LString(u.Bytes())) + return 1 +} + +func (n *NakamaModule) httpRequest(l *lua.LState) int { + url := l.CheckString(1) + method := l.CheckString(2) + headers := l.CheckTable(3) + body := l.OptString(4, "") + if url == "" { + l.ArgError(1, "expects URL string") + return 0 + } + if method == "" { + l.ArgError(2, "expects method string") + return 0 + } + + // Prepare request body, if any. + var requestBody io.Reader + if body != "" { + requestBody = strings.NewReader(body) + } + // Prepare the request. + req, err := http.NewRequest(method, url, requestBody) + if err != nil { + l.RaiseError("HTTP request error: %v", err.Error()) + return 0 + } + // Apply any request headers. + httpHeaders := ConvertLuaTable(headers) + for k, v := range httpHeaders { + if vs, ok := v.(string); !ok { + l.RaiseError("HTTP header values must be strings") + return 0 + } else { + req.Header.Add(k, vs) + } + } + // Execute the request. + resp, err := n.client.Do(req) + if err != nil { + l.RaiseError("HTTP request error: %v", err.Error()) + return 0 + } + // Read the response body. + responseBody, err := ioutil.ReadAll(resp.Body) + resp.Body.Close() + if err != nil { + l.RaiseError("HTTP response body error: %v", err.Error()) + return 0 + } + // Read the response headers. + responseHeaders := make(map[string]interface{}, len(resp.Header)) + for k, vs := range resp.Header { + // TODO accept multiple values per header + for _, v := range vs { + responseHeaders[k] = v + break + } + } + + l.Push(lua.LNumber(resp.StatusCode)) + l.Push(ConvertMap(l, responseHeaders)) + l.Push(lua.LString(string(responseBody))) + return 3 +} + +func (n *NakamaModule) jsonEncode(l *lua.LState) int { + jsonTable := l.Get(1) + if jsonTable == nil { + l.ArgError(1, "expects a non-nil value to encode") + return 0 + } + + jsonData := convertLuaValue(jsonTable) + jsonBytes, err := json.Marshal(jsonData) + if err != nil { + l.RaiseError("error encoding to JSON: %v", err.Error()) + return 0 + } + + l.Push(lua.LString(string(jsonBytes))) + return 1 +} + +func (n *NakamaModule) jsonDecode(l *lua.LState) int { + jsonString := l.CheckString(1) + if jsonString == "" { + l.ArgError(1, "expects JSON string") + return 0 + } + + var jsonData interface{} + if err := json.Unmarshal([]byte(jsonString), &jsonData); err != nil { + l.RaiseError("not a valid JSON string: %v", err.Error()) + return 0 + } + + l.Push(convertValue(l, jsonData)) + return 1 +} + +func (n *NakamaModule) base64Encode(l *lua.LState) int { + input := l.CheckString(1) + if input == "" { + l.ArgError(1, "expects string") + return 0 + } + + output := base64.StdEncoding.EncodeToString([]byte(input)) + l.Push(lua.LString(output)) + return 1 +} + +func (n *NakamaModule) base64Decode(l *lua.LState) int { + input := l.CheckString(1) + if input == "" { + l.ArgError(1, "expects string") + return 0 + } + + output, err := base64.RawStdEncoding.DecodeString(input) + if err != nil { + l.RaiseError("not a valid base64 string: %v", err.Error()) + return 0 + } + + l.Push(lua.LString(output)) + return 1 +} + +func (n *NakamaModule) base16Encode(l *lua.LState) int { + input := l.CheckString(1) + if input == "" { + l.ArgError(1, "expects string") + return 0 + } + + output := hex.EncodeToString([]byte(input)) + l.Push(lua.LString(output)) + return 1 +} + +func (n *NakamaModule) base16decode(l *lua.LState) int { + input := l.CheckString(1) + if input == "" { + l.ArgError(1, "expects string") + return 0 + } + + output, err := hex.DecodeString(input) + if err != nil { + l.RaiseError("not a valid base16 string: %v", err.Error()) + return 0 + } + + l.Push(lua.LString(output)) + return 1 +} + +func (n *NakamaModule) aes128encrypt(l *lua.LState) int { + input := l.CheckString(1) + if input == "" { + l.ArgError(1, "expects string") + return 0 + } + key := l.CheckString(2) + if len(key) != 16 { + l.ArgError(2, "expects key 16 bytes long") + return 0 + } + + // Pad string up to length multiple of 4 if needed. + if maybePad := len(input) % 4; maybePad != 0 { + input += strings.Repeat(" ", 4-maybePad) + } + + block, err := aes.NewCipher([]byte(key)) + if err != nil { + l.RaiseError("error creating cipher block: %v", err.Error()) + return 0 + } + + cipherText := make([]byte, aes.BlockSize+len(input)) + iv := cipherText[:aes.BlockSize] + if _, err = io.ReadFull(rand.Reader, iv); err != nil { + l.RaiseError("error getting iv: %v", err.Error()) + return 0 + } + + stream := cipher.NewCFBEncrypter(block, iv) + stream.XORKeyStream(cipherText[aes.BlockSize:], []byte(input)) + + l.Push(lua.LString(cipherText)) + return 1 +} + +func (n *NakamaModule) aes128decrypt(l *lua.LState) int { + input := l.CheckString(1) + if input == "" { + l.ArgError(1, "expects string") + return 0 + } + key := l.CheckString(2) + if len(key) != 16 { + l.ArgError(2, "expects key 16 bytes long") + return 0 + } + + if len(input) < aes.BlockSize { + l.RaiseError("input too short") + return 0 + } + + block, err := aes.NewCipher([]byte(key)) + if err != nil { + l.RaiseError("error creating cipher block: %v", err.Error()) + return 0 + } + + cipherText := []byte(input) + iv := cipherText[:aes.BlockSize] + cipherText = cipherText[aes.BlockSize:] + + stream := cipher.NewCFBDecrypter(block, iv) + stream.XORKeyStream(cipherText, cipherText) + + l.Push(lua.LString(cipherText)) + return 1 +} + +func (n *NakamaModule) bcryptHash(l *lua.LState) int { + input := l.CheckString(1) + if input == "" { + l.ArgError(1, "expects string") + return 0 + } + + hash, err := bcrypt.GenerateFromPassword([]byte(input), bcrypt.DefaultCost) + if err != nil { + l.RaiseError("error hashing input: %v", err.Error()) + return 0 + } + + l.Push(lua.LString(hash)) + return 1 +} + +func (n *NakamaModule) bcryptCompare(l *lua.LState) int { + hash := l.CheckString(1) + if hash == "" { + l.ArgError(1, "expects string") + return 0 + } + plaintext := l.CheckString(2) + if plaintext == "" { + l.ArgError(2, "expects string") + return 0 + } + + err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(plaintext)) + if err == nil { + l.Push(lua.LBool(true)) + return 1 + } else if err == bcrypt.ErrHashTooShort || err == bcrypt.ErrMismatchedHashAndPassword { + l.Push(lua.LBool(false)) + return 1 + } + + l.RaiseError("error comparing hash and plaintext: %v", err.Error()) + return 0 +} + +func (n *NakamaModule) authTokenGenerate(l *lua.LState) int { + // Parse input User ID. + userIDString := l.CheckString(1) + if userIDString == "" { + l.ArgError(1, "expects user id") + return 0 + } + _, err := uuid.FromString(userIDString) + if err != nil { + l.ArgError(1, "expects valid user id") + return 0 + } + + // Input username. + username := l.CheckString(2) + if username == "" { + l.ArgError(2, "expects username") + return 0 + } + + exp := l.OptInt64(3, 0) + if exp == 0 { + // If expiry is 0 or not set, use standard configured expiry. + exp = time.Now().UTC().Add(time.Duration(n.config.GetSession().TokenExpiryMs) * time.Millisecond).Unix() + } + + token := generateTokenWithExpiry(n.config, userIDString, username, exp) + + l.Push(lua.LString(token)) + return 1 +} + +func (n *NakamaModule) cronNext(l *lua.LState) int { + cron := l.CheckString(1) + if cron == "" { + l.ArgError(1, "expects cron string") + return 0 + } + ts := l.CheckInt64(2) + if ts == 0 { + l.ArgError(1, "expects timestamp in seconds") + return 0 + } + + expr, err := cronexpr.Parse(cron) + if err != nil { + l.ArgError(1, "expects a valid cron string") + return 0 + } + t := time.Unix(ts, 0).UTC() + next := expr.Next(t) + nextTs := next.UTC().Unix() + l.Push(lua.LNumber(nextTs)) + return 1 +} + +func (n *NakamaModule) loggerInfo(l *lua.LState) int { + message := l.CheckString(1) + if message == "" { + l.ArgError(1, "expects message string") + return 0 + } + n.logger.Info(message) + l.Push(lua.LString(message)) + return 1 +} + +func (n *NakamaModule) loggerWarn(l *lua.LState) int { + message := l.CheckString(1) + if message == "" { + l.ArgError(1, "expects message string") + return 0 + } + n.logger.Warn(message) + l.Push(lua.LString(message)) + return 1 +} + +func (n *NakamaModule) loggerError(l *lua.LState) int { + message := l.CheckString(1) + if message == "" { + l.ArgError(1, "expects message string") + return 0 + } + n.logger.Error(message) + l.Push(lua.LString(message)) + return 1 +} + +func (n *NakamaModule) streamUserGet(l *lua.LState) int { + // Parse input User ID. + userIDString := l.CheckString(1) + if userIDString == "" { + l.ArgError(1, "expects user id") + return 0 + } + userID, err := uuid.FromString(userIDString) + if err != nil { + l.ArgError(1, "expects valid user id") + return 0 + } + + // Parse input Session ID. + sessionIDString := l.CheckString(2) + if sessionIDString == "" { + l.ArgError(2, "expects session id") + return 0 + } + sessionID, err := uuid.FromString(sessionIDString) + if err != nil { + l.ArgError(2, "expects valid session id") + return 0 + } + + // Parse input stream identifier. + streamTable := l.CheckTable(3) + if streamTable == nil || streamTable.Len() == 0 { + l.ArgError(3, "expects a valid stream") + return 0 + } + stream := PresenceStream{} + conversionError := "" + streamTable.ForEach(func(k lua.LValue, v lua.LValue) { + switch k.String() { + case "Mode": + if v.Type() != lua.LTNumber { + conversionError = "stream Mode must be a number" + return + } + stream.Mode = uint8(lua.LVAsNumber(v)) + case "Subject": + if v.Type() != lua.LTString { + conversionError = "stream Subject must be a string" + return + } + sid, err := uuid.FromString(v.String()) + if err != nil { + conversionError = "stream Subject must be a valid identifier" + return + } + stream.Subject = sid + case "Descriptor": + if v.Type() != lua.LTString { + conversionError = "stream Descriptor must be a string" + return + } + did, err := uuid.FromString(v.String()) + if err != nil { + conversionError = "stream Descriptor must be a valid identifier" + return + } + stream.Subject = did + case "Label": + if v.Type() != lua.LTString { + conversionError = "stream Label must be a string" + return + } + stream.Label = v.String() + } + }) + if conversionError != "" { + l.ArgError(3, conversionError) + return 0 + } + + meta := n.tracker.GetLocalBySessionIDStreamUserID(sessionID, stream, userID) + if meta == nil { + l.Push(lua.LNil) + } else { + metaTable := l.NewTable() + metaTable.RawSetString("Hidden", lua.LBool(meta.Hidden)) + metaTable.RawSetString("Persistence", lua.LBool(meta.Persistence)) + metaTable.RawSetString("Username", lua.LString(meta.Username)) + metaTable.RawSetString("Status", lua.LString(meta.Status)) + l.Push(metaTable) + } + return 1 +} + +func (n *NakamaModule) streamUserJoin(l *lua.LState) int { + // Parse input User ID. + userIDString := l.CheckString(1) + if userIDString == "" { + l.ArgError(1, "expects user id") + return 0 + } + userID, err := uuid.FromString(userIDString) + if err != nil { + l.ArgError(1, "expects valid user id") + return 0 + } + + // Parse input Session ID. + sessionIDString := l.CheckString(2) + if sessionIDString == "" { + l.ArgError(2, "expects session id") + return 0 + } + sessionID, err := uuid.FromString(sessionIDString) + if err != nil { + l.ArgError(2, "expects valid session id") + return 0 + } + + // Parse input stream identifier. + streamTable := l.CheckTable(3) + if streamTable == nil || streamTable.Len() == 0 { + l.ArgError(3, "expects a valid stream") + return 0 + } + stream := PresenceStream{} + conversionError := "" + streamTable.ForEach(func(k lua.LValue, v lua.LValue) { + switch k.String() { + case "Mode": + if v.Type() != lua.LTNumber { + conversionError = "stream Mode must be a number" + return + } + stream.Mode = uint8(lua.LVAsNumber(v)) + case "Subject": + if v.Type() != lua.LTString { + conversionError = "stream Subject must be a string" + return + } + sid, err := uuid.FromString(v.String()) + if err != nil { + conversionError = "stream Subject must be a valid identifier" + return + } + stream.Subject = sid + case "Descriptor": + if v.Type() != lua.LTString { + conversionError = "stream Descriptor must be a string" + return + } + did, err := uuid.FromString(v.String()) + if err != nil { + conversionError = "stream Descriptor must be a valid identifier" + return + } + stream.Subject = did + case "Label": + if v.Type() != lua.LTString { + conversionError = "stream Label must be a string" + return + } + stream.Label = v.String() + } + }) + if conversionError != "" { + l.ArgError(3, conversionError) + return 0 + } + + // By default generate presence events. + hidden := l.OptBool(4, false) + // By default persistence is enabled, if the stream supports it. + persistence := l.OptBool(5, true) + + // Look up the session. + session := n.registry.Get(sessionID) + if session == nil { + l.ArgError(2, "session id does not exist") + return 0 + } + + alreadyTracked := n.tracker.Track(sessionID, stream, userID, PresenceMeta{ + Format: session.Format(), + Hidden: hidden, + Persistence: persistence, + Username: session.Username(), + }) + + l.Push(lua.LBool(alreadyTracked)) + return 1 +} + +func (n *NakamaModule) streamUserLeave(l *lua.LState) int { + // Parse input User ID. + userIDString := l.CheckString(1) + if userIDString == "" { + l.ArgError(1, "expects user id") + return 0 + } + userID, err := uuid.FromString(userIDString) + if err != nil { + l.ArgError(1, "expects valid user id") + return 0 + } + + // Parse input Session ID. + sessionIDString := l.CheckString(2) + if sessionIDString == "" { + l.ArgError(2, "expects session id") + return 0 + } + sessionID, err := uuid.FromString(sessionIDString) + if err != nil { + l.ArgError(2, "expects valid session id") + return 0 + } + + // Parse input stream identifier. + streamTable := l.CheckTable(3) + if streamTable == nil || streamTable.Len() == 0 { + l.ArgError(3, "expects a valid stream") + return 0 + } + stream := PresenceStream{} + conversionError := "" + streamTable.ForEach(func(k lua.LValue, v lua.LValue) { + switch k.String() { + case "Mode": + if v.Type() != lua.LTNumber { + conversionError = "stream Mode must be a number" + return + } + stream.Mode = uint8(lua.LVAsNumber(v)) + case "Subject": + if v.Type() != lua.LTString { + conversionError = "stream Subject must be a string" + return + } + sid, err := uuid.FromString(v.String()) + if err != nil { + conversionError = "stream Subject must be a valid identifier" + return + } + stream.Subject = sid + case "Descriptor": + if v.Type() != lua.LTString { + conversionError = "stream Descriptor must be a string" + return + } + did, err := uuid.FromString(v.String()) + if err != nil { + conversionError = "stream Descriptor must be a valid identifier" + return + } + stream.Subject = did + case "Label": + if v.Type() != lua.LTString { + conversionError = "stream Label must be a string" + return + } + stream.Label = v.String() + } + }) + if conversionError != "" { + l.ArgError(3, conversionError) + return 0 + } + + n.tracker.Untrack(sessionID, stream, userID) + + return 0 +} + +func (n *NakamaModule) streamCount(l *lua.LState) int { + // Parse input stream identifier. + streamTable := l.CheckTable(1) + if streamTable == nil || streamTable.Len() == 0 { + l.ArgError(1, "expects a valid stream") + return 0 + } + stream := PresenceStream{} + conversionError := "" + streamTable.ForEach(func(k lua.LValue, v lua.LValue) { + switch k.String() { + case "Mode": + if v.Type() != lua.LTNumber { + conversionError = "stream Mode must be a number" + return + } + stream.Mode = uint8(lua.LVAsNumber(v)) + case "Subject": + if v.Type() != lua.LTString { + conversionError = "stream Subject must be a string" + return + } + sid, err := uuid.FromString(v.String()) + if err != nil { + conversionError = "stream Subject must be a valid identifier" + return + } + stream.Subject = sid + case "Descriptor": + if v.Type() != lua.LTString { + conversionError = "stream Descriptor must be a string" + return + } + did, err := uuid.FromString(v.String()) + if err != nil { + conversionError = "stream Descriptor must be a valid identifier" + return + } + stream.Subject = did + case "Label": + if v.Type() != lua.LTString { + conversionError = "stream Label must be a string" + return + } + stream.Label = v.String() + } + }) + if conversionError != "" { + l.ArgError(1, conversionError) + return 0 + } + + count := n.tracker.CountByStream(stream) + + l.Push(lua.LNumber(count)) + return 1 +} + +func (n *NakamaModule) streamClose(l *lua.LState) int { + // Parse input stream identifier. + streamTable := l.CheckTable(1) + if streamTable == nil || streamTable.Len() == 0 { + l.ArgError(1, "expects a valid stream") + return 0 + } + stream := PresenceStream{} + conversionError := "" + streamTable.ForEach(func(k lua.LValue, v lua.LValue) { + switch k.String() { + case "Mode": + if v.Type() != lua.LTNumber { + conversionError = "stream Mode must be a number" + return + } + stream.Mode = uint8(lua.LVAsNumber(v)) + case "Subject": + if v.Type() != lua.LTString { + conversionError = "stream Subject must be a string" + return + } + sid, err := uuid.FromString(v.String()) + if err != nil { + conversionError = "stream Subject must be a valid identifier" + return + } + stream.Subject = sid + case "Descriptor": + if v.Type() != lua.LTString { + conversionError = "stream Descriptor must be a string" + return + } + did, err := uuid.FromString(v.String()) + if err != nil { + conversionError = "stream Descriptor must be a valid identifier" + return + } + stream.Subject = did + case "Label": + if v.Type() != lua.LTString { + conversionError = "stream Label must be a string" + return + } + stream.Label = v.String() + } + }) + if conversionError != "" { + l.ArgError(1, conversionError) + return 0 + } + + n.tracker.UntrackByStream(stream) + + return 0 +} + +func (n *NakamaModule) streamSend(l *lua.LState) int { + // Parse input stream identifier. + streamTable := l.CheckTable(1) + if streamTable == nil || streamTable.Len() == 0 { + l.ArgError(1, "expects a valid stream") + return 0 + } + stream := PresenceStream{} + conversionError := "" + streamTable.ForEach(func(k lua.LValue, v lua.LValue) { + switch k.String() { + case "Mode": + if v.Type() != lua.LTNumber { + conversionError = "stream Mode must be a number" + return + } + stream.Mode = uint8(lua.LVAsNumber(v)) + case "Subject": + if v.Type() != lua.LTString { + conversionError = "stream Subject must be a string" + return + } + sid, err := uuid.FromString(v.String()) + if err != nil { + conversionError = "stream Subject must be a valid identifier" + return + } + stream.Subject = sid + case "Descriptor": + if v.Type() != lua.LTString { + conversionError = "stream Descriptor must be a string" + return + } + did, err := uuid.FromString(v.String()) + if err != nil { + conversionError = "stream Descriptor must be a valid identifier" + return + } + stream.Subject = did + case "Label": + if v.Type() != lua.LTString { + conversionError = "stream Label must be a string" + return + } + stream.Label = v.String() + } + }) + if conversionError != "" { + l.ArgError(1, conversionError) + return 0 + } + + // Grab payload to send, allow empty data. + data := l.CheckString(2) + + streamWire := &rtapi.Stream{ + Mode: int32(stream.Mode), + Label: stream.Label, + } + if stream.Subject != uuid.Nil { + streamWire.Subject = stream.Subject.String() + } + if stream.Descriptor != uuid.Nil { + streamWire.Descriptor_ = stream.Descriptor.String() + } + msg := &rtapi.Envelope{Message: &rtapi.Envelope_StreamData{StreamData: &rtapi.StreamData{ + Stream: streamWire, + // No sender. + Data: data, + }}} + n.router.SendToStream(n.logger, stream, msg) + + return 0 +} + +func (n *NakamaModule) registerRPC(l *lua.LState) int { + fn := l.CheckFunction(1) + id := l.CheckString(2) + + if id == "" { + l.ArgError(2, "expects rpc id") + return 0 + } + + id = strings.ToLower(id) + + rc := l.Context().Value(CALLBACKS).(*Callbacks) + rc.RPC[id] = fn + if n.announceRPC != nil { + n.announceRPC(id) + } + return 0 +} + +func (n *NakamaModule) runOnce(l *lua.LState) int { + n.once.Do(func() { + fn := l.CheckFunction(1) + if fn == nil { + l.ArgError(1, "expects a function") + return + } + + l.Push(fn) + if err := l.PCall(0, lua.MultRet, nil); err != nil { + l.RaiseError("error in run_once function: %v", err.Error()) + } + }) + + return 0 +} diff --git a/server/runtime_oslib.go b/server/runtime_oslib.go new file mode 100644 index 0000000000000000000000000000000000000000..c01edd5380c35c64e8188db4e71da51d0ef2a605 --- /dev/null +++ b/server/runtime_oslib.go @@ -0,0 +1,128 @@ +// The MIT License (MIT) +// +// Copyright (c) 2015 Yusuke Inuzuka +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package server + +import ( + "github.com/yuin/gopher-lua" + "strings" + "time" +) + +var startedAt time.Time + +func init() { + startedAt = time.Now() +} + +func getIntField(L *lua.LState, tb *lua.LTable, key string, v int) int { + ret := tb.RawGetString(key) + if ln, ok := ret.(lua.LNumber); ok { + return int(ln) + } + return v +} + +func getBoolField(L *lua.LState, tb *lua.LTable, key string, v bool) bool { + ret := tb.RawGetString(key) + if lb, ok := ret.(lua.LBool); ok { + return bool(lb) + } + return v +} + +func OpenOs(L *lua.LState) int { + osmod := L.RegisterModule(lua.OsLibName, osFuncs) + L.Push(osmod) + return 1 +} + +var osFuncs = map[string]lua.LGFunction{ + "clock": osClock, + "difftime": osDiffTime, + "date": osDate, + "time": osTime, +} + +func osClock(L *lua.LState) int { + L.Push(lua.LNumber(float64(time.Now().Sub(startedAt)) / float64(time.Second))) + return 1 +} + +func osDiffTime(L *lua.LState) int { + L.Push(lua.LNumber(L.CheckInt64(1) - L.CheckInt64(2))) + return 1 +} + +func osDate(L *lua.LState) int { + t := time.Now().UTC() + cfmt := "%c" + if L.GetTop() >= 1 { + cfmt = L.CheckString(1) + if strings.HasPrefix(cfmt, "!") { + t = time.Now().UTC() + cfmt = strings.TrimLeft(cfmt, "!") + } + if L.GetTop() >= 2 { + t = time.Unix(L.CheckInt64(2), 0) + } + if strings.HasPrefix(cfmt, "*t") { + ret := L.NewTable() + ret.RawSetString("year", lua.LNumber(t.Year())) + ret.RawSetString("month", lua.LNumber(t.Month())) + ret.RawSetString("day", lua.LNumber(t.Day())) + ret.RawSetString("hour", lua.LNumber(t.Hour())) + ret.RawSetString("min", lua.LNumber(t.Minute())) + ret.RawSetString("sec", lua.LNumber(t.Second())) + ret.RawSetString("wday", lua.LNumber(t.Weekday())) + ret.RawSetString("yday", lua.LNumber(t.YearDay())) + // TODO dst + ret.RawSetString("isdst", lua.LFalse) + L.Push(ret) + return 1 + } + } + L.Push(lua.LString(strftime(t, cfmt))) + return 1 +} + +func osTime(L *lua.LState) int { + if L.GetTop() == 0 { + L.Push(lua.LNumber(time.Now().UTC().Unix())) + } else { + tbl := L.CheckTable(1) + sec := getIntField(L, tbl, "sec", 0) + min := getIntField(L, tbl, "min", 0) + hour := getIntField(L, tbl, "hour", 12) + day := getIntField(L, tbl, "day", -1) + month := getIntField(L, tbl, "month", -1) + year := getIntField(L, tbl, "year", -1) + isdst := getBoolField(L, tbl, "isdst", false) + t := time.Date(year, time.Month(month), day, hour, min, sec, 0, time.UTC) + // TODO dst + if false { + print(isdst) + } + L.Push(lua.LNumber(t.UTC().Unix())) + } + return 1 +} diff --git a/server/runtime_utils.go b/server/runtime_utils.go new file mode 100644 index 0000000000000000000000000000000000000000..2a984595b678bb778dca182ee489fa82d6ebd2e6 --- /dev/null +++ b/server/runtime_utils.go @@ -0,0 +1,111 @@ +// The MIT License (MIT) +// +// Copyright (c) 2015 Yusuke Inuzuka +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package server + +import ( + "fmt" + "time" +) + +type flagScanner struct { + flag byte + start string + end string + buf []byte + str string + Length int + Pos int + HasFlag bool + ChangeFlag bool +} + +func newFlagScanner(flag byte, start, end, str string) *flagScanner { + return &flagScanner{flag, start, end, make([]byte, 0, len(str)), str, len(str), 0, false, false} +} + +func (fs *flagScanner) AppendString(str string) { fs.buf = append(fs.buf, str...) } + +func (fs *flagScanner) AppendChar(ch byte) { fs.buf = append(fs.buf, ch) } + +func (fs *flagScanner) String() string { return string(fs.buf) } + +func (fs *flagScanner) Next() (byte, bool) { + c := byte('\000') + fs.ChangeFlag = false + if fs.Pos == fs.Length { + if fs.HasFlag { + fs.AppendString(fs.end) + } + return c, true + } else { + c = fs.str[fs.Pos] + if c == fs.flag { + if fs.Pos < (fs.Length-1) && fs.str[fs.Pos+1] == fs.flag { + fs.HasFlag = false + fs.AppendChar(fs.flag) + fs.Pos += 2 + return fs.Next() + } else if fs.Pos != fs.Length-1 { + if fs.HasFlag { + fs.AppendString(fs.end) + } + fs.AppendString(fs.start) + fs.ChangeFlag = true + fs.HasFlag = true + } + } + } + fs.Pos++ + return c, false +} + +var cDateFlagToGo = map[byte]string{ + 'a': "mon", 'A': "Monday", 'b': "Jan", 'B': "January", 'c': "02 Jan 06 15:04 MST", 'd': "02", + 'F': "2006-01-02", 'H': "15", 'I': "03", 'm': "01", 'M': "04", 'p': "PM", 'P': "pm", 'S': "05", + 'x': "15/04/05", 'X': "15:04:05", 'y': "06", 'Y': "2006", 'z': "-0700", 'Z': "MST"} + +func strftime(t time.Time, cfmt string) string { + sc := newFlagScanner('%', "", "", cfmt) + for c, eos := sc.Next(); !eos; c, eos = sc.Next() { + if !sc.ChangeFlag { + if sc.HasFlag { + if v, ok := cDateFlagToGo[c]; ok { + sc.AppendString(t.Format(v)) + } else { + switch c { + case 'w': + sc.AppendString(fmt.Sprint(int(t.Weekday()))) + default: + sc.AppendChar('%') + sc.AppendChar(c) + } + } + sc.HasFlag = false + } else { + sc.AppendChar(c) + } + } + } + + return sc.String() +} diff --git a/server/session_ws.go b/server/session_ws.go index 169ecec3138f5e57a9fca3178e1c25b8b989b6a7..c9ee60721d1aaa01aa726dfbe9cfcbd02222d53f 100644 --- a/server/session_ws.go +++ b/server/session_ws.go @@ -42,8 +42,8 @@ type sessionWS struct { jsonpbMarshaler *jsonpb.Marshaler jsonpbUnmarshaler *jsonpb.Unmarshaler - tracker Tracker registry *SessionRegistry + tracker Tracker stopped bool conn *websocket.Conn @@ -52,7 +52,7 @@ type sessionWS struct { outgoingStopCh chan struct{} } -func NewSessionWS(logger *zap.Logger, config Config, userID uuid.UUID, username string, expiry int64, jsonpbMarshaler *jsonpb.Marshaler, jsonpbUnmarshaler *jsonpb.Unmarshaler, conn *websocket.Conn, tracker Tracker, registry *SessionRegistry) session { +func NewSessionWS(logger *zap.Logger, config Config, userID uuid.UUID, username string, expiry int64, jsonpbMarshaler *jsonpb.Marshaler, jsonpbUnmarshaler *jsonpb.Unmarshaler, conn *websocket.Conn, registry *SessionRegistry, tracker Tracker) session { sessionID := uuid.NewV4() sessionLogger := logger.With(zap.String("uid", userID.String()), zap.String("sid", sessionID.String())) @@ -69,8 +69,8 @@ func NewSessionWS(logger *zap.Logger, config Config, userID uuid.UUID, username jsonpbMarshaler: jsonpbMarshaler, jsonpbUnmarshaler: jsonpbUnmarshaler, - tracker: tracker, registry: registry, + tracker: tracker, stopped: false, conn: conn, diff --git a/server/socket_ws.go b/server/socket_ws.go index 809519fda8dbf2bef2f0c81d3b5e4438c43d4a2f..b27a1860b30782140206049f54dad2d34d7005ab 100644 --- a/server/socket_ws.go +++ b/server/socket_ws.go @@ -22,7 +22,7 @@ import ( "github.com/heroiclabs/nakama/rtapi" ) -func NewSocketWsAcceptor(logger *zap.Logger, config Config, tracker Tracker, registry *SessionRegistry, jsonpbMarshaler *jsonpb.Marshaler, jsonpbUnmarshaler *jsonpb.Unmarshaler, processRequest func(*zap.Logger, session, *rtapi.Envelope)) func(http.ResponseWriter, *http.Request) { +func NewSocketWsAcceptor(logger *zap.Logger, config Config, registry *SessionRegistry, tracker Tracker, jsonpbMarshaler *jsonpb.Marshaler, jsonpbUnmarshaler *jsonpb.Unmarshaler, processRequest func(*zap.Logger, session, *rtapi.Envelope)) func(http.ResponseWriter, *http.Request) { upgrader := &websocket.Upgrader{ ReadBufferSize: 1024, WriteBufferSize: 1024, @@ -52,7 +52,7 @@ func NewSocketWsAcceptor(logger *zap.Logger, config Config, tracker Tracker, reg } // Wrap the connection for application handling. - s := NewSessionWS(logger, config, userID, username, expiry, jsonpbMarshaler, jsonpbUnmarshaler, conn, tracker, registry) + s := NewSessionWS(logger, config, userID, username, expiry, jsonpbMarshaler, jsonpbUnmarshaler, conn, registry, tracker) // Add to the session registry. registry.add(s) diff --git a/server/tracker.go b/server/tracker.go index c1d364927fdb85295087f92bc347f6275a27fc28..cecb2297cf3933fa47201649d6bbaeb60f9e5640 100644 --- a/server/tracker.go +++ b/server/tracker.go @@ -72,6 +72,8 @@ type Tracker interface { Update(sessionID uuid.UUID, stream PresenceStream, userID uuid.UUID, meta PresenceMeta) bool // Remove all presences on a stream, effectively closing it. + UntrackByStream(stream PresenceStream) + // Remove all presences on a stream from the local node. UntrackLocalByStream(stream PresenceStream) // List the nodes that have at least one presence for the given stream. @@ -338,6 +340,33 @@ func (t *LocalTracker) UntrackLocalByStream(stream PresenceStream) { t.Unlock() } +func (t *LocalTracker) UntrackByStream(stream PresenceStream) { + // NOTE: Generates no presence notifications as everyone on the stream is going away all at once. + t.Lock() + + byStream, anyTracked := t.presencesByStream[stream] + if !anyTracked { + // Nothing tracked for the stream. + t.Unlock() + return + } + + // Drop the presences from tracking for each session. + for pc, _ := range byStream { + if bySession := t.presencesBySession[pc.ID.SessionID]; len(bySession) == 1 { + // This is the only presence for that session, discard the whole list. + delete(t.presencesBySession, pc.ID.SessionID) + } else { + // There were other presences for the session, drop just this one. + delete(bySession, pc) + } + } + // Discard the tracking for stream. + delete(t.presencesByStream, stream) + + t.Unlock() +} + func (t *LocalTracker) ListNodesForStream(stream PresenceStream) []string { t.RLock() _, anyTracked := t.presencesByStream[stream] diff --git a/vendor/github.com/golang/protobuf/proto/BUILD.bazel b/vendor/github.com/golang/protobuf/proto/BUILD.bazel deleted file mode 100644 index 01d14e7245545d2fab94b60738866064884837ad..0000000000000000000000000000000000000000 --- a/vendor/github.com/golang/protobuf/proto/BUILD.bazel +++ /dev/null @@ -1,55 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") - -go_library( - name = "go_default_library", - srcs = [ - "clone.go", - "decode.go", - "encode.go", - "equal.go", - "extensions.go", - "lib.go", - "message_set.go", - "pointer_unsafe.go", - "properties.go", - "text.go", - "text_parser.go", - ], - importpath = "github.com/golang/protobuf/proto", - visibility = ["//visibility:public"], -) - -go_test( - name = "go_default_test", - srcs = [ - "message_set_test.go", - "size2_test.go", - ], - embed = [":go_default_library"], -) - -go_test( - name = "go_default_xtest", - srcs = [ - "all_test.go", - "any_test.go", - "clone_test.go", - "decode_test.go", - "encode_test.go", - "equal_test.go", - "extensions_test.go", - "map_test.go", - "proto3_test.go", - "size_test.go", - "text_parser_test.go", - "text_test.go", - ], - deps = [ - ":go_default_library", - "//vendor/github.com/golang/protobuf/proto/proto3_proto:go_default_library", - "//vendor/github.com/golang/protobuf/proto/testdata:go_default_library", - "//vendor/github.com/golang/protobuf/ptypes:go_default_library", - "//vendor/github.com/golang/protobuf/ptypes/any:go_default_library", - "@org_golang_x_sync//errgroup:go_default_library", - ], -) diff --git a/vendor/github.com/golang/protobuf/proto/discard.go b/vendor/github.com/golang/protobuf/proto/discard.go new file mode 100644 index 0000000000000000000000000000000000000000..bd0e3bb4c85106c3dd93fa78a0f0fee307ebb4b5 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/discard.go @@ -0,0 +1,151 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2017 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package proto + +import ( + "fmt" + "reflect" + "strings" +) + +// DiscardUnknown recursively discards all unknown fields from this message +// and all embedded messages. +// +// When unmarshaling a message with unrecognized fields, the tags and values +// of such fields are preserved in the Message. This allows a later call to +// marshal to be able to produce a message that continues to have those +// unrecognized fields. To avoid this, DiscardUnknown is used to +// explicitly clear the unknown fields after unmarshaling. +// +// For proto2 messages, the unknown fields of message extensions are only +// discarded from messages that have been accessed via GetExtension. +func DiscardUnknown(m Message) { + discardLegacy(m) +} + +func discardLegacy(m Message) { + v := reflect.ValueOf(m) + if v.Kind() != reflect.Ptr || v.IsNil() { + return + } + v = v.Elem() + if v.Kind() != reflect.Struct { + return + } + t := v.Type() + + for i := 0; i < v.NumField(); i++ { + f := t.Field(i) + if strings.HasPrefix(f.Name, "XXX_") { + continue + } + vf := v.Field(i) + tf := f.Type + + // Unwrap tf to get its most basic type. + var isPointer, isSlice bool + if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 { + isSlice = true + tf = tf.Elem() + } + if tf.Kind() == reflect.Ptr { + isPointer = true + tf = tf.Elem() + } + if isPointer && isSlice && tf.Kind() != reflect.Struct { + panic(fmt.Sprintf("%T.%s cannot be a slice of pointers to primitive types", m, f.Name)) + } + + switch tf.Kind() { + case reflect.Struct: + switch { + case !isPointer: + panic(fmt.Sprintf("%T.%s cannot be a direct struct value", m, f.Name)) + case isSlice: // E.g., []*pb.T + for j := 0; j < vf.Len(); j++ { + discardLegacy(vf.Index(j).Interface().(Message)) + } + default: // E.g., *pb.T + discardLegacy(vf.Interface().(Message)) + } + case reflect.Map: + switch { + case isPointer || isSlice: + panic(fmt.Sprintf("%T.%s cannot be a pointer to a map or a slice of map values", m, f.Name)) + default: // E.g., map[K]V + tv := vf.Type().Elem() + if tv.Kind() == reflect.Ptr && tv.Implements(protoMessageType) { // Proto struct (e.g., *T) + for _, key := range vf.MapKeys() { + val := vf.MapIndex(key) + discardLegacy(val.Interface().(Message)) + } + } + } + case reflect.Interface: + // Must be oneof field. + switch { + case isPointer || isSlice: + panic(fmt.Sprintf("%T.%s cannot be a pointer to a interface or a slice of interface values", m, f.Name)) + default: // E.g., test_proto.isCommunique_Union interface + if !vf.IsNil() && f.Tag.Get("protobuf_oneof") != "" { + vf = vf.Elem() // E.g., *test_proto.Communique_Msg + if !vf.IsNil() { + vf = vf.Elem() // E.g., test_proto.Communique_Msg + vf = vf.Field(0) // E.g., Proto struct (e.g., *T) or primitive value + if vf.Kind() == reflect.Ptr { + discardLegacy(vf.Interface().(Message)) + } + } + } + } + } + } + + if vf := v.FieldByName("XXX_unrecognized"); vf.IsValid() { + if vf.Type() != reflect.TypeOf([]byte{}) { + panic("expected XXX_unrecognized to be of type []byte") + } + vf.Set(reflect.ValueOf([]byte(nil))) + } + + // For proto2 messages, only discard unknown fields in message extensions + // that have been accessed via GetExtension. + if em, ok := extendable(m); ok { + // Ignore lock since discardLegacy is not concurrency safe. + emm, _ := em.extensionsRead() + for _, mx := range emm { + if m, ok := mx.value.(Message); ok { + discardLegacy(m) + } + } + } +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/BUILD.bazel b/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/BUILD.bazel deleted file mode 100644 index cc50beeb91c3df928f1297eb3881187503123e1d..0000000000000000000000000000000000000000 --- a/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/BUILD.bazel +++ /dev/null @@ -1,9 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = ["descriptor.pb.go"], - importpath = "github.com/golang/protobuf/protoc-gen-go/descriptor", - visibility = ["//visibility:public"], - deps = ["//vendor/github.com/golang/protobuf/proto:go_default_library"], -) diff --git a/vendor/github.com/gorhill/cronexpr/APLv2 b/vendor/github.com/gorhill/cronexpr/APLv2 new file mode 100644 index 0000000000000000000000000000000000000000..d645695673349e3947e8e5ae42332d0ac3164cd7 --- /dev/null +++ b/vendor/github.com/gorhill/cronexpr/APLv2 @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/gorhill/cronexpr/GPLv3 b/vendor/github.com/gorhill/cronexpr/GPLv3 new file mode 100644 index 0000000000000000000000000000000000000000..c13fcfaf1dafc23ae844a9c993219396f7845439 --- /dev/null +++ b/vendor/github.com/gorhill/cronexpr/GPLv3 @@ -0,0 +1,674 @@ +GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. {http://fsf.org/} + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {one line to give the program's name and a brief idea of what it does.} + Copyright (C) {year} {name of author} + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see {http://www.gnu.org/licenses/}. + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + cronexpr Copyright (C) 2013 Raymond Hill + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +{http://www.gnu.org/licenses/}. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +{http://www.gnu.org/philosophy/why-not-lgpl.html}. diff --git a/vendor/github.com/gorhill/cronexpr/README.md b/vendor/github.com/gorhill/cronexpr/README.md new file mode 100644 index 0000000000000000000000000000000000000000..e8c56d29d2220063a5cb3d1a860bad48164fa889 --- /dev/null +++ b/vendor/github.com/gorhill/cronexpr/README.md @@ -0,0 +1,134 @@ +Golang Cron expression parser +============================= +Given a cron expression and a time stamp, you can get the next time stamp which satisfies the cron expression. + +In another project, I decided to use cron expression syntax to encode scheduling information. Thus this standalone library to parse and apply time stamps to cron expressions. + +The time-matching algorithm in this implementation is efficient, it avoids as much as possible to guess the next matching time stamp, a common technique seen in a number of implementations out there. + +There is also a companion command-line utility to evaluate cron time expressions: (which of course uses this library). + +Implementation +-------------- +The reference documentation for this implementation is found at +, which I copy/pasted here (laziness!) with modifications where this implementation differs: + + Field name Mandatory? Allowed values Allowed special characters + ---------- ---------- -------------- -------------------------- + Seconds No 0-59 * / , - + Minutes Yes 0-59 * / , - + Hours Yes 0-23 * / , - + Day of month Yes 1-31 * / , - L W + Month Yes 1-12 or JAN-DEC * / , - + Day of week Yes 0-6 or SUN-SAT * / , - L # + Year No 1970–2099 * / , - + +#### Asterisk ( * ) +The asterisk indicates that the cron expression matches for all values of the field. E.g., using an asterisk in the 4th field (month) indicates every month. + +#### Slash ( / ) +Slashes describe increments of ranges. For example `3-59/15` in the minute field indicate the third minute of the hour and every 15 minutes thereafter. The form `*/...` is equivalent to the form "first-last/...", that is, an increment over the largest possible range of the field. + +#### Comma ( , ) +Commas are used to separate items of a list. For example, using `MON,WED,FRI` in the 5th field (day of week) means Mondays, Wednesdays and Fridays. + +#### Hyphen ( - ) +Hyphens define ranges. For example, 2000-2010 indicates every year between 2000 and 2010 AD, inclusive. + +#### L +`L` stands for "last". When used in the day-of-week field, it allows you to specify constructs such as "the last Friday" (`5L`) of a given month. In the day-of-month field, it specifies the last day of the month. + +#### W +The `W` character is allowed for the day-of-month field. This character is used to specify the business day (Monday-Friday) nearest the given day. As an example, if you were to specify `15W` as the value for the day-of-month field, the meaning is: "the nearest business day to the 15th of the month." + +So, if the 15th is a Saturday, the trigger fires on Friday the 14th. If the 15th is a Sunday, the trigger fires on Monday the 16th. If the 15th is a Tuesday, then it fires on Tuesday the 15th. However if you specify `1W` as the value for day-of-month, and the 1st is a Saturday, the trigger fires on Monday the 3rd, as it does not 'jump' over the boundary of a month's days. + +The `W` character can be specified only when the day-of-month is a single day, not a range or list of days. + +The `W` character can also be combined with `L`, i.e. `LW` to mean "the last business day of the month." + +#### Hash ( # ) +`#` is allowed for the day-of-week field, and must be followed by a number between one and five. It allows you to specify constructs such as "the second Friday" of a given month. + +Predefined cron expressions +--------------------------- +(Copied from , with text modified according to this implementation) + + Entry Description Equivalent to + @annually Run once a year at midnight in the morning of January 1 0 0 0 1 1 * * + @yearly Run once a year at midnight in the morning of January 1 0 0 0 1 1 * * + @monthly Run once a month at midnight in the morning of the first of the month 0 0 0 1 * * * + @weekly Run once a week at midnight in the morning of Sunday 0 0 0 * * 0 * + @daily Run once a day at midnight 0 0 0 * * * * + @hourly Run once an hour at the beginning of the hour 0 0 * * * * * + @reboot Not supported + +Other details +------------- +* If only six fields are present, a `0` second field is prepended, that is, `* * * * * 2013` internally become `0 * * * * * 2013`. +* If only five fields are present, a `0` second field is prepended and a wildcard year field is appended, that is, `* * * * Mon` internally become `0 * * * * Mon *`. +* Domain for day-of-week field is [0-7] instead of [0-6], 7 being Sunday (like 0). This to comply with http://linux.die.net/man/5/crontab#. +* As of now, the behavior of the code is undetermined if a malformed cron expression is supplied + +Install +------- + go get github.com/gorhill/cronexpr + +Usage +----- +Import the library: + + import "github.com/gorhill/cronexpr" + import "time" + +Simplest way: + + nextTime := cronexpr.MustParse("0 0 29 2 *").Next(time.Now()) + +Assuming `time.Now()` is "2013-08-29 09:28:00", then `nextTime` will be "2016-02-29 00:00:00". + +You can keep the returned Expression pointer around if you want to reuse it: + + expr := cronexpr.MustParse("0 0 29 2 *") + nextTime := expr.Next(time.Now()) + ... + nextTime = expr.Next(nextTime) + +Use `time.IsZero()` to find out whether a valid time was returned. For example, + + cronexpr.MustParse("* * * * * 1980").Next(time.Now()).IsZero() + +will return `true`, whereas + + cronexpr.MustParse("* * * * * 2050").Next(time.Now()).IsZero() + +will return `false` (as of 2013-08-29...) + +You may also query for `n` next time stamps: + + cronexpr.MustParse("0 0 29 2 *").NextN(time.Now(), 5) + +which returns a slice of time.Time objects, containing the following time stamps (as of 2013-08-30): + + 2016-02-29 00:00:00 + 2020-02-29 00:00:00 + 2024-02-29 00:00:00 + 2028-02-29 00:00:00 + 2032-02-29 00:00:00 + +The time zone of time values returned by `Next` and `NextN` is always the +time zone of the time value passed as argument, unless a zero time value is +returned. + +API +--- + + +License +------- + +License: pick the one which suits you best: + +- GPL v3 see +- APL v2 see + diff --git a/vendor/github.com/gorhill/cronexpr/cronexpr.go b/vendor/github.com/gorhill/cronexpr/cronexpr.go new file mode 100644 index 0000000000000000000000000000000000000000..58b518fa58de9466ad29c9a421a21174427c4dc8 --- /dev/null +++ b/vendor/github.com/gorhill/cronexpr/cronexpr.go @@ -0,0 +1,266 @@ +/*! + * Copyright 2013 Raymond Hill + * + * Project: github.com/gorhill/cronexpr + * File: cronexpr.go + * Version: 1.0 + * License: pick the one which suits you : + * GPL v3 see + * APL v2 see + * + */ + +// Package cronexpr parses cron time expressions. +package cronexpr + +/******************************************************************************/ + +import ( + "fmt" + "sort" + "time" +) + +/******************************************************************************/ + +// A Expression represents a specific cron time expression as defined at +// +type Expression struct { + expression string + secondList []int + minuteList []int + hourList []int + daysOfMonth map[int]bool + workdaysOfMonth map[int]bool + lastDayOfMonth bool + lastWorkdayOfMonth bool + daysOfMonthRestricted bool + actualDaysOfMonthList []int + monthList []int + daysOfWeek map[int]bool + specificWeekDaysOfWeek map[int]bool + lastWeekDaysOfWeek map[int]bool + daysOfWeekRestricted bool + yearList []int +} + +/******************************************************************************/ + +// MustParse returns a new Expression pointer. It expects a well-formed cron +// expression. If a malformed cron expression is supplied, it will `panic`. +// See for documentation +// about what is a well-formed cron expression from this library's point of +// view. +func MustParse(cronLine string) *Expression { + expr, err := Parse(cronLine) + if err != nil { + panic(err) + } + return expr +} + +/******************************************************************************/ + +// Parse returns a new Expression pointer. An error is returned if a malformed +// cron expression is supplied. +// See for documentation +// about what is a well-formed cron expression from this library's point of +// view. +func Parse(cronLine string) (*Expression, error) { + + // Maybe one of the built-in aliases is being used + cron := cronNormalizer.Replace(cronLine) + + indices := fieldFinder.FindAllStringIndex(cron, -1) + fieldCount := len(indices) + if fieldCount < 5 { + return nil, fmt.Errorf("missing field(s)") + } + // ignore fields beyond 7th + if fieldCount > 7 { + fieldCount = 7 + } + + var expr = Expression{} + var field = 0 + var err error + + // second field (optional) + if fieldCount == 7 { + err = expr.secondFieldHandler(cron[indices[field][0]:indices[field][1]]) + if err != nil { + return nil, err + } + field += 1 + } else { + expr.secondList = []int{0} + } + + // minute field + err = expr.minuteFieldHandler(cron[indices[field][0]:indices[field][1]]) + if err != nil { + return nil, err + } + field += 1 + + // hour field + err = expr.hourFieldHandler(cron[indices[field][0]:indices[field][1]]) + if err != nil { + return nil, err + } + field += 1 + + // day of month field + err = expr.domFieldHandler(cron[indices[field][0]:indices[field][1]]) + if err != nil { + return nil, err + } + field += 1 + + // month field + err = expr.monthFieldHandler(cron[indices[field][0]:indices[field][1]]) + if err != nil { + return nil, err + } + field += 1 + + // day of week field + err = expr.dowFieldHandler(cron[indices[field][0]:indices[field][1]]) + if err != nil { + return nil, err + } + field += 1 + + // year field + if field < fieldCount { + err = expr.yearFieldHandler(cron[indices[field][0]:indices[field][1]]) + if err != nil { + return nil, err + } + } else { + expr.yearList = yearDescriptor.defaultList + } + + return &expr, nil +} + +/******************************************************************************/ + +// Next returns the closest time instant immediately following `fromTime` which +// matches the cron expression `expr`. +// +// The `time.Location` of the returned time instant is the same as that of +// `fromTime`. +// +// The zero value of time.Time is returned if no matching time instant exists +// or if a `fromTime` is itself a zero value. +func (expr *Expression) Next(fromTime time.Time) time.Time { + // Special case + if fromTime.IsZero() { + return fromTime + } + + // Since expr.nextSecond()-expr.nextMonth() expects that the + // supplied time stamp is a perfect match to the underlying cron + // expression, and since this function is an entry point where `fromTime` + // does not necessarily matches the underlying cron expression, + // we first need to ensure supplied time stamp matches + // the cron expression. If not, this means the supplied time + // stamp falls in between matching time stamps, thus we move + // to closest future matching immediately upon encountering a mismatching + // time stamp. + + // year + v := fromTime.Year() + i := sort.SearchInts(expr.yearList, v) + if i == len(expr.yearList) { + return time.Time{} + } + if v != expr.yearList[i] { + return expr.nextYear(fromTime) + } + // month + v = int(fromTime.Month()) + i = sort.SearchInts(expr.monthList, v) + if i == len(expr.monthList) { + return expr.nextYear(fromTime) + } + if v != expr.monthList[i] { + return expr.nextMonth(fromTime) + } + + expr.actualDaysOfMonthList = expr.calculateActualDaysOfMonth(fromTime.Year(), int(fromTime.Month())) + if len(expr.actualDaysOfMonthList) == 0 { + return expr.nextMonth(fromTime) + } + + // day of month + v = fromTime.Day() + i = sort.SearchInts(expr.actualDaysOfMonthList, v) + if i == len(expr.actualDaysOfMonthList) { + return expr.nextMonth(fromTime) + } + if v != expr.actualDaysOfMonthList[i] { + return expr.nextDayOfMonth(fromTime) + } + // hour + v = fromTime.Hour() + i = sort.SearchInts(expr.hourList, v) + if i == len(expr.hourList) { + return expr.nextDayOfMonth(fromTime) + } + if v != expr.hourList[i] { + return expr.nextHour(fromTime) + } + // minute + v = fromTime.Minute() + i = sort.SearchInts(expr.minuteList, v) + if i == len(expr.minuteList) { + return expr.nextHour(fromTime) + } + if v != expr.minuteList[i] { + return expr.nextMinute(fromTime) + } + // second + v = fromTime.Second() + i = sort.SearchInts(expr.secondList, v) + if i == len(expr.secondList) { + return expr.nextMinute(fromTime) + } + + // If we reach this point, there is nothing better to do + // than to move to the next second + + return expr.nextSecond(fromTime) +} + +/******************************************************************************/ + +// NextN returns a slice of `n` closest time instants immediately following +// `fromTime` which match the cron expression `expr`. +// +// The time instants in the returned slice are in chronological ascending order. +// The `time.Location` of the returned time instants is the same as that of +// `fromTime`. +// +// A slice with len between [0-`n`] is returned, that is, if not enough existing +// matching time instants exist, the number of returned entries will be less +// than `n`. +func (expr *Expression) NextN(fromTime time.Time, n uint) []time.Time { + nextTimes := make([]time.Time, 0, n) + if n > 0 { + fromTime = expr.Next(fromTime) + for { + if fromTime.IsZero() { + break + } + nextTimes = append(nextTimes, fromTime) + n -= 1 + if n == 0 { + break + } + fromTime = expr.nextSecond(fromTime) + } + } + return nextTimes +} diff --git a/vendor/github.com/gorhill/cronexpr/cronexpr/README.md b/vendor/github.com/gorhill/cronexpr/cronexpr/README.md new file mode 100644 index 0000000000000000000000000000000000000000..685c278c9fa531b7827db7a28a13393b3884bb0c --- /dev/null +++ b/vendor/github.com/gorhill/cronexpr/cronexpr/README.md @@ -0,0 +1,122 @@ +cronexpr: command-line utility +============================== + +A command-line utility written in Go to evaluate cron time expressions. + +It is based on the standalone Go library . + +## Install + + go get github.com/gorhill/cronexpr + go install github.com/gorhill/cronexpr + +## Usage + + cronexpr [options] "{cron expression}" + +## Options + +`-l`: + +Go-compliant time layout to use for outputting time value(s), see . + +Default is `"Mon, 02 Jan 2006 15:04:05 MST"` + +`-n`: + +Number of resulting time values to output. + +Default is 1. + +`-t`: + +Whole or partial RFC3339 time value (i.e. `2006-01-02T15:04:05Z07:00`) against which the cron expression is evaluated. Examples of valid values include (assuming EST time zone): + +`13` = 2013-01-01T00:00:00-05:00 +`2013` = 2013-01-01T00:00:00-05:00 +`2013-08` = 2013-08-01T00:00:00-05:00 +`2013-08-31` = 2013-08-31T00:00:00-05:00 +`2013-08-31T12` = 2013-08-31T12:00:00-05:00 +`2013-08-31T12:40` = 2013-08-31T12:40:00-05:00 +`2013-08-31T12:40:35` = 2013-08-31T12:40:35-05:00 +`2013-08-31T12:40:35-10:00` = 2013-08-31T12:40:35-10:00 + +Default time is current time, and default time zone is local time zone. + +## Examples + +#### Example 1 + +Midnight on December 31st of any year. + +Command: + + cronexpr -t="2013-08-31" -n=5 "0 0 31 12 *" + +Output (assuming computer is in EST time zone): + + # "0 0 31 12 *" + "2013-08-31T00:00:00-04:00" = + Tue, 31 Dec 2013 00:00:00 EST + Wed, 31 Dec 2014 00:00:00 EST + Thu, 31 Dec 2015 00:00:00 EST + Sat, 31 Dec 2016 00:00:00 EST + Sun, 31 Dec 2017 00:00:00 EST + +#### Example 2 + +2pm on February 29th of any year. + +Command: + + cronexpr -t=2000 -n=10 "0 14 29 2 *" + +Output (assuming computer is in EST time zone): + + # "0 14 29 2 *" + "2000-01-01T00:00:00-05:00" = + Tue, 29 Feb 2000 14:00:00 EST + Sun, 29 Feb 2004 14:00:00 EST + Fri, 29 Feb 2008 14:00:00 EST + Wed, 29 Feb 2012 14:00:00 EST + Mon, 29 Feb 2016 14:00:00 EST + Sat, 29 Feb 2020 14:00:00 EST + Thu, 29 Feb 2024 14:00:00 EST + Tue, 29 Feb 2028 14:00:00 EST + Sun, 29 Feb 2032 14:00:00 EST + Fri, 29 Feb 2036 14:00:00 EST + +#### Example 3 + +12pm on the work day closest to the 15th of March and every three month +thereafter. + +Command: + + cronexpr -t=2013-09-01 -n=5 "0 12 15W 3/3 *" + +Output (assuming computer is in EST time zone): + + # "0 12 15W 3/3 *" + "2013-09-01T00:00:00-04:00" = + Mon, 16 Sep 2013 12:00:00 EDT + Mon, 16 Dec 2013 12:00:00 EST + Fri, 14 Mar 2014 12:00:00 EDT + Mon, 16 Jun 2014 12:00:00 EDT + Mon, 15 Sep 2014 12:00:00 EDT + +#### Example 4 + +Midnight on the fifth Saturday of any month (twist: not all months have a 5th +specific day of week). + +Command: + + cronexpr -t=2013-09-02 -n 5 "0 0 * * 6#5" + +Output (assuming computer is in EST time zone): + + # "0 0 * * 6#5" + "2013-09-02T00:00:00-04:00" = + Sat, 30 Nov 2013 00:00:00 EST + Sat, 29 Mar 2014 00:00:00 EDT + Sat, 31 May 2014 00:00:00 EDT + Sat, 30 Aug 2014 00:00:00 EDT + Sat, 29 Nov 2014 00:00:00 EST + diff --git a/vendor/github.com/gorhill/cronexpr/cronexpr/main.go b/vendor/github.com/gorhill/cronexpr/cronexpr/main.go new file mode 100644 index 0000000000000000000000000000000000000000..1d9abe5bca8587dd36fe15090801a76fcc277d88 --- /dev/null +++ b/vendor/github.com/gorhill/cronexpr/cronexpr/main.go @@ -0,0 +1,111 @@ +/*! + * Copyright 2013 Raymond Hill + * + * Project: github.com/gorhill/cronexpr + * File: main.go + * Version: 1.0 + * License: GPL v3 see + * + */ + +package main + +/******************************************************************************/ + +import ( + "flag" + "fmt" + "os" + "time" + + "github.com/gorhill/cronexpr" +) + +/******************************************************************************/ + +var ( + usage = func() { + fmt.Fprintf(os.Stderr, "usage:\n %s [options] \"{cron expression}\"\noptions:\n", os.Args[0]) + flag.PrintDefaults() + } + inTimeStr string + outTimeCount uint + outTimeLayout string +) + +/******************************************************************************/ + +func main() { + var err error + + flag.Usage = usage + flag.StringVar(&inTimeStr, "t", "", `whole or partial RFC3339 time value (i.e. "2006-01-02T15:04:05Z07:00") against which the cron expression is evaluated, now if not present`) + flag.UintVar(&outTimeCount, "n", 1, `number of resulting time values to output`) + flag.StringVar(&outTimeLayout, "l", "Mon, 02 Jan 2006 15:04:05 MST", `Go-compliant time layout to use for outputting time value(s), see `) + flag.Parse() + + cronStr := flag.Arg(0) + if len(cronStr) == 0 { + flag.Usage() + return + } + + inTime := time.Now() + inTimeLayout := "" + timeStrLen := len(inTimeStr) + if timeStrLen == 2 { + inTimeLayout = "06" + } else if timeStrLen >= 4 { + inTimeLayout += "2006" + if timeStrLen >= 7 { + inTimeLayout += "-01" + if timeStrLen >= 10 { + inTimeLayout += "-02" + if timeStrLen >= 13 { + inTimeLayout += "T15" + if timeStrLen >= 16 { + inTimeLayout += ":04" + if timeStrLen >= 19 { + inTimeLayout += ":05" + if timeStrLen >= 20 { + inTimeLayout += "Z07:00" + } + } + } + } + } + } + } + + if len(inTimeLayout) > 0 { + // default to local time zone + if timeStrLen < 20 { + inTime, err = time.ParseInLocation(inTimeLayout, inTimeStr, time.Local) + } else { + inTime, err = time.Parse(inTimeLayout, inTimeStr) + } + if err != nil { + fmt.Fprintf(os.Stderr, "# error: unparseable time value: \"%s\"\n", inTimeStr) + os.Exit(1) + } + } + + expr, err := cronexpr.Parse(cronStr) + if err != nil { + fmt.Fprintf(os.Stderr, "# %s: %s\n", os.Args[0], err) + os.Exit(1) + } + + // Anything on the output which starts with '#' can be ignored if the caller + // is interested only in the time values. There is only one time + // value per line, and they are always in chronological ascending order. + fmt.Printf("# \"%s\" + \"%s\" =\n", cronStr, inTime.Format(time.RFC3339)) + + if outTimeCount < 1 { + outTimeCount = 1 + } + outTimes := expr.NextN(inTime, outTimeCount) + for _, outTime := range outTimes { + fmt.Println(outTime.Format(outTimeLayout)) + } +} diff --git a/vendor/github.com/gorhill/cronexpr/cronexpr_next.go b/vendor/github.com/gorhill/cronexpr/cronexpr_next.go new file mode 100644 index 0000000000000000000000000000000000000000..a0ebdb6b203bc2e356fb55c7a46e73663770d694 --- /dev/null +++ b/vendor/github.com/gorhill/cronexpr/cronexpr_next.go @@ -0,0 +1,292 @@ +/*! + * Copyright 2013 Raymond Hill + * + * Project: github.com/gorhill/cronexpr + * File: cronexpr_next.go + * Version: 1.0 + * License: pick the one which suits you : + * GPL v3 see + * APL v2 see + * + */ + +package cronexpr + +/******************************************************************************/ + +import ( + "sort" + "time" +) + +/******************************************************************************/ + +var dowNormalizedOffsets = [][]int{ + {1, 8, 15, 22, 29}, + {2, 9, 16, 23, 30}, + {3, 10, 17, 24, 31}, + {4, 11, 18, 25}, + {5, 12, 19, 26}, + {6, 13, 20, 27}, + {7, 14, 21, 28}, +} + +/******************************************************************************/ + +func (expr *Expression) nextYear(t time.Time) time.Time { + // Find index at which item in list is greater or equal to + // candidate year + i := sort.SearchInts(expr.yearList, t.Year()+1) + if i == len(expr.yearList) { + return time.Time{} + } + // Year changed, need to recalculate actual days of month + expr.actualDaysOfMonthList = expr.calculateActualDaysOfMonth(expr.yearList[i], expr.monthList[0]) + if len(expr.actualDaysOfMonthList) == 0 { + return expr.nextMonth(time.Date( + expr.yearList[i], + time.Month(expr.monthList[0]), + 1, + expr.hourList[0], + expr.minuteList[0], + expr.secondList[0], + 0, + t.Location())) + } + return time.Date( + expr.yearList[i], + time.Month(expr.monthList[0]), + expr.actualDaysOfMonthList[0], + expr.hourList[0], + expr.minuteList[0], + expr.secondList[0], + 0, + t.Location()) +} + +/******************************************************************************/ + +func (expr *Expression) nextMonth(t time.Time) time.Time { + // Find index at which item in list is greater or equal to + // candidate month + i := sort.SearchInts(expr.monthList, int(t.Month())+1) + if i == len(expr.monthList) { + return expr.nextYear(t) + } + // Month changed, need to recalculate actual days of month + expr.actualDaysOfMonthList = expr.calculateActualDaysOfMonth(t.Year(), expr.monthList[i]) + if len(expr.actualDaysOfMonthList) == 0 { + return expr.nextMonth(time.Date( + t.Year(), + time.Month(expr.monthList[i]), + 1, + expr.hourList[0], + expr.minuteList[0], + expr.secondList[0], + 0, + t.Location())) + } + + return time.Date( + t.Year(), + time.Month(expr.monthList[i]), + expr.actualDaysOfMonthList[0], + expr.hourList[0], + expr.minuteList[0], + expr.secondList[0], + 0, + t.Location()) +} + +/******************************************************************************/ + +func (expr *Expression) nextDayOfMonth(t time.Time) time.Time { + // Find index at which item in list is greater or equal to + // candidate day of month + i := sort.SearchInts(expr.actualDaysOfMonthList, t.Day()+1) + if i == len(expr.actualDaysOfMonthList) { + return expr.nextMonth(t) + } + + return time.Date( + t.Year(), + t.Month(), + expr.actualDaysOfMonthList[i], + expr.hourList[0], + expr.minuteList[0], + expr.secondList[0], + 0, + t.Location()) +} + +/******************************************************************************/ + +func (expr *Expression) nextHour(t time.Time) time.Time { + // Find index at which item in list is greater or equal to + // candidate hour + i := sort.SearchInts(expr.hourList, t.Hour()+1) + if i == len(expr.hourList) { + return expr.nextDayOfMonth(t) + } + + return time.Date( + t.Year(), + t.Month(), + t.Day(), + expr.hourList[i], + expr.minuteList[0], + expr.secondList[0], + 0, + t.Location()) +} + +/******************************************************************************/ + +func (expr *Expression) nextMinute(t time.Time) time.Time { + // Find index at which item in list is greater or equal to + // candidate minute + i := sort.SearchInts(expr.minuteList, t.Minute()+1) + if i == len(expr.minuteList) { + return expr.nextHour(t) + } + + return time.Date( + t.Year(), + t.Month(), + t.Day(), + t.Hour(), + expr.minuteList[i], + expr.secondList[0], + 0, + t.Location()) +} + +/******************************************************************************/ + +func (expr *Expression) nextSecond(t time.Time) time.Time { + // nextSecond() assumes all other fields are exactly matched + // to the cron expression + + // Find index at which item in list is greater or equal to + // candidate second + i := sort.SearchInts(expr.secondList, t.Second()+1) + if i == len(expr.secondList) { + return expr.nextMinute(t) + } + + return time.Date( + t.Year(), + t.Month(), + t.Day(), + t.Hour(), + t.Minute(), + expr.secondList[i], + 0, + t.Location()) +} + +/******************************************************************************/ + +func (expr *Expression) calculateActualDaysOfMonth(year, month int) []int { + actualDaysOfMonthMap := make(map[int]bool) + firstDayOfMonth := time.Date(year, time.Month(month), 1, 0, 0, 0, 0, time.UTC) + lastDayOfMonth := firstDayOfMonth.AddDate(0, 1, -1) + + // As per crontab man page (http://linux.die.net/man/5/crontab#): + // "The day of a command's execution can be specified by two + // "fields - day of month, and day of week. If both fields are + // "restricted (ie, aren't *), the command will be run when + // "either field matches the current time" + + // If both fields are not restricted, all days of the month are a hit + if expr.daysOfMonthRestricted == false && expr.daysOfWeekRestricted == false { + return genericDefaultList[1 : lastDayOfMonth.Day()+1] + } + + // day-of-month != `*` + if expr.daysOfMonthRestricted { + // Last day of month + if expr.lastDayOfMonth { + actualDaysOfMonthMap[lastDayOfMonth.Day()] = true + } + // Last work day of month + if expr.lastWorkdayOfMonth { + actualDaysOfMonthMap[workdayOfMonth(lastDayOfMonth, lastDayOfMonth)] = true + } + // Days of month + for v := range expr.daysOfMonth { + // Ignore days beyond end of month + if v <= lastDayOfMonth.Day() { + actualDaysOfMonthMap[v] = true + } + } + // Work days of month + // As per Wikipedia: month boundaries are not crossed. + for v := range expr.workdaysOfMonth { + // Ignore days beyond end of month + if v <= lastDayOfMonth.Day() { + actualDaysOfMonthMap[workdayOfMonth(firstDayOfMonth.AddDate(0, 0, v-1), lastDayOfMonth)] = true + } + } + } + + // day-of-week != `*` + if expr.daysOfWeekRestricted { + // How far first sunday is from first day of month + offset := 7 - int(firstDayOfMonth.Weekday()) + // days of week + // offset : (7 - day_of_week_of_1st_day_of_month) + // target : 1 + (7 * week_of_month) + (offset + day_of_week) % 7 + for v := range expr.daysOfWeek { + w := dowNormalizedOffsets[(offset+v)%7] + actualDaysOfMonthMap[w[0]] = true + actualDaysOfMonthMap[w[1]] = true + actualDaysOfMonthMap[w[2]] = true + actualDaysOfMonthMap[w[3]] = true + if len(w) > 4 && w[4] <= lastDayOfMonth.Day() { + actualDaysOfMonthMap[w[4]] = true + } + } + // days of week of specific week in the month + // offset : (7 - day_of_week_of_1st_day_of_month) + // target : 1 + (7 * week_of_month) + (offset + day_of_week) % 7 + for v := range expr.specificWeekDaysOfWeek { + v = 1 + 7*(v/7) + (offset+v)%7 + if v <= lastDayOfMonth.Day() { + actualDaysOfMonthMap[v] = true + } + } + // Last days of week of the month + lastWeekOrigin := firstDayOfMonth.AddDate(0, 1, -7) + offset = 7 - int(lastWeekOrigin.Weekday()) + for v := range expr.lastWeekDaysOfWeek { + v = lastWeekOrigin.Day() + (offset+v)%7 + if v <= lastDayOfMonth.Day() { + actualDaysOfMonthMap[v] = true + } + } + } + + return toList(actualDaysOfMonthMap) +} + +func workdayOfMonth(targetDom, lastDom time.Time) int { + // If saturday, then friday + // If sunday, then monday + dom := targetDom.Day() + dow := targetDom.Weekday() + if dow == time.Saturday { + if dom > 1 { + dom -= 1 + } else { + dom += 2 + } + } else if dow == time.Sunday { + if dom < lastDom.Day() { + dom += 1 + } else { + dom -= 2 + } + } + return dom +} diff --git a/vendor/github.com/gorhill/cronexpr/cronexpr_parse.go b/vendor/github.com/gorhill/cronexpr/cronexpr_parse.go new file mode 100644 index 0000000000000000000000000000000000000000..be6ef1769fe48c68826b2b892fb3c9f0c63b11c7 --- /dev/null +++ b/vendor/github.com/gorhill/cronexpr/cronexpr_parse.go @@ -0,0 +1,498 @@ +/*! + * Copyright 2013 Raymond Hill + * + * Project: github.com/gorhill/cronexpr + * File: cronexpr_parse.go + * Version: 1.0 + * License: pick the one which suits you best: + * GPL v3 see + * APL v2 see + * + */ + +package cronexpr + +/******************************************************************************/ + +import ( + "fmt" + "regexp" + "sort" + "strings" +) + +/******************************************************************************/ + +var ( + genericDefaultList = []int{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + } + yearDefaultList = []int{ + 1970, 1971, 1972, 1973, 1974, 1975, 1976, 1977, 1978, 1979, + 1980, 1981, 1982, 1983, 1984, 1985, 1986, 1987, 1988, 1989, + 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, + 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, + 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021, 2022, 2023, 2024, 2025, 2026, 2027, 2028, 2029, + 2030, 2031, 2032, 2033, 2034, 2035, 2036, 2037, 2038, 2039, + 2040, 2041, 2042, 2043, 2044, 2045, 2046, 2047, 2048, 2049, + 2050, 2051, 2052, 2053, 2054, 2055, 2056, 2057, 2058, 2059, + 2060, 2061, 2062, 2063, 2064, 2065, 2066, 2067, 2068, 2069, + 2070, 2071, 2072, 2073, 2074, 2075, 2076, 2077, 2078, 2079, + 2080, 2081, 2082, 2083, 2084, 2085, 2086, 2087, 2088, 2089, + 2090, 2091, 2092, 2093, 2094, 2095, 2096, 2097, 2098, 2099, + } +) + +/******************************************************************************/ + +var ( + numberTokens = map[string]int{ + "0": 0, "1": 1, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "8": 8, "9": 9, + "00": 0, "01": 1, "02": 2, "03": 3, "04": 4, "05": 5, "06": 6, "07": 7, "08": 8, "09": 9, + "10": 10, "11": 11, "12": 12, "13": 13, "14": 14, "15": 15, "16": 16, "17": 17, "18": 18, "19": 19, + "20": 20, "21": 21, "22": 22, "23": 23, "24": 24, "25": 25, "26": 26, "27": 27, "28": 28, "29": 29, + "30": 30, "31": 31, "32": 32, "33": 33, "34": 34, "35": 35, "36": 36, "37": 37, "38": 38, "39": 39, + "40": 40, "41": 41, "42": 42, "43": 43, "44": 44, "45": 45, "46": 46, "47": 47, "48": 48, "49": 49, + "50": 50, "51": 51, "52": 52, "53": 53, "54": 54, "55": 55, "56": 56, "57": 57, "58": 58, "59": 59, + "1970": 1970, "1971": 1971, "1972": 1972, "1973": 1973, "1974": 1974, "1975": 1975, "1976": 1976, "1977": 1977, "1978": 1978, "1979": 1979, + "1980": 1980, "1981": 1981, "1982": 1982, "1983": 1983, "1984": 1984, "1985": 1985, "1986": 1986, "1987": 1987, "1988": 1988, "1989": 1989, + "1990": 1990, "1991": 1991, "1992": 1992, "1993": 1993, "1994": 1994, "1995": 1995, "1996": 1996, "1997": 1997, "1998": 1998, "1999": 1999, + "2000": 2000, "2001": 2001, "2002": 2002, "2003": 2003, "2004": 2004, "2005": 2005, "2006": 2006, "2007": 2007, "2008": 2008, "2009": 2009, + "2010": 2010, "2011": 2011, "2012": 2012, "2013": 2013, "2014": 2014, "2015": 2015, "2016": 2016, "2017": 2017, "2018": 2018, "2019": 2019, + "2020": 2020, "2021": 2021, "2022": 2022, "2023": 2023, "2024": 2024, "2025": 2025, "2026": 2026, "2027": 2027, "2028": 2028, "2029": 2029, + "2030": 2030, "2031": 2031, "2032": 2032, "2033": 2033, "2034": 2034, "2035": 2035, "2036": 2036, "2037": 2037, "2038": 2038, "2039": 2039, + "2040": 2040, "2041": 2041, "2042": 2042, "2043": 2043, "2044": 2044, "2045": 2045, "2046": 2046, "2047": 2047, "2048": 2048, "2049": 2049, + "2050": 2050, "2051": 2051, "2052": 2052, "2053": 2053, "2054": 2054, "2055": 2055, "2056": 2056, "2057": 2057, "2058": 2058, "2059": 2059, + "2060": 2060, "2061": 2061, "2062": 2062, "2063": 2063, "2064": 2064, "2065": 2065, "2066": 2066, "2067": 2067, "2068": 2068, "2069": 2069, + "2070": 2070, "2071": 2071, "2072": 2072, "2073": 2073, "2074": 2074, "2075": 2075, "2076": 2076, "2077": 2077, "2078": 2078, "2079": 2079, + "2080": 2080, "2081": 2081, "2082": 2082, "2083": 2083, "2084": 2084, "2085": 2085, "2086": 2086, "2087": 2087, "2088": 2088, "2089": 2089, + "2090": 2090, "2091": 2091, "2092": 2092, "2093": 2093, "2094": 2094, "2095": 2095, "2096": 2096, "2097": 2097, "2098": 2098, "2099": 2099, + } + monthTokens = map[string]int{ + `1`: 1, `jan`: 1, `january`: 1, + `2`: 2, `feb`: 2, `february`: 2, + `3`: 3, `mar`: 3, `march`: 3, + `4`: 4, `apr`: 4, `april`: 4, + `5`: 5, `may`: 5, + `6`: 6, `jun`: 6, `june`: 6, + `7`: 7, `jul`: 7, `july`: 7, + `8`: 8, `aug`: 8, `august`: 8, + `9`: 9, `sep`: 9, `september`: 9, + `10`: 10, `oct`: 10, `october`: 10, + `11`: 11, `nov`: 11, `november`: 11, + `12`: 12, `dec`: 12, `december`: 12, + } + dowTokens = map[string]int{ + `0`: 0, `sun`: 0, `sunday`: 0, + `1`: 1, `mon`: 1, `monday`: 1, + `2`: 2, `tue`: 2, `tuesday`: 2, + `3`: 3, `wed`: 3, `wednesday`: 3, + `4`: 4, `thu`: 4, `thursday`: 4, + `5`: 5, `fri`: 5, `friday`: 5, + `6`: 6, `sat`: 6, `saturday`: 6, + `7`: 0, + } +) + +/******************************************************************************/ + +func atoi(s string) int { + return numberTokens[s] +} + +type fieldDescriptor struct { + name string + min, max int + defaultList []int + valuePattern string + atoi func(string) int +} + +var ( + secondDescriptor = fieldDescriptor{ + name: "second", + min: 0, + max: 59, + defaultList: genericDefaultList[0:60], + valuePattern: `0?[0-9]|[1-5][0-9]`, + atoi: atoi, + } + minuteDescriptor = fieldDescriptor{ + name: "minute", + min: 0, + max: 59, + defaultList: genericDefaultList[0:60], + valuePattern: `0?[0-9]|[1-5][0-9]`, + atoi: atoi, + } + hourDescriptor = fieldDescriptor{ + name: "hour", + min: 0, + max: 23, + defaultList: genericDefaultList[0:24], + valuePattern: `0?[0-9]|1[0-9]|2[0-3]`, + atoi: atoi, + } + domDescriptor = fieldDescriptor{ + name: "day-of-month", + min: 1, + max: 31, + defaultList: genericDefaultList[1:32], + valuePattern: `0?[1-9]|[12][0-9]|3[01]`, + atoi: atoi, + } + monthDescriptor = fieldDescriptor{ + name: "month", + min: 1, + max: 12, + defaultList: genericDefaultList[1:13], + valuePattern: `0?[1-9]|1[012]|jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec|january|february|march|april|march|april|june|july|august|september|october|november|december`, + atoi: func(s string) int { + return monthTokens[s] + }, + } + dowDescriptor = fieldDescriptor{ + name: "day-of-week", + min: 0, + max: 6, + defaultList: genericDefaultList[0:7], + valuePattern: `0?[0-7]|sun|mon|tue|wed|thu|fri|sat|sunday|monday|tuesday|wednesday|thursday|friday|saturday`, + atoi: func(s string) int { + return dowTokens[s] + }, + } + yearDescriptor = fieldDescriptor{ + name: "year", + min: 1970, + max: 2099, + defaultList: yearDefaultList[:], + valuePattern: `19[789][0-9]|20[0-9]{2}`, + atoi: atoi, + } +) + +/******************************************************************************/ + +var ( + layoutWildcard = `^\*$|^\?$` + layoutValue = `^(%value%)$` + layoutRange = `^(%value%)-(%value%)$` + layoutWildcardAndInterval = `^\*/(\d+)$` + layoutValueAndInterval = `^(%value%)/(\d+)$` + layoutRangeAndInterval = `^(%value%)-(%value%)/(\d+)$` + layoutLastDom = `^l$` + layoutWorkdom = `^(%value%)w$` + layoutLastWorkdom = `^lw$` + layoutDowOfLastWeek = `^(%value%)l$` + layoutDowOfSpecificWeek = `^(%value%)#([1-5])$` + fieldFinder = regexp.MustCompile(`\S+`) + entryFinder = regexp.MustCompile(`[^,]+`) + layoutRegexp = make(map[string]*regexp.Regexp) +) + +/******************************************************************************/ + +var cronNormalizer = strings.NewReplacer( + "@yearly", "0 0 0 1 1 * *", + "@annually", "0 0 0 1 1 * *", + "@monthly", "0 0 0 1 * * *", + "@weekly", "0 0 0 * * 0 *", + "@daily", "0 0 0 * * * *", + "@hourly", "0 0 * * * * *") + +/******************************************************************************/ + +func (expr *Expression) secondFieldHandler(s string) error { + var err error + expr.secondList, err = genericFieldHandler(s, secondDescriptor) + return err +} + +/******************************************************************************/ + +func (expr *Expression) minuteFieldHandler(s string) error { + var err error + expr.minuteList, err = genericFieldHandler(s, minuteDescriptor) + return err +} + +/******************************************************************************/ + +func (expr *Expression) hourFieldHandler(s string) error { + var err error + expr.hourList, err = genericFieldHandler(s, hourDescriptor) + return err +} + +/******************************************************************************/ + +func (expr *Expression) monthFieldHandler(s string) error { + var err error + expr.monthList, err = genericFieldHandler(s, monthDescriptor) + return err +} + +/******************************************************************************/ + +func (expr *Expression) yearFieldHandler(s string) error { + var err error + expr.yearList, err = genericFieldHandler(s, yearDescriptor) + return err +} + +/******************************************************************************/ + +const ( + none = 0 + one = 1 + span = 2 + all = 3 +) + +type cronDirective struct { + kind int + first int + last int + step int + sbeg int + send int +} + +func genericFieldHandler(s string, desc fieldDescriptor) ([]int, error) { + directives, err := genericFieldParse(s, desc) + if err != nil { + return nil, err + } + values := make(map[int]bool) + for _, directive := range directives { + switch directive.kind { + case none: + return nil, fmt.Errorf("syntax error in %s field: '%s'", desc.name, s[directive.sbeg:directive.send]) + case one: + populateOne(values, directive.first) + case span: + populateMany(values, directive.first, directive.last, directive.step) + case all: + return desc.defaultList, nil + } + } + return toList(values), nil +} + +func (expr *Expression) dowFieldHandler(s string) error { + expr.daysOfWeekRestricted = true + expr.daysOfWeek = make(map[int]bool) + expr.lastWeekDaysOfWeek = make(map[int]bool) + expr.specificWeekDaysOfWeek = make(map[int]bool) + + directives, err := genericFieldParse(s, dowDescriptor) + if err != nil { + return err + } + + for _, directive := range directives { + switch directive.kind { + case none: + sdirective := s[directive.sbeg:directive.send] + snormal := strings.ToLower(sdirective) + // `5L` + pairs := makeLayoutRegexp(layoutDowOfLastWeek, dowDescriptor.valuePattern).FindStringSubmatchIndex(snormal) + if len(pairs) > 0 { + populateOne(expr.lastWeekDaysOfWeek, dowDescriptor.atoi(snormal[pairs[2]:pairs[3]])) + } else { + // `5#3` + pairs := makeLayoutRegexp(layoutDowOfSpecificWeek, dowDescriptor.valuePattern).FindStringSubmatchIndex(snormal) + if len(pairs) > 0 { + populateOne(expr.specificWeekDaysOfWeek, (dowDescriptor.atoi(snormal[pairs[4]:pairs[5]])-1)*7+(dowDescriptor.atoi(snormal[pairs[2]:pairs[3]])%7)) + } else { + return fmt.Errorf("syntax error in day-of-week field: '%s'", sdirective) + } + } + case one: + populateOne(expr.daysOfWeek, directive.first) + case span: + populateMany(expr.daysOfWeek, directive.first, directive.last, directive.step) + case all: + populateMany(expr.daysOfWeek, directive.first, directive.last, directive.step) + expr.daysOfWeekRestricted = false + } + } + return nil +} + +func (expr *Expression) domFieldHandler(s string) error { + expr.daysOfMonthRestricted = true + expr.lastDayOfMonth = false + expr.lastWorkdayOfMonth = false + expr.daysOfMonth = make(map[int]bool) // days of month map + expr.workdaysOfMonth = make(map[int]bool) // work days of month map + + directives, err := genericFieldParse(s, domDescriptor) + if err != nil { + return err + } + + for _, directive := range directives { + switch directive.kind { + case none: + sdirective := s[directive.sbeg:directive.send] + snormal := strings.ToLower(sdirective) + // `L` + if makeLayoutRegexp(layoutLastDom, domDescriptor.valuePattern).MatchString(snormal) { + expr.lastDayOfMonth = true + } else { + // `LW` + if makeLayoutRegexp(layoutLastWorkdom, domDescriptor.valuePattern).MatchString(snormal) { + expr.lastWorkdayOfMonth = true + } else { + // `15W` + pairs := makeLayoutRegexp(layoutWorkdom, domDescriptor.valuePattern).FindStringSubmatchIndex(snormal) + if len(pairs) > 0 { + populateOne(expr.workdaysOfMonth, domDescriptor.atoi(snormal[pairs[2]:pairs[3]])) + } else { + return fmt.Errorf("syntax error in day-of-month field: '%s'", sdirective) + } + } + } + case one: + populateOne(expr.daysOfMonth, directive.first) + case span: + populateMany(expr.daysOfMonth, directive.first, directive.last, directive.step) + case all: + populateMany(expr.daysOfMonth, directive.first, directive.last, directive.step) + expr.daysOfMonthRestricted = false + } + } + return nil +} + +/******************************************************************************/ + +func populateOne(values map[int]bool, v int) { + values[v] = true +} + +func populateMany(values map[int]bool, min, max, step int) { + for i := min; i <= max; i += step { + values[i] = true + } +} + +func toList(set map[int]bool) []int { + list := make([]int, len(set)) + i := 0 + for k := range set { + list[i] = k + i += 1 + } + sort.Ints(list) + return list +} + +/******************************************************************************/ + +func genericFieldParse(s string, desc fieldDescriptor) ([]*cronDirective, error) { + // At least one entry must be present + indices := entryFinder.FindAllStringIndex(s, -1) + if len(indices) == 0 { + return nil, fmt.Errorf("%s field: missing directive", desc.name) + } + + directives := make([]*cronDirective, 0, len(indices)) + + for i := range indices { + directive := cronDirective{ + sbeg: indices[i][0], + send: indices[i][1], + } + snormal := strings.ToLower(s[indices[i][0]:indices[i][1]]) + + // `*` + if makeLayoutRegexp(layoutWildcard, desc.valuePattern).MatchString(snormal) { + directive.kind = all + directive.first = desc.min + directive.last = desc.max + directive.step = 1 + directives = append(directives, &directive) + continue + } + // `5` + if makeLayoutRegexp(layoutValue, desc.valuePattern).MatchString(snormal) { + directive.kind = one + directive.first = desc.atoi(snormal) + directives = append(directives, &directive) + continue + } + // `5-20` + pairs := makeLayoutRegexp(layoutRange, desc.valuePattern).FindStringSubmatchIndex(snormal) + if len(pairs) > 0 { + directive.kind = span + directive.first = desc.atoi(snormal[pairs[2]:pairs[3]]) + directive.last = desc.atoi(snormal[pairs[4]:pairs[5]]) + directive.step = 1 + directives = append(directives, &directive) + continue + } + // `*/2` + pairs = makeLayoutRegexp(layoutWildcardAndInterval, desc.valuePattern).FindStringSubmatchIndex(snormal) + if len(pairs) > 0 { + directive.kind = span + directive.first = desc.min + directive.last = desc.max + directive.step = atoi(snormal[pairs[2]:pairs[3]]) + if directive.step < 1 || directive.step > desc.max { + return nil, fmt.Errorf("invalid interval %s", snormal) + } + directives = append(directives, &directive) + continue + } + // `5/2` + pairs = makeLayoutRegexp(layoutValueAndInterval, desc.valuePattern).FindStringSubmatchIndex(snormal) + if len(pairs) > 0 { + directive.kind = span + directive.first = desc.atoi(snormal[pairs[2]:pairs[3]]) + directive.last = desc.max + directive.step = atoi(snormal[pairs[4]:pairs[5]]) + if directive.step < 1 || directive.step > desc.max { + return nil, fmt.Errorf("invalid interval %s", snormal) + } + directives = append(directives, &directive) + continue + } + // `5-20/2` + pairs = makeLayoutRegexp(layoutRangeAndInterval, desc.valuePattern).FindStringSubmatchIndex(snormal) + if len(pairs) > 0 { + directive.kind = span + directive.first = desc.atoi(snormal[pairs[2]:pairs[3]]) + directive.last = desc.atoi(snormal[pairs[4]:pairs[5]]) + directive.step = atoi(snormal[pairs[6]:pairs[7]]) + if directive.step < 1 || directive.step > desc.max { + return nil, fmt.Errorf("invalid interval %s", snormal) + } + directives = append(directives, &directive) + continue + } + // No behavior for this one, let caller deal with it + directive.kind = none + directives = append(directives, &directive) + } + return directives, nil +} + +/******************************************************************************/ + +func makeLayoutRegexp(layout, value string) *regexp.Regexp { + layout = strings.Replace(layout, `%value%`, value, -1) + re := layoutRegexp[layout] + if re == nil { + re = regexp.MustCompile(layout) + layoutRegexp[layout] = re + } + return re +} diff --git a/vendor/github.com/gorhill/cronexpr/cronexpr_test.go b/vendor/github.com/gorhill/cronexpr/cronexpr_test.go new file mode 100644 index 0000000000000000000000000000000000000000..f170769d04007eb29aaf943745f277537a29259a --- /dev/null +++ b/vendor/github.com/gorhill/cronexpr/cronexpr_test.go @@ -0,0 +1,344 @@ +/*! + * Copyright 2013 Raymond Hill + * + * Project: github.com/gorhill/cronexpr + * File: cronexpr_test.go + * Version: 1.0 + * License: pick the one which suits you best: + * GPL v3 see + * APL v2 see + * + */ + +package cronexpr_test + +/******************************************************************************/ + +import ( + "testing" + "time" + + "github.com/gorhill/cronexpr" +) + +/******************************************************************************/ + +type crontimes struct { + from string + next string +} + +type crontest struct { + expr string + layout string + times []crontimes +} + +var crontests = []crontest{ + // Seconds + { + "* * * * * * *", + "2006-01-02 15:04:05", + []crontimes{ + {"2013-01-01 00:00:00", "2013-01-01 00:00:01"}, + {"2013-01-01 00:00:59", "2013-01-01 00:01:00"}, + {"2013-01-01 00:59:59", "2013-01-01 01:00:00"}, + {"2013-01-01 23:59:59", "2013-01-02 00:00:00"}, + {"2013-02-28 23:59:59", "2013-03-01 00:00:00"}, + {"2016-02-28 23:59:59", "2016-02-29 00:00:00"}, + {"2012-12-31 23:59:59", "2013-01-01 00:00:00"}, + }, + }, + + // every 5 Second + { + "*/5 * * * * * *", + "2006-01-02 15:04:05", + []crontimes{ + {"2013-01-01 00:00:00", "2013-01-01 00:00:05"}, + {"2013-01-01 00:00:59", "2013-01-01 00:01:00"}, + {"2013-01-01 00:59:59", "2013-01-01 01:00:00"}, + {"2013-01-01 23:59:59", "2013-01-02 00:00:00"}, + {"2013-02-28 23:59:59", "2013-03-01 00:00:00"}, + {"2016-02-28 23:59:59", "2016-02-29 00:00:00"}, + {"2012-12-31 23:59:59", "2013-01-01 00:00:00"}, + }, + }, + + // Minutes + { + "* * * * *", + "2006-01-02 15:04:05", + []crontimes{ + {"2013-01-01 00:00:00", "2013-01-01 00:01:00"}, + {"2013-01-01 00:00:59", "2013-01-01 00:01:00"}, + {"2013-01-01 00:59:00", "2013-01-01 01:00:00"}, + {"2013-01-01 23:59:00", "2013-01-02 00:00:00"}, + {"2013-02-28 23:59:00", "2013-03-01 00:00:00"}, + {"2016-02-28 23:59:00", "2016-02-29 00:00:00"}, + {"2012-12-31 23:59:00", "2013-01-01 00:00:00"}, + }, + }, + + // Minutes with interval + { + "17-43/5 * * * *", + "2006-01-02 15:04:05", + []crontimes{ + {"2013-01-01 00:00:00", "2013-01-01 00:17:00"}, + {"2013-01-01 00:16:59", "2013-01-01 00:17:00"}, + {"2013-01-01 00:30:00", "2013-01-01 00:32:00"}, + {"2013-01-01 00:50:00", "2013-01-01 01:17:00"}, + {"2013-01-01 23:50:00", "2013-01-02 00:17:00"}, + {"2013-02-28 23:50:00", "2013-03-01 00:17:00"}, + {"2016-02-28 23:50:00", "2016-02-29 00:17:00"}, + {"2012-12-31 23:50:00", "2013-01-01 00:17:00"}, + }, + }, + + // Minutes interval, list + { + "15-30/4,55 * * * *", + "2006-01-02 15:04:05", + []crontimes{ + {"2013-01-01 00:00:00", "2013-01-01 00:15:00"}, + {"2013-01-01 00:16:00", "2013-01-01 00:19:00"}, + {"2013-01-01 00:30:00", "2013-01-01 00:55:00"}, + {"2013-01-01 00:55:00", "2013-01-01 01:15:00"}, + {"2013-01-01 23:55:00", "2013-01-02 00:15:00"}, + {"2013-02-28 23:55:00", "2013-03-01 00:15:00"}, + {"2016-02-28 23:55:00", "2016-02-29 00:15:00"}, + {"2012-12-31 23:54:00", "2012-12-31 23:55:00"}, + {"2012-12-31 23:55:00", "2013-01-01 00:15:00"}, + }, + }, + + // Days of week + { + "0 0 * * MON", + "Mon 2006-01-02 15:04", + []crontimes{ + {"2013-01-01 00:00:00", "Mon 2013-01-07 00:00"}, + {"2013-01-28 00:00:00", "Mon 2013-02-04 00:00"}, + {"2013-12-30 00:30:00", "Mon 2014-01-06 00:00"}, + }, + }, + { + "0 0 * * friday", + "Mon 2006-01-02 15:04", + []crontimes{ + {"2013-01-01 00:00:00", "Fri 2013-01-04 00:00"}, + {"2013-01-28 00:00:00", "Fri 2013-02-01 00:00"}, + {"2013-12-30 00:30:00", "Fri 2014-01-03 00:00"}, + }, + }, + { + "0 0 * * 6,7", + "Mon 2006-01-02 15:04", + []crontimes{ + {"2013-01-01 00:00:00", "Sat 2013-01-05 00:00"}, + {"2013-01-28 00:00:00", "Sat 2013-02-02 00:00"}, + {"2013-12-30 00:30:00", "Sat 2014-01-04 00:00"}, + }, + }, + + // Specific days of week + { + "0 0 * * 6#5", + "Mon 2006-01-02 15:04", + []crontimes{ + {"2013-09-02 00:00:00", "Sat 2013-11-30 00:00"}, + }, + }, + + // Work day of month + { + "0 0 14W * *", + "Mon 2006-01-02 15:04", + []crontimes{ + {"2013-03-31 00:00:00", "Mon 2013-04-15 00:00"}, + {"2013-08-31 00:00:00", "Fri 2013-09-13 00:00"}, + }, + }, + + // Work day of month -- end of month + { + "0 0 30W * *", + "Mon 2006-01-02 15:04", + []crontimes{ + {"2013-03-02 00:00:00", "Fri 2013-03-29 00:00"}, + {"2013-06-02 00:00:00", "Fri 2013-06-28 00:00"}, + {"2013-09-02 00:00:00", "Mon 2013-09-30 00:00"}, + {"2013-11-02 00:00:00", "Fri 2013-11-29 00:00"}, + }, + }, + + // Last day of month + { + "0 0 L * *", + "Mon 2006-01-02 15:04", + []crontimes{ + {"2013-09-02 00:00:00", "Mon 2013-09-30 00:00"}, + {"2014-01-01 00:00:00", "Fri 2014-01-31 00:00"}, + {"2014-02-01 00:00:00", "Fri 2014-02-28 00:00"}, + {"2016-02-15 00:00:00", "Mon 2016-02-29 00:00"}, + }, + }, + + // Last work day of month + { + "0 0 LW * *", + "Mon 2006-01-02 15:04", + []crontimes{ + {"2013-09-02 00:00:00", "Mon 2013-09-30 00:00"}, + {"2013-11-02 00:00:00", "Fri 2013-11-29 00:00"}, + {"2014-08-15 00:00:00", "Fri 2014-08-29 00:00"}, + }, + }, + + // TODO: more tests +} + +func TestExpressions(t *testing.T) { + for _, test := range crontests { + for _, times := range test.times { + from, _ := time.Parse("2006-01-02 15:04:05", times.from) + expr, err := cronexpr.Parse(test.expr) + if err != nil { + t.Errorf(`cronexpr.Parse("%s") returned "%s"`, test.expr, err.Error()) + } + next := expr.Next(from) + nextstr := next.Format(test.layout) + if nextstr != times.next { + t.Errorf(`("%s").Next("%s") = "%s", got "%s"`, test.expr, times.from, times.next, nextstr) + } + } + } +} + +/******************************************************************************/ + +func TestZero(t *testing.T) { + from, _ := time.Parse("2006-01-02", "2013-08-31") + next := cronexpr.MustParse("* * * * * 1980").Next(from) + if next.IsZero() == false { + t.Error(`("* * * * * 1980").Next("2013-08-31").IsZero() returned 'false', expected 'true'`) + } + + next = cronexpr.MustParse("* * * * * 2050").Next(from) + if next.IsZero() == true { + t.Error(`("* * * * * 2050").Next("2013-08-31").IsZero() returned 'true', expected 'false'`) + } + + next = cronexpr.MustParse("* * * * * 2099").Next(time.Time{}) + if next.IsZero() == false { + t.Error(`("* * * * * 2014").Next(time.Time{}).IsZero() returned 'true', expected 'false'`) + } +} + +/******************************************************************************/ + +func TestNextN(t *testing.T) { + expected := []string{ + "Sat, 30 Nov 2013 00:00:00", + "Sat, 29 Mar 2014 00:00:00", + "Sat, 31 May 2014 00:00:00", + "Sat, 30 Aug 2014 00:00:00", + "Sat, 29 Nov 2014 00:00:00", + } + from, _ := time.Parse("2006-01-02 15:04:05", "2013-09-02 08:44:30") + result := cronexpr.MustParse("0 0 * * 6#5").NextN(from, uint(len(expected))) + if len(result) != len(expected) { + t.Errorf(`MustParse("0 0 * * 6#5").NextN("2013-09-02 08:44:30", 5):\n"`) + t.Errorf(` Expected %d returned time values but got %d instead`, len(expected), len(result)) + } + for i, next := range result { + nextStr := next.Format("Mon, 2 Jan 2006 15:04:15") + if nextStr != expected[i] { + t.Errorf(`MustParse("0 0 * * 6#5").NextN("2013-09-02 08:44:30", 5):\n"`) + t.Errorf(` result[%d]: expected "%s" but got "%s"`, i, expected[i], nextStr) + } + } +} + +func TestNextN_every5min(t *testing.T) { + expected := []string{ + "Mon, 2 Sep 2013 08:45:00", + "Mon, 2 Sep 2013 08:50:00", + "Mon, 2 Sep 2013 08:55:00", + "Mon, 2 Sep 2013 09:00:00", + "Mon, 2 Sep 2013 09:05:00", + } + from, _ := time.Parse("2006-01-02 15:04:05", "2013-09-02 08:44:32") + result := cronexpr.MustParse("*/5 * * * *").NextN(from, uint(len(expected))) + if len(result) != len(expected) { + t.Errorf(`MustParse("*/5 * * * *").NextN("2013-09-02 08:44:30", 5):\n"`) + t.Errorf(` Expected %d returned time values but got %d instead`, len(expected), len(result)) + } + for i, next := range result { + nextStr := next.Format("Mon, 2 Jan 2006 15:04:05") + if nextStr != expected[i] { + t.Errorf(`MustParse("*/5 * * * *").NextN("2013-09-02 08:44:30", 5):\n"`) + t.Errorf(` result[%d]: expected "%s" but got "%s"`, i, expected[i], nextStr) + } + } +} + +// Issue: https://github.com/gorhill/cronexpr/issues/16 +func TestInterval_Interval60Issue(t *testing.T){ + _, err := cronexpr.Parse("*/60 * * * * *") + if err == nil { + t.Errorf("parsing with interval 60 should return err") + } + + _, err = cronexpr.Parse("*/61 * * * * *") + if err == nil { + t.Errorf("parsing with interval 61 should return err") + } + + _, err = cronexpr.Parse("2/60 * * * * *") + if err == nil { + t.Errorf("parsing with interval 60 should return err") + } + + _, err = cronexpr.Parse("2-20/61 * * * * *") + if err == nil { + t.Errorf("parsing with interval 60 should return err") + } +} + +/******************************************************************************/ + +var benchmarkExpressions = []string{ + "* * * * *", + "@hourly", + "@weekly", + "@yearly", + "30 3 15W 3/3 *", + "30 0 0 1-31/5 Oct-Dec * 2000,2006,2008,2013-2015", + "0 0 0 * Feb-Nov/2 thu#3 2000-2050", +} +var benchmarkExpressionsLen = len(benchmarkExpressions) + +func BenchmarkParse(b *testing.B) { + for i := 0; i < b.N; i++ { + _ = cronexpr.MustParse(benchmarkExpressions[i%benchmarkExpressionsLen]) + } +} + +func BenchmarkNext(b *testing.B) { + exprs := make([]*cronexpr.Expression, benchmarkExpressionsLen) + for i := 0; i < benchmarkExpressionsLen; i++ { + exprs[i] = cronexpr.MustParse(benchmarkExpressions[i]) + } + from := time.Now() + b.ResetTimer() + for i := 0; i < b.N; i++ { + expr := exprs[i%benchmarkExpressionsLen] + next := expr.Next(from) + next = expr.Next(next) + next = expr.Next(next) + next = expr.Next(next) + next = expr.Next(next) + } +} diff --git a/vendor/github.com/gorhill/cronexpr/example_test.go b/vendor/github.com/gorhill/cronexpr/example_test.go new file mode 100644 index 0000000000000000000000000000000000000000..3dc27d06978ebe046892a3b428d0256e1f14716f --- /dev/null +++ b/vendor/github.com/gorhill/cronexpr/example_test.go @@ -0,0 +1,37 @@ +/*! + * Copyright 2013 Raymond Hill + * + * Project: github.com/gorhill/example_test.go + * File: example_test.go + * Version: 1.0 + * License: GPL v3 see + * + */ + +package cronexpr_test + +/******************************************************************************/ + +import ( + "fmt" + "time" + + "github.com/gorhill/cronexpr" +) + +/******************************************************************************/ + +// ExampleMustParse +func ExampleMustParse() { + t := time.Date(2013, time.August, 31, 0, 0, 0, 0, time.UTC) + nextTimes := cronexpr.MustParse("0 0 29 2 *").NextN(t, 5) + for i := range nextTimes { + fmt.Println(nextTimes[i].Format(time.RFC1123)) + // Output: + // Mon, 29 Feb 2016 00:00:00 UTC + // Sat, 29 Feb 2020 00:00:00 UTC + // Thu, 29 Feb 2024 00:00:00 UTC + // Tue, 29 Feb 2028 00:00:00 UTC + // Sun, 29 Feb 2032 00:00:00 UTC + } +} diff --git a/vendor/github.com/rubenv/sql-migrate/BUILD.bazel b/vendor/github.com/rubenv/sql-migrate/BUILD.bazel deleted file mode 100644 index 99a338b54be17e7c481616b3b4d63e46e8375720..0000000000000000000000000000000000000000 --- a/vendor/github.com/rubenv/sql-migrate/BUILD.bazel +++ /dev/null @@ -1,32 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "migrate.go", - ], - importpath = "github.com/rubenv/sql-migrate", - visibility = ["//visibility:public"], - deps = [ - "//vendor/github.com/rubenv/sql-migrate/sqlparse:go_default_library", - "//vendor/gopkg.in/gorp.v1:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = [ - "bindata_test.go", - "init_test.go", - "migrate_test.go", - "sort_test.go", - "toapply_test.go", - ], - embed = [":go_default_library"], - deps = [ - "//vendor/gopkg.in/gorp.v1:go_default_library", - "@com_github_mattn_go_sqlite3//:go_default_library", - "@in_gopkg_check_v1//:go_default_library", - ], -) diff --git a/vendor/github.com/yuin/gopher-lua/.github/CONTRIBUTING.md b/vendor/github.com/yuin/gopher-lua/.github/CONTRIBUTING.md new file mode 100644 index 0000000000000000000000000000000000000000..eb2dc91eb47e89ab7c348e5a2e5109b4f7409205 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/.github/CONTRIBUTING.md @@ -0,0 +1,49 @@ +# How to Contribute +Any kind of contributions are welcome. + +## Building GopherLua + +GopherLua uses simple inlining tool for generate efficient codes. This tool requires python interpreter. Files name of which starts with `_` genarate files name of which does not starts with `_` . For instance, `_state.go` generate `state.go` . You do not edit generated sources. +To generate sources, some make target is available. + +```bash +make build +make glua +make test +``` + +You have to run `make build` before committing to the repository. + +## Pull requests +Our workflow is based on the [github-flow](https://guides.github.com/introduction/flow/>) . + +1. Create a new issue. +2. Fork the project. +3. Clone your fork and add the upstream. + ```bash + git remote add upstream https://github.com/yuin/gopher-lua.git + ``` + +4. Pull new changes from the upstream. + ```bash + git checkout master + git fetch upstream + git merge upstream/master + ``` + +5. Create a feature branch + ```bash + git checkout -b + ``` + +6. Commit your changes and reference the issue number in your comment. + ```bash + git commit -m "Issue # : " + ``` + +7. Push the feature branch to your remote repository. + ```bash + git push origin + ``` + +8. Open new pull request. diff --git a/vendor/github.com/yuin/gopher-lua/.github/ISSUE_TEMPLATE.md b/vendor/github.com/yuin/gopher-lua/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000000000000000000000000000000000000..899ddf73f6c334c758a35314aa7bf91618fb277e --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,12 @@ +- [ ] GopherLua is a Lua5.1 implementation. You should be familiar with Lua programming language. Have you read [Lua 5.1 reference manual](http://www.lua.org/manual/5.1/) carefully? +- [ ] GopherLua is a Lua5.1 implementation. In Lua, to keep it simple, **it is more important to remove functionalities rather than to add functionalities unlike other languages** . If you are going to introduce some new cool functionalities into the GopherLua code base and the functionalities can be implemented by existing APIs, It should be implemented as a library. + +Please answer the following before submitting your issue: + +1. What version of GopherLua are you using? : +2. What version of Go are you using? : +3. What operating system and processor architecture are you using? : +4. What did you do? : +5. What did you expect to see? : +6. What did you see instead? : + diff --git a/vendor/github.com/yuin/gopher-lua/.github/PULL_REQUEST_TEMPLATE.md b/vendor/github.com/yuin/gopher-lua/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000000000000000000000000000000000000..917c8aa900cacb98a673265bc4d544ad2333f4d5 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,8 @@ +Fixes # . + +Changes proposed in this pull request: + +- a +- b +- c +- d diff --git a/vendor/github.com/yuin/gopher-lua/.travis.yml b/vendor/github.com/yuin/gopher-lua/.travis.yml new file mode 100644 index 0000000000000000000000000000000000000000..fdaf5365dbb3d76cfb6b12fccdaccd9a3c951421 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/.travis.yml @@ -0,0 +1,15 @@ +language: go + +go: + - 1.7 + - 1.8 + - 1.9 + +before_install: + - go get github.com/axw/gocov/gocov + - go get github.com/mattn/goveralls + - if ! go get code.google.com/p/go.tools/cmd/cover; then go get golang.org/x/tools/cmd/cover; fi +install: + - go get -u -v $(go list -f '{{join .Imports "\n"}}{{"\n"}}{{join .TestImports "\n"}}' ./... | sort | uniq | grep -v gopher-lua) +script: + - $HOME/gopath/bin/goveralls -service=travis-ci diff --git a/vendor/github.com/yuin/gopher-lua/LICENSE b/vendor/github.com/yuin/gopher-lua/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..4daf480a2fd02bb2ab11a04335a5a43dfbab9d1b --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Yusuke Inuzuka + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/yuin/gopher-lua/Makefile b/vendor/github.com/yuin/gopher-lua/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..6d9e55c35f7817b4017102f8006e277aa0c5f2a4 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/Makefile @@ -0,0 +1,10 @@ +.PHONY: build test glua + +build: + ./_tools/go-inline *.go && go fmt . && go build + +glua: *.go pm/*.go cmd/glua/glua.go + ./_tools/go-inline *.go && go fmt . && go build cmd/glua/glua.go + +test: + ./_tools/go-inline *.go && go fmt . && go test diff --git a/vendor/github.com/yuin/gopher-lua/README.rst b/vendor/github.com/yuin/gopher-lua/README.rst new file mode 100644 index 0000000000000000000000000000000000000000..fc5f6df517b0575ed19787f41d3183065d8eda1f --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/README.rst @@ -0,0 +1,802 @@ +=============================================================================== +GopherLua: VM and compiler for Lua in Go. +=============================================================================== + +.. image:: https://godoc.org/github.com/yuin/gopher-lua?status.svg + :target: http://godoc.org/github.com/yuin/gopher-lua + +.. image:: https://travis-ci.org/yuin/gopher-lua.svg + :target: https://travis-ci.org/yuin/gopher-lua + +.. image:: https://coveralls.io/repos/yuin/gopher-lua/badge.svg + :target: https://coveralls.io/r/yuin/gopher-lua + +.. image:: https://badges.gitter.im/Join%20Chat.svg + :alt: Join the chat at https://gitter.im/yuin/gopher-lua + :target: https://gitter.im/yuin/gopher-lua?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge + +| + + +GopherLua is a Lua5.1 VM and compiler written in Go. GopherLua has a same goal +with Lua: **Be a scripting language with extensible semantics** . It provides +Go APIs that allow you to easily embed a scripting language to your Go host +programs. + +.. contents:: + :depth: 1 + +---------------------------------------------------------------- +Design principle +---------------------------------------------------------------- + +- Be a scripting language with extensible semantics. +- User-friendly Go API + - The stack based API like the one used in the original Lua + implementation will cause a performance improvements in GopherLua + (It will reduce memory allocations and concrete type <-> interface conversions). + GopherLua API is **not** the stack based API. + GopherLua give preference to the user-friendliness over the performance. + +---------------------------------------------------------------- +How about performance? +---------------------------------------------------------------- +GopherLua is not fast but not too slow, I think. + +GopherLua has almost equivalent ( or little bit better ) performance as Python3 on micro benchmarks. + +There are some benchmarks on the `wiki page `_ . + +---------------------------------------------------------------- +Installation +---------------------------------------------------------------- + +.. code-block:: bash + + go get github.com/yuin/gopher-lua + +GopherLua supports >= Go1.7. + +---------------------------------------------------------------- +Usage +---------------------------------------------------------------- +GopherLua APIs perform in much the same way as Lua, **but the stack is used only +for passing arguments and receiving returned values.** + +GopherLua supports channel operations. See **"Goroutines"** section. + +Import a package. + +.. code-block:: go + + import ( + "github.com/yuin/gopher-lua" + ) + +Run scripts in the VM. + +.. code-block:: go + + L := lua.NewState() + defer L.Close() + if err := L.DoString(`print("hello")`); err != nil { + panic(err) + } + +.. code-block:: go + + L := lua.NewState() + defer L.Close() + if err := L.DoFile("hello.lua"); err != nil { + panic(err) + } + +Refer to `Lua Reference Manual `_ and `Go doc `_ for further information. + +Note that elements that are not commented in `Go doc `_ equivalent to `Lua Reference Manual `_ , except GopherLua uses objects instead of Lua stack indices. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Data model +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +All data in a GopherLua program is an ``LValue`` . ``LValue`` is an interface +type that has following methods. + +- ``String() string`` +- ``Type() LValueType`` + + +Objects implement an LValue interface are + +================ ========================= ================== ======================= + Type name Go type Type() value Constants +================ ========================= ================== ======================= + ``LNilType`` (constants) ``LTNil`` ``LNil`` + ``LBool`` (constants) ``LTBool`` ``LTrue``, ``LFalse`` + ``LNumber`` float64 ``LTNumber`` ``-`` + ``LString`` string ``LTString`` ``-`` + ``LFunction`` struct pointer ``LTFunction`` ``-`` + ``LUserData`` struct pointer ``LTUserData`` ``-`` + ``LState`` struct pointer ``LTThread`` ``-`` + ``LTable`` struct pointer ``LTTable`` ``-`` + ``LChannel`` chan LValue ``LTChannel`` ``-`` +================ ========================= ================== ======================= + +You can test an object type in Go way(type assertion) or using a ``Type()`` value. + +.. code-block:: go + + lv := L.Get(-1) // get the value at the top of the stack + if str, ok := lv.(lua.LString); ok { + // lv is LString + fmt.Println(string(str)) + } + if lv.Type() != lua.LTString { + panic("string required.") + } + +.. code-block:: go + + lv := L.Get(-1) // get the value at the top of the stack + if tbl, ok := lv.(*lua.LTable); ok { + // lv is LTable + fmt.Println(L.ObjLen(tbl)) + } + +Note that ``LBool`` , ``LNumber`` , ``LString`` is not a pointer. + +To test ``LNilType`` and ``LBool``, You **must** use pre-defined constants. + +.. code-block:: go + + lv := L.Get(-1) // get the value at the top of the stack + + if lv == lua.LTrue { // correct + } + + if bl, ok := lv.(lua.LBool); ok && bool(bl) { // wrong + } + +In Lua, both ``nil`` and ``false`` make a condition false. ``LVIsFalse`` and ``LVAsBool`` implement this specification. + +.. code-block:: go + + lv := L.Get(-1) // get the value at the top of the stack + if lua.LVIsFalse(lv) { // lv is nil or false + } + + if lua.LVAsBool(lv) { // lv is neither nil nor false + } + +Objects that based on go structs(``LFunction``. ``LUserData``, ``LTable``) +have some public methods and fields. You can use these methods and fields for +performance and debugging, but there are some limitations. + +- Metatable does not work. +- No error handlings. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Callstack & Registry size +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Size of the callstack & registry is **fixed** for mainly performance. +You can change the default size of the callstack & registry. + +.. code-block:: go + + lua.RegistrySize = 1024 * 20 + lua.CallStackSize = 1024 + L := lua.NewState() + defer L.Close() + +You can also create an LState object that has the callstack & registry size specified by ``Options`` . + +.. code-block:: go + + L := lua.NewState(lua.Options{ + CallStackSize: 120, + RegistrySize: 120*20, + }) + +An LState object that has been created by ``*LState#NewThread()`` inherits the callstack & registry size from the parent LState object. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Miscellaneous lua.NewState options +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +- **Options.SkipOpenLibs bool(default false)** + - By default, GopherLua opens all built-in libraries when new LState is created. + - You can skip this behaviour by setting this to ``true`` . + - Using the various `OpenXXX(L *LState) int` functions you can open only those libraries that you require, for an example see below. +- **Options.IncludeGoStackTrace bool(default false)** + - By default, GopherLua does not show Go stack traces when panics occur. + - You can get Go stack traces by setting this to ``true`` . + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +API +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Refer to `Lua Reference Manual `_ and `Go doc(LState methods) `_ for further information. + ++++++++++++++++++++++++++++++++++++++++++ +Calling Go from Lua ++++++++++++++++++++++++++++++++++++++++++ + +.. code-block:: go + + func Double(L *lua.LState) int { + lv := L.ToInt(1) /* get argument */ + L.Push(lua.LNumber(lv * 2)) /* push result */ + return 1 /* number of results */ + } + + func main() { + L := lua.NewState() + defer L.Close() + L.SetGlobal("double", L.NewFunction(Double)) /* Original lua_setglobal uses stack... */ + } + +.. code-block:: lua + + print(double(20)) -- > "40" + +Any function registered with GopherLua is a ``lua.LGFunction``, defined in ``value.go`` + +.. code-block:: go + + type LGFunction func(*LState) int + +Working with coroutines. + +.. code-block:: go + + co, _ := L.NewThread() /* create a new thread */ + fn := L.GetGlobal("coro").(*lua.LFunction) /* get function from lua */ + for { + st, err, values := L.Resume(co, fn) + if st == lua.ResumeError { + fmt.Println("yield break(error)") + fmt.Println(err.Error()) + break + } + + for i, lv := range values { + fmt.Printf("%v : %v\n", i, lv) + } + + if st == lua.ResumeOK { + fmt.Println("yield break(ok)") + break + } + } + ++++++++++++++++++++++++++++++++++++++++++ +Opening a subset of builtin modules ++++++++++++++++++++++++++++++++++++++++++ + +The following demonstrates how to open a subset of the built-in modules in Lua, say for example to avoid enabling modules with access to local files or system calls. + +main.go + +.. code-block:: go + + func main() { + L := lua.NewState(lua.Options{SkipOpenLibs: true}) + defer L.Close() + for _, pair := range []struct { + n string + f lua.LGFunction + }{ + {lua.LoadLibName, lua.OpenPackage}, // Must be first + {lua.BaseLibName, lua.OpenBase}, + {lua.TabLibName, lua.OpenTable}, + } { + if err := L.CallByParam(lua.P{ + Fn: L.NewFunction(pair.f), + NRet: 0, + Protect: true, + }, lua.LString(pair.n)); err != nil { + panic(err) + } + } + if err := L.DoFile("main.lua"); err != nil { + panic(err) + } + } + ++++++++++++++++++++++++++++++++++++++++++ +Creating a module by Go ++++++++++++++++++++++++++++++++++++++++++ + +mymodule.go + +.. code-block:: go + + package mymodule + + import ( + "github.com/yuin/gopher-lua" + ) + + func Loader(L *lua.LState) int { + // register functions to the table + mod := L.SetFuncs(L.NewTable(), exports) + // register other stuff + L.SetField(mod, "name", lua.LString("value")) + + // returns the module + L.Push(mod) + return 1 + } + + var exports = map[string]lua.LGFunction{ + "myfunc": myfunc, + } + + func myfunc(L *lua.LState) int { + return 0 + } + +mymain.go + +.. code-block:: go + + package main + + import ( + "./mymodule" + "github.com/yuin/gopher-lua" + ) + + func main() { + L := lua.NewState() + defer L.Close() + L.PreloadModule("mymodule", mymodule.Loader) + if err := L.DoFile("main.lua"); err != nil { + panic(err) + } + } + +main.lua + +.. code-block:: lua + + local m = require("mymodule") + m.myfunc() + print(m.name) + + ++++++++++++++++++++++++++++++++++++++++++ +Calling Lua from Go ++++++++++++++++++++++++++++++++++++++++++ + +.. code-block:: go + + L := lua.NewState() + defer L.Close() + if err := L.DoFile("double.lua"); err != nil { + panic(err) + } + if err := L.CallByParam(lua.P{ + Fn: L.GetGlobal("double"), + NRet: 1, + Protect: true, + }, lua.LNumber(10)); err != nil { + panic(err) + } + ret := L.Get(-1) // returned value + L.Pop(1) // remove received value + +If ``Protect`` is false, GopherLua will panic instead of returning an ``error`` value. + ++++++++++++++++++++++++++++++++++++++++++ +User-Defined types ++++++++++++++++++++++++++++++++++++++++++ +You can extend GopherLua with new types written in Go. +``LUserData`` is provided for this purpose. + +.. code-block:: go + + type Person struct { + Name string + } + + const luaPersonTypeName = "person" + + // Registers my person type to given L. + func registerPersonType(L *lua.LState) { + mt := L.NewTypeMetatable(luaPersonTypeName) + L.SetGlobal("person", mt) + // static attributes + L.SetField(mt, "new", L.NewFunction(newPerson)) + // methods + L.SetField(mt, "__index", L.SetFuncs(L.NewTable(), personMethods)) + } + + // Constructor + func newPerson(L *lua.LState) int { + person := &Person{L.CheckString(1)} + ud := L.NewUserData() + ud.Value = person + L.SetMetatable(ud, L.GetTypeMetatable(luaPersonTypeName)) + L.Push(ud) + return 1 + } + + // Checks whether the first lua argument is a *LUserData with *Person and returns this *Person. + func checkPerson(L *lua.LState) *Person { + ud := L.CheckUserData(1) + if v, ok := ud.Value.(*Person); ok { + return v + } + L.ArgError(1, "person expected") + return nil + } + + var personMethods = map[string]lua.LGFunction{ + "name": personGetSetName, + } + + // Getter and setter for the Person#Name + func personGetSetName(L *lua.LState) int { + p := checkPerson(L) + if L.GetTop() == 2 { + p.Name = L.CheckString(2) + return 0 + } + L.Push(lua.LString(p.Name)) + return 1 + } + + func main() { + L := lua.NewState() + defer L.Close() + registerPersonType(L) + if err := L.DoString(` + p = person.new("Steeve") + print(p:name()) -- "Steeve" + p:name("Alice") + print(p:name()) -- "Alice" + `); err != nil { + panic(err) + } + } + ++++++++++++++++++++++++++++++++++++++++++ +Terminating a running LState ++++++++++++++++++++++++++++++++++++++++++ +GopherLua supports the `Go Concurrency Patterns: Context `_ . + + +.. code-block:: go + + L := lua.NewState() + defer L.Close() + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + // set the context to our LState + L.SetContext(ctx) + err := L.DoString(` + local clock = os.clock + function sleep(n) -- seconds + local t0 = clock() + while clock() - t0 <= n do end + end + sleep(3) + `) + // err.Error() contains "context deadline exceeded" + +With coroutines + +.. code-block:: go + + L := lua.NewState() + defer L.Close() + ctx, cancel := context.WithCancel(context.Background()) + L.SetContext(ctx) + defer cancel() + L.DoString(` + function coro() + local i = 0 + while true do + coroutine.yield(i) + i = i+1 + end + return i + end + `) + co, cocancel := L.NewThread() + defer cocancel() + fn := L.GetGlobal("coro").(*LFunction) + + _, err, values := L.Resume(co, fn) // err is nil + + cancel() // cancel the parent context + + _, err, values = L.Resume(co, fn) // err is NOT nil : child context was canceled + +**Note that using a context causes performance degradation.** + +.. code-block:: + + time ./glua-with-context.exe fib.lua + 9227465 + 0.01s user 0.11s system 1% cpu 7.505 total + + time ./glua-without-context.exe fib.lua + 9227465 + 0.01s user 0.01s system 0% cpu 5.306 total + + ++++++++++++++++++++++++++++++++++++++++++ +Goroutines ++++++++++++++++++++++++++++++++++++++++++ +The ``LState`` is not goroutine-safe. It is recommended to use one LState per goroutine and communicate between goroutines by using channels. + +Channels are represented by ``channel`` objects in GopherLua. And a ``channel`` table provides functions for performing channel operations. + +Some objects can not be sent over channels due to having non-goroutine-safe objects inside itself. + +- a thread(state) +- a function +- an userdata +- a table with a metatable + +You **must not** send these objects from Go APIs to channels. + + + +.. code-block:: go + + func receiver(ch, quit chan lua.LValue) { + L := lua.NewState() + defer L.Close() + L.SetGlobal("ch", lua.LChannel(ch)) + L.SetGlobal("quit", lua.LChannel(quit)) + if err := L.DoString(` + local exit = false + while not exit do + channel.select( + {"|<-", ch, function(ok, v) + if not ok then + print("channel closed") + exit = true + else + print("received:", v) + end + end}, + {"|<-", quit, function(ok, v) + print("quit") + exit = true + end} + ) + end + `); err != nil { + panic(err) + } + } + + func sender(ch, quit chan lua.LValue) { + L := lua.NewState() + defer L.Close() + L.SetGlobal("ch", lua.LChannel(ch)) + L.SetGlobal("quit", lua.LChannel(quit)) + if err := L.DoString(` + ch:send("1") + ch:send("2") + `); err != nil { + panic(err) + } + ch <- lua.LString("3") + quit <- lua.LTrue + } + + func main() { + ch := make(chan lua.LValue) + quit := make(chan lua.LValue) + go receiver(ch, quit) + go sender(ch, quit) + time.Sleep(3 * time.Second) + } + +''''''''''''''' +Go API +''''''''''''''' + +``ToChannel``, ``CheckChannel``, ``OptChannel`` are available. + +Refer to `Go doc(LState methods) `_ for further information. + +''''''''''''''' +Lua API +''''''''''''''' + +- **channel.make([buf:int]) -> ch:channel** + - Create new channel that has a buffer size of ``buf``. By default, ``buf`` is 0. + +- **channel.select(case:table [, case:table, case:table ...]) -> {index:int, recv:any, ok}** + - Same as the ``select`` statement in Go. It returns the index of the chosen case and, if that + case was a receive operation, the value received and a boolean indicating whether the channel has been closed. + - ``case`` is a table that outlined below. + - receiving: `{"|<-", ch:channel [, handler:func(ok, data:any)]}` + - sending: `{"<-|", ch:channel, data:any [, handler:func(data:any)]}` + - default: `{"default" [, handler:func()]}` + +``channel.select`` examples: + +.. code-block:: lua + + local idx, recv, ok = channel.select( + {"|<-", ch1}, + {"|<-", ch2} + ) + if not ok then + print("closed") + elseif idx == 1 then -- received from ch1 + print(recv) + elseif idx == 2 then -- received from ch2 + print(recv) + end + +.. code-block:: lua + + channel.select( + {"|<-", ch1, function(ok, data) + print(ok, data) + end}, + {"<-|", ch2, "value", function(data) + print(data) + end}, + {"default", function() + print("default action") + end} + ) + +- **channel:send(data:any)** + - Send ``data`` over the channel. +- **channel:receive() -> ok:bool, data:any** + - Receive some data over the channel. +- **channel:close()** + - Close the channel. + +'''''''''''''''''''''''''''''' +The LState pool pattern +'''''''''''''''''''''''''''''' +To create per-thread LState instances, You can use the ``sync.Pool`` like mechanism. + +.. code-block:: go + + type lStatePool struct { + m sync.Mutex + saved []*lua.LState + } + + func (pl *lStatePool) Get() *lua.LState { + pl.m.Lock() + defer pl.m.Unlock() + n := len(pl.saved) + if n == 0 { + return pl.New() + } + x := pl.saved[n-1] + pl.saved = pl.saved[0 : n-1] + return x + } + + func (pl *lStatePool) New() *lua.LState { + L := lua.NewState() + // setting the L up here. + // load scripts, set global variables, share channels, etc... + return L + } + + func (pl *lStatePool) Put(L *lua.LState) { + pl.m.Lock() + defer pl.m.Unlock() + pl.saved = append(pl.saved, L) + } + + func (pl *lStatePool) Shutdown() { + for _, L := range pl.saved { + L.Close() + } + } + + // Global LState pool + var luaPool = &lStatePool{ + saved: make([]*lua.LState, 0, 4), + } + +Now, you can get per-thread LState objects from the ``luaPool`` . + +.. code-block:: go + + func MyWorker() { + L := luaPool.Get() + defer luaPool.Put(L) + /* your code here */ + } + + func main() { + defer luaPool.Shutdown() + go MyWorker() + go MyWorker() + /* etc... */ + } + + +---------------------------------------------------------------- +Differences between Lua and GopherLua +---------------------------------------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Goroutines +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- GopherLua supports channel operations. + - GopherLua has a type named ``channel``. + - The ``channel`` table provides functions for performing channel operations. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Unsupported functions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- ``string.dump`` +- ``os.setlocale`` +- ``lua_Debug.namewhat`` +- ``package.loadlib`` +- debug hooks + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Miscellaneous notes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- ``collectgarbage`` does not take any arguments and runs the garbage collector for the entire Go program. +- ``file:setvbuf`` does not support a line buffering. +- Daylight saving time is not supported. +- GopherLua has a function to set an environment variable : ``os.setenv(name, value)`` + +---------------------------------------------------------------- +Standalone interpreter +---------------------------------------------------------------- +Lua has an interpreter called ``lua`` . GopherLua has an interpreter called ``glua`` . + +.. code-block:: bash + + go get github.com/yuin/gopher-lua/cmd/glua + +``glua`` has same options as ``lua`` . + +---------------------------------------------------------------- +How to Contribute +---------------------------------------------------------------- +See `Guidlines for contributors `_ . + +---------------------------------------------------------------- +Libraries for GopherLua +---------------------------------------------------------------- + +- `gopher-luar `_ : Custom type reflection for gopher-lua +- `gluamapper `_ : Mapping a Lua table to a Go struct +- `gluare `_ : Regular expressions for gopher-lua +- `gluahttp `_ : HTTP request module for gopher-lua +- `gopher-json `_ : A simple JSON encoder/decoder for gopher-lua +- `gluayaml `_ : Yaml parser for gopher-lua +- `glua-lfs `_ : Partially implements the luafilesystem module for gopher-lua +- `gluaurl `_ : A url parser/builder module for gopher-lua +- `gluahttpscrape `_ : A simple HTML scraper module for gopher-lua +- `gluaxmlpath `_ : An xmlpath module for gopher-lua +- `gluasocket `_ : A LuaSocket library for the GopherLua VM +- `gluabit32 `_ : A native Go implementation of bit32 for the GopherLua VM. + +---------------------------------------------------------------- +Donation +---------------------------------------------------------------- + +BTC: 1NEDSyUmo4SMTDP83JJQSWi1MvQUGGNMZB + +---------------------------------------------------------------- +License +---------------------------------------------------------------- +MIT + +---------------------------------------------------------------- +Author +---------------------------------------------------------------- +Yusuke Inuzuka diff --git a/vendor/github.com/yuin/gopher-lua/_glua-tests/base.lua b/vendor/github.com/yuin/gopher-lua/_glua-tests/base.lua new file mode 100644 index 0000000000000000000000000000000000000000..2bc64a8b5b39688c6f3f99c14d01c35917c8e8f1 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/_glua-tests/base.lua @@ -0,0 +1,48 @@ +local ok, msg = pcall(function() + dofile("notexist") +end) +assert(not ok and string.find(msg, ".*notexist.*")) + +local ok, msg = pcall(function() + assert(getfenv(2) == _G) +end) +assert(ok) + +local i = 1 +local fn = assert(load(function() + local tbl = {"return ", "1", "+", "1"} + local v = tbl[i] + i = i + 1 + return v +end)) +assert(fn() == 2) + +local fn, msg = load(function() + return {} +end) +assert(not fn and string.find(msg, "must return a string")) + +local i = 1 +local fn, msg = load(function() + if i == 1 then + i = i + 1 + return "returna" + end +end) +assert(not fn and string.find(string.lower(msg), "eof")) + +local ok, a, b = xpcall(function() + return "a", "b" + end, + function(err) + assert(nil) + end) +assert(ok and a == "a" and b == "b") + +local ok, a, b = xpcall(function() + error("error!") + end, + function(err) + return err .. "!", "b" + end) +assert(not ok and string.find(a, "error!!") and b == nil) diff --git a/vendor/github.com/yuin/gopher-lua/_glua-tests/coroutine.lua b/vendor/github.com/yuin/gopher-lua/_glua-tests/coroutine.lua new file mode 100644 index 0000000000000000000000000000000000000000..fd6ee73b2b7abbcf4c6ec08380920ea722e389ed --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/_glua-tests/coroutine.lua @@ -0,0 +1,17 @@ +co = coroutine.wrap(function() + co() +end) + +local ok, msg = pcall(function() + co() +end) +assert(not ok and string.find(msg, "can not resume a running thread")) + +co = coroutine.wrap(function() + return 1 +end) +assert(co() == 1) +local ok, msg = pcall(function() + co() +end) +assert(not ok and string.find(msg, "can not resume a dead thread")) diff --git a/vendor/github.com/yuin/gopher-lua/_glua-tests/db.lua b/vendor/github.com/yuin/gopher-lua/_glua-tests/db.lua new file mode 100644 index 0000000000000000000000000000000000000000..b0de5ad2ba4f6bbe593888af6ea5cdf983ebaa50 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/_glua-tests/db.lua @@ -0,0 +1,86 @@ +-- debug lib tests +-- debug stuff are partially implemented; hooks are not supported. + +local function f1() +end +local env = {} +local mt = {} +debug.setfenv(f1, env) +assert(debug.getfenv(f1) == env) +debug.setmetatable(f1, mt) +assert(debug.getmetatable(f1) == mt) + +local function f2() + local info = debug.getinfo(1, "Slunf") + assert(info.currentline == 14) + assert(info.linedefined == 13) + assert(info.func == f2) + assert(info.lastlinedefined == 25) + assert(info.nups == 1) + assert(info.name == "f2") + assert(info.what == "Lua") + if string.find(_VERSION, "GopherLua") then + assert(info.source == "db.lua") + end +end +f2() + +local function f3() +end +local info = debug.getinfo(f3) +assert(info.currentline == -1) +assert(info.linedefined == 28) +assert(info.func == f3) +assert(info.lastlinedefined == 29) +assert(info.nups == 0) +assert(info.name == nil) +assert(info.what == "Lua") +if string.find(_VERSION, "GopherLua") then + assert(info.source == "db.lua") +end + +local function f4() + local a,b,c = 1,2,3 + local function f5() + local name, value = debug.getlocal(2, 2) + assert(debug.getlocal(2, 10) == nil) + assert(name == "b") + assert(value == 2) + name = debug.setlocal(2, 2, 10) + assert(debug.setlocal(2, 10, 10) == nil) + assert(name == "b") + + local d = a + local e = c + + local tb = debug.traceback("--msg--") + assert(string.find(tb, "\\-\\-msg\\-\\-")) + assert(string.find(tb, "in.*f5")) + assert(string.find(tb, "in.*f4")) + end + f5() + local name, value = debug.getupvalue(f5, 1) + assert(debug.getupvalue(f5, 10) == nil) + assert(name == "a") + assert(value == 1) + name = debug.setupvalue(f5, 1, 11) + assert(debug.setupvalue(f5, 10, 11) == nil) + assert(name == "a") + assert(a == 11) + + assert(b == 10) -- changed by debug.setlocal in f4 +end +f4() + +local ok, msg = pcall(function() + debug.getlocal(10, 1) +end) +assert(not ok and string.find(msg, "level out of range")) + +local ok, msg = pcall(function() + debug.setlocal(10, 1, 1) +end) +assert(not ok and string.find(msg, "level out of range")) + +assert(debug.getinfo(100) == nil) +assert(debug.getinfo(1, "a") == nil) diff --git a/vendor/github.com/yuin/gopher-lua/_glua-tests/issues.lua b/vendor/github.com/yuin/gopher-lua/_glua-tests/issues.lua new file mode 100644 index 0000000000000000000000000000000000000000..35ecf5da6a6d6a9a51eb1cee92a59323159cd244 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/_glua-tests/issues.lua @@ -0,0 +1,184 @@ + +-- issue #10 +local function inspect(options) + options = options or {} + return type(options) +end +assert(inspect(nil) == "table") + +local function inspect(options) + options = options or setmetatable({}, {__mode = "test"}) + return type(options) +end +assert(inspect(nil) == "table") + +-- issue #16 +local ok, msg = pcall(function() + local a = {} + a[nil] = 1 +end) +assert(not ok and string.find(msg, "table index is nil", 1, true)) + +-- issue #19 +local tbl = {1,2,3,4,5} +assert(#tbl == 5) +assert(table.remove(tbl) == 5) +assert(#tbl == 4) +assert(table.remove(tbl, 3) == 3) +assert(#tbl == 3) + +-- issue #24 +local tbl = {string.find('hello.world', '.', 0)} +assert(tbl[1] == 1 and tbl[2] == 1) +assert(string.sub('hello.world', 0, 2) == "he") + +-- issue 33 +local a,b +a = function () + pcall(function() + end) + coroutine.yield("a") + return b() +end + +b = function () + return "b" +end + +local co = coroutine.create(a) +assert(select(2, coroutine.resume(co)) == "a") +assert(select(2, coroutine.resume(co)) == "b") +assert(coroutine.status(co) == "dead") + +-- issue 37 +function test(a, b, c) + b = b or string.format("b%s", a) + c = c or string.format("c%s", a) + assert(a == "test") + assert(b == "btest") + assert(c == "ctest") +end +test("test") + +-- issue 39 +assert(string.match("ã‚ã„ã†ãˆãŠ", ".*ã‚.*") == "ã‚ã„ã†ãˆãŠ") +assert(string.match("ã‚ã„ã†ãˆãŠ", "ã‚ã„ã†ãˆãŠ") == "ã‚ã„ã†ãˆãŠ") + +-- issue 47 +assert(string.gsub("A\nA", ".", "A") == "AAA") + +-- issue 62 +local function level4() error("error!") end +local function level3() level4() end +local function level2() level3() end +local function level1() level2() end +local ok, result = xpcall(level1, function(err) + return debug.traceback("msg", 10) +end) +assert(result == [[msg +stack traceback:]]) +ok, result = xpcall(level1, function(err) + return debug.traceback("msg", 9) +end) +assert(result == string.gsub([[msg +stack traceback: +@TAB@[G]: ?]], "@TAB@", "\t")) +local ok, result = xpcall(level1, function(err) + return debug.traceback("msg", 0) +end) + +assert(result == string.gsub([[msg +stack traceback: +@TAB@[G]: in function 'traceback' +@TAB@issues.lua:87: in function +@TAB@[G]: in function 'error' +@TAB@issues.lua:71: in function 'level4' +@TAB@issues.lua:72: in function 'level3' +@TAB@issues.lua:73: in function 'level2' +@TAB@issues.lua:74: in function +@TAB@[G]: in function 'xpcall' +@TAB@issues.lua:86: in main chunk +@TAB@[G]: ?]], "@TAB@", "\t")) + +local ok, result = xpcall(level1, function(err) + return debug.traceback("msg", 3) +end) + +assert(result == string.gsub([[msg +stack traceback: +@TAB@issues.lua:71: in function 'level4' +@TAB@issues.lua:72: in function 'level3' +@TAB@issues.lua:73: in function 'level2' +@TAB@issues.lua:74: in function +@TAB@[G]: in function 'xpcall' +@TAB@issues.lua:103: in main chunk +@TAB@[G]: ?]], "@TAB@", "\t")) + +-- issue 81 +local tbl = { + [-1] = "a", + [0] = "b", + [1] = "c", +} +local a, b = next(tbl, nil) +assert( a == -1 and b == "a" or a == 0 and b == "b" or a == 1 and b == "c") +local a, b = next(tbl, a) +assert( a == -1 and b == "a" or a == 0 and b == "b" or a == 1 and b == "c") +local a, b = next(tbl, a) +assert( a == -1 and b == "a" or a == 0 and b == "b" or a == 1 and b == "c") +local a, b = next(tbl, a) +assert( a == nil and b == nil) + +local tbl = {'a', 'b'} +local a, b = next(tbl, nil) +assert(a == 1 and b == "a") +local a, b = next(tbl, a) +assert(a == 2 and b == "b") +local a, b = next(tbl, a) +assert(a == nil and b == nil) + +-- issue 82 +local cr = function() + return coroutine.wrap(function() + coroutine.yield(1, "a") + coroutine.yield(2, "b") + end) +end + +local f = cr() +local a, b = f() +assert(a == 1 and b == "a") +local a, b = f() +assert(a == 2 and b == "b") + +-- issue 91, 92 +local url = "www.aaa.bbb_abc123-321-cba_abc123" +assert(string.match(url, ".-([%w-]*)[.]*") == "www") + +local s = "hello.world" +assert(s:match("([^.]+).world") == "hello") + +local s = "hello-world" +assert(s:match("([^-]+)-world") == "hello") + +-- issue 93 +local t = {} +local ok, msg = pcall(function() t.notfound() end) +assert(not ok and string.find(msg, "attempt to call a non-function object", 1, true)) + +-- issue 150 +local util = { + fn = function() end +} +local b +local x = util.fn( + 1, + (b or {}).x) + +local s = [=[["a"]['b'][9] - ["a"]['b'][8] > ]=] +local result = {} +for i in s:gmatch([=[[[][^%s,]*[]]]=]) do + table.insert(result, i) +end +assert(result[1] == [=[["a"]['b'][9]]=]) +assert(result[2] == [=[["a"]['b'][8]]=]) diff --git a/vendor/github.com/yuin/gopher-lua/_glua-tests/math.lua b/vendor/github.com/yuin/gopher-lua/_glua-tests/math.lua new file mode 100644 index 0000000000000000000000000000000000000000..871d4041958c4b97d49a0dfa97c404cecafa4b1b --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/_glua-tests/math.lua @@ -0,0 +1,12 @@ +assert(math.fmod(13.5, 2) == 1.5) +assert(math.pow(7, 2) == 49) + +local ok, msg = pcall(function() + math.max() +end) +assert(not ok and string.find(msg, "wrong number of arguments")) + +local ok, msg = pcall(function() + math.min() +end) +assert(not ok and string.find(msg, "wrong number of arguments")) diff --git a/vendor/github.com/yuin/gopher-lua/_glua-tests/os.lua b/vendor/github.com/yuin/gopher-lua/_glua-tests/os.lua new file mode 100644 index 0000000000000000000000000000000000000000..4aa89c6f8c57dc88e4203c01ff23db8083bd23b9 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/_glua-tests/os.lua @@ -0,0 +1,18 @@ +local osname = "linux" +if string.find(os.getenv("OS") or "", "Windows") then + osname = "windows" +end + +if osname == "linux" then + -- travis ci failed to start date command? + -- assert(os.execute("date") == 0) + assert(os.execute("date -a") == 1) +else + assert(os.execute("date /T") == 0) + assert(os.execute("md") == 1) +end + +assert(os.getenv("PATH") ~= "") +assert(os.getenv("_____GLUATEST______") == nil) +assert(os.setenv("_____GLUATEST______", "1")) +assert(os.getenv("_____GLUATEST______") == "1") diff --git a/vendor/github.com/yuin/gopher-lua/_glua-tests/strings.lua b/vendor/github.com/yuin/gopher-lua/_glua-tests/strings.lua new file mode 100644 index 0000000000000000000000000000000000000000..273226d9250ae81d81498bfd7c4b4ed4baacaf8a --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/_glua-tests/strings.lua @@ -0,0 +1,13 @@ + +local ok, msg = pcall(function() + string.dump() +end) +assert(not ok and string.find(msg, "GopherLua does not support the string.dump")) +assert(string.find("","aaa") == nil) +assert(string.gsub("hello world", "(%w+)", "%1 %1 %c") == "hello hello %c world world %c") + +local ret1, ret2, ret3, ret4 = string.find("aaa bbb", "(%w+())") +assert(ret1 == 1) +assert(ret2 == 3) +assert(ret3 == "aaa") +assert(ret4 == 4) diff --git a/vendor/github.com/yuin/gopher-lua/_glua-tests/table.lua b/vendor/github.com/yuin/gopher-lua/_glua-tests/table.lua new file mode 100644 index 0000000000000000000000000000000000000000..80579e89cc8100b50592a2b5a0599d9b6228e093 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/_glua-tests/table.lua @@ -0,0 +1,37 @@ +local a = {} +assert(table.maxn(a) == 0) +a["key"] = 1 +assert(table.maxn(a) == 0) +table.insert(a, 10) +table.insert(a, 3, 10) +assert(table.maxn(a) == 3) + +local ok, msg = pcall(function() + table.insert(a) +end) +assert(not ok and string.find(msg, "wrong number of arguments")) + +a = {} +a["key0"] = "0" +a["key1"] = "1" +a[1] = 1 +a[2] = 2 +a[true] = "true" +a[false] = "false" +for k, v in pairs(a) do + if k == "key0" then + assert(v == "0") + elseif k == "key1" then + assert(v == "1") + elseif k == 1 then + assert(v == 1) + elseif k == 2 then + assert(v == 2) + elseif k == true then + assert(v == "true") + elseif k == false then + assert(v == "false") + else + error("unexpected key:" .. tostring(k)) + end +end diff --git a/vendor/github.com/yuin/gopher-lua/_glua-tests/vm.lua b/vendor/github.com/yuin/gopher-lua/_glua-tests/vm.lua new file mode 100644 index 0000000000000000000000000000000000000000..9c40b949f3242841b1646a790bc3af2401e4fc85 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/_glua-tests/vm.lua @@ -0,0 +1,136 @@ +for i, v in ipairs({"hoge", {}, function() end, true, nil}) do + local ok, msg = pcall(function() + print(-v) + end) + assert(not ok and string.find(msg, "__unm undefined")) +end + +assert(#"abc" == 3) +local tbl = {1,2,3} +setmetatable(tbl, {__len = function(self) + return 10 +end}) +assert(#tbl == 10) + +setmetatable(tbl, nil) +assert(#tbl == 3) + +local ok, msg = pcall(function() + return 1 < "hoge" +end) +assert(not ok and string.find(msg, "attempt to compare number with string")) + +local ok, msg = pcall(function() + return {} < (function() end) +end) +assert(not ok and string.find(msg, "attempt to compare table with function")) + +local ok, msg = pcall(function() + for n = nil,1 do + print(1) + end +end) +assert(not ok and string.find(msg, "for statement init must be a number")) + +local ok, msg = pcall(function() + for n = 1,nil do + print(1) + end +end) +assert(not ok and string.find(msg, "for statement limit must be a number")) + +local ok, msg = pcall(function() + for n = 1,10,nil do + print(1) + end +end) +assert(not ok and string.find(msg, "for statement step must be a number")) + +local ok, msg = pcall(function() + return {} + (function() end) +end) +assert(not ok and string.find(msg, "cannot perform add operation between table and function")) + +local ok, msg = pcall(function() + return {} .. (function() end) +end) +assert(not ok and string.find(msg, "cannot perform concat operation between table and function")) + +-- test table with initial elements over 511 +local bigtable = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,10} +assert(bigtable[601] == 10) + +local ok, msg = loadstring([[ + function main( + a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, + a17, a18, a19, a20, a21, a22, a23, a24, + a25, a26, a27, a28, a29, a30, a31, a32, + a33, a34, a35, a36, a37, a38, a39, a40, + a41, a42, a43, a44, a45, a46, a47, a48, + a49, a50, a51, a52, a53, a54, a55, a56, + a57, a58, a59, a60, a61, a62, a63, a64, + a65, a66, a67, a68, a69, a70, a71, a72, + a73, a74, a75, a76, a77, a78, a79, a80, + a81, a82, a83, a84, a85, a86, a87, a88, + a89, a90, a91, a92, a93, a94, a95, a96, + a97, a98, a99, a100, a101, a102, a103, + a104, a105, a106, a107, a108, a109, a110, + a111, a112, a113, a114, a115, a116, a117, + a118, a119, a120, a121, a122, a123, a124, + a125, a126, a127, a128, a129, a130, a131, + a132, a133, a134, a135, a136, a137, a138, + a139, a140, a141, a142, a143, a144, a145, + a146, a147, a148, a149, a150, a151, a152, + a153, a154, a155, a156, a157, a158, a159, + a160, a161, a162, a163, a164, a165, a166, + a167, a168, a169, a170, a171, a172, a173, + a174, a175, a176, a177, a178, a179, a180, + a181, a182, a183, a184, a185, a186, a187, + a188, a189, a190, a191, a192, a193, a194, + a195, a196, a197, a198, a199, a200, a201, + a202, a203, a204, a205, a206, a207, a208, + a209, a210, a211, a212, a213, a214, a215, + a216, a217, a218, a219, a220, a221, a222, + a223, a224, a225, a226, a227, a228, a229, + a230, a231, a232, a233, a234, a235, a236, + a237, a238, a239, a240, a241, a242, a243, + a244, a245, a246, a247, a248, a249, a250, + a251, a252, a253, a254, a255, a256, a257, + a258, a259, a260, a261, a262, a263, a264, + a265, a266, a267, a268, a269, a270, a271, + a272, a273, a274, a275, a276, a277, a278, + a279, a280, a281, a282, a283, a284, a285, + a286, a287, a288, a289, a290, a291, a292, + a293, a294, a295, a296, a297, a298, a299, + a300, a301, a302) end +]]) +assert(not ok and string.find(msg, "register overflow")) + +local ok, msg = loadstring([[ + function main() + local a = {...} + end +]]) +assert(not ok and string.find(msg, "cannot use '...' outside a vararg function")) diff --git a/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/README b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/README new file mode 100644 index 0000000000000000000000000000000000000000..e2d4b28501dc674ab27eece2a3f98d8393268373 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/README @@ -0,0 +1,41 @@ +This tarball contains the official test scripts for Lua 5.1. +Unlike Lua itself, these tests do not aim portability, small footprint, +or easy of use. (Their main goal is to try to crash Lua.) They are not +intended for general use. You are wellcome to use them, but expect to +have to "dirt your hands". + +The tarball should expand in the following contents: + - several .lua scripts with the tests + - a main "all.lua" Lua script that invokes all the other scripts + - a subdirectory "libs" with an empty subdirectory "libs/P1", + to be used by the scripts + - a subdirectory "etc" with some extra files + +To run the tests, do as follows: + +- go to the test directory + +- set LUA_PATH to "?;./?.lua" (or, better yet, set LUA_PATH to "./?.lua;;" + and LUA_INIT to "package.path = '?;'..package.path") + +- run "lua all.lua" + + +-------------------------------------------- +Internal tests +-------------------------------------------- + +Some tests need a special library, "testC", that gives access to +several internal structures in Lua. +This library is only available when Lua is compiled in debug mode. +The scripts automatically detect its absence and skip those tests. + +If you want to run these tests, move etc/ltests.c and etc/ltests.h to +the directory with the source Lua files, and recompile Lua with +the option -DLUA_USER_H='"ltests.h"' (or its equivalent to define +LUA_USER_H as the string "ltests.h", including the quotes). This +option not only adds the testC library, but it adds several other +internal tests as well. After the recompilation, run the tests +as before. + + diff --git a/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/all.lua b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/all.lua new file mode 100644 index 0000000000000000000000000000000000000000..8c4afaced73afb3b0f72756af4a6653996af4d88 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/all.lua @@ -0,0 +1,137 @@ +#!../lua + +math.randomseed(0) + +collectgarbage("setstepmul", 180) +collectgarbage("setpause", 190) + + +--[=[ + example of a long [comment], + [[spanning several [lines]]] + +]=] + +print("current path:\n " .. string.gsub(package.path, ";", "\n ")) + + +local msgs = {} +function Message (m) + print(m) + msgs[#msgs+1] = string.sub(m, 3, -3) +end + + +local c = os.clock() + +assert(os.setlocale"C") + +local T,print,gcinfo,format,write,assert,type = + T,print,gcinfo,string.format,io.write,assert,type + +local function formatmem (m) + if m < 1024 then return m + else + m = m/1024 - m/1024%1 + if m < 1024 then return m.."K" + else + m = m/1024 - m/1024%1 + return m.."M" + end + end +end + +local showmem = function () + if not T then + print(format(" ---- total memory: %s ----\n", formatmem(gcinfo()))) + else + T.checkmemory() + local a,b,c = T.totalmem() + local d,e = gcinfo() + print(format( + "\n ---- total memory: %s (%dK), max use: %s, blocks: %d\n", + formatmem(a), d, formatmem(c), b)) + end +end + + +-- +-- redefine dofile to run files through dump/undump +-- +dofile = function (n) + showmem() + local f = assert(loadfile(n)) + local b = string.dump(f) + f = assert(loadstring(b)) + return f() +end + +dofile('main.lua') + +do + local u = newproxy(true) + local newproxy, stderr = newproxy, io.stderr + getmetatable(u).__gc = function (o) + stderr:write'.' + newproxy(o) + end +end + +local f = assert(loadfile('gc.lua')) +f() +dofile('db.lua') +assert(dofile('calls.lua') == deep and deep) +dofile('strings.lua') +dofile('literals.lua') +assert(dofile('attrib.lua') == 27) +assert(dofile('locals.lua') == 5) +dofile('constructs.lua') +dofile('code.lua') +do + local f = coroutine.wrap(assert(loadfile('big.lua'))) + assert(f() == 'b') + assert(f() == 'a') +end +dofile('nextvar.lua') +dofile('pm.lua') +dofile('api.lua') +assert(dofile('events.lua') == 12) +dofile('vararg.lua') +dofile('closure.lua') +dofile('errors.lua') +dofile('math.lua') +dofile('sort.lua') +assert(dofile('verybig.lua') == 10); collectgarbage() +dofile('files.lua') + +if #msgs > 0 then + print("\ntests not performed:") + for i=1,#msgs do + print(msgs[i]) + end + print() +end + +print("final OK !!!") +print('cleaning all!!!!') + +debug.sethook(function (a) assert(type(a) == 'string') end, "cr") + +local _G, collectgarbage, showmem, print, format, clock = + _G, collectgarbage, showmem, print, format, os.clock + +local a={} +for n in pairs(_G) do a[n] = 1 end +a.tostring = nil +a.___Glob = nil +for n in pairs(a) do _G[n] = nil end + +a = nil +collectgarbage() +collectgarbage() +collectgarbage() +collectgarbage() +collectgarbage() +collectgarbage();showmem() + +print(format("\n\ntotal time: %.2f\n", clock()-c)) diff --git a/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/api.lua b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/api.lua new file mode 100644 index 0000000000000000000000000000000000000000..c2d262f07b3bbe3052105f93596f26141ab71eed --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/api.lua @@ -0,0 +1,711 @@ + +if T==nil then + (Message or print)('\a\n >>> testC not active: skipping API tests <<<\n\a') + return +end + + + +function tcheck (t1, t2) + table.remove(t1, 1) -- remove code + assert(table.getn(t1) == table.getn(t2)) + for i=1,table.getn(t1) do assert(t1[i] == t2[i]) end +end + +function pack(...) return arg end + + +print('testing C API') + +-- testing allignment +a = T.d2s(12458954321123) +assert(string.len(a) == 8) -- sizeof(double) +assert(T.s2d(a) == 12458954321123) + +a,b,c = T.testC("pushnum 1; pushnum 2; pushnum 3; return 2") +assert(a == 2 and b == 3 and not c) + +-- test that all trues are equal +a,b,c = T.testC("pushbool 1; pushbool 2; pushbool 0; return 3") +assert(a == b and a == true and c == false) +a,b,c = T.testC"pushbool 0; pushbool 10; pushnil;\ + tobool -3; tobool -3; tobool -3; return 3" +assert(a==0 and b==1 and c==0) + + +a,b,c = T.testC("gettop; return 2", 10, 20, 30, 40) +assert(a == 40 and b == 5 and not c) + +t = pack(T.testC("settop 5; gettop; return .", 2, 3)) +tcheck(t, {n=4,2,3}) + +t = pack(T.testC("settop 0; settop 15; return 10", 3, 1, 23)) +assert(t.n == 10 and t[1] == nil and t[10] == nil) + +t = pack(T.testC("remove -2; gettop; return .", 2, 3, 4)) +tcheck(t, {n=2,2,4}) + +t = pack(T.testC("insert -1; gettop; return .", 2, 3)) +tcheck(t, {n=2,2,3}) + +t = pack(T.testC("insert 3; gettop; return .", 2, 3, 4, 5)) +tcheck(t, {n=4,2,5,3,4}) + +t = pack(T.testC("replace 2; gettop; return .", 2, 3, 4, 5)) +tcheck(t, {n=3,5,3,4}) + +t = pack(T.testC("replace -2; gettop; return .", 2, 3, 4, 5)) +tcheck(t, {n=3,2,3,5}) + +t = pack(T.testC("remove 3; gettop; return .", 2, 3, 4, 5)) +tcheck(t, {n=3,2,4,5}) + +t = pack(T.testC("insert 3; pushvalue 3; remove 3; pushvalue 2; remove 2; \ + insert 2; pushvalue 1; remove 1; insert 1; \ + insert -2; pushvalue -2; remove -3; gettop; return .", + 2, 3, 4, 5, 10, 40, 90)) +tcheck(t, {n=7,2,3,4,5,10,40,90}) + +t = pack(T.testC("concat 5; gettop; return .", "alo", 2, 3, "joao", 12)) +tcheck(t, {n=1,"alo23joao12"}) + +-- testing MULTRET +t = pack(T.testC("rawcall 2,-1; gettop; return .", + function (a,b) return 1,2,3,4,a,b end, "alo", "joao")) +tcheck(t, {n=6,1,2,3,4,"alo", "joao"}) + +do -- test returning more results than fit in the caller stack + local a = {} + for i=1,1000 do a[i] = true end; a[999] = 10 + local b = T.testC([[call 1 -1; pop 1; tostring -1; return 1]], unpack, a) + assert(b == "10") +end + + +-- testing lessthan +assert(T.testC("lessthan 2 5, return 1", 3, 2, 2, 4, 2, 2)) +assert(T.testC("lessthan 5 2, return 1", 4, 2, 2, 3, 2, 2)) +assert(not T.testC("lessthan 2 -3, return 1", "4", "2", "2", "3", "2", "2")) +assert(not T.testC("lessthan -3 2, return 1", "3", "2", "2", "4", "2", "2")) + +local b = {__lt = function (a,b) return a[1] < b[1] end} +local a1,a3,a4 = setmetatable({1}, b), + setmetatable({3}, b), + setmetatable({4}, b) +assert(T.testC("lessthan 2 5, return 1", a3, 2, 2, a4, 2, 2)) +assert(T.testC("lessthan 5 -6, return 1", a4, 2, 2, a3, 2, 2)) +a,b = T.testC("lessthan 5 -6, return 2", a1, 2, 2, a3, 2, 20) +assert(a == 20 and b == false) + + +-- testing lua_is + +function count (x, n) + n = n or 2 + local prog = [[ + isnumber %d; + isstring %d; + isfunction %d; + iscfunction %d; + istable %d; + isuserdata %d; + isnil %d; + isnull %d; + return 8 + ]] + prog = string.format(prog, n, n, n, n, n, n, n, n) + local a,b,c,d,e,f,g,h = T.testC(prog, x) + return a+b+c+d+e+f+g+(100*h) +end + +assert(count(3) == 2) +assert(count('alo') == 1) +assert(count('32') == 2) +assert(count({}) == 1) +assert(count(print) == 2) +assert(count(function () end) == 1) +assert(count(nil) == 1) +assert(count(io.stdin) == 1) +assert(count(nil, 15) == 100) + +-- testing lua_to... + +function to (s, x, n) + n = n or 2 + return T.testC(string.format("%s %d; return 1", s, n), x) +end + +assert(to("tostring", {}) == nil) +assert(to("tostring", "alo") == "alo") +assert(to("tostring", 12) == "12") +assert(to("tostring", 12, 3) == nil) +assert(to("objsize", {}) == 0) +assert(to("objsize", "alo\0\0a") == 6) +assert(to("objsize", T.newuserdata(0)) == 0) +assert(to("objsize", T.newuserdata(101)) == 101) +assert(to("objsize", 12) == 2) +assert(to("objsize", 12, 3) == 0) +assert(to("tonumber", {}) == 0) +assert(to("tonumber", "12") == 12) +assert(to("tonumber", "s2") == 0) +assert(to("tonumber", 1, 20) == 0) +a = to("tocfunction", math.deg) +assert(a(3) == math.deg(3) and a ~= math.deg) + + +-- testing errors + +a = T.testC([[ + loadstring 2; call 0,1; + pushvalue 3; insert -2; call 1, 1; + call 0, 0; + return 1 +]], "x=150", function (a) assert(a==nil); return 3 end) + +assert(type(a) == 'string' and x == 150) + +function check3(p, ...) + assert(arg.n == 3) + assert(string.find(arg[3], p)) +end +check3(":1:", T.testC("loadstring 2; gettop; return .", "x=")) +check3("cannot read", T.testC("loadfile 2; gettop; return .", ".")) +check3("cannot open xxxx", T.testC("loadfile 2; gettop; return .", "xxxx")) + +-- testing table access + +a = {x=0, y=12} +x, y = T.testC("gettable 2; pushvalue 4; gettable 2; return 2", + a, 3, "y", 4, "x") +assert(x == 0 and y == 12) +T.testC("settable -5", a, 3, 4, "x", 15) +assert(a.x == 15) +a[a] = print +x = T.testC("gettable 2; return 1", a) -- table and key are the same object! +assert(x == print) +T.testC("settable 2", a, "x") -- table and key are the same object! +assert(a[a] == "x") + +b = setmetatable({p = a}, {}) +getmetatable(b).__index = function (t, i) return t.p[i] end +k, x = T.testC("gettable 3, return 2", 4, b, 20, 35, "x") +assert(x == 15 and k == 35) +getmetatable(b).__index = function (t, i) return a[i] end +getmetatable(b).__newindex = function (t, i,v ) a[i] = v end +y = T.testC("insert 2; gettable -5; return 1", 2, 3, 4, "y", b) +assert(y == 12) +k = T.testC("settable -5, return 1", b, 3, 4, "x", 16) +assert(a.x == 16 and k == 4) +a[b] = 'xuxu' +y = T.testC("gettable 2, return 1", b) +assert(y == 'xuxu') +T.testC("settable 2", b, 19) +assert(a[b] == 19) + +-- testing next +a = {} +t = pack(T.testC("next; gettop; return .", a, nil)) +tcheck(t, {n=1,a}) +a = {a=3} +t = pack(T.testC("next; gettop; return .", a, nil)) +tcheck(t, {n=3,a,'a',3}) +t = pack(T.testC("next; pop 1; next; gettop; return .", a, nil)) +tcheck(t, {n=1,a}) + + + +-- testing upvalues + +do + local A = T.testC[[ pushnum 10; pushnum 20; pushcclosure 2; return 1]] + t, b, c = A([[pushvalue U0; pushvalue U1; pushvalue U2; return 3]]) + assert(b == 10 and c == 20 and type(t) == 'table') + a, b = A([[tostring U3; tonumber U4; return 2]]) + assert(a == nil and b == 0) + A([[pushnum 100; pushnum 200; replace U2; replace U1]]) + b, c = A([[pushvalue U1; pushvalue U2; return 2]]) + assert(b == 100 and c == 200) + A([[replace U2; replace U1]], {x=1}, {x=2}) + b, c = A([[pushvalue U1; pushvalue U2; return 2]]) + assert(b.x == 1 and c.x == 2) + T.checkmemory() +end + +local f = T.testC[[ pushnum 10; pushnum 20; pushcclosure 2; return 1]] +assert(T.upvalue(f, 1) == 10 and + T.upvalue(f, 2) == 20 and + T.upvalue(f, 3) == nil) +T.upvalue(f, 2, "xuxu") +assert(T.upvalue(f, 2) == "xuxu") + + +-- testing environments + +assert(T.testC"pushvalue G; return 1" == _G) +assert(T.testC"pushvalue E; return 1" == _G) +local a = {} +T.testC("replace E; return 1", a) +assert(T.testC"pushvalue G; return 1" == _G) +assert(T.testC"pushvalue E; return 1" == a) +assert(debug.getfenv(T.testC) == a) +assert(debug.getfenv(T.upvalue) == _G) +-- userdata inherit environment +local u = T.testC"newuserdata 0; return 1" +assert(debug.getfenv(u) == a) +-- functions inherit environment +u = T.testC"pushcclosure 0; return 1" +assert(debug.getfenv(u) == a) +debug.setfenv(T.testC, _G) +assert(T.testC"pushvalue E; return 1" == _G) + +local b = newproxy() +assert(debug.getfenv(b) == _G) +assert(debug.setfenv(b, a)) +assert(debug.getfenv(b) == a) + + + +-- testing locks (refs) + +-- reuse of references +local i = T.ref{} +T.unref(i) +assert(T.ref{} == i) + +Arr = {} +Lim = 100 +for i=1,Lim do -- lock many objects + Arr[i] = T.ref({}) +end + +assert(T.ref(nil) == -1 and T.getref(-1) == nil) +T.unref(-1); T.unref(-1) + +for i=1,Lim do -- unlock all them + T.unref(Arr[i]) +end + +function printlocks () + local n = T.testC("gettable R; return 1", "n") + print("n", n) + for i=0,n do + print(i, T.testC("gettable R; return 1", i)) + end +end + + +for i=1,Lim do -- lock many objects + Arr[i] = T.ref({}) +end + +for i=1,Lim,2 do -- unlock half of them + T.unref(Arr[i]) +end + +assert(type(T.getref(Arr[2])) == 'table') + + +assert(T.getref(-1) == nil) + + +a = T.ref({}) + +collectgarbage() + +assert(type(T.getref(a)) == 'table') + + +-- colect in cl the `val' of all collected userdata +tt = {} +cl = {n=0} +A = nil; B = nil +local F +F = function (x) + local udval = T.udataval(x) + table.insert(cl, udval) + local d = T.newuserdata(100) -- cria lixo + d = nil + assert(debug.getmetatable(x).__gc == F) + loadstring("table.insert({}, {})")() -- cria mais lixo + collectgarbage() -- forca coleta de lixo durante coleta! + assert(debug.getmetatable(x).__gc == F) -- coleta anterior nao melou isso? + local dummy = {} -- cria lixo durante coleta + if A ~= nil then + assert(type(A) == "userdata") + assert(T.udataval(A) == B) + debug.getmetatable(A) -- just acess it + end + A = x -- ressucita userdata + B = udval + return 1,2,3 +end +tt.__gc = F + +-- test whether udate collection frees memory in the right time +do + collectgarbage(); + collectgarbage(); + local x = collectgarbage("count"); + local a = T.newuserdata(5001) + assert(T.testC("objsize 2; return 1", a) == 5001) + assert(collectgarbage("count") >= x+4) + a = nil + collectgarbage(); + assert(collectgarbage("count") <= x+1) + -- udata without finalizer + x = collectgarbage("count") + collectgarbage("stop") + for i=1,1000 do newproxy(false) end + assert(collectgarbage("count") > x+10) + collectgarbage() + assert(collectgarbage("count") <= x+1) + -- udata with finalizer + x = collectgarbage("count") + collectgarbage() + collectgarbage("stop") + a = newproxy(true) + getmetatable(a).__gc = function () end + for i=1,1000 do newproxy(a) end + assert(collectgarbage("count") >= x+10) + collectgarbage() -- this collection only calls TM, without freeing memory + assert(collectgarbage("count") >= x+10) + collectgarbage() -- now frees memory + assert(collectgarbage("count") <= x+1) +end + + +collectgarbage("stop") + +-- create 3 userdatas with tag `tt' +a = T.newuserdata(0); debug.setmetatable(a, tt); na = T.udataval(a) +b = T.newuserdata(0); debug.setmetatable(b, tt); nb = T.udataval(b) +c = T.newuserdata(0); debug.setmetatable(c, tt); nc = T.udataval(c) + +-- create userdata without meta table +x = T.newuserdata(4) +y = T.newuserdata(0) + +assert(debug.getmetatable(x) == nil and debug.getmetatable(y) == nil) + +d=T.ref(a); +e=T.ref(b); +f=T.ref(c); +t = {T.getref(d), T.getref(e), T.getref(f)} +assert(t[1] == a and t[2] == b and t[3] == c) + +t=nil; a=nil; c=nil; +T.unref(e); T.unref(f) + +collectgarbage() + +-- check that unref objects have been collected +assert(table.getn(cl) == 1 and cl[1] == nc) + +x = T.getref(d) +assert(type(x) == 'userdata' and debug.getmetatable(x) == tt) +x =nil +tt.b = b -- create cycle +tt=nil -- frees tt for GC +A = nil +b = nil +T.unref(d); +n5 = T.newuserdata(0) +debug.setmetatable(n5, {__gc=F}) +n5 = T.udataval(n5) +collectgarbage() +assert(table.getn(cl) == 4) +-- check order of collection +assert(cl[2] == n5 and cl[3] == nb and cl[4] == na) + + +a, na = {}, {} +for i=30,1,-1 do + a[i] = T.newuserdata(0) + debug.setmetatable(a[i], {__gc=F}) + na[i] = T.udataval(a[i]) +end +cl = {} +a = nil; collectgarbage() +assert(table.getn(cl) == 30) +for i=1,30 do assert(cl[i] == na[i]) end +na = nil + + +for i=2,Lim,2 do -- unlock the other half + T.unref(Arr[i]) +end + +x = T.newuserdata(41); debug.setmetatable(x, {__gc=F}) +assert(T.testC("objsize 2; return 1", x) == 41) +cl = {} +a = {[x] = 1} +x = T.udataval(x) +collectgarbage() +-- old `x' cannot be collected (`a' still uses it) +assert(table.getn(cl) == 0) +for n in pairs(a) do a[n] = nil end +collectgarbage() +assert(table.getn(cl) == 1 and cl[1] == x) -- old `x' must be collected + +-- testing lua_equal +assert(T.testC("equal 2 4; return 1", print, 1, print, 20)) +assert(T.testC("equal 3 2; return 1", 'alo', "alo")) +assert(T.testC("equal 2 3; return 1", nil, nil)) +assert(not T.testC("equal 2 3; return 1", {}, {})) +assert(not T.testC("equal 2 3; return 1")) +assert(not T.testC("equal 2 3; return 1", 3)) + +-- testing lua_equal with fallbacks +do + local map = {} + local t = {__eq = function (a,b) return map[a] == map[b] end} + local function f(x) + local u = T.newuserdata(0) + debug.setmetatable(u, t) + map[u] = x + return u + end + assert(f(10) == f(10)) + assert(f(10) ~= f(11)) + assert(T.testC("equal 2 3; return 1", f(10), f(10))) + assert(not T.testC("equal 2 3; return 1", f(10), f(20))) + t.__eq = nil + assert(f(10) ~= f(10)) +end + +print'+' + + + +------------------------------------------------------------------------- +do -- testing errors during GC + local a = {} + for i=1,20 do + a[i] = T.newuserdata(i) -- creates several udata + end + for i=1,20,2 do -- mark half of them to raise error during GC + debug.setmetatable(a[i], {__gc = function (x) error("error inside gc") end}) + end + for i=2,20,2 do -- mark the other half to count and to create more garbage + debug.setmetatable(a[i], {__gc = function (x) loadstring("A=A+1")() end}) + end + _G.A = 0 + a = 0 + while 1 do + if xpcall(collectgarbage, function (s) a=a+1 end) then + break -- stop if no more errors + end + end + assert(a == 10) -- number of errors + assert(A == 10) -- number of normal collections +end +------------------------------------------------------------------------- +-- test for userdata vals +do + local a = {}; local lim = 30 + for i=0,lim do a[i] = T.pushuserdata(i) end + for i=0,lim do assert(T.udataval(a[i]) == i) end + for i=0,lim do assert(T.pushuserdata(i) == a[i]) end + for i=0,lim do a[a[i]] = i end + for i=0,lim do a[T.pushuserdata(i)] = i end + assert(type(tostring(a[1])) == "string") +end + + +------------------------------------------------------------------------- +-- testing multiple states +T.closestate(T.newstate()); +L1 = T.newstate() +assert(L1) +assert(pack(T.doremote(L1, "function f () return 'alo', 3 end; f()")).n == 0) + +a, b = T.doremote(L1, "return f()") +assert(a == 'alo' and b == '3') + +T.doremote(L1, "_ERRORMESSAGE = nil") +-- error: `sin' is not defined +a, b = T.doremote(L1, "return sin(1)") +assert(a == nil and b == 2) -- 2 == run-time error + +-- error: syntax error +a, b, c = T.doremote(L1, "return a+") +assert(a == nil and b == 3 and type(c) == "string") -- 3 == syntax error + +T.loadlib(L1) +a, b = T.doremote(L1, [[ + a = strlibopen() + a = packageopen() + a = baselibopen(); assert(a == _G and require("_G") == a) + a = iolibopen(); assert(type(a.read) == "function") + assert(require("io") == a) + a = tablibopen(); assert(type(a.insert) == "function") + a = dblibopen(); assert(type(a.getlocal) == "function") + a = mathlibopen(); assert(type(a.sin) == "function") + return string.sub('okinama', 1, 2) +]]) +assert(a == "ok") + +T.closestate(L1); + +L1 = T.newstate() +T.loadlib(L1) +T.doremote(L1, "a = {}") +T.testC(L1, [[pushstring a; gettable G; pushstring x; pushnum 1; + settable -3]]) +assert(T.doremote(L1, "return a.x") == "1") + +T.closestate(L1) + +L1 = nil + +print('+') + +------------------------------------------------------------------------- +-- testing memory limits +------------------------------------------------------------------------- +collectgarbage() +T.totalmem(T.totalmem()+5000) -- set low memory limit (+5k) +assert(not pcall(loadstring"local a={}; for i=1,100000 do a[i]=i end")) +T.totalmem(1000000000) -- restore high limit + + +local function stack(x) if x>0 then stack(x-1) end end + +-- test memory errors; increase memory limit in small steps, so that +-- we get memory errors in different parts of a given task, up to there +-- is enough memory to complete the task without errors +function testamem (s, f) + collectgarbage() + stack(10) -- ensure minimum stack size + local M = T.totalmem() + local oldM = M + local a,b = nil + while 1 do + M = M+3 -- increase memory limit in small steps + T.totalmem(M) + a, b = pcall(f) + if a and b then break end -- stop when no more errors + collectgarbage() + if not a and not string.find(b, "memory") then -- `real' error? + T.totalmem(1000000000) -- restore high limit + error(b, 0) + end + end + T.totalmem(1000000000) -- restore high limit + print("\nlimit for " .. s .. ": " .. M-oldM) + return b +end + + +-- testing memory errors when creating a new state + +b = testamem("state creation", T.newstate) +T.closestate(b); -- close new state + + +-- testing threads + +function expand (n,s) + if n==0 then return "" end + local e = string.rep("=", n) + return string.format("T.doonnewstack([%s[ %s;\n collectgarbage(); %s]%s])\n", + e, s, expand(n-1,s), e) +end + +G=0; collectgarbage(); a =collectgarbage("count") +loadstring(expand(20,"G=G+1"))() +assert(G==20); collectgarbage(); -- assert(gcinfo() <= a+1) + +testamem("thread creation", function () + return T.doonnewstack("x=1") == 0 -- try to create thread +end) + + +-- testing memory x compiler + +testamem("loadstring", function () + return loadstring("x=1") -- try to do a loadstring +end) + + +local testprog = [[ +local function foo () return end +local t = {"x"} +a = "aaa" +for _, v in ipairs(t) do a=a..v end +return true +]] + +-- testing memory x dofile +_G.a = nil +local t =os.tmpname() +local f = assert(io.open(t, "w")) +f:write(testprog) +f:close() +testamem("dofile", function () + local a = loadfile(t) + return a and a() +end) +assert(os.remove(t)) +assert(_G.a == "aaax") + + +-- other generic tests + +testamem("string creation", function () + local a, b = string.gsub("alo alo", "(a)", function (x) return x..'b' end) + return (a == 'ablo ablo') +end) + +testamem("dump/undump", function () + local a = loadstring(testprog) + local b = a and string.dump(a) + a = b and loadstring(b) + return a and a() +end) + +local t = os.tmpname() +testamem("file creation", function () + local f = assert(io.open(t, 'w')) + assert (not io.open"nomenaoexistente") + io.close(f); + return not loadfile'nomenaoexistente' +end) +assert(os.remove(t)) + +testamem("table creation", function () + local a, lim = {}, 10 + for i=1,lim do a[i] = i; a[i..'a'] = {} end + return (type(a[lim..'a']) == 'table' and a[lim] == lim) +end) + +local a = 1 +close = nil +testamem("closure creation", function () + function close (b,c) + return function (x) return a+b+c+x end + end + return (close(2,3)(4) == 10) +end) + +testamem("coroutines", function () + local a = coroutine.wrap(function () + coroutine.yield(string.rep("a", 10)) + return {} + end) + assert(string.len(a()) == 10) + return a() +end) + +print'+' + +-- testing some auxlib functions +assert(T.gsub("alo.alo.uhuh.", ".", "//") == "alo//alo//uhuh//") +assert(T.gsub("alo.alo.uhuh.", "alo", "//") == "//.//.uhuh.") +assert(T.gsub("", "alo", "//") == "") +assert(T.gsub("...", ".", "/.") == "/././.") +assert(T.gsub("...", "...", "") == "") + + +print'OK' + diff --git a/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/attrib.lua b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/attrib.lua new file mode 100644 index 0000000000000000000000000000000000000000..c03163678e1f0f8d8de215336c4c099d6a252856 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/attrib.lua @@ -0,0 +1,341 @@ +do --[ + +print "testing require" + +assert(require"string" == string) +assert(require"math" == math) +assert(require"table" == table) +assert(require"io" == io) +assert(require"os" == os) +assert(require"debug" == debug) +assert(require"coroutine" == coroutine) + +assert(type(package.path) == "string") +assert(type(package.cpath) == "string") +assert(type(package.loaded) == "table") +assert(type(package.preload) == "table") + + +local DIR = "libs/" + +local function createfiles (files, preextras, posextras) + for n,c in pairs(files) do + io.output(DIR..n) + io.write(string.format(preextras, n)) + io.write(c) + io.write(string.format(posextras, n)) + io.close(io.output()) + end +end + +function removefiles (files) + for n in pairs(files) do + os.remove(DIR..n) + end +end + +local files = { + ["A.lua"] = "", + ["B.lua"] = "assert(...=='B');require 'A'", + ["A.lc"] = "", + ["A"] = "", + ["L"] = "", + ["XXxX"] = "", + ["C.lua"] = "package.loaded[...] = 25; require'C'" +} + +AA = nil +local extras = [[ +NAME = '%s' +REQUIRED = ... +return AA]] + +createfiles(files, "", extras) + + +local oldpath = package.path + +package.path = string.gsub("D/?.lua;D/?.lc;D/?;D/??x?;D/L", "D/", DIR) + +local try = function (p, n, r) + NAME = nil + local rr = require(p) + assert(NAME == n) + assert(REQUIRED == p) + assert(rr == r) +end + +assert(require"C" == 25) +assert(require"C" == 25) +AA = nil +try('B', 'B.lua', true) +assert(package.loaded.B) +assert(require"B" == true) +assert(package.loaded.A) +package.loaded.A = nil +try('B', nil, true) -- should not reload package +try('A', 'A.lua', true) +package.loaded.A = nil +os.remove(DIR..'A.lua') +AA = {} +try('A', 'A.lc', AA) -- now must find second option +assert(require("A") == AA) +AA = false +try('K', 'L', false) -- default option +try('K', 'L', false) -- default option (should reload it) +assert(rawget(_G, "_REQUIREDNAME") == nil) + +AA = "x" +try("X", "XXxX", AA) + + +removefiles(files) + + +-- testing require of sub-packages + +package.path = string.gsub("D/?.lua;D/?/init.lua", "D/", DIR) + +files = { + ["P1/init.lua"] = "AA = 10", + ["P1/xuxu.lua"] = "AA = 20", +} + +createfiles(files, "module(..., package.seeall)\n", "") +AA = 0 + +local m = assert(require"P1") +assert(m == P1 and m._NAME == "P1" and AA == 0 and m.AA == 10) +assert(require"P1" == P1 and P1 == m) +assert(require"P1" == P1) +assert(P1._PACKAGE == "") + +local m = assert(require"P1.xuxu") +assert(m == P1.xuxu and m._NAME == "P1.xuxu" and AA == 0 and m.AA == 20) +assert(require"P1.xuxu" == P1.xuxu and P1.xuxu == m) +assert(require"P1.xuxu" == P1.xuxu) +assert(require"P1" == P1) +assert(P1.xuxu._PACKAGE == "P1.") +assert(P1.AA == 10 and P1._PACKAGE == "") +assert(P1._G == _G and P1.xuxu._G == _G) + + + +removefiles(files) + + +package.path = "" +assert(not pcall(require, "file_does_not_exist")) +package.path = "??\0?" +assert(not pcall(require, "file_does_not_exist1")) + +package.path = oldpath + +-- check 'require' error message +-- local fname = "file_does_not_exist2" +-- local m, err = pcall(require, fname) +-- for t in string.gmatch(package.path..";"..package.cpath, "[^;]+") do +-- t = string.gsub(t, "?", fname) +-- print(t, err) +-- assert(string.find(err, t, 1, true)) +-- end + + +local function import(...) + local f = {...} + return function (m) + for i=1, #f do m[f[i]] = _G[f[i]] end + end +end + +local assert, module, package = assert, module, package +X = nil; x = 0; assert(_G.x == 0) -- `x' must be a global variable +module"X"; x = 1; assert(_M.x == 1) +module"X.a.b.c"; x = 2; assert(_M.x == 2) +module("X.a.b", package.seeall); x = 3 +assert(X._NAME == "X" and X.a.b.c._NAME == "X.a.b.c" and X.a.b._NAME == "X.a.b") +assert(X._M == X and X.a.b.c._M == X.a.b.c and X.a.b._M == X.a.b) +assert(X.x == 1 and X.a.b.c.x == 2 and X.a.b.x == 3) +assert(X._PACKAGE == "" and X.a.b.c._PACKAGE == "X.a.b." and + X.a.b._PACKAGE == "X.a.") +assert(_PACKAGE.."c" == "X.a.c") +assert(X.a._NAME == nil and X.a._M == nil) +module("X.a", import("X")) ; x = 4 +assert(X.a._NAME == "X.a" and X.a.x == 4 and X.a._M == X.a) +module("X.a.b", package.seeall); assert(x == 3); x = 5 +assert(_NAME == "X.a.b" and X.a.b.x == 5) + +assert(X._G == nil and X.a._G == nil and X.a.b._G == _G and X.a.b.c._G == nil) + +setfenv(1, _G) +assert(x == 0) + +assert(not pcall(module, "x")) +assert(not pcall(module, "math.sin")) + + +-- testing C libraries + + +local p = "" -- On Mac OS X, redefine this to "_" + +-- assert(loadlib == package.loadlib) -- only for compatibility +-- local f, err, when = package.loadlib("libs/lib1.so", p.."luaopen_lib1") +local f = nil +if not f then + (Message or print)('\a\n >>> cannot load dynamic library <<<\n\a') + print(err, when) +else + f() -- open library + assert(require("lib1") == lib1) + collectgarbage() + assert(lib1.id("x") == "x") + f = assert(package.loadlib("libs/lib1.so", p.."anotherfunc")) + assert(f(10, 20) == "1020\n") + f, err, when = package.loadlib("libs/lib1.so", p.."xuxu") + assert(not f and type(err) == "string" and when == "init") + package.cpath = "libs/?.so" + require"lib2" + assert(lib2.id("x") == "x") + local fs = require"lib1.sub" + assert(fs == lib1.sub and next(lib1.sub) == nil) + module("lib2", package.seeall) + f = require"-lib2" + assert(f.id("x") == "x" and _M == f and _NAME == "lib2") + module("lib1.sub", package.seeall) + assert(_M == fs) + setfenv(1, _G) + +end +-- f, err, when = package.loadlib("donotexist", p.."xuxu") +-- assert(not f and type(err) == "string" and (when == "open" or when == "absent")) + + +-- testing preload + +do + local p = package + package = {} + p.preload.pl = function (...) + module(...) + function xuxu (x) return x+20 end + end + + require"pl" + assert(require"pl" == pl) + assert(pl.xuxu(10) == 30) + + package = p + assert(type(package.path) == "string") +end + + + +end --] + +print('+') + +print("testing assignments, logical operators, and constructors") + +local res, res2 = 27 + +a, b = 1, 2+3 +assert(a==1 and b==5) +a={} +function f() return 10, 11, 12 end +a.x, b, a[1] = 1, 2, f() +assert(a.x==1 and b==2 and a[1]==10) +a[f()], b, a[f()+3] = f(), a, 'x' +assert(a[10] == 10 and b == a and a[13] == 'x') + +do + local f = function (n) local x = {}; for i=1,n do x[i]=i end; + return unpack(x) end; + local a,b,c + a,b = 0, f(1) + assert(a == 0 and b == 1) + A,b = 0, f(1) + assert(A == 0 and b == 1) + a,b,c = 0,5,f(4) + assert(a==0 and b==5 and c==1) + a,b,c = 0,5,f(0) + assert(a==0 and b==5 and c==nil) +end + + +a, b, c, d = 1 and nil, 1 or nil, (1 and (nil or 1)), 6 +assert(not a and b and c and d==6) + +d = 20 +a, b, c, d = f() +assert(a==10 and b==11 and c==12 and d==nil) +a,b = f(), 1, 2, 3, f() +assert(a==10 and b==1) + +assert(ab == true) +assert((10 and 2) == 2) +assert((10 or 2) == 10) +assert((10 or assert(nil)) == 10) +assert(not (nil and assert(nil))) +assert((nil or "alo") == "alo") +assert((nil and 10) == nil) +assert((false and 10) == false) +assert((true or 10) == true) +assert((false or 10) == 10) +assert(false ~= nil) +assert(nil ~= false) +assert(not nil == true) +assert(not not nil == false) +assert(not not 1 == true) +assert(not not a == true) +assert(not not (6 or nil) == true) +assert(not not (nil and 56) == false) +assert(not not (nil and true) == false) +print('+') + +a = {} +a[true] = 20 +a[false] = 10 +assert(a[1<2] == 20 and a[1>2] == 10) + +function f(a) return a end + +local a = {} +for i=3000,-3000,-1 do a[i] = i; end +a[10e30] = "alo"; a[true] = 10; a[false] = 20 +assert(a[10e30] == 'alo' and a[not 1] == 20 and a[10<20] == 10) +for i=3000,-3000,-1 do assert(a[i] == i); end +a[print] = assert +a[f] = print +a[a] = a +assert(a[a][a][a][a][print] == assert) +a[print](a[a[f]] == a[print]) +a = nil + +a = {10,9,8,7,6,5,4,3,2; [-3]='a', [f]=print, a='a', b='ab'} +a, a.x, a.y = a, a[-3] +assert(a[1]==10 and a[-3]==a.a and a[f]==print and a.x=='a' and not a.y) +a[1], f(a)[2], b, c = {['alo']=assert}, 10, a[1], a[f], 6, 10, 23, f(a), 2 +a[1].alo(a[2]==10 and b==10 and c==print) + +a[2^31] = 10; a[2^31+1] = 11; a[-2^31] = 12; +a[2^32] = 13; a[-2^32] = 14; a[2^32+1] = 15; a[10^33] = 16; + +assert(a[2^31] == 10 and a[2^31+1] == 11 and a[-2^31] == 12 and + a[2^32] == 13 and a[-2^32] == 14 and a[2^32+1] == 15 and + a[10^33] == 16) + +a = nil + + +-- do +-- local a,i,j,b +-- a = {'a', 'b'}; i=1; j=2; b=a +-- i, a[i], a, j, a[j], a[i+j] = j, i, i, b, j, i +-- assert(i == 2 and b[1] == 1 and a == 1 and j == b and b[2] == 2 and +-- b[3] == 1) +-- end + +print('OK') + +return res diff --git a/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/big.lua b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/big.lua new file mode 100644 index 0000000000000000000000000000000000000000..4b03c2bc8ac65997364d0b6bc2638d0d277db53c --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/big.lua @@ -0,0 +1,382 @@ +print "testing string length overflow" + +local longs = string.rep("\0", 2^25) +local function catter (i) + return assert(loadstring( + string.format("return function(a) return a%s end", + string.rep("..a", i-1))))() +end +rep129 = catter(129) +local a, b = pcall(rep129, longs) +print(b) +assert(not a and string.find(b, "overflow")) +print('+') + + +require "checktable" + +--[[ lots of empty lines (to force SETLINEW) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +--]] + + +a,b = nil,nil +while not b do +if a then +b = { -- lots of strings (to force JMPW and PUSHCONSTANTW) +"n1", "n2", "n3", "n4", "n5", "n6", "n7", "n8", "n9", "n10", +"n11", "n12", "j301", "j302", "j303", "j304", "j305", "j306", "j307", "j308", +"j309", "a310", "n311", "n312", "n313", "n314", "n315", "n316", "n317", "n318", +"n319", "n320", "n321", "n322", "n323", "n324", "n325", "n326", "n327", "n328", +"a329", "n330", "n331", "n332", "n333", "n334", "n335", "n336", "n337", "n338", +"n339", "n340", "n341", "z342", "n343", "n344", "n345", "n346", "n347", "n348", +"n349", "n350", "n351", "n352", "r353", "n354", "n355", "n356", "n357", "n358", +"n359", "n360", "n361", "n362", "n363", "n364", "n365", "n366", "z367", "n368", +"n369", "n370", "n371", "n372", "n373", "n374", "n375", "a376", "n377", "n378", +"n379", "n380", "n381", "n382", "n383", "n384", "n385", "n386", "n387", "n388", +"n389", "n390", "n391", "n392", "n393", "n394", "n395", "n396", "n397", "n398", +"n399", "n400", "n13", "n14", "n15", "n16", "n17", "n18", "n19", "n20", +"n21", "n22", "n23", "a24", "n25", "n26", "n27", "n28", "n29", "j30", +"n31", "n32", "n33", "n34", "n35", "n36", "n37", "n38", "n39", "n40", +"n41", "n42", "n43", "n44", "n45", "n46", "n47", "n48", "n49", "n50", +"n51", "n52", "n53", "n54", "n55", "n56", "n57", "n58", "n59", "n60", +"n61", "n62", "n63", "n64", "n65", "a66", "z67", "n68", "n69", "n70", +"n71", "n72", "n73", "n74", "n75", "n76", "n77", "n78", "n79", "n80", +"n81", "n82", "n83", "n84", "n85", "n86", "n87", "n88", "n89", "n90", +"n91", "n92", "n93", "n94", "n95", "n96", "n97", "n98", "n99", "n100", +"n201", "n202", "n203", "n204", "n205", "n206", "n207", "n208", "n209", "n210", +"n211", "n212", "n213", "n214", "n215", "n216", "n217", "n218", "n219", "n220", +"n221", "n222", "n223", "n224", "n225", "n226", "n227", "n228", "n229", "n230", +"n231", "n232", "n233", "n234", "n235", "n236", "n237", "n238", "n239", "a240", +"a241", "a242", "a243", "a244", "a245", "a246", "a247", "a248", "a249", "n250", +"n251", "n252", "n253", "n254", "n255", "n256", "n257", "n258", "n259", "n260", +"n261", "n262", "n263", "n264", "n265", "n266", "n267", "n268", "n269", "n270", +"n271", "n272", "n273", "n274", "n275", "n276", "n277", "n278", "n279", "n280", +"n281", "n282", "n283", "n284", "n285", "n286", "n287", "n288", "n289", "n290", +"n291", "n292", "n293", "n294", "n295", "n296", "n297", "n298", "n299" +; x=23} +else a = 1 end + + +end + +assert(b.x == 23) +print('+') + +stat(b) + +repeat +a = { +n1 = 1.5, n2 = 2.5, n3 = 3.5, n4 = 4.5, n5 = 5.5, n6 = 6.5, n7 = 7.5, +n8 = 8.5, n9 = 9.5, n10 = 10.5, n11 = 11.5, n12 = 12.5, +j301 = 301.5, j302 = 302.5, j303 = 303.5, j304 = 304.5, j305 = 305.5, +j306 = 306.5, j307 = 307.5, j308 = 308.5, j309 = 309.5, a310 = 310.5, +n311 = 311.5, n312 = 312.5, n313 = 313.5, n314 = 314.5, n315 = 315.5, +n316 = 316.5, n317 = 317.5, n318 = 318.5, n319 = 319.5, n320 = 320.5, +n321 = 321.5, n322 = 322.5, n323 = 323.5, n324 = 324.5, n325 = 325.5, +n326 = 326.5, n327 = 327.5, n328 = 328.5, a329 = 329.5, n330 = 330.5, +n331 = 331.5, n332 = 332.5, n333 = 333.5, n334 = 334.5, n335 = 335.5, +n336 = 336.5, n337 = 337.5, n338 = 338.5, n339 = 339.5, n340 = 340.5, +n341 = 341.5, z342 = 342.5, n343 = 343.5, n344 = 344.5, n345 = 345.5, +n346 = 346.5, n347 = 347.5, n348 = 348.5, n349 = 349.5, n350 = 350.5, +n351 = 351.5, n352 = 352.5, r353 = 353.5, n354 = 354.5, n355 = 355.5, +n356 = 356.5, n357 = 357.5, n358 = 358.5, n359 = 359.5, n360 = 360.5, +n361 = 361.5, n362 = 362.5, n363 = 363.5, n364 = 364.5, n365 = 365.5, +n366 = 366.5, z367 = 367.5, n368 = 368.5, n369 = 369.5, n370 = 370.5, +n371 = 371.5, n372 = 372.5, n373 = 373.5, n374 = 374.5, n375 = 375.5, +a376 = 376.5, n377 = 377.5, n378 = 378.5, n379 = 379.5, n380 = 380.5, +n381 = 381.5, n382 = 382.5, n383 = 383.5, n384 = 384.5, n385 = 385.5, +n386 = 386.5, n387 = 387.5, n388 = 388.5, n389 = 389.5, n390 = 390.5, +n391 = 391.5, n392 = 392.5, n393 = 393.5, n394 = 394.5, n395 = 395.5, +n396 = 396.5, n397 = 397.5, n398 = 398.5, n399 = 399.5, n400 = 400.5, +n13 = 13.5, n14 = 14.5, n15 = 15.5, n16 = 16.5, n17 = 17.5, +n18 = 18.5, n19 = 19.5, n20 = 20.5, n21 = 21.5, n22 = 22.5, +n23 = 23.5, a24 = 24.5, n25 = 25.5, n26 = 26.5, n27 = 27.5, +n28 = 28.5, n29 = 29.5, j30 = 30.5, n31 = 31.5, n32 = 32.5, +n33 = 33.5, n34 = 34.5, n35 = 35.5, n36 = 36.5, n37 = 37.5, +n38 = 38.5, n39 = 39.5, n40 = 40.5, n41 = 41.5, n42 = 42.5, +n43 = 43.5, n44 = 44.5, n45 = 45.5, n46 = 46.5, n47 = 47.5, +n48 = 48.5, n49 = 49.5, n50 = 50.5, n51 = 51.5, n52 = 52.5, +n53 = 53.5, n54 = 54.5, n55 = 55.5, n56 = 56.5, n57 = 57.5, +n58 = 58.5, n59 = 59.5, n60 = 60.5, n61 = 61.5, n62 = 62.5, +n63 = 63.5, n64 = 64.5, n65 = 65.5, a66 = 66.5, z67 = 67.5, +n68 = 68.5, n69 = 69.5, n70 = 70.5, n71 = 71.5, n72 = 72.5, +n73 = 73.5, n74 = 74.5, n75 = 75.5, n76 = 76.5, n77 = 77.5, +n78 = 78.5, n79 = 79.5, n80 = 80.5, n81 = 81.5, n82 = 82.5, +n83 = 83.5, n84 = 84.5, n85 = 85.5, n86 = 86.5, n87 = 87.5, +n88 = 88.5, n89 = 89.5, n90 = 90.5, n91 = 91.5, n92 = 92.5, +n93 = 93.5, n94 = 94.5, n95 = 95.5, n96 = 96.5, n97 = 97.5, +n98 = 98.5, n99 = 99.5, n100 = 100.5, n201 = 201.5, n202 = 202.5, +n203 = 203.5, n204 = 204.5, n205 = 205.5, n206 = 206.5, n207 = 207.5, +n208 = 208.5, n209 = 209.5, n210 = 210.5, n211 = 211.5, n212 = 212.5, +n213 = 213.5, n214 = 214.5, n215 = 215.5, n216 = 216.5, n217 = 217.5, +n218 = 218.5, n219 = 219.5, n220 = 220.5, n221 = 221.5, n222 = 222.5, +n223 = 223.5, n224 = 224.5, n225 = 225.5, n226 = 226.5, n227 = 227.5, +n228 = 228.5, n229 = 229.5, n230 = 230.5, n231 = 231.5, n232 = 232.5, +n233 = 233.5, n234 = 234.5, n235 = 235.5, n236 = 236.5, n237 = 237.5, +n238 = 238.5, n239 = 239.5, a240 = 240.5, a241 = 241.5, a242 = 242.5, +a243 = 243.5, a244 = 244.5, a245 = 245.5, a246 = 246.5, a247 = 247.5, +a248 = 248.5, a249 = 249.5, n250 = 250.5, n251 = 251.5, n252 = 252.5, +n253 = 253.5, n254 = 254.5, n255 = 255.5, n256 = 256.5, n257 = 257.5, +n258 = 258.5, n259 = 259.5, n260 = 260.5, n261 = 261.5, n262 = 262.5, +n263 = 263.5, n264 = 264.5, n265 = 265.5, n266 = 266.5, n267 = 267.5, +n268 = 268.5, n269 = 269.5, n270 = 270.5, n271 = 271.5, n272 = 272.5, +n273 = 273.5, n274 = 274.5, n275 = 275.5, n276 = 276.5, n277 = 277.5, +n278 = 278.5, n279 = 279.5, n280 = 280.5, n281 = 281.5, n282 = 282.5, +n283 = 283.5, n284 = 284.5, n285 = 285.5, n286 = 286.5, n287 = 287.5, +n288 = 288.5, n289 = 289.5, n290 = 290.5, n291 = 291.5, n292 = 292.5, +n293 = 293.5, n294 = 294.5, n295 = 295.5, n296 = 296.5, n297 = 297.5, +n298 = 298.5, n299 = 299.5, j300 = 300} or 1 +until 1 + +assert(a.n299 == 299.5) +xxx = 1 +assert(xxx == 1) + +stat(a) + +function a:findfield (f) + local i,v = next(self, nil) + while i ~= f do + if not i then return end + i,v = next(self, i) + end + return v +end + +local ii = 0 +i = 1 +while b[i] do + local r = a:findfield(b[i]); + assert(a[b[i]] == r) + ii = math.max(ii,i) + i = i+1 +end + +assert(ii == 299) + +function xxxx (x) coroutine.yield('b'); return ii+x end + +assert(xxxx(10) == 309) + +a = nil +b = nil +a1 = nil + +print("tables with table indices:") +i = 1; a={} +while i <= 1023 do a[{}] = i; i=i+1 end +stat(a) +a = nil + +print("tables with function indices:") +a={} +for i=1,511 do local x; a[function () return x end] = i end +stat(a) +a = nil + +print'OK' + +return 'a' diff --git a/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/calls.lua b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/calls.lua new file mode 100644 index 0000000000000000000000000000000000000000..b55d184ca6c46257a7e271a11e3fa1e495c4ef29 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/calls.lua @@ -0,0 +1,295 @@ +print("testing functions and calls") + +-- get the opportunity to test 'type' too ;) + +assert(type(1<2) == 'boolean') +assert(type(true) == 'boolean' and type(false) == 'boolean') +assert(type(nil) == 'nil' and type(-3) == 'number' and type'x' == 'string' and + type{} == 'table' and type(type) == 'function') + +assert(type(assert) == type(print)) +f = nil +function f (x) return a:x (x) end +assert(type(f) == 'function') + + +-- testing local-function recursion +fact = false +do + local res = 1 + local function fact (n) + if n==0 then return res + else return n*fact(n-1) + end + end + assert(fact(5) == 120) +end +assert(fact == false) + +-- testing declarations +a = {i = 10} +self = 20 +function a:x (x) return x+self.i end +function a.y (x) return x+self end + +assert(a:x(1)+10 == a.y(1)) + +a.t = {i=-100} +a["t"].x = function (self, a,b) return self.i+a+b end + +assert(a.t:x(2,3) == -95) + +do + local a = {x=0} + function a:add (x) self.x, a.y = self.x+x, 20; return self end + assert(a:add(10):add(20):add(30).x == 60 and a.y == 20) +end + +local a = {b={c={}}} + +function a.b.c.f1 (x) return x+1 end +function a.b.c:f2 (x,y) self[x] = y end +assert(a.b.c.f1(4) == 5) +a.b.c:f2('k', 12); assert(a.b.c.k == 12) + +print('+') + +t = nil -- 'declare' t +function f(a,b,c) local d = 'a'; t={a,b,c,d} end + +f( -- this line change must be valid + 1,2) +assert(t[1] == 1 and t[2] == 2 and t[3] == nil and t[4] == 'a') +f(1,2, -- this one too + 3,4) +assert(t[1] == 1 and t[2] == 2 and t[3] == 3 and t[4] == 'a') + +function fat(x) + if x <= 1 then return 1 + else return x*loadstring("return fat(" .. x-1 .. ")")() + end +end + +assert(loadstring "loadstring 'assert(fat(6)==720)' () ")() +a = loadstring('return fat(5), 3') +a,b = a() +assert(a == 120 and b == 3) +print('+') + +function err_on_n (n) + if n==0 then error(); exit(1); + else err_on_n (n-1); exit(1); + end +end + +do + function dummy (n) + if n > 0 then + assert(not pcall(err_on_n, n)) + dummy(n-1) + end + end +end + +dummy(10) + +function deep (n) + if n>0 then deep(n-1) end +end +deep(10) +deep(200) + +-- testing tail call +function deep (n) if n>0 then return deep(n-1) else return 101 end end +assert(deep(30000) == 101) +a = {} +function a:deep (n) if n>0 then return self:deep(n-1) else return 101 end end +assert(a:deep(30000) == 101) + +print('+') + + +a = nil +(function (x) a=x end)(23) +assert(a == 23 and (function (x) return x*2 end)(20) == 40) + + +local x,y,z,a +a = {}; lim = 2000 +for i=1, lim do a[i]=i end +assert(select(lim, unpack(a)) == lim and select('#', unpack(a)) == lim) +x = unpack(a) +assert(x == 1) +x = {unpack(a)} +assert(table.getn(x) == lim and x[1] == 1 and x[lim] == lim) +x = {unpack(a, lim-2)} +assert(table.getn(x) == 3 and x[1] == lim-2 and x[3] == lim) +x = {unpack(a, 10, 6)} +assert(next(x) == nil) -- no elements +x = {unpack(a, 11, 10)} +assert(next(x) == nil) -- no elements +x,y = unpack(a, 10, 10) +assert(x == 10 and y == nil) +x,y,z = unpack(a, 10, 11) +assert(x == 10 and y == 11 and z == nil) +a,x = unpack{1} +assert(a==1 and x==nil) +a,x = unpack({1,2}, 1, 1) +assert(a==1 and x==nil) + + +-- testing closures + +-- fixed-point operator +Y = function (le) + local function a (f) + return le(function (x) return f(f)(x) end) + end + return a(a) + end + + +-- non-recursive factorial + +F = function (f) + return function (n) + if n == 0 then return 1 + else return n*f(n-1) end + end + end + +fat = Y(F) + +assert(fat(0) == 1 and fat(4) == 24 and Y(F)(5)==5*Y(F)(4)) + +local function g (z) + local function f (a,b,c,d) + return function (x,y) return a+b+c+d+a+x+y+z end + end + return f(z,z+1,z+2,z+3) +end + +f = g(10) +assert(f(9, 16) == 10+11+12+13+10+9+16+10) + +Y, F, f = nil +print('+') + +-- testing multiple returns + +function unlpack (t, i) + i = i or 1 + if (i <= table.getn(t)) then + return t[i], unlpack(t, i+1) + end +end + +function equaltab (t1, t2) + assert(table.getn(t1) == table.getn(t2)) + for i,v1 in ipairs(t1) do + assert(v1 == t2[i]) + end +end + +local function pack (...) + local x = {...} + x.n = select('#', ...) + return x +end + +function f() return 1,2,30,4 end +function ret2 (a,b) return a,b end + +local a,b,c,d = unlpack{1,2,3} +assert(a==1 and b==2 and c==3 and d==nil) +a = {1,2,3,4,false,10,'alo',false,assert} +equaltab(pack(unlpack(a)), a) +equaltab(pack(unlpack(a), -1), {1,-1}) +a,b,c,d = ret2(f()), ret2(f()) +assert(a==1 and b==1 and c==2 and d==nil) +a,b,c,d = unlpack(pack(ret2(f()), ret2(f()))) +assert(a==1 and b==1 and c==2 and d==nil) +a,b,c,d = unlpack(pack(ret2(f()), (ret2(f())))) +assert(a==1 and b==1 and c==nil and d==nil) + +a = ret2{ unlpack{1,2,3}, unlpack{3,2,1}, unlpack{"a", "b"}} +assert(a[1] == 1 and a[2] == 3 and a[3] == "a" and a[4] == "b") + + +-- testing calls with 'incorrect' arguments +rawget({}, "x", 1) +rawset({}, "x", 1, 2) +assert(math.sin(1,2) == math.sin(1)) +table.sort({10,9,8,4,19,23,0,0}, function (a,b) return a" then + assert(val==nil) + else + assert(t[key] == val) + local mp = T.hash(key, t) + if l[i] then + assert(l[i] == mp) + elseif mp ~= i then + l[i] = mp + else -- list head + l[mp] = {mp} -- first element + while next do + assert(ff <= next and next < hsize) + if l[next] then assert(l[next] == mp) else l[next] = mp end + table.insert(l[mp], next) + key,val,next = T.querytab(t, next) + assert(key) + end + end + end + end + l.asize = asize; l.hsize = hsize; l.ff = ff + return l +end + +function mostra (t) + local asize, hsize, ff = T.querytab(t) + print(asize, hsize, ff) + print'------' + for i=0,asize-1 do + local _, v = T.querytab(t, i) + print(string.format("[%d] -", i), v) + end + print'------' + for i=0,hsize-1 do + print(i, T.querytab(t, i+asize)) + end + print'-------------' +end + +function stat (t) + t = checktable(t) + local nelem, nlist = 0, 0 + local maxlist = {} + for i=0,t.hsize-1 do + if type(t[i]) == 'table' then + local n = table.getn(t[i]) + nlist = nlist+1 + nelem = nelem + n + if not maxlist[n] then maxlist[n] = 0 end + maxlist[n] = maxlist[n]+1 + end + end + print(string.format("hsize=%d elements=%d load=%.2f med.len=%.2f (asize=%d)", + t.hsize, nelem, nelem/t.hsize, nelem/nlist, t.asize)) + for i=1,table.getn(maxlist) do + local n = maxlist[i] or 0 + print(string.format("%5d %10d %.2f%%", i, n, n*100/nlist)) + end +end + diff --git a/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/closure.lua b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/closure.lua new file mode 100644 index 0000000000000000000000000000000000000000..f01ad6ffd56123f7b4ac4bfb4f4d3918a564d91a --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/closure.lua @@ -0,0 +1,425 @@ +print "testing closures and coroutines" +--[[ + +local A,B = 0,{g=10} +function f(x) + local a = {} + for i=1,1000 do + local y = 0 + do + a[i] = function () B.g = B.g+1; y = y+x; return y+A end + end + end + local dummy = function () return a[A] end + collectgarbage() + A = 1; assert(dummy() == a[1]); A = 0; + assert(a[1]() == x) + assert(a[3]() == x) + collectgarbage() + assert(B.g == 12) + return a +end + +a = f(10) +-- force a GC in this level +local x = {[1] = {}} -- to detect a GC +setmetatable(x, {__mode = 'kv'}) +while x[1] do -- repeat until GC + local a = A..A..A..A -- create garbage + A = A+1 +end +assert(a[1]() == 20+A) +assert(a[1]() == 30+A) +assert(a[2]() == 10+A) +collectgarbage() +assert(a[2]() == 20+A) +assert(a[2]() == 30+A) +assert(a[3]() == 20+A) +assert(a[8]() == 10+A) +assert(getmetatable(x).__mode == 'kv') +assert(B.g == 19) +--]] + +-- testing closures with 'for' control variable +a = {} +for i=1,10 do + a[i] = {set = function(x) i=x end, get = function () return i end} + if i == 3 then break end +end +assert(a[4] == nil) +a[1].set(10) +assert(a[2].get() == 2) +a[2].set('a') +assert(a[3].get() == 3) +assert(a[2].get() == 'a') + +a = {} +for i, k in pairs{'a', 'b'} do + a[i] = {set = function(x, y) i=x; k=y end, + get = function () return i, k end} + if i == 2 then break end +end +a[1].set(10, 20) +local r,s = a[2].get() +assert(r == 2 and s == 'b') +r,s = a[1].get() +assert(r == 10 and s == 20) +a[2].set('a', 'b') +r,s = a[2].get() +assert(r == "a" and s == "b") + + +-- testing closures with 'for' control variable x break +for i=1,3 do + f = function () return i end + break +end +assert(f() == 1) + +for k, v in pairs{"a", "b"} do + f = function () return k, v end + break +end +assert(({f()})[1] == 1) +assert(({f()})[2] == "a") + + +-- testing closure x break x return x errors + +local b +function f(x) + local first = 1 + while 1 do + if x == 3 and not first then return end + local a = 'xuxu' + b = function (op, y) + if op == 'set' then + a = x+y + else + return a + end + end + if x == 1 then do break end + elseif x == 2 then return + else if x ~= 3 then error() end + end + first = nil + end +end + +for i=1,3 do + f(i) + assert(b('get') == 'xuxu') + b('set', 10); assert(b('get') == 10+i) + b = nil +end + +pcall(f, 4); +assert(b('get') == 'xuxu') +b('set', 10); assert(b('get') == 14) + + +local w +-- testing multi-level closure +function f(x) + return function (y) + return function (z) return w+x+y+z end + end +end + +y = f(10) +w = 1.345 +assert(y(20)(30) == 60+w) + +-- testing closures x repeat-until + +local a = {} +local i = 1 +repeat + local x = i + a[i] = function () i = x+1; return x end +until i > 10 or a[i]() ~= x +assert(i == 11 and a[1]() == 1 and a[3]() == 3 and i == 4) + +print'+' + + +-- test for correctly closing upvalues in tail calls of vararg functions +local function t () + local function c(a,b) assert(a=="test" and b=="OK") end + local function v(f, ...) c("test", f() ~= 1 and "FAILED" or "OK") end + local x = 1 + return v(function() return x end) +end +t() + + +-- coroutine tests + +local f + +assert(coroutine.running() == nil) + + +-- tests for global environment + +local function foo (a) + setfenv(0, a) + coroutine.yield(getfenv()) + assert(getfenv(0) == a) + assert(getfenv(1) == _G) + return getfenv(1) +end + +f = coroutine.wrap(foo) +local a = {} +assert(f(a) == _G) +local a,b = pcall(f) +assert(a and b == _G) + + +-- tests for multiple yield/resume arguments + +local function eqtab (t1, t2) + assert(table.getn(t1) == table.getn(t2)) + for i,v in ipairs(t1) do + assert(t2[i] == v) + end +end + +_G.x = nil -- declare x +function foo (a, ...) + assert(coroutine.running() == f) + assert(coroutine.status(f) == "running") + local arg = {...} + for i=1,table.getn(arg) do + _G.x = {coroutine.yield(unpack(arg[i]))} + end + return unpack(a) +end + +f = coroutine.create(foo) +assert(type(f) == "thread" and coroutine.status(f) == "suspended") +assert(string.find(tostring(f), "thread")) +local s,a,b,c,d +s,a,b,c,d = coroutine.resume(f, {1,2,3}, {}, {1}, {'a', 'b', 'c'}) +assert(s and a == nil and coroutine.status(f) == "suspended") +s,a,b,c,d = coroutine.resume(f) +eqtab(_G.x, {}) +assert(s and a == 1 and b == nil) +s,a,b,c,d = coroutine.resume(f, 1, 2, 3) +eqtab(_G.x, {1, 2, 3}) +assert(s and a == 'a' and b == 'b' and c == 'c' and d == nil) +s,a,b,c,d = coroutine.resume(f, "xuxu") +eqtab(_G.x, {"xuxu"}) +assert(s and a == 1 and b == 2 and c == 3 and d == nil) +assert(coroutine.status(f) == "dead") +s, a = coroutine.resume(f, "xuxu") +assert(not s and string.find(a, "dead") and coroutine.status(f) == "dead") + + +-- yields in tail calls +local function foo (i) return coroutine.yield(i) end +f = coroutine.wrap(function () + for i=1,10 do + assert(foo(i) == _G.x) + end + return 'a' +end) +for i=1,10 do _G.x = i; assert(f(i) == i) end +_G.x = 'xuxu'; assert(f('xuxu') == 'a') + +-- recursive +function pf (n, i) + coroutine.yield(n) + pf(n*i, i+1) +end + +f = coroutine.wrap(pf) +local s=1 +for i=1,10 do + assert(f(1, 1) == s) + s = s*i +end + +-- sieve +function gen (n) + return coroutine.wrap(function () + for i=2,n do coroutine.yield(i) end + end) +end + + +function filter (p, g) + return coroutine.wrap(function () + while 1 do + local n = g() + if n == nil then return end + if math.mod(n, p) ~= 0 then coroutine.yield(n) end + end + end) +end + +local x = gen(100) +local a = {} +while 1 do + local n = x() + if n == nil then break end + table.insert(a, n) + x = filter(n, x) +end + +assert(table.getn(a) == 25 and a[table.getn(a)] == 97) + + +-- errors in coroutines +function foo () + assert(debug.getinfo(1).currentline == debug.getinfo(foo).linedefined + 1) + assert(debug.getinfo(2).currentline == debug.getinfo(goo).linedefined) + coroutine.yield(3) + error(foo) +end + +function goo() foo() end +x = coroutine.wrap(goo) +assert(x() == 3) +local a,b = pcall(x) +assert(not a and b == foo) + +x = coroutine.create(goo) +a,b = coroutine.resume(x) +assert(a and b == 3) +a,b = coroutine.resume(x) +assert(not a and b == foo and coroutine.status(x) == "dead") +a,b = coroutine.resume(x) +assert(not a and string.find(b, "dead") and coroutine.status(x) == "dead") + + +-- co-routines x for loop +function all (a, n, k) + if k == 0 then coroutine.yield(a) + else + for i=1,n do + a[k] = i + all(a, n, k-1) + end + end +end + +local a = 0 +for t in coroutine.wrap(function () all({}, 5, 4) end) do + a = a+1 +end +assert(a == 5^4) + + +-- access to locals of collected corroutines +--[[ +local C = {}; setmetatable(C, {__mode = "kv"}) +local x = coroutine.wrap (function () + local a = 10 + local function f () a = a+10; return a end + while true do + a = a+1 + coroutine.yield(f) + end + end) + +C[1] = x; + +local f = x() +assert(f() == 21 and x()() == 32 and x() == f) +x = nil +collectgarbage() +assert(C[1] == nil) +assert(f() == 43 and f() == 53) +--]] + + +-- old bug: attempt to resume itself + +function co_func (current_co) + assert(coroutine.running() == current_co) + assert(coroutine.resume(current_co) == false) + assert(coroutine.resume(current_co) == false) + return 10 +end + +local co = coroutine.create(co_func) +local a,b = coroutine.resume(co, co) +assert(a == true and b == 10) +assert(coroutine.resume(co, co) == false) +assert(coroutine.resume(co, co) == false) + +-- access to locals of erroneous coroutines +local x = coroutine.create (function () + local a = 10 + _G.f = function () a=a+1; return a end + error('x') + end) + +assert(not coroutine.resume(x)) +-- overwrite previous position of local `a' +assert(not coroutine.resume(x, 1, 1, 1, 1, 1, 1, 1)) +assert(_G.f() == 11) +assert(_G.f() == 12) + + +if not T then + (Message or print)('\a\n >>> testC not active: skipping yield/hook tests <<<\n\a') +else + + local turn + + function fact (t, x) + assert(turn == t) + if x == 0 then return 1 + else return x*fact(t, x-1) + end + end + + local A,B,a,b = 0,0,0,0 + + local x = coroutine.create(function () + T.setyhook("", 2) + A = fact("A", 10) + end) + + local y = coroutine.create(function () + T.setyhook("", 3) + B = fact("B", 11) + end) + + while A==0 or B==0 do + if A==0 then turn = "A"; T.resume(x) end + if B==0 then turn = "B"; T.resume(y) end + end + + assert(B/A == 11) +end + + +-- leaving a pending coroutine open +_X = coroutine.wrap(function () + local a = 10 + local x = function () a = a+1 end + coroutine.yield() + end) + +_X() + + +-- coroutine environments +co = coroutine.create(function () + coroutine.yield(getfenv(0)) + return loadstring("return a")() + end) + +a = {a = 15} +debug.setfenv(co, a) +assert(debug.getfenv(co) == a) +assert(select(2, coroutine.resume(co)) == a) +assert(select(2, coroutine.resume(co)) == a.a) + + +print'OK' diff --git a/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/code.lua b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/code.lua new file mode 100644 index 0000000000000000000000000000000000000000..efb13c7ae374e21829713a63a187272ad9fc695b --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/code.lua @@ -0,0 +1,143 @@ + +if T==nil then + (Message or print)('\a\n >>> testC not active: skipping opcode tests <<<\n\a') + return +end +print "testing code generation and optimizations" + + +-- this code gave an error for the code checker +do + local function f (a) + for k,v,w in a do end + end +end + + +function check (f, ...) + local c = T.listcode(f) + for i=1, arg.n do + -- print(arg[i], c[i]) + assert(string.find(c[i], '- '..arg[i]..' *%d')) + end + assert(c[arg.n+2] == nil) +end + + +function checkequal (a, b) + a = T.listcode(a) + b = T.listcode(b) + for i = 1, table.getn(a) do + a[i] = string.gsub(a[i], '%b()', '') -- remove line number + b[i] = string.gsub(b[i], '%b()', '') -- remove line number + assert(a[i] == b[i]) + end +end + + +-- some basic instructions +check(function () + (function () end){f()} +end, 'CLOSURE', 'NEWTABLE', 'GETGLOBAL', 'CALL', 'SETLIST', 'CALL', 'RETURN') + + +-- sequence of LOADNILs +check(function () + local a,b,c + local d; local e; + a = nil; d=nil +end, 'RETURN') + + +-- single return +check (function (a,b,c) return a end, 'RETURN') + + +-- infinite loops +check(function () while true do local a = -1 end end, +'LOADK', 'JMP', 'RETURN') + +check(function () while 1 do local a = -1 end end, +'LOADK', 'JMP', 'RETURN') + +check(function () repeat local x = 1 until false end, +'LOADK', 'JMP', 'RETURN') + +check(function () repeat local x until nil end, +'LOADNIL', 'JMP', 'RETURN') + +check(function () repeat local x = 1 until true end, +'LOADK', 'RETURN') + + +-- concat optimization +check(function (a,b,c,d) return a..b..c..d end, + 'MOVE', 'MOVE', 'MOVE', 'MOVE', 'CONCAT', 'RETURN') + +-- not +check(function () return not not nil end, 'LOADBOOL', 'RETURN') +check(function () return not not false end, 'LOADBOOL', 'RETURN') +check(function () return not not true end, 'LOADBOOL', 'RETURN') +check(function () return not not 1 end, 'LOADBOOL', 'RETURN') + +-- direct access to locals +check(function () + local a,b,c,d + a = b*2 + c[4], a[b] = -((a + d/-20.5 - a[b]) ^ a.x), b +end, + 'MUL', + 'DIV', 'ADD', 'GETTABLE', 'SUB', 'GETTABLE', 'POW', + 'UNM', 'SETTABLE', 'SETTABLE', 'RETURN') + + +-- direct access to constants +check(function () + local a,b + a.x = 0 + a.x = b + a[b] = 'y' + a = 1 - a + b = 1/a + b = 5+4 + a[true] = false +end, + 'SETTABLE', 'SETTABLE', 'SETTABLE', 'SUB', 'DIV', 'LOADK', + 'SETTABLE', 'RETURN') + +local function f () return -((2^8 + -(-1)) % 8)/2 * 4 - 3 end + +check(f, 'LOADK', 'RETURN') +assert(f() == -5) + +check(function () + local a,b,c + b[c], a = c, b + b[a], a = c, b + a, b = c, a + a = a +end, + 'MOVE', 'MOVE', 'SETTABLE', + 'MOVE', 'MOVE', 'MOVE', 'SETTABLE', + 'MOVE', 'MOVE', 'MOVE', + -- no code for a = a + 'RETURN') + + +-- x == nil , x ~= nil +checkequal(function () if (a==nil) then a=1 end; if a~=nil then a=1 end end, + function () if (a==9) then a=1 end; if a~=9 then a=1 end end) + +check(function () if a==nil then a=1 end end, +'GETGLOBAL', 'EQ', 'JMP', 'LOADK', 'SETGLOBAL', 'RETURN') + +-- de morgan +checkequal(function () local a; if not (a or b) then b=a end end, + function () local a; if (not a and not b) then b=a end end) + +checkequal(function (l) local a; return 0 <= a and a <= l end, + function (l) local a; return not (not(a >= 0) or not(a <= l)) end) + + +print 'OK' + diff --git a/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/constructs.lua b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/constructs.lua new file mode 100644 index 0000000000000000000000000000000000000000..470f85396fe7f5bd80eb6e075a01521c9f156edc --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/constructs.lua @@ -0,0 +1,240 @@ +print "testing syntax" + +-- testing priorities + +assert(2^3^2 == 2^(3^2)); +assert(2^3*4 == (2^3)*4); +assert(2^-2 == 1/4 and -2^- -2 == - - -4); +assert(not nil and 2 and not(2>3 or 3<2)); +assert(-3-1-5 == 0+0-9); +assert(-2^2 == -4 and (-2)^2 == 4 and 2*2-3-1 == 0); +assert(2*1+3/3 == 3 and 1+2 .. 3*1 == "33"); +assert(not(2+1 > 3*1) and "a".."b" > "a"); + +assert(not ((true or false) and nil)) +assert( true or false and nil) + +local a,b = 1,nil; +assert(-(1 or 2) == -1 and (1 and 2)+(-1.25 or -4) == 0.75); +x = ((b or a)+1 == 2 and (10 or a)+1 == 11); assert(x); +x = (((2<3) or 1) == true and (2<3 and 4) == 4); assert(x); + +x,y=1,2; +assert((x>y) and x or y == 2); +x,y=2,1; +assert((x>y) and x or y == 2); + +assert(1234567890 == tonumber('1234567890') and 1234567890+1 == 1234567891) + + +-- silly loops +repeat until 1; repeat until true; +while false do end; while nil do end; + +do -- test old bug (first name could not be an `upvalue') + local a; function f(x) x={a=1}; x={x=1}; x={G=1} end +end + +function f (i) + if type(i) ~= 'number' then return i,'jojo'; end; + if i > 0 then return i, f(i-1); end; +end + +x = {f(3), f(5), f(10);}; +assert(x[1] == 3 and x[2] == 5 and x[3] == 10 and x[4] == 9 and x[12] == 1); +assert(x[nil] == nil) +x = {f'alo', f'xixi', nil}; +assert(x[1] == 'alo' and x[2] == 'xixi' and x[3] == nil); +x = {f'alo'..'xixi'}; +assert(x[1] == 'aloxixi') +x = {f{}} +assert(x[2] == 'jojo' and type(x[1]) == 'table') + + +local f = function (i) + if i < 10 then return 'a'; + elseif i < 20 then return 'b'; + elseif i < 30 then return 'c'; + end; +end + +assert(f(3) == 'a' and f(12) == 'b' and f(26) == 'c' and f(100) == nil) + +for i=1,1000 do break; end; +n=100; +i=3; +t = {}; +a=nil +while not a do + a=0; for i=1,n do for i=i,1,-1 do a=a+1; t[i]=1; end; end; +end +assert(a == n*(n+1)/2 and i==3); +assert(t[1] and t[n] and not t[0] and not t[n+1]) + +function f(b) + local x = 1; + repeat + local a; + if b==1 then local b=1; x=10; break + elseif b==2 then x=20; break; + elseif b==3 then x=30; + else local a,b,c,d=math.sin(1); x=x+1; + end + until x>=12; + return x; +end; + +assert(f(1) == 10 and f(2) == 20 and f(3) == 30 and f(4)==12) + + +local f = function (i) + if i < 10 then return 'a' + elseif i < 20 then return 'b' + elseif i < 30 then return 'c' + else return 8 + end +end + +assert(f(3) == 'a' and f(12) == 'b' and f(26) == 'c' and f(100) == 8) + +local a, b = nil, 23 +x = {f(100)*2+3 or a, a or b+2} +assert(x[1] == 19 and x[2] == 25) +x = {f=2+3 or a, a = b+2} +assert(x.f == 5 and x.a == 25) + +a={y=1} +x = {a.y} +assert(x[1] == 1) + +function f(i) + while 1 do + if i>0 then i=i-1; + else return; end; + end; +end; + +function g(i) + while 1 do + if i>0 then i=i-1 + else return end + end +end + +f(10); g(10); + +do + function f () return 1,2,3; end + local a, b, c = f(); + assert(a==1 and b==2 and c==3) + a, b, c = (f()); + assert(a==1 and b==nil and c==nil) +end + +local a,b = 3 and f(); +assert(a==1 and b==nil) + +function g() f(); return; end; +assert(g() == nil) +function g() return nil or f() end +a,b = g() +assert(a==1 and b==nil) + +print'+'; + + +f = [[ +return function ( a , b , c , d , e ) + local x = a >= b or c or ( d and e ) or nil + return x +end , { a = 1 , b = 2 >= 1 , } or { 1 }; +]] +f = string.gsub(f, "%s+", "\n"); -- force a SETLINE between opcodes +f,a = loadstring(f)(); +assert(a.a == 1 and a.b) + +function g (a,b,c,d,e) + if not (a>=b or c or d and e or nil) then return 0; else return 1; end; +end + +function h (a,b,c,d,e) + while (a>=b or c or (d and e) or nil) do return 1; end; + return 0; +end; + +assert(f(2,1) == true and g(2,1) == 1 and h(2,1) == 1) +assert(f(1,2,'a') == 'a' and g(1,2,'a') == 1 and h(1,2,'a') == 1) +assert(f(1,2,'a') +~= -- force SETLINE before nil +nil, "") +assert(f(1,2,'a') == 'a' and g(1,2,'a') == 1 and h(1,2,'a') == 1) +assert(f(1,2,nil,1,'x') == 'x' and g(1,2,nil,1,'x') == 1 and + h(1,2,nil,1,'x') == 1) +assert(f(1,2,nil,nil,'x') == nil and g(1,2,nil,nil,'x') == 0 and + h(1,2,nil,nil,'x') == 0) +assert(f(1,2,nil,1,nil) == nil and g(1,2,nil,1,nil) == 0 and + h(1,2,nil,1,nil) == 0) + +assert(1 and 2<3 == true and 2<3 and 'a'<'b' == true) +x = 2<3 and not 3; assert(x==false) +x = 2<1 or (2>1 and 'a'); assert(x=='a') + + +do + local a; if nil then a=1; else a=2; end; -- this nil comes as PUSHNIL 2 + assert(a==2) +end + +function F(a) + assert(debug.getinfo(1, "n").name == 'F') + return a,2,3 +end + +a,b = F(1)~=nil; assert(a == true and b == nil); +a,b = F(nil)==nil; assert(a == true and b == nil) + +---------------------------------------------------------------- +-- creates all combinations of +-- [not] ([not] arg op [not] (arg op [not] arg )) +-- and tests each one + +function ID(x) return x end + +function f(t, i) + local b = t.n + local res = math.mod(math.floor(i/c), b)+1 + c = c*b + return t[res] +end + +local arg = {" ( 1 < 2 ) ", " ( 1 >= 2 ) ", " F ( ) ", " nil "; n=4} + +local op = {" and ", " or ", " == ", " ~= "; n=4} + +local neg = {" ", " not "; n=2} + +local i = 0 +repeat + c = 1 + local s = f(neg, i)..'ID('..f(neg, i)..f(arg, i)..f(op, i).. + f(neg, i)..'ID('..f(arg, i)..f(op, i)..f(neg, i)..f(arg, i)..'))' + local s1 = string.gsub(s, 'ID', '') + K,X,NX,WX1,WX2 = nil + s = string.format([[ + local a = %s + local b = not %s + K = b + local xxx; + if %s then X = a else X = b end + if %s then NX = b else NX = a end + while %s do WX1 = a; break end + while %s do WX2 = a; break end + repeat if (%s) then break end; assert(b) until not(%s) + ]], s1, s, s1, s, s1, s, s1, s, s) + assert(loadstring(s))() + assert(X and not NX and not WX1 == K and not WX2 == K) + if math.mod(i,4000) == 0 then print('+') end + i = i+1 +until i==c + +print'OK' diff --git a/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/db.lua b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/db.lua new file mode 100644 index 0000000000000000000000000000000000000000..09496f6fa534de33a7d601f43bb8c2fb29d9d050 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/db.lua @@ -0,0 +1,499 @@ +-- testing debug library + +local function dostring(s) return assert(loadstring(s))() end + +print"testing debug library and debug information" + +do +local a=1 +end + +function test (s, l, p) + collectgarbage() -- avoid gc during trace + local function f (event, line) + assert(event == 'line') + local l = table.remove(l, 1) + if p then print(l, line) end + assert(l == line, "wrong trace!!") + end + debug.sethook(f,"l"); loadstring(s)(); debug.sethook() + assert(table.getn(l) == 0) +end + + +do + local a = debug.getinfo(print) + assert(a.what == "C" and a.short_src == "[C]") + local b = debug.getinfo(test, "SfL") + assert(b.name == nil and b.what == "Lua" and b.linedefined == 11 and + b.lastlinedefined == b.linedefined + 10 and + b.func == test and not string.find(b.short_src, "%[")) + assert(b.activelines[b.linedefined + 1] and + b.activelines[b.lastlinedefined]) + assert(not b.activelines[b.linedefined] and + not b.activelines[b.lastlinedefined + 1]) +end + + +-- test file and string names truncation +a = "function f () end" +local function dostring (s, x) return loadstring(s, x)() end +dostring(a) +assert(debug.getinfo(f).short_src == string.format('[string "%s"]', a)) +dostring(a..string.format("; %s\n=1", string.rep('p', 400))) +assert(string.find(debug.getinfo(f).short_src, '^%[string [^\n]*%.%.%."%]$')) +dostring("\n"..a) +assert(debug.getinfo(f).short_src == '[string "..."]') +dostring(a, "") +assert(debug.getinfo(f).short_src == '[string ""]') +dostring(a, "@xuxu") +assert(debug.getinfo(f).short_src == "xuxu") +dostring(a, "@"..string.rep('p', 1000)..'t') +assert(string.find(debug.getinfo(f).short_src, "^%.%.%.p*t$")) +dostring(a, "=xuxu") +assert(debug.getinfo(f).short_src == "xuxu") +dostring(a, string.format("=%s", string.rep('x', 500))) +assert(string.find(debug.getinfo(f).short_src, "^x*")) +dostring(a, "=") +assert(debug.getinfo(f).short_src == "") +a = nil; f = nil; + + +repeat + local g = {x = function () + local a = debug.getinfo(2) + assert(a.name == 'f' and a.namewhat == 'local') + a = debug.getinfo(1) + assert(a.name == 'x' and a.namewhat == 'field') + return 'xixi' + end} + local f = function () return 1+1 and (not 1 or g.x()) end + assert(f() == 'xixi') + g = debug.getinfo(f) + assert(g.what == "Lua" and g.func == f and g.namewhat == "" and not g.name) + + function f (x, name) -- local! + name = name or 'f' + local a = debug.getinfo(1) + assert(a.name == name and a.namewhat == 'local') + return x + end + + -- breaks in different conditions + if 3>4 then break end; f() + if 3<4 then a=1 else break end; f() + while 1 do local x=10; break end; f() + local b = 1 + if 3>4 then return math.sin(1) end; f() + a = 3<4; f() + a = 3<4 or 1; f() + repeat local x=20; if 4>3 then f() else break end; f() until 1 + g = {} + f(g).x = f(2) and f(10)+f(9) + assert(g.x == f(19)) + function g(x) if not x then return 3 end return (x('a', 'x')) end + assert(g(f) == 'a') +until 1 + +test([[if +math.sin(1) +then + a=1 +else + a=2 +end +]], {2,4,7}) + +test([[-- +if nil then + a=1 +else + a=2 +end +]], {2,5,6}) + +test([[a=1 +repeat + a=a+1 +until a==3 +]], {1,3,4,3,4}) + +test([[ do + return +end +]], {2}) + +test([[local a +a=1 +while a<=3 do + a=a+1 +end +]], {2,3,4,3,4,3,4,3,5}) + +test([[while math.sin(1) do + if math.sin(1) + then + break + end +end +a=1]], {1,2,4,7}) + +test([[for i=1,3 do + a=i +end +]], {1,2,1,2,1,2,1,3}) + +test([[for i,v in pairs{'a','b'} do + a=i..v +end +]], {1,2,1,2,1,3}) + +test([[for i=1,4 do a=1 end]], {1,1,1,1,1}) + + + +print'+' + +a = {}; L = nil +local glob = 1 +local oldglob = glob +debug.sethook(function (e,l) + collectgarbage() -- force GC during a hook + local f, m, c = debug.gethook() + assert(m == 'crl' and c == 0) + if e == "line" then + if glob ~= oldglob then + L = l-1 -- get the first line where "glob" has changed + oldglob = glob + end + elseif e == "call" then + local f = debug.getinfo(2, "f").func + a[f] = 1 + else assert(e == "return") + end +end, "crl") + +function f(a,b) + collectgarbage() + local _, x = debug.getlocal(1, 1) + local _, y = debug.getlocal(1, 2) + assert(x == a and y == b) + assert(debug.setlocal(2, 3, "pera") == "AA".."AA") + assert(debug.setlocal(2, 4, "maçã") == "B") + x = debug.getinfo(2) + assert(x.func == g and x.what == "Lua" and x.name == 'g' and + x.nups == 0 and string.find(x.source, "^@.*db%.lua")) + glob = glob+1 + assert(debug.getinfo(1, "l").currentline == L+1) + assert(debug.getinfo(1, "l").currentline == L+2) +end + +function foo() + glob = glob+1 + assert(debug.getinfo(1, "l").currentline == L+1) +end; foo() -- set L +-- check line counting inside strings and empty lines + +_ = 'alo\ +alo' .. [[ + +]] +--[[ +]] +assert(debug.getinfo(1, "l").currentline == L+11) -- check count of lines + + +function g(...) + do local a,b,c; a=math.sin(40); end + local feijao + local AAAA,B = "xuxu", "mamão" + f(AAAA,B) + assert(AAAA == "pera" and B == "maçã") + do + local B = 13 + local x,y = debug.getlocal(1,5) + assert(x == 'B' and y == 13) + end +end + +g() + + +assert(a[f] and a[g] and a[assert] and a[debug.getlocal] and not a[print]) + + +-- tests for manipulating non-registered locals (C and Lua temporaries) + +local n, v = debug.getlocal(0, 1) +assert(v == 0 and n == "(*temporary)") +local n, v = debug.getlocal(0, 2) +assert(v == 2 and n == "(*temporary)") +assert(not debug.getlocal(0, 3)) +assert(not debug.getlocal(0, 0)) + +function f() + assert(select(2, debug.getlocal(2,3)) == 1) + assert(not debug.getlocal(2,4)) + debug.setlocal(2, 3, 10) + return 20 +end + +function g(a,b) return (a+1) + f() end + +assert(g(0,0) == 30) + + +debug.sethook(nil); +assert(debug.gethook() == nil) + + +-- testing access to function arguments + +X = nil +a = {} +function a:f (a, b, ...) local c = 13 end +debug.sethook(function (e) + assert(e == "call") + dostring("XX = 12") -- test dostring inside hooks + -- testing errors inside hooks + assert(not pcall(loadstring("a='joao'+1"))) + debug.sethook(function (e, l) + assert(debug.getinfo(2, "l").currentline == l) + local f,m,c = debug.gethook() + assert(e == "line") + assert(m == 'l' and c == 0) + debug.sethook(nil) -- hook is called only once + assert(not X) -- check that + X = {}; local i = 1 + local x,y + while 1 do + x,y = debug.getlocal(2, i) + if x==nil then break end + X[x] = y + i = i+1 + end + end, "l") +end, "c") + +a:f(1,2,3,4,5) +assert(X.self == a and X.a == 1 and X.b == 2 and X.arg.n == 3 and X.c == nil) +assert(XX == 12) +assert(debug.gethook() == nil) + + +-- testing upvalue access +local function getupvalues (f) + local t = {} + local i = 1 + while true do + local name, value = debug.getupvalue(f, i) + if not name then break end + assert(not t[name]) + t[name] = value + i = i + 1 + end + return t +end + +local a,b,c = 1,2,3 +local function foo1 (a) b = a; return c end +local function foo2 (x) a = x; return c+b end +assert(debug.getupvalue(foo1, 3) == nil) +assert(debug.getupvalue(foo1, 0) == nil) +assert(debug.setupvalue(foo1, 3, "xuxu") == nil) +local t = getupvalues(foo1) +assert(t.a == nil and t.b == 2 and t.c == 3) +t = getupvalues(foo2) +assert(t.a == 1 and t.b == 2 and t.c == 3) +assert(debug.setupvalue(foo1, 1, "xuxu") == "b") +assert(({debug.getupvalue(foo2, 3)})[2] == "xuxu") +-- cannot manipulate C upvalues from Lua +assert(debug.getupvalue(io.read, 1) == nil) +assert(debug.setupvalue(io.read, 1, 10) == nil) + + +-- testing count hooks +local a=0 +debug.sethook(function (e) a=a+1 end, "", 1) +a=0; for i=1,1000 do end; assert(1000 < a and a < 1012) +debug.sethook(function (e) a=a+1 end, "", 4) +a=0; for i=1,1000 do end; assert(250 < a and a < 255) +local f,m,c = debug.gethook() +assert(m == "" and c == 4) +debug.sethook(function (e) a=a+1 end, "", 4000) +a=0; for i=1,1000 do end; assert(a == 0) +debug.sethook(print, "", 2^24 - 1) -- count upperbound +local f,m,c = debug.gethook() +assert(({debug.gethook()})[3] == 2^24 - 1) +debug.sethook() + + +-- tests for tail calls +local function f (x) + if x then + assert(debug.getinfo(1, "S").what == "Lua") + local tail = debug.getinfo(2) + assert(not pcall(getfenv, 3)) + assert(tail.what == "tail" and tail.short_src == "(tail call)" and + tail.linedefined == -1 and tail.func == nil) + assert(debug.getinfo(3, "f").func == g1) + assert(getfenv(3)) + assert(debug.getinfo(4, "S").what == "tail") + assert(not pcall(getfenv, 5)) + assert(debug.getinfo(5, "S").what == "main") + assert(getfenv(5)) + print"+" + end +end + +function g(x) return f(x) end + +function g1(x) g(x) end + +local function h (x) local f=g1; return f(x) end + +h(true) + +local b = {} +debug.sethook(function (e) table.insert(b, e) end, "cr") +h(false) +debug.sethook() +local res = {"return", -- first return (from sethook) + "call", "call", "call", "call", + "return", "tail return", "return", "tail return", + "call", -- last call (to sethook) +} +for _, k in ipairs(res) do assert(k == table.remove(b, 1)) end + + +lim = 30000 +local function foo (x) + if x==0 then + assert(debug.getinfo(lim+2).what == "main") + for i=2,lim do assert(debug.getinfo(i, "S").what == "tail") end + else return foo(x-1) + end +end + +foo(lim) + + +print"+" + + +-- testing traceback + +assert(debug.traceback(print) == print) +assert(debug.traceback(print, 4) == print) +assert(string.find(debug.traceback("hi", 4), "^hi\n")) +assert(string.find(debug.traceback("hi"), "^hi\n")) +assert(not string.find(debug.traceback("hi"), "'traceback'")) +assert(string.find(debug.traceback("hi", 0), "'traceback'")) +assert(string.find(debug.traceback(), "^stack traceback:\n")) + +-- testing debugging of coroutines + +local function checktraceback (co, p) + local tb = debug.traceback(co) + local i = 0 + for l in string.gmatch(tb, "[^\n]+\n?") do + assert(i == 0 or string.find(l, p[i])) + i = i+1 + end + assert(p[i] == nil) +end + + +local function f (n) + if n > 0 then return f(n-1) + else coroutine.yield() end +end + +local co = coroutine.create(f) +coroutine.resume(co, 3) +checktraceback(co, {"yield", "db.lua", "tail", "tail", "tail"}) + + +co = coroutine.create(function (x) + local a = 1 + coroutine.yield(debug.getinfo(1, "l")) + coroutine.yield(debug.getinfo(1, "l").currentline) + return a + end) + +local tr = {} +local foo = function (e, l) table.insert(tr, l) end +debug.sethook(co, foo, "l") + +local _, l = coroutine.resume(co, 10) +local x = debug.getinfo(co, 1, "lfLS") +assert(x.currentline == l.currentline and x.activelines[x.currentline]) +assert(type(x.func) == "function") +for i=x.linedefined + 1, x.lastlinedefined do + assert(x.activelines[i]) + x.activelines[i] = nil +end +assert(next(x.activelines) == nil) -- no 'extra' elements +assert(debug.getinfo(co, 2) == nil) +local a,b = debug.getlocal(co, 1, 1) +assert(a == "x" and b == 10) +a,b = debug.getlocal(co, 1, 2) +assert(a == "a" and b == 1) +debug.setlocal(co, 1, 2, "hi") +assert(debug.gethook(co) == foo) +assert(table.getn(tr) == 2 and + tr[1] == l.currentline-1 and tr[2] == l.currentline) + +a,b,c = pcall(coroutine.resume, co) +assert(a and b and c == l.currentline+1) +checktraceback(co, {"yield", "in function <"}) + +a,b = coroutine.resume(co) +assert(a and b == "hi") +assert(table.getn(tr) == 4 and tr[4] == l.currentline+2) +assert(debug.gethook(co) == foo) +assert(debug.gethook() == nil) +checktraceback(co, {}) + + +-- check traceback of suspended (or dead with error) coroutines + +function f(i) if i==0 then error(i) else coroutine.yield(); f(i-1) end end + +co = coroutine.create(function (x) f(x) end) +a, b = coroutine.resume(co, 3) +t = {"'yield'", "'f'", "in function <"} +while coroutine.status(co) == "suspended" do + checktraceback(co, t) + a, b = coroutine.resume(co) + table.insert(t, 2, "'f'") -- one more recursive call to 'f' +end +t[1] = "'error'" +checktraceback(co, t) + + +-- test acessing line numbers of a coroutine from a resume inside +-- a C function (this is a known bug in Lua 5.0) + +local function g(x) + coroutine.yield(x) +end + +local function f (i) + debug.sethook(function () end, "l") + for j=1,1000 do + g(i+j) + end +end + +local co = coroutine.wrap(f) +co(10) +pcall(co) +pcall(co) + + +assert(type(debug.getregistry()) == "table") + + +print"OK" + diff --git a/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/errors.lua b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/errors.lua new file mode 100644 index 0000000000000000000000000000000000000000..3cc3211d7cb834375bcf8cf8f276df2d263c5e87 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/errors.lua @@ -0,0 +1,250 @@ +print("testing errors") + +function doit (s) + local f, msg = loadstring(s) + if f == nil then return msg end + local cond, msg = pcall(f) + return (not cond) and msg +end + + +function checkmessage (prog, msg) + assert(string.find(doit(prog), msg, 1, true)) +end + +function checksyntax (prog, extra, token, line) + local msg = doit(prog) + token = string.gsub(token, "(%p)", "%%%1") + local pt = string.format([[^%%[string ".*"%%]:%d: .- near '%s'$]], + line, token) + assert(string.find(msg, pt)) + assert(string.find(msg, msg, 1, true)) +end + + +-- test error message with no extra info +assert(doit("error('hi', 0)") == 'hi') + +-- test error message with no info +assert(doit("error()") == nil) + + +-- test common errors/errors that crashed in the past +assert(doit("unpack({}, 1, n=2^30)")) +assert(doit("a=math.sin()")) +assert(not doit("tostring(1)") and doit("tostring()")) +assert(doit"tonumber()") +assert(doit"repeat until 1; a") +checksyntax("break label", "", "label", 1) +assert(doit";") +assert(doit"a=1;;") +assert(doit"return;;") +assert(doit"assert(false)") +assert(doit"assert(nil)") +assert(doit"a=math.sin\n(3)") +assert(doit("function a (... , ...) end")) +assert(doit("function a (, ...) end")) + +checksyntax([[ + local a = {4 + +]], "'}' expected (to close '{' at line 1)", "", 3) + + +-- tests for better error messages + +checkmessage("a=1; bbbb=2; a=math.sin(3)+bbbb(3)", "global 'bbbb'") +checkmessage("a=1; local a,bbbb=2,3; a = math.sin(1) and bbbb(3)", + "local 'bbbb'") +checkmessage("a={}; do local a=1 end a:bbbb(3)", "method 'bbbb'") +checkmessage("local a={}; a.bbbb(3)", "field 'bbbb'") +assert(not string.find(doit"a={13}; local bbbb=1; a[bbbb](3)", "'bbbb'")) +checkmessage("a={13}; local bbbb=1; a[bbbb](3)", "number") + +aaa = nil +checkmessage("aaa.bbb:ddd(9)", "global 'aaa'") +checkmessage("local aaa={bbb=1}; aaa.bbb:ddd(9)", "field 'bbb'") +checkmessage("local aaa={bbb={}}; aaa.bbb:ddd(9)", "method 'ddd'") +checkmessage("local a,b,c; (function () a = b+1 end)()", "upvalue 'b'") +assert(not doit"local aaa={bbb={ddd=next}}; aaa.bbb:ddd(nil)") + +checkmessage("b=1; local aaa='a'; x=aaa+b", "local 'aaa'") +checkmessage("aaa={}; x=3/aaa", "global 'aaa'") +checkmessage("aaa='2'; b=nil;x=aaa*b", "global 'b'") +checkmessage("aaa={}; x=-aaa", "global 'aaa'") +assert(not string.find(doit"aaa={}; x=(aaa or aaa)+(aaa and aaa)", "'aaa'")) +assert(not string.find(doit"aaa={}; (aaa or aaa)()", "'aaa'")) + +checkmessage([[aaa=9 +repeat until 3==3 +local x=math.sin(math.cos(3)) +if math.sin(1) == x then return math.sin(1) end -- tail call +local a,b = 1, { + {x='a'..'b'..'c', y='b', z=x}, + {1,2,3,4,5} or 3+3<=3+3, + 3+1>3+1, + {d = x and aaa[x or y]}} +]], "global 'aaa'") + +checkmessage([[ +local x,y = {},1 +if math.sin(1) == 0 then return 3 end -- return +x.a()]], "field 'a'") + +checkmessage([[ +prefix = nil +insert = nil +while 1 do + local a + if nil then break end + insert(prefix, a) +end]], "global 'insert'") + +checkmessage([[ -- tail call + return math.sin("a") +]], "'sin'") + +checkmessage([[collectgarbage("nooption")]], "invalid option") + +checkmessage([[x = print .. "a"]], "concatenate") + +checkmessage("getmetatable(io.stdin).__gc()", "no value") + +print'+' + + +-- testing line error + +function lineerror (s) + local err,msg = pcall(loadstring(s)) + local line = string.match(msg, ":(%d+):") + return line and line+0 +end + +assert(lineerror"local a\n for i=1,'a' do \n print(i) \n end" == 2) +assert(lineerror"\n local a \n for k,v in 3 \n do \n print(k) \n end" == 3) +assert(lineerror"\n\n for k,v in \n 3 \n do \n print(k) \n end" == 4) +assert(lineerror"function a.x.y ()\na=a+1\nend" == 1) + +local p = [[ +function g() f() end +function f(x) error('a', X) end +g() +]] +X=3;assert(lineerror(p) == 3) +X=0;assert(lineerror(p) == nil) +X=1;assert(lineerror(p) == 2) +X=2;assert(lineerror(p) == 1) + +lineerror = nil + +C = 0 +local l = debug.getinfo(1, "l").currentline; function y () C=C+1; y() end + +local function checkstackmessage (m) + return (string.find(m, "^.-:%d+: stack overflow")) +end +assert(checkstackmessage(doit('y()'))) +assert(checkstackmessage(doit('y()'))) +assert(checkstackmessage(doit('y()'))) +-- teste de linhas em erro +C = 0 +local l1 +local function g() + l1 = debug.getinfo(1, "l").currentline; y() +end +local _, stackmsg = xpcall(g, debug.traceback) +local stack = {} +for line in string.gmatch(stackmsg, "[^\n]*") do + local curr = string.match(line, ":(%d+):") + if curr then table.insert(stack, tonumber(curr)) end +end +local i=1 +while stack[i] ~= l1 do + assert(stack[i] == l) + i = i+1 +end +assert(i > 15) + + +-- error in error handling +local res, msg = xpcall(error, error) +assert(not res and type(msg) == 'string') + +local function f (x) + if x==0 then error('a\n') + else + local aux = function () return f(x-1) end + local a,b = xpcall(aux, aux) + return a,b + end +end +f(3) + +-- non string messages +function f() error{msg='x'} end +res, msg = xpcall(f, function (r) return {msg=r.msg..'y'} end) +assert(msg.msg == 'xy') + +print('+') +checksyntax("syntax error", "", "error", 1) +checksyntax("1.000", "", "1.000", 1) +checksyntax("[[a]]", "", "[[a]]", 1) +checksyntax("'aa'", "", "'aa'", 1) + +-- test 255 as first char in a chunk +checksyntax("\255a = 1", "", "\255", 1) + +doit('I = loadstring("a=9+"); a=3') +assert(a==3 and I == nil) +print('+') + +lim = 1000 +if rawget(_G, "_soft") then lim = 100 end +for i=1,lim do + doit('a = ') + doit('a = 4+nil') +end + + +-- testing syntax limits +local function testrep (init, rep) + local s = "local a; "..init .. string.rep(rep, 400) + local a,b = loadstring(s) + assert(not a and string.find(b, "syntax levels")) +end +testrep("a=", "{") +testrep("a=", "(") +testrep("", "a(") +testrep("", "do ") +testrep("", "while a do ") +testrep("", "if a then else ") +testrep("", "function foo () ") +testrep("a=", "a..") +testrep("a=", "a^") + + +-- testing other limits +-- upvalues +local s = "function foo ()\n local " +for j = 1,70 do + s = s.."a"..j..", " +end +s = s.."b\n" +for j = 1,70 do + s = s.."function foo"..j.." ()\n a"..j.."=3\n" +end +local a,b = loadstring(s) +assert(string.find(b, "line 3")) + +-- local variables +s = "\nfunction foo ()\n local " +for j = 1,300 do + s = s.."a"..j..", " +end +s = s.."b\n" +local a,b = loadstring(s) +assert(string.find(b, "line 2")) + + +print('OK') diff --git a/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/events.lua b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/events.lua new file mode 100644 index 0000000000000000000000000000000000000000..d75c16c61b75d80dd33afa142356d46cb6fd4f40 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/events.lua @@ -0,0 +1,362 @@ +print('testing metatables') + +X = 20; B = 30 + +setfenv(1, setmetatable({}, {__index=_G})) + +collectgarbage() + +X = X+10 +assert(X == 30 and _G.X == 20) +B = false +assert(B == false) +B = nil +assert(B == 30) + +assert(getmetatable{} == nil) +assert(getmetatable(4) == nil) +assert(getmetatable(nil) == nil) +a={}; setmetatable(a, {__metatable = "xuxu", + __tostring=function(x) return x.name end}) +assert(getmetatable(a) == "xuxu") +assert(tostring(a) == nil) +-- cannot change a protected metatable +assert(pcall(setmetatable, a, {}) == false) +a.name = "gororoba" +assert(tostring(a) == "gororoba") + +local a, t = {10,20,30; x="10", y="20"}, {} +assert(setmetatable(a,t) == a) +assert(getmetatable(a) == t) +assert(setmetatable(a,nil) == a) +assert(getmetatable(a) == nil) +assert(setmetatable(a,t) == a) + + +function f (t, i, e) + assert(not e) + local p = rawget(t, "parent") + return (p and p[i]+3), "dummy return" +end + +t.__index = f + +a.parent = {z=25, x=12, [4] = 24} +assert(a[1] == 10 and a.z == 28 and a[4] == 27 and a.x == "10") + +collectgarbage() + +a = setmetatable({}, t) +function f(t, i, v) rawset(t, i, v-3) end +t.__newindex = f +a[1] = 30; a.x = "101"; a[5] = 200 +assert(a[1] == 27 and a.x == 98 and a[5] == 197) + + +local c = {} +a = setmetatable({}, t) +t.__newindex = c +a[1] = 10; a[2] = 20; a[3] = 90 +assert(c[1] == 10 and c[2] == 20 and c[3] == 90) + + +do + local a; + a = setmetatable({}, {__index = setmetatable({}, + {__index = setmetatable({}, + {__index = function (_,n) return a[n-3]+4, "lixo" end})})}) + a[0] = 20 + for i=0,10 do + assert(a[i*3] == 20 + i*4) + end +end + + +do -- newindex + local foi + local a = {} + for i=1,10 do a[i] = 0; a['a'..i] = 0; end + setmetatable(a, {__newindex = function (t,k,v) foi=true; rawset(t,k,v) end}) + foi = false; a[1]=0; assert(not foi) + foi = false; a['a1']=0; assert(not foi) + foi = false; a['a11']=0; assert(foi) + foi = false; a[11]=0; assert(foi) + foi = false; a[1]=nil; assert(not foi) + foi = false; a[1]=nil; assert(foi) +end + + +function f (t, ...) return t, {...} end +t.__call = f + +do + local x,y = a(unpack{'a', 1}) + assert(x==a and y[1]=='a' and y[2]==1 and y[3]==nil) + x,y = a() + assert(x==a and y[1]==nil) +end + + +local b = setmetatable({}, t) +setmetatable(b,t) + +function f(op) + return function (...) cap = {[0] = op, ...} ; return (...) end +end +t.__add = f("add") +t.__sub = f("sub") +t.__mul = f("mul") +t.__div = f("div") +t.__mod = f("mod") +t.__unm = f("unm") +t.__pow = f("pow") + +assert(b+5 == b) +assert(cap[0] == "add" and cap[1] == b and cap[2] == 5 and cap[3]==nil) +assert(b+'5' == b) +assert(cap[0] == "add" and cap[1] == b and cap[2] == '5' and cap[3]==nil) +assert(5+b == 5) +assert(cap[0] == "add" and cap[1] == 5 and cap[2] == b and cap[3]==nil) +assert('5'+b == '5') +assert(cap[0] == "add" and cap[1] == '5' and cap[2] == b and cap[3]==nil) +b=b-3; assert(getmetatable(b) == t) +assert(5-a == 5) +assert(cap[0] == "sub" and cap[1] == 5 and cap[2] == a and cap[3]==nil) +assert('5'-a == '5') +assert(cap[0] == "sub" and cap[1] == '5' and cap[2] == a and cap[3]==nil) +assert(a*a == a) +assert(cap[0] == "mul" and cap[1] == a and cap[2] == a and cap[3]==nil) +assert(a/0 == a) +assert(cap[0] == "div" and cap[1] == a and cap[2] == 0 and cap[3]==nil) +assert(a%2 == a) +assert(cap[0] == "mod" and cap[1] == a and cap[2] == 2 and cap[3]==nil) +assert(-a == a) +assert(cap[0] == "unm" and cap[1] == a) +assert(a^4 == a) +assert(cap[0] == "pow" and cap[1] == a and cap[2] == 4 and cap[3]==nil) +assert(a^'4' == a) +assert(cap[0] == "pow" and cap[1] == a and cap[2] == '4' and cap[3]==nil) +assert(4^a == 4) +assert(cap[0] == "pow" and cap[1] == 4 and cap[2] == a and cap[3]==nil) +assert('4'^a == '4') +assert(cap[0] == "pow" and cap[1] == '4' and cap[2] == a and cap[3]==nil) + + +t = {} +t.__lt = function (a,b,c) + collectgarbage() + assert(c == nil) + if type(a) == 'table' then a = a.x end + if type(b) == 'table' then b = b.x end + return aOp(1)) and not(Op(1)>Op(2)) and (Op(2)>Op(1))) + assert(not(Op('a')>Op('a')) and not(Op('a')>Op('b')) and (Op('b')>Op('a'))) + assert((Op(1)>=Op(1)) and not(Op(1)>=Op(2)) and (Op(2)>=Op(1))) + assert((Op('a')>=Op('a')) and not(Op('a')>=Op('b')) and (Op('b')>=Op('a'))) +end + +test() + +t.__le = function (a,b,c) + assert(c == nil) + if type(a) == 'table' then a = a.x end + if type(b) == 'table' then b = b.x end + return a<=b, "dummy" +end + +test() -- retest comparisons, now using both `lt' and `le' + + +-- test `partial order' + +local function Set(x) + local y = {} + for _,k in pairs(x) do y[k] = 1 end + return setmetatable(y, t) +end + +t.__lt = function (a,b) + for k in pairs(a) do + if not b[k] then return false end + b[k] = nil + end + return next(b) ~= nil +end + +t.__le = nil + +assert(Set{1,2,3} < Set{1,2,3,4}) +assert(not(Set{1,2,3,4} < Set{1,2,3,4})) +assert((Set{1,2,3,4} <= Set{1,2,3,4})) +assert((Set{1,2,3,4} >= Set{1,2,3,4})) +assert((Set{1,3} <= Set{3,5})) -- wrong!! model needs a `le' method ;-) + +t.__le = function (a,b) + for k in pairs(a) do + if not b[k] then return false end + end + return true +end + +assert(not (Set{1,3} <= Set{3,5})) -- now its OK! +assert(not(Set{1,3} <= Set{3,5})) +assert(not(Set{1,3} >= Set{3,5})) + +t.__eq = function (a,b) + for k in pairs(a) do + if not b[k] then return false end + b[k] = nil + end + return next(b) == nil +end + +local s = Set{1,3,5} +assert(s == Set{3,5,1}) +assert(not rawequal(s, Set{3,5,1})) +assert(rawequal(s, s)) +assert(Set{1,3,5,1} == Set{3,5,1}) +assert(Set{1,3,5} ~= Set{3,5,1,6}) +t[Set{1,3,5}] = 1 +assert(t[Set{1,3,5}] == nil) -- `__eq' is not valid for table accesses + + +t.__concat = function (a,b,c) + assert(c == nil) + if type(a) == 'table' then a = a.val end + if type(b) == 'table' then b = b.val end + if A then return a..b + else + return setmetatable({val=a..b}, t) + end +end + +c = {val="c"}; setmetatable(c, t) +d = {val="d"}; setmetatable(d, t) + +A = true +assert(c..d == 'cd') +assert(0 .."a".."b"..c..d.."e".."f"..(5+3).."g" == "0abcdef8g") + +A = false +x = c..d +assert(getmetatable(x) == t and x.val == 'cd') +x = 0 .."a".."b"..c..d.."e".."f".."g" +assert(x.val == "0abcdefg") + + +-- test comparison compatibilities +local t1, t2, c, d +t1 = {}; c = {}; setmetatable(c, t1) +d = {} +t1.__eq = function () return true end +t1.__lt = function () return true end +assert(c ~= d and not pcall(function () return c < d end)) +setmetatable(d, t1) +assert(c == d and c < d and not(d <= c)) +t2 = {} +t2.__eq = t1.__eq +t2.__lt = t1.__lt +setmetatable(d, t2) +assert(c == d and c < d and not(d <= c)) + + + +-- test for several levels of calls +local i +local tt = { + __call = function (t, ...) + i = i+1 + if t.f then return t.f(...) + else return {...} + end + end +} + +local a = setmetatable({}, tt) +local b = setmetatable({f=a}, tt) +local c = setmetatable({f=b}, tt) + +i = 0 +x = c(3,4,5) +assert(i == 3 and x[1] == 3 and x[3] == 5) + + +assert(_G.X == 20) +assert(_G == getfenv(0)) + +print'+' + +local _g = _G +setfenv(1, setmetatable({}, {__index=function (_,k) return _g[k] end})) + +--[[ +-- testing proxies +assert(getmetatable(newproxy()) == nil) +assert(getmetatable(newproxy(false)) == nil) + +local u = newproxy(true) + +getmetatable(u).__newindex = function (u,k,v) + getmetatable(u)[k] = v +end + +getmetatable(u).__index = function (u,k) + return getmetatable(u)[k] +end + +for i=1,10 do u[i] = i end +for i=1,10 do assert(u[i] == i) end + +local k = newproxy(u) +assert(getmetatable(k) == getmetatable(u)) + + +a = {} +rawset(a, "x", 1, 2, 3) +assert(a.x == 1 and rawget(a, "x", 3) == 1) + +print '+' +--]] + +-- testing metatables for basic types +mt = {} +debug.setmetatable(10, mt) +assert(getmetatable(-2) == mt) +mt.__index = function (a,b) return a+b end +assert((10)[3] == 13) +assert((10)["3"] == 13) +debug.setmetatable(23, nil) +assert(getmetatable(-2) == nil) + +debug.setmetatable(true, mt) +assert(getmetatable(false) == mt) +mt.__index = function (a,b) return a or b end +assert((true)[false] == true) +assert((false)[false] == false) +debug.setmetatable(false, nil) +assert(getmetatable(true) == nil) + +debug.setmetatable(nil, mt) +assert(getmetatable(nil) == mt) +mt.__add = function (a,b) return (a or 0) + (b or 0) end +assert(10 + nil == 10) +assert(nil + 23 == 23) +assert(nil + nil == 0) +debug.setmetatable(nil, nil) +assert(getmetatable(nil) == nil) + +debug.setmetatable(nil, {}) + + +print 'OK' + +return 12 diff --git a/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/files.lua b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/files.lua new file mode 100644 index 0000000000000000000000000000000000000000..b5dc410e5f7e302d25cfd24e02c35b5178997f65 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/files.lua @@ -0,0 +1,313 @@ +local file = os.tmpname() +local otherfile = os.tmpname() + +-- assert(os.setlocale('C', 'all')) + +io.input(io.stdin); io.output(io.stdout); + +os.remove(file) +assert(loadfile(file) == nil) +assert(io.open(file) == nil) +io.output(file) +assert(io.output() ~= io.stdout) + +assert(io.output():seek() == 0) +assert(io.write("alo alo")) +assert(io.output():seek() == string.len("alo alo")) +assert(io.output():seek("cur", -3) == string.len("alo alo")-3) +assert(io.write("joao")) +assert(io.output():seek("end") == string.len("alo joao")) + +assert(io.output():seek("set") == 0) + +assert(io.write('"álo"', "{a}\n", "second line\n", "third line \n")) +assert(io.write('çfourth_line')) +io.output():close() +io.output(io.stdout) +-- collectgarbage() -- file should be closed by GC +assert(io.input() == io.stdin and rawequal(io.output(), io.stdout)) +print('+') + +-- test GC for files +-- collectgarbage() +-- for i=1,120 do +-- for i=1,5 do +-- io.input(file) +-- assert(io.open(file, 'r')) +-- io.lines(file) +-- end +-- collectgarbage() +-- end + +assert(os.rename(file, otherfile)) +assert(os.rename(file, otherfile) == nil) + +io.output(io.open(otherfile, "a")) +assert(io.write("\n\n\t\t 3450\n")); +io.close() + +-- test line generators +assert(os.rename(otherfile, file)) +io.output(otherfile) +local f = io.lines(file) +while f() do end; +assert(not pcall(f)) -- read lines after EOF +assert(not pcall(f)) -- read lines after EOF +-- copy from file to otherfile +for l in io.lines(file) do io.write(l, "\n") end +io.close() +-- copy from otherfile back to file +local f = assert(io.open(otherfile)) +assert(io.type(f) == "file") +io.output(file) +assert(io.output():read() == nil) +for l in f:lines() do io.write(l, "\n") end +assert(f:close()); io.close() +assert(not pcall(io.close, f)) -- error trying to close again +assert(tostring(f) == "file (closed)") +assert(io.type(f) == "closed file") +io.input(file) +local of =io.open(otherfile) +f = of:lines() +for l in io.lines() do + assert(l == f()) +end +of:close() +assert(os.remove(otherfile)) +assert(io.close(io.input())) + +io.input(file) +do -- test error returns + local a,b,c = io.input():write("xuxu") + assert(not a and type(b) == "string" and type(c) == "number") +end +assert(io.read(0) == "") -- not eof +assert(io.read(5, '*l') == '"álo"') +assert(io.read(0) == "") +assert(io.read() == "second line") +local x = io.input():seek() +assert(io.read() == "third line ") +assert(io.input():seek("set", x)) +assert(io.read('*l') == "third line ") +assert(io.read(1) == "ç") +assert(io.read(string.len"fourth_line") == "fourth_line") +assert(io.input():seek("cur", -string.len"fourth_line")) +assert(io.read() == "fourth_line") +assert(io.read() == "") -- empty line +assert(io.read('*n') == 3450) +assert(io.read(1) == '\n') +assert(io.read(0) == nil) -- end of file +assert(io.read(1) == nil) -- end of file +assert(({io.read(1)})[2] == nil) +assert(io.read() == nil) -- end of file +assert(({io.read()})[2] == nil) +assert(io.read('*n') == nil) -- end of file +assert(({io.read('*n')})[2] == nil) +assert(io.read('*a') == '') -- end of file (OK for `*a') +assert(io.read('*a') == '') -- end of file (OK for `*a') +collectgarbage() +print('+') +io.close(io.input()) +assert(not pcall(io.read)) + +assert(os.remove(file)) + +local t = '0123456789' +for i=1,12 do t = t..t; end +assert(string.len(t) == 10*2^12) + +io.output(file) +io.write("alo\n") +io.close() +assert(not pcall(io.write)) +local f = io.open(file, "a") +io.output(f) +collectgarbage() + +assert(io.write(' ' .. t .. ' ')) +assert(io.write(';', 'end of file\n')) +f:flush(); io.flush() +f:close() +print('+') + +io.input(file) +assert(io.read() == "alo") +assert(io.read(1) == ' ') +assert(io.read(string.len(t)) == t) +assert(io.read(1) == ' ') +assert(io.read(0)) +assert(io.read('*a') == ';end of file\n') +assert(io.read(0) == nil) +assert(io.close(io.input())) + +assert(os.remove(file)) +print('+') + +local x1 = "string\n\n\\com \"\"''coisas [[estranhas]] ]]'" +io.output(file) +assert(io.write(string.format("x2 = %q\n-- comment without ending EOS", x1))) +io.close() +assert(loadfile(file))() +assert(x1 == x2) +print('+') +assert(os.remove(file)) +assert(os.remove(file) == nil) +assert(os.remove(otherfile) == nil) + +io.output(file) +assert(io.write("qualquer coisa\n")) +assert(io.write("mais qualquer coisa")) +io.close() +io.output(assert(io.open(otherfile, 'wb'))) +assert(io.write("outra coisa\0\1\3\0\0\0\0\255\0")) +io.close() + +local filehandle = assert(io.open(file, 'r')) +local otherfilehandle = assert(io.open(otherfile, 'rb')) +assert(filehandle ~= otherfilehandle) +assert(type(filehandle) == "userdata") +assert(filehandle:read('*l') == "qualquer coisa") +io.input(otherfilehandle) +assert(io.read(string.len"outra coisa") == "outra coisa") +assert(filehandle:read('*l') == "mais qualquer coisa") +filehandle:close(); +assert(type(filehandle) == "userdata") +io.input(otherfilehandle) +assert(io.read(4) == "\0\1\3\0") +assert(io.read(3) == "\0\0\0") +assert(io.read(0) == "") -- 255 is not eof +assert(io.read(1) == "\255") +assert(io.read('*a') == "\0") +assert(not io.read(0)) +assert(otherfilehandle == io.input()) +otherfilehandle:close() +assert(os.remove(file)) +assert(os.remove(otherfile)) +collectgarbage() + +io.output(file) +io.write[[ + 123.4 -56e-2 not a number +second line +third line + +and the rest of the file +]] +io.close() +io.input(file) +local _,a,b,c,d,e,h,__ = io.read(1, '*n', '*n', '*l', '*l', '*l', '*a', 10) +assert(io.close(io.input())) +assert(_ == ' ' and __ == nil) +assert(type(a) == 'number' and a==123.4 and b==-56e-2) +assert(d=='second line' and e=='third line') +assert(h==[[ + +and the rest of the file +]]) +assert(os.remove(file)) +collectgarbage() + +-- testing buffers +do + local f = assert(io.open(file, "w")) + local fr = assert(io.open(file, "r")) + assert(f:setvbuf("full", 2000)) + f:write("x") + assert(fr:read("*all") == "") -- full buffer; output not written yet + f:close() + fr:seek("set") + assert(fr:read("*all") == "x") -- `close' flushes it + f = assert(io.open(file, "w")) + assert(f:setvbuf("no")) + f:write("x") + fr:seek("set") + assert(fr:read("*all") == "x") -- no buffer; output is ready + f:close() + fr:close() + -- f = assert(io.open(file, "a")) + -- assert(f:setvbuf("line")) + -- f:write("x") + -- fr:seek("set", 1) + -- assert(fr:read("*all") == "") -- line buffer; no output without `\n' + -- f:write("a\n") + -- fr:seek("set", 1) + -- assert(fr:read("*all") == "xa\n") -- now we have a whole line + -- f:close(); fr:close() +end + + +-- testing large files (> BUFSIZ) +io.output(file) +for i=1,5001 do io.write('0123456789123') end +io.write('\n12346') +io.close() +io.input(file) +local x = io.read('*a') +io.input():seek('set', 0) +local y = io.read(30001)..io.read(1005)..io.read(0)..io.read(1)..io.read(100003) +assert(x == y and string.len(x) == 5001*13 + 6) +io.input():seek('set', 0) +y = io.read() -- huge line +assert(x == y..'\n'..io.read()) +assert(io.read() == nil) +io.close(io.input()) +assert(os.remove(file)) +x = nil; y = nil + +x, y = pcall(io.popen, "ls") +if x then + assert(y:read("*a")) + assert(y:close()) +else + (Message or print)('\a\n >>> popen not available<<<\n\a') +end + +print'+' + +local t = os.time() +-- T = os.date("*t", t) +-- loadstring(os.date([[assert(T.year==%Y and T.month==%m and T.day==%d and +-- T.hour==%H and T.min==%M and T.sec==%S and +-- T.wday==%w+1 and T.yday==%j and type(T.isdst) == 'boolean')]], t))() +-- +-- assert(os.time(T) == t) +-- +T = os.date("!*t", t) +-- loadstring(os.date([[!assert(T.year==%Y and T.month==%m and T.day==%d and +-- T.hour==%H and T.min==%M and T.sec==%S and +-- T.wday==%w+1 and T.yday==%j and type(T.isdst) == 'boolean')]], t))() + +do + local T = os.date("*t") + local t = os.time(T) + assert(type(T.isdst) == 'boolean') + T.isdst = nil + local t1 = os.time(T) + assert(t == t1) -- if isdst is absent uses correct default +end + +t = os.time(T) +T.year = T.year-1; +local t1 = os.time(T) +-- allow for leap years +assert(math.abs(os.difftime(t,t1)/(24*3600) - 365) < 2) + +t = os.time() +t1 = os.time(os.date("*t")) +assert(os.difftime(t1,t) <= 2) + +local t1 = os.time{year=2000, month=10, day=1, hour=23, min=12, sec=17} +local t2 = os.time{year=2000, month=10, day=1, hour=23, min=10, sec=19} +assert(os.difftime(t1,t2) == 60*2-2) + +io.output(io.stdout) +local d = os.date('%d') +local m = os.date('%m') +local a = os.date('%Y') +local ds = os.date('%w') + 1 +local h = os.date('%H') +local min = os.date('%M') +local s = os.date('%S') +io.write(string.format('test done on %2.2d/%2.2d/%d', d, m, a)) +io.write(string.format(', at %2.2d:%2.2d:%2.2d\n', h, min, s)) +io.write(string.format('%s\n', _VERSION)) diff --git a/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/gc.lua b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/gc.lua new file mode 100644 index 0000000000000000000000000000000000000000..86a9f7582c652dc897e90359e62fbb5202a4a48e --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/gc.lua @@ -0,0 +1,312 @@ +print('testing garbage collection') + +collectgarbage() + +_G["while"] = 234 + +limit = 5000 + + + +contCreate = 0 + +print('tables') +while contCreate <= limit do + local a = {}; a = nil + contCreate = contCreate+1 +end + +a = "a" + +contCreate = 0 +print('strings') +while contCreate <= limit do + a = contCreate .. "b"; + a = string.gsub(a, '(%d%d*)', string.upper) + a = "a" + contCreate = contCreate+1 +end + + +contCreate = 0 + +a = {} + +print('functions') +function a:test () + while contCreate <= limit do + loadstring(string.format("function temp(a) return 'a%d' end", contCreate))() + assert(temp() == string.format('a%d', contCreate)) + contCreate = contCreate+1 + end +end + +a:test() + +-- collection of functions without locals, globals, etc. +do local f = function () end end + + +print("functions with errors") +prog = [[ +do + a = 10; + function foo(x,y) + a = sin(a+0.456-0.23e-12); + return function (z) return sin(%x+z) end + end + local x = function (w) a=a+w; end +end +]] +do + local step = 1 + if rawget(_G, "_soft") then step = 13 end + for i=1, string.len(prog), step do + for j=i, string.len(prog), step do + pcall(loadstring(string.sub(prog, i, j))) + end + end +end + +print('long strings') +x = "01234567890123456789012345678901234567890123456789012345678901234567890123456789" +assert(string.len(x)==80) +s = '' +n = 0 +k = 300 +while n < k do s = s..x; n=n+1; j=tostring(n) end +assert(string.len(s) == k*80) +s = string.sub(s, 1, 20000) +s, i = string.gsub(s, '(%d%d%d%d)', math.sin) +assert(i==20000/4) +s = nil +x = nil + +assert(_G["while"] == 234) + + +local bytes = gcinfo() +while 1 do + local nbytes = gcinfo() + if nbytes < bytes then break end -- run until gc + bytes = nbytes + a = {} +end + + +local function dosteps (siz) + collectgarbage() + collectgarbage"stop" + local a = {} + for i=1,100 do a[i] = {{}}; local b = {} end + local x = gcinfo() + local i = 0 + repeat + i = i+1 + until collectgarbage("step", siz) + assert(gcinfo() < x) + return i +end + +assert(dosteps(0) > 10) +assert(dosteps(6) < dosteps(2)) +assert(dosteps(10000) == 1) +assert(collectgarbage("step", 1000000) == true) +assert(collectgarbage("step", 1000000)) + + +do + local x = gcinfo() + collectgarbage() + collectgarbage"stop" + repeat + local a = {} + until gcinfo() > 1000 + collectgarbage"restart" + repeat + local a = {} + until gcinfo() < 1000 +end + +lim = 15 +a = {} +-- fill a with `collectable' indices +for i=1,lim do a[{}] = i end +b = {} +for k,v in pairs(a) do b[k]=v end +-- remove all indices and collect them +for n in pairs(b) do + a[n] = nil + assert(type(n) == 'table' and next(n) == nil) + collectgarbage() +end +b = nil +collectgarbage() +for n in pairs(a) do error'cannot be here' end +for i=1,lim do a[i] = i end +for i=1,lim do assert(a[i] == i) end + + +print('weak tables') +a = {}; setmetatable(a, {__mode = 'k'}); +-- fill a with some `collectable' indices +for i=1,lim do a[{}] = i end +-- and some non-collectable ones +for i=1,lim do local t={}; a[t]=t end +for i=1,lim do a[i] = i end +for i=1,lim do local s=string.rep('@', i); a[s] = s..'#' end +collectgarbage() +local i = 0 +for k,v in pairs(a) do assert(k==v or k..'#'==v); i=i+1 end +assert(i == 3*lim) + +a = {}; setmetatable(a, {__mode = 'v'}); +a[1] = string.rep('b', 21) +collectgarbage() +assert(a[1]) -- strings are *values* +a[1] = nil +-- fill a with some `collectable' values (in both parts of the table) +for i=1,lim do a[i] = {} end +for i=1,lim do a[i..'x'] = {} end +-- and some non-collectable ones +for i=1,lim do local t={}; a[t]=t end +for i=1,lim do a[i+lim]=i..'x' end +collectgarbage() +local i = 0 +for k,v in pairs(a) do assert(k==v or k-lim..'x' == v); i=i+1 end +assert(i == 2*lim) + +a = {}; setmetatable(a, {__mode = 'vk'}); +local x, y, z = {}, {}, {} +-- keep only some items +a[1], a[2], a[3] = x, y, z +a[string.rep('$', 11)] = string.rep('$', 11) +-- fill a with some `collectable' values +for i=4,lim do a[i] = {} end +for i=1,lim do a[{}] = i end +for i=1,lim do local t={}; a[t]=t end +collectgarbage() +assert(next(a) ~= nil) +local i = 0 +for k,v in pairs(a) do + assert((k == 1 and v == x) or + (k == 2 and v == y) or + (k == 3 and v == z) or k==v); + i = i+1 +end +assert(i == 4) +x,y,z=nil +collectgarbage() +assert(next(a) == string.rep('$', 11)) + + +-- testing userdata +collectgarbage("stop") -- stop collection +local u = newproxy(true) +local s = 0 +local a = {[u] = 0}; setmetatable(a, {__mode = 'vk'}) +for i=1,10 do a[newproxy(u)] = i end +for k in pairs(a) do assert(getmetatable(k) == getmetatable(u)) end +local a1 = {}; for k,v in pairs(a) do a1[k] = v end +for k,v in pairs(a1) do a[v] = k end +for i =1,10 do assert(a[i]) end +getmetatable(u).a = a1 +getmetatable(u).u = u +do + local u = u + getmetatable(u).__gc = function (o) + assert(a[o] == 10-s) + assert(a[10-s] == nil) -- udata already removed from weak table + assert(getmetatable(o) == getmetatable(u)) + assert(getmetatable(o).a[o] == 10-s) + s=s+1 + end +end +a1, u = nil +assert(next(a) ~= nil) +collectgarbage() +assert(s==11) +collectgarbage() +assert(next(a) == nil) -- finalized keys are removed in two cycles + + +-- __gc x weak tables +local u = newproxy(true) +setmetatable(getmetatable(u), {__mode = "v"}) +getmetatable(u).__gc = function (o) os.exit(1) end -- cannot happen +collectgarbage() + +local u = newproxy(true) +local m = getmetatable(u) +m.x = {[{0}] = 1; [0] = {1}}; setmetatable(m.x, {__mode = "kv"}); +m.__gc = function (o) + assert(next(getmetatable(o).x) == nil) + m = 10 +end +u, m = nil +collectgarbage() +assert(m==10) + + +-- errors during collection +u = newproxy(true) +getmetatable(u).__gc = function () error "!!!" end +u = nil +assert(not pcall(collectgarbage)) + + +if not rawget(_G, "_soft") then + print("deep structures") + local a = {} + for i = 1,200000 do + a = {next = a} + end + collectgarbage() +end + +-- create many threads with self-references and open upvalues +local thread_id = 0 +local threads = {} + +function fn(thread) + local x = {} + threads[thread_id] = function() + thread = x + end + coroutine.yield() +end + +while thread_id < 1000 do + local thread = coroutine.create(fn) + coroutine.resume(thread, thread) + thread_id = thread_id + 1 +end + + + +-- create a userdata to be collected when state is closed +do + local newproxy,assert,type,print,getmetatable = + newproxy,assert,type,print,getmetatable + local u = newproxy(true) + local tt = getmetatable(u) + ___Glob = {u} -- avoid udata being collected before program end + tt.__gc = function (o) + assert(getmetatable(o) == tt) + -- create new objects during GC + local a = 'xuxu'..(10+3)..'joao', {} + ___Glob = o -- ressurect object! + newproxy(o) -- creates a new one with same metatable + print(">>> closing state " .. "<<<\n") + end +end + +-- create several udata to raise errors when collected while closing state +do + local u = newproxy(true) + getmetatable(u).__gc = function (o) return o + 1 end + table.insert(___Glob, u) -- preserve udata until the end + for i = 1,10 do table.insert(___Glob, newproxy(u)) end +end + +print('OK') diff --git a/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/literals.lua b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/literals.lua new file mode 100644 index 0000000000000000000000000000000000000000..01d84d5af676bf553e237855f83574dfd0f2fd0d --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/literals.lua @@ -0,0 +1,176 @@ +print('testing scanner') + +local function dostring (x) return assert(loadstring(x))() end + +dostring("x = 'a\0a'") +assert(x == 'a\0a' and string.len(x) == 3) + +-- escape sequences +assert('\n\"\'\\' == [[ + +"'\]]) + +assert(string.find("\a\b\f\n\r\t\v", "^%c%c%c%c%c%c%c$")) + +-- assume ASCII just for tests: +assert("\09912" == 'c12') +assert("\99ab" == 'cab') +assert("\099" == '\99') +assert("\099\n" == 'c\10') +assert('\0\0\0alo' == '\0' .. '\0\0' .. 'alo') + +assert(010 .. 020 .. -030 == "1020-30") + +-- long variable names + +var = string.rep('a', 15000) +prog = string.format("%s = 5", var) +dostring(prog) +assert(_G[var] == 5) +var = nil +print('+') + +-- escapes -- +assert("\n\t" == [[ + + ]]) +assert([[ + + $debug]] == "\n $debug") +assert([[ [ ]] ~= [[ ] ]]) +-- long strings -- +b = "001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789" +assert(string.len(b) == 960) +prog = [=[ +print('+') + +a1 = [["isto e' um string com várias 'aspas'"]] +a2 = "'aspas'" + +assert(string.find(a1, a2) == 31) +print('+') + +a1 = [==[temp = [[um valor qualquer]]; ]==] +assert(loadstring(a1))() +assert(temp == 'um valor qualquer') +-- long strings -- +b = "001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789" +assert(string.len(b) == 960) +print('+') + +a = [[00123456789012345678901234567890123456789123456789012345678901234567890123456789 +00123456789012345678901234567890123456789123456789012345678901234567890123456789 +00123456789012345678901234567890123456789123456789012345678901234567890123456789 +00123456789012345678901234567890123456789123456789012345678901234567890123456789 +00123456789012345678901234567890123456789123456789012345678901234567890123456789 +00123456789012345678901234567890123456789123456789012345678901234567890123456789 +00123456789012345678901234567890123456789123456789012345678901234567890123456789 +00123456789012345678901234567890123456789123456789012345678901234567890123456789 +00123456789012345678901234567890123456789123456789012345678901234567890123456789 +00123456789012345678901234567890123456789123456789012345678901234567890123456789 +00123456789012345678901234567890123456789123456789012345678901234567890123456789 +00123456789012345678901234567890123456789123456789012345678901234567890123456789 +00123456789012345678901234567890123456789123456789012345678901234567890123456789 +00123456789012345678901234567890123456789123456789012345678901234567890123456789 +00123456789012345678901234567890123456789123456789012345678901234567890123456789 +00123456789012345678901234567890123456789123456789012345678901234567890123456789 +00123456789012345678901234567890123456789123456789012345678901234567890123456789 +00123456789012345678901234567890123456789123456789012345678901234567890123456789 +00123456789012345678901234567890123456789123456789012345678901234567890123456789 +00123456789012345678901234567890123456789123456789012345678901234567890123456789 +00123456789012345678901234567890123456789123456789012345678901234567890123456789 +00123456789012345678901234567890123456789123456789012345678901234567890123456789 +00123456789012345678901234567890123456789123456789012345678901234567890123456789 +]] +assert(string.len(a) == 1863) +assert(string.sub(a, 1, 40) == string.sub(b, 1, 40)) +x = 1 +]=] + +print('+') +x = nil +dostring(prog) +assert(x) + +prog = nil +a = nil +b = nil + + +-- testing line ends +prog = [[ +a = 1 -- a comment +b = 2 + + +x = [=[ +hi +]=] +y = "\ +hello\r\n\ +" +return debug.getinfo(1).currentline +]] + +for _, n in pairs{"\n", "\r", "\n\r", "\r\n"} do + local prog, nn = string.gsub(prog, "\n", n) + assert(dostring(prog) == nn) + assert(_G.x == "hi\n" and _G.y == "\nhello\r\n\n") +end + + +-- testing comments and strings with long brackets +a = [==[]=]==] +assert(a == "]=") + +a = [==[[===[[=[]]=][====[]]===]===]==] +assert(a == "[===[[=[]]=][====[]]===]===") + +a = [====[[===[[=[]]=][====[]]===]===]====] +assert(a == "[===[[=[]]=][====[]]===]===") + +a = [=[]]]]]]]]]=] +assert(a == "]]]]]]]]") + + +--[===[ +x y z [==[ blu foo +]== +] +]=]==] +error error]=]===] + +-- generate all strings of four of these chars +local x = {"=", "[", "]", "\n"} +local len = 4 +local function gen (c, n) + if n==0 then coroutine.yield(c) + else + for _, a in pairs(x) do + gen(c..a, n-1) + end + end +end + +for s in coroutine.wrap(function () gen("", len) end) do + assert(s == loadstring("return [====[\n"..s.."]====]")()) +end + + +-- testing decimal point locale +if os.setlocale("pt_BR") or os.setlocale("ptb") then + assert(tonumber("3,4") == 3.4 and tonumber"3.4" == nil) + assert(assert(loadstring("return 3.4"))() == 3.4) + assert(assert(loadstring("return .4,3"))() == .4) + assert(assert(loadstring("return 4."))() == 4.) + assert(assert(loadstring("return 4.+.5"))() == 4.5) + local a,b = loadstring("return 4.5.") + assert(string.find(b, "'4%.5%.'")) + assert(os.setlocale("C")) +else + (Message or print)( + '\a\n >>> pt_BR locale not available: skipping decimal point tests <<<\n\a') +end + + +print('OK') diff --git a/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/locals.lua b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/locals.lua new file mode 100644 index 0000000000000000000000000000000000000000..b0fc556f697555c372622ac77ae2854ca2353ba6 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/locals.lua @@ -0,0 +1,127 @@ +print('testing local variables plus some extra stuff') + +do + local i = 10 + do local i = 100; assert(i==100) end + do local i = 1000; assert(i==1000) end + assert(i == 10) + if i ~= 10 then + local i = 20 + else + local i = 30 + assert(i == 30) + end +end + + + +f = nil + +local f +x = 1 + +a = nil +loadstring('local a = {}')() +assert(type(a) ~= 'table') + +function f (a) + local _1, _2, _3, _4, _5 + local _6, _7, _8, _9, _10 + local x = 3 + local b = a + local c,d = a,b + if (d == b) then + local x = 'q' + x = b + assert(x == 2) + else + assert(nil) + end + assert(x == 3) + local f = 10 +end + +local b=10 +local a; repeat local b; a,b=1,2; assert(a+1==b); until a+b==3 + + +assert(x == 1) + +f(2) +assert(type(f) == 'function') + + +-- testing globals ;-) +do + local f = {} + local _G = _G + for i=1,10 do f[i] = function (x) A=A+1; return A, _G.getfenv(x) end end + A=10; assert(f[1]() == 11) + for i=1,10 do assert(setfenv(f[i], {A=i}) == f[i]) end + assert(f[3]() == 4 and A == 11) + local a,b = f[8](1) + assert(b.A == 9) + a,b = f[8](0) + assert(b.A == 11) -- `real' global + local g + local function f () assert(setfenv(2, {a='10'}) == g) end + g = function () f(); _G.assert(_G.getfenv(1).a == '10') end + g(); assert(getfenv(g).a == '10') +end + +-- test for global table of loaded chunks +local function foo (s) + return loadstring(s) +end + +assert(getfenv(foo("")) == _G) +local a = {loadstring = loadstring} +setfenv(foo, a) +assert(getfenv(foo("")) == _G) +setfenv(0, a) -- change global environment +assert(getfenv(foo("")) == a) +setfenv(0, _G) + + +-- testing limits for special instructions + +local a +local p = 4 +for i=2,31 do + for j=-3,3 do + assert(loadstring(string.format([[local a=%s;a=a+ + %s; + assert(a + ==2^%s)]], j, p-j, i))) () + assert(loadstring(string.format([[local a=%s; + a=a-%s; + assert(a==-2^%s)]], -j, p-j, i))) () + assert(loadstring(string.format([[local a,b=0,%s; + a=b-%s; + assert(a==-2^%s)]], -j, p-j, i))) () + end + p =2*p +end + +print'+' + + +if rawget(_G, "querytab") then + -- testing clearing of dead elements from tables + collectgarbage("stop") -- stop GC + local a = {[{}] = 4, [3] = 0, alo = 1, + a1234567890123456789012345678901234567890 = 10} + + local t = querytab(a) + + for k,_ in pairs(a) do a[k] = nil end + collectgarbage() -- restore GC and collect dead fiels in `a' + for i=0,t-1 do + local k = querytab(a, i) + assert(k == nil or type(k) == 'number' or k == 'alo') + end +end + +print('OK') + +return 5,f diff --git a/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/main.lua b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/main.lua new file mode 100644 index 0000000000000000000000000000000000000000..22b4f74b027bf7b5c52610b2ecfb401b70117b36 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/main.lua @@ -0,0 +1,159 @@ +# testing special comment on first line + +print ("testing lua.c options") + +assert(os.execute() ~= 0) -- machine has a system command + +prog = os.tmpname() +otherprog = os.tmpname() +out = os.tmpname() + +do + local i = 0 + while arg[i] do i=i-1 end + progname = '"'..arg[i+1]..'"' +end +print(progname) + +local prepfile = function (s, p) + p = p or prog + io.output(p) + io.write(s) + assert(io.close()) +end + +function checkout (s) + io.input(out) + local t = io.read("*a") + io.input():close() + assert(os.remove(out)) + if s ~= t then print(string.format("'%s' - '%s'\n", s, t)) end + assert(s == t) + return t +end + +function auxrun (...) + local s = string.format(...) + s = string.gsub(s, "lua", progname, 1) + return os.execute(s) +end + +function RUN (...) + assert(auxrun(...) == 0) +end + +function NoRun (...) + print("\n(the next error is expected by the test)") + assert(auxrun(...) ~= 0) +end + +-- test 2 files +prepfile("print(1); a=2") +prepfile("print(a)", otherprog) +RUN("lua -l %s -l%s -lstring -l io %s > %s", prog, otherprog, otherprog, out) +checkout("1\n2\n2\n") + +local a = [[ + assert(table.getn(arg) == 3 and arg[1] == 'a' and + arg[2] == 'b' and arg[3] == 'c') + assert(arg[-1] == '--' and arg[-2] == "-e " and arg[-3] == %s) + assert(arg[4] == nil and arg[-4] == nil) + local a, b, c = ... + assert(... == 'a' and a == 'a' and b == 'b' and c == 'c') +]] +a = string.format(a, progname) +prepfile(a) +RUN('lua "-e " -- %s a b c', prog) + +prepfile"assert(arg==nil)" +prepfile("assert(arg)", otherprog) +RUN("lua -l%s - < %s", prog, otherprog) + +prepfile"" +RUN("lua - < %s > %s", prog, out) +checkout("") + +-- test many arguments +prepfile[[print(({...})[30])]] +RUN("lua %s %s > %s", prog, string.rep(" a", 30), out) +checkout("a\n") + +RUN([[lua "-eprint(1)" -ea=3 -e "print(a)" > %s]], out) +checkout("1\n3\n") + +prepfile[[ + print( +1, a +) +]] +RUN("lua - < %s > %s", prog, out) +checkout("1\tnil\n") + +prepfile[[ += (6*2-6) -- === +a += 10 +print(a) += a]] +RUN([[lua -e"_PROMPT='' _PROMPT2=''" -i < %s > %s]], prog, out) +checkout("6\n10\n10\n\n") + +prepfile("a = [[b\nc\nd\ne]]\n=a") +print(prog) +RUN([[lua -e"_PROMPT='' _PROMPT2=''" -i < %s > %s]], prog, out) +checkout("b\nc\nd\ne\n\n") + +prompt = "alo" +prepfile[[ -- +a = 2 +]] +RUN([[lua "-e_PROMPT='%s'" -i < %s > %s]], prompt, prog, out) +checkout(string.rep(prompt, 3).."\n") + +s = [=[ -- +function f ( x ) + local a = [[ +xuxu +]] + local b = "\ +xuxu\n" + if x == 11 then return 1 , 2 end --[[ test multiple returns ]] + return x + 1 + --\\ +end +=( f( 10 ) ) +assert( a == b ) +=f( 11 ) ]=] +s = string.gsub(s, ' ', '\n\n') +prepfile(s) +RUN([[lua -e"_PROMPT='' _PROMPT2=''" -i < %s > %s]], prog, out) +checkout("11\n1\t2\n\n") + +prepfile[[#comment in 1st line without \n at the end]] +RUN("lua %s", prog) + +prepfile("#comment with a binary file\n"..string.dump(loadstring("print(1)"))) +RUN("lua %s > %s", prog, out) +checkout("1\n") + +prepfile("#comment with a binary file\r\n"..string.dump(loadstring("print(1)"))) +RUN("lua %s > %s", prog, out) +checkout("1\n") + +-- close Lua with an open file +prepfile(string.format([[io.output(%q); io.write('alo')]], out)) +RUN("lua %s", prog) +checkout('alo') + +assert(os.remove(prog)) +assert(os.remove(otherprog)) +assert(not os.remove(out)) + +RUN("lua -v") + +NoRun("lua -h") +NoRun("lua -e") +NoRun("lua -e a") +NoRun("lua -f") + +print("OK") diff --git a/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/math.lua b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/math.lua new file mode 100644 index 0000000000000000000000000000000000000000..21429a6f1c9da76ccc2623fb73ee20816a11b4c0 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/math.lua @@ -0,0 +1,210 @@ +print("testing numbers and math lib") + +do + local a,b,c = "2", " 3e0 ", " 10 " + assert(a+b == 5 and -b == -3 and b+"2" == 5 and "10"-c == 0) + assert(type(a) == 'string' and type(b) == 'string' and type(c) == 'string') + assert(a == "2" and b == " 3e0 " and c == " 10 " and -c == -" 10 ") + assert(c%a == 0 and a^b == 8) +end + + +do + local a,b = math.modf(3.5) + assert(a == 3 and b == 0.5) + assert(math.huge > 10e30) + assert(-math.huge < -10e30) +end + +function f(...) + if select('#', ...) == 1 then + return (...) + else + return "***" + end +end + +assert(tonumber{} == nil) +assert(tonumber'+0.01' == 1/100 and tonumber'+.01' == 0.01 and + tonumber'.01' == 0.01 and tonumber'-1.' == -1 and + tonumber'+1.' == 1) +assert(tonumber'+ 0.01' == nil and tonumber'+.e1' == nil and + tonumber'1e' == nil and tonumber'1.0e+' == nil and + tonumber'.' == nil) +assert(tonumber('-12') == -10-2) +assert(tonumber('-1.2e2') == - - -120) +assert(f(tonumber('1 a')) == nil) +assert(f(tonumber('e1')) == nil) +assert(f(tonumber('e 1')) == nil) +assert(f(tonumber(' 3.4.5 ')) == nil) +assert(f(tonumber('')) == nil) +assert(f(tonumber('', 8)) == nil) +assert(f(tonumber(' ')) == nil) +assert(f(tonumber(' ', 9)) == nil) +assert(f(tonumber('99', 8)) == nil) +assert(tonumber(' 1010 ', 2) == 10) +assert(tonumber('10', 36) == 36) +assert(tonumber('\n -10 \n', 36) == -36) +assert(tonumber('-fFfa', 16) == -(10+(16*(15+(16*(15+(16*15))))))) +assert(tonumber('fFfa', 15) == nil) +assert(tonumber(string.rep('1', 42), 2) + 1 == 2^42) +assert(tonumber(string.rep('1', 32), 2) + 1 == 2^32) +assert(tonumber('-fffffFFFFF', 16)-1 == -2^40) +assert(tonumber('ffffFFFF', 16)+1 == 2^32) +assert(tonumber('0xF') == 15) + +assert(1.1 == 1.+.1) +print(100.0, 1E2, .01) +assert(100.0 == 1E2 and .01 == 1e-2) +assert(1111111111111111-1111111111111110== 1000.00e-03) +-- 1234567890123456 +assert(1.1 == '1.'+'.1') +assert('1111111111111111'-'1111111111111110' == tonumber" +0.001e+3 \n\t") + +function eq (a,b,limit) + if not limit then limit = 10E-10 end + return math.abs(a-b) <= limit +end + +assert(0.1e-30 > 0.9E-31 and 0.9E30 < 0.1e31) + +assert(0.123456 > 0.123455) + +assert(tonumber('+1.23E30') == 1.23*10^30) + +-- testing order operators +assert(not(1<1) and (1<2) and not(2<1)) +assert(not('a'<'a') and ('a'<'b') and not('b'<'a')) +assert((1<=1) and (1<=2) and not(2<=1)) +assert(('a'<='a') and ('a'<='b') and not('b'<='a')) +assert(not(1>1) and not(1>2) and (2>1)) +assert(not('a'>'a') and not('a'>'b') and ('b'>'a')) +assert((1>=1) and not(1>=2) and (2>=1)) +assert(('a'>='a') and not('a'>='b') and ('b'>='a')) + +-- testing mod operator +assert(-4%3 == 2) +assert(4%-3 == -2) +assert(math.pi - math.pi % 1 == 3) +assert(math.pi - math.pi % 0.001 == 3.141) + +local function testbit(a, n) + return a/2^n % 2 >= 1 +end + +assert(eq(math.sin(-9.8)^2 + math.cos(-9.8)^2, 1)) +assert(eq(math.tan(math.pi/4), 1)) +assert(eq(math.sin(math.pi/2), 1) and eq(math.cos(math.pi/2), 0)) +assert(eq(math.atan(1), math.pi/4) and eq(math.acos(0), math.pi/2) and + eq(math.asin(1), math.pi/2)) +assert(eq(math.deg(math.pi/2), 90) and eq(math.rad(90), math.pi/2)) +assert(math.abs(-10) == 10) +assert(eq(math.atan2(1,0), math.pi/2)) +assert(math.ceil(4.5) == 5.0) +assert(math.floor(4.5) == 4.0) +assert(math.mod(10,3) == 1) +assert(eq(math.sqrt(10)^2, 10)) +assert(eq(math.log10(2), math.log(2)/math.log(10))) +assert(eq(math.exp(0), 1)) +assert(eq(math.sin(10), math.sin(10%(2*math.pi)))) +local v,e = math.frexp(math.pi) +assert(eq(math.ldexp(v,e), math.pi)) + +assert(eq(math.tanh(3.5), math.sinh(3.5)/math.cosh(3.5))) + +assert(tonumber(' 1.3e-2 ') == 1.3e-2) +assert(tonumber(' -1.00000000000001 ') == -1.00000000000001) + +-- testing constant limits +-- 2^23 = 8388608 +assert(8388609 + -8388609 == 0) +assert(8388608 + -8388608 == 0) +assert(8388607 + -8388607 == 0) + +if rawget(_G, "_soft") then return end + +f = io.tmpfile() +assert(f) +f:write("a = {") +i = 1 +repeat + f:write("{", math.sin(i), ", ", math.cos(i), ", ", i/3, "},\n") + i=i+1 +until i > 1000 +f:write("}") +f:seek("set", 0) +assert(loadstring(f:read('*a')))() +assert(f:close()) + +assert(eq(a[300][1], math.sin(300))) +assert(eq(a[600][1], math.sin(600))) +assert(eq(a[500][2], math.cos(500))) +assert(eq(a[800][2], math.cos(800))) +assert(eq(a[200][3], 200/3)) +assert(eq(a[1000][3], 1000/3, 0.001)) +print('+') + +do -- testing NaN + local NaN = 10e500 - 10e400 + assert(NaN ~= NaN) + assert(not (NaN < NaN)) + assert(not (NaN <= NaN)) + assert(not (NaN > NaN)) + assert(not (NaN >= NaN)) + assert(not (0 < NaN)) + assert(not (NaN < 0)) + local a = {} + assert(not pcall(function () a[NaN] = 1 end)) + assert(a[NaN] == nil) + a[1] = 1 + assert(not pcall(function () a[NaN] = 1 end)) + assert(a[NaN] == nil) +end + +require "checktable" +stat(a) + +a = nil + +-- testing implicit convertions + +local a,b = '10', '20' +assert(a*b == 200 and a+b == 30 and a-b == -10 and a/b == 0.5 and -b == -20) +assert(a == '10' and b == '20') + + +math.randomseed(0) + +local i = 0 +local Max = 0 +local Min = 2 +repeat + local t = math.random() + Max = math.max(Max, t) + Min = math.min(Min, t) + i=i+1 + flag = eq(Max, 1, 0.001) and eq(Min, 0, 0.001) +until flag or i>10000 +assert(0 <= Min and Max<1) +assert(flag); + +for i=1,10 do + local t = math.random(5) + assert(1 <= t and t <= 5) +end + +i = 0 +Max = -200 +Min = 200 +repeat + local t = math.random(-10,0) + Max = math.max(Max, t) + Min = math.min(Min, t) + i=i+1 + flag = (Max == 0 and Min == -10) +until flag or i>10000 +assert(-10 <= Min and Max<=0) +assert(flag); + + +print('OK') diff --git a/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/nextvar.lua b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/nextvar.lua new file mode 100644 index 0000000000000000000000000000000000000000..23be43d8eca5a698cb53061027a358ce05f24656 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/nextvar.lua @@ -0,0 +1,396 @@ +print('testing tables, next, and for') + +local a = {} + +-- make sure table has lots of space in hash part +for i=1,100 do a[i.."+"] = true end +for i=1,100 do a[i.."+"] = nil end +-- fill hash part with numeric indices testing size operator +for i=1,100 do + a[i] = true + assert(#a == i) +end + + +if T then +-- testing table sizes + +local l2 = math.log(2) +local function log2 (x) return math.log(x)/l2 end + +local function mp2 (n) -- minimum power of 2 >= n + local mp = 2^math.ceil(log2(n)) + assert(n == 0 or (mp/2 < n and n <= mp)) + return mp +end + +local function fb (n) + local r, nn = T.int2fb(n) + assert(r < 256) + return nn +end + +-- test fb function +local a = 1 +local lim = 2^30 +while a < lim do + local n = fb(a) + assert(a <= n and n <= a*1.125) + a = math.ceil(a*1.3) +end + + +local function check (t, na, nh) + local a, h = T.querytab(t) + if a ~= na or h ~= nh then + print(na, nh, a, h) + assert(nil) + end +end + +-- testing constructor sizes +local lim = 40 +local s = 'return {' +for i=1,lim do + s = s..i..',' + local s = s + for k=0,lim do + local t = loadstring(s..'}')() + assert(#t == i) + check(t, fb(i), mp2(k)) + s = string.format('%sa%d=%d,', s, k, k) + end +end + + +-- tests with unknown number of elements +local a = {} +for i=1,lim do a[i] = i end -- build auxiliary table +for k=0,lim do + local a = {unpack(a,1,k)} + assert(#a == k) + check(a, k, 0) + a = {1,2,3,unpack(a,1,k)} + check(a, k+3, 0) + assert(#a == k + 3) +end + + +print'+' + +-- testing tables dynamically built +local lim = 130 +local a = {}; a[2] = 1; check(a, 0, 1) +a = {}; a[0] = 1; check(a, 0, 1); a[2] = 1; check(a, 0, 2) +a = {}; a[0] = 1; a[1] = 1; check(a, 1, 1) +a = {} +for i = 1,lim do + a[i] = 1 + assert(#a == i) + check(a, mp2(i), 0) +end + +a = {} +for i = 1,lim do + a['a'..i] = 1 + assert(#a == 0) + check(a, 0, mp2(i)) +end + +a = {} +for i=1,16 do a[i] = i end +check(a, 16, 0) +for i=1,11 do a[i] = nil end +for i=30,40 do a[i] = nil end -- force a rehash (?) +check(a, 0, 8) +a[10] = 1 +for i=30,40 do a[i] = nil end -- force a rehash (?) +check(a, 0, 8) +for i=1,14 do a[i] = nil end +for i=30,50 do a[i] = nil end -- force a rehash (?) +check(a, 0, 4) + +-- reverse filling +for i=1,lim do + local a = {} + for i=i,1,-1 do a[i] = i end -- fill in reverse + check(a, mp2(i), 0) +end + +-- size tests for vararg +lim = 35 +function foo (n, ...) + local arg = {...} + check(arg, n, 0) + assert(select('#', ...) == n) + arg[n+1] = true + check(arg, mp2(n+1), 0) + arg.x = true + check(arg, mp2(n+1), 1) +end +local a = {} +for i=1,lim do a[i] = true; foo(i, unpack(a)) end + +end + + +-- test size operation on empty tables +assert(#{} == 0) +assert(#{nil} == 0) +assert(#{nil, nil} == 0) +assert(#{nil, nil, nil} == 0) +assert(#{nil, nil, nil, nil} == 0) +print'+' + + +local nofind = {} + +a,b,c = 1,2,3 +a,b,c = nil + +local function find (name) + local n,v + while 1 do + n,v = next(_G, n) + if not n then return nofind end + assert(v ~= nil) + if n == name then return v end + end +end + +local function find1 (name) + for n,v in pairs(_G) do + if n==name then return v end + end + return nil -- not found +end + +do -- create 10000 new global variables + for i=1,10000 do _G[i] = i end +end + + +a = {x=90, y=8, z=23} +assert(table.foreach(a, function(i,v) if i=='x' then return v end end) == 90) +assert(table.foreach(a, function(i,v) if i=='a' then return v end end) == nil) +table.foreach({}, error) + +table.foreachi({x=10, y=20}, error) +local a = {n = 1} +table.foreachi({n=3}, function (i, v) + assert(a.n == i and not v) + a.n=a.n+1 +end) +a = {10,20,30,nil,50} +table.foreachi(a, function (i,v) assert(a[i] == v) end) +assert(table.foreachi({'a', 'b', 'c'}, function (i,v) + if i==2 then return v end + end) == 'b') + + +assert(print==find("print") and print == find1("print")) +assert(_G["print"]==find("print")) +assert(assert==find1("assert")) +assert(nofind==find("return")) +assert(not find1("return")) +_G["ret" .. "urn"] = nil +assert(nofind==find("return")) +_G["xxx"] = 1 +assert(xxx==find("xxx")) +print('+') + +a = {} +for i=0,10000 do + if math.mod(i,10) ~= 0 then + a['x'..i] = i + end +end + +n = {n=0} +for i,v in pairs(a) do + n.n = n.n+1 + assert(i and v and a[i] == v) +end +assert(n.n == 9000) +a = nil + +-- remove those 10000 new global variables +for i=1,10000 do _G[i] = nil end + +do -- clear global table + local a = {} + local preserve = {io = 1, string = 1, debug = 1, os = 1, + coroutine = 1, table = 1, math = 1} + for n,v in pairs(_G) do a[n]=v end + for n,v in pairs(a) do + if not preserve[n] and type(v) ~= "function" and + not string.find(n, "^[%u_]") then + _G[n] = nil + end + collectgarbage() + end +end + +local function foo () + local getfenv, setfenv, assert, next = + getfenv, setfenv, assert, next + local n = {gl1=3} + setfenv(foo, n) + assert(getfenv(foo) == getfenv(1)) + assert(getfenv(foo) == n) + assert(print == nil and gl1 == 3) + gl1 = nil + gl = 1 + assert(n.gl == 1 and next(n, 'gl') == nil) +end +foo() + +print'+' + +local function checknext (a) + local b = {} + table.foreach(a, function (k,v) b[k] = v end) + for k,v in pairs(b) do assert(a[k] == v) end + for k,v in pairs(a) do assert(b[k] == v) end + b = {} + do local k,v = next(a); while k do b[k] = v; k,v = next(a,k) end end + for k,v in pairs(b) do assert(a[k] == v) end + for k,v in pairs(a) do assert(b[k] == v) end +end + +checknext{1,x=1,y=2,z=3} +checknext{1,2,x=1,y=2,z=3} +checknext{1,2,3,x=1,y=2,z=3} +checknext{1,2,3,4,x=1,y=2,z=3} +checknext{1,2,3,4,5,x=1,y=2,z=3} + +assert(table.getn{} == 0) +assert(table.getn{[-1] = 2} == 0) +assert(table.getn{1,2,3,nil,nil} == 3) +for i=0,40 do + local a = {} + for j=1,i do a[j]=j end + assert(table.getn(a) == i) +end + + +assert(table.maxn{} == 0) +assert(table.maxn{["1000"] = true} == 0) +assert(table.maxn{["1000"] = true, [24.5] = 3} == 24.5) +assert(table.maxn{[1000] = true} == 1000) +assert(table.maxn{[10] = true, [100*math.pi] = print} == 100*math.pi) + + +-- int overflow +a = {} +for i=0,50 do a[math.pow(2,i)] = true end +assert(a[table.getn(a)]) + +print("+") + + +-- erasing values +local t = {[{1}] = 1, [{2}] = 2, [string.rep("x ", 4)] = 3, + [100.3] = 4, [4] = 5} + +local n = 0 +for k, v in pairs( t ) do + n = n+1 + assert(t[k] == v) + t[k] = nil + collectgarbage() + assert(t[k] == nil) +end +assert(n == 5) + + +local function test (a) + table.insert(a, 10); table.insert(a, 2, 20); + table.insert(a, 1, -1); table.insert(a, 40); + table.insert(a, table.getn(a)+1, 50) + table.insert(a, 2, -2) + assert(table.remove(a,1) == -1) + assert(table.remove(a,1) == -2) + assert(table.remove(a,1) == 10) + assert(table.remove(a,1) == 20) + assert(table.remove(a,1) == 40) + assert(table.remove(a,1) == 50) + assert(table.remove(a,1) == nil) +end + +a = {n=0, [-7] = "ban"} +test(a) +assert(a.n == 0 and a[-7] == "ban") + +a = {[-7] = "ban"}; +test(a) +assert(a.n == nil and table.getn(a) == 0 and a[-7] == "ban") + + +table.insert(a, 1, 10); table.insert(a, 1, 20); table.insert(a, 1, -1) +assert(table.remove(a) == 10) +assert(table.remove(a) == 20) +assert(table.remove(a) == -1) + +a = {'c', 'd'} +table.insert(a, 3, 'a') +table.insert(a, 'b') +assert(table.remove(a, 1) == 'c') +assert(table.remove(a, 1) == 'd') +assert(table.remove(a, 1) == 'a') +assert(table.remove(a, 1) == 'b') +assert(table.getn(a) == 0 and a.n == nil) +print("+") + +a = {} +for i=1,1000 do + a[i] = i; a[i-1] = nil +end +assert(next(a,nil) == 1000 and next(a,1000) == nil) + +assert(next({}) == nil) +assert(next({}, nil) == nil) + +for a,b in pairs{} do error"not here" end +for i=1,0 do error'not here' end +for i=0,1,-1 do error'not here' end +a = nil; for i=1,1 do assert(not a); a=1 end; assert(a) +a = nil; for i=1,1,-1 do assert(not a); a=1 end; assert(a) + +a = 0; for i=0, 1, 0.1 do a=a+1 end; assert(a==11) +-- precision problems +--a = 0; for i=1, 0, -0.01 do a=a+1 end; assert(a==101) +a = 0; for i=0, 0.999999999, 0.1 do a=a+1 end; assert(a==10) +a = 0; for i=1, 1, 1 do a=a+1 end; assert(a==1) +a = 0; for i=1e10, 1e10, -1 do a=a+1 end; assert(a==1) +a = 0; for i=1, 0.99999, 1 do a=a+1 end; assert(a==0) +a = 0; for i=99999, 1e5, -1 do a=a+1 end; assert(a==0) +a = 0; for i=1, 0.99999, -1 do a=a+1 end; assert(a==1) + +-- conversion +a = 0; for i="10","1","-2" do a=a+1 end; assert(a==5) + + +collectgarbage() + + +-- testing generic 'for' + +local function f (n, p) + local t = {}; for i=1,p do t[i] = i*10 end + return function (_,n) + if n > 0 then + n = n-1 + return n, unpack(t) + end + end, nil, n +end + +local x = 0 +for n,a,b,c,d in f(5,3) do + x = x+1 + assert(a == 10 and b == 20 and c == 30 and d == nil) +end +assert(x == 5) + +print"OK" diff --git a/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/pm.lua b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/pm.lua new file mode 100644 index 0000000000000000000000000000000000000000..85b03846f6344f70dc3b44dbe8b5628288d85046 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/pm.lua @@ -0,0 +1,282 @@ +print('testing pattern matching') + +function f(s, p) + local i,e = string.find(s, p) + if i then return string.sub(s, i, e) end +end + +function f1(s, p) + p = string.gsub(p, "%%([0-9])", function (s) return "%" .. (s+1) end) + p = string.gsub(p, "^(^?)", "%1()", 1) + p = string.gsub(p, "($?)$", "()%1", 1) + local t = {string.match(s, p)} + return string.sub(s, t[1], t[#t] - 1) +end + +a,b = string.find('', '') -- empty patterns are tricky +assert(a == 1 and b == 0); +a,b = string.find('alo', '') +assert(a == 1 and b == 0) +a,b = string.find('a\0o a\0o a\0o', 'a', 1) -- first position +assert(a == 1 and b == 1) +a,b = string.find('a\0o a\0o a\0o', 'a\0o', 2) -- starts in the midle +assert(a == 5 and b == 7) +a,b = string.find('a\0o a\0o a\0o', 'a\0o', 9) -- starts in the midle +assert(a == 9 and b == 11) +a,b = string.find('a\0a\0a\0a\0\0ab', '\0ab', 2); -- finds at the end +assert(a == 9 and b == 11); +a,b = string.find('a\0a\0a\0a\0\0ab', 'b') -- last position +assert(a == 11 and b == 11) +assert(string.find('a\0a\0a\0a\0\0ab', 'b\0') == nil) -- check ending +assert(string.find('', '\0') == nil) +assert(string.find('alo123alo', '12') == 4) +assert(string.find('alo123alo', '^12') == nil) + +assert(f('aloALO', '%l*') == 'alo') +assert(f('aLo_ALO', '%a*') == 'aLo') + +assert(f('aaab', 'a*') == 'aaa'); +assert(f('aaa', '^.*$') == 'aaa'); +assert(f('aaa', 'b*') == ''); +assert(f('aaa', 'ab*a') == 'aa') +assert(f('aba', 'ab*a') == 'aba') +assert(f('aaab', 'a+') == 'aaa') +assert(f('aaa', '^.+$') == 'aaa') +assert(f('aaa', 'b+') == nil) +assert(f('aaa', 'ab+a') == nil) +assert(f('aba', 'ab+a') == 'aba') +assert(f('a$a', '.$') == 'a') +assert(f('a$a', '.%$') == 'a$') +assert(f('a$a', '.$.') == 'a$a') +assert(f('a$a', '$$') == nil) +assert(f('a$b', 'a$') == nil) +assert(f('a$a', '$') == '') +assert(f('', 'b*') == '') +assert(f('aaa', 'bb*') == nil) +assert(f('aaab', 'a-') == '') +assert(f('aaa', '^.-$') == 'aaa') +assert(f('aabaaabaaabaaaba', 'b.*b') == 'baaabaaabaaab') +assert(f('aabaaabaaabaaaba', 'b.-b') == 'baaab') +assert(f('alo xo', '.o$') == 'xo') +assert(f(' \n isto é assim', '%S%S*') == 'isto') +assert(f(' \n isto é assim', '%S*$') == 'assim') +assert(f(' \n isto é assim', '[a-z]*$') == 'assim') +assert(f('um caracter ? extra', '[^%sa-z]') == '?') +assert(f('', 'a?') == '') +assert(f('á', 'á?') == 'á') +assert(f('ábl', 'á?b?l?') == 'ábl') +assert(f(' ábl', 'á?b?l?') == '') +assert(f('aa', '^aa?a?a') == 'aa') +-- assert(f(']]]áb', '[^]]') == 'á') +assert(f(']]]áb', '[^%]]') == 'á') +assert(f("0alo alo", "%x*") == "0a") +assert(f("alo alo", "%C+") == "alo alo") +print('+') + +assert(f1('alo alx 123 b\0o b\0o', '(..*) %1') == "b\0o b\0o") +assert(f1('axz123= 4= 4 34', '(.+)=(.*)=%2 %1') == '3= 4= 4 3') +assert(f1('=======', '^(=*)=%1$') == '=======') +assert(string.match('==========', '^([=]*)=%1$') == nil) + +local function range (i, j) + if i <= j then + return i, range(i+1, j) + end +end + +local function range (i, j) + local ret = {} + for k=i, j do; table.insert(ret, k); end + return unpack(ret) +end + +local abc = string.char(range(0, 255)); + +assert(string.len(abc) == 256) + +function strset (p) + local res = {s=''} + string.gsub(abc, p, function (c) res.s = res.s .. c end) + return res.s +end; + +assert(string.len(strset('[\200-\210]')) == 11) + +assert(strset('[a-z]') == "abcdefghijklmnopqrstuvwxyz") +assert(strset('[a-z%d]') == strset('[%da-uu-z]')) +-- assert(strset('[a-]') == "-a") +assert(strset('[a%-]') == "-a") +assert(strset('[^%W]') == strset('[%w]')) +-- assert(strset('[]%%]') == '%]') +assert(strset('[%]%%]') == '%]') +assert(strset('[a%-z]') == '-az') +assert(strset('[%^%[%-a%]%-b]') == '-[]^ab') +assert(strset('%Z') == strset('[\1-\255]')) +assert(strset('.') == strset('[\1-\255%z]')) +print('+'); + +assert(string.match("alo xyzK", "(%w+)K") == "xyz") +assert(string.match("254 K", "(%d*)K") == "") +assert(string.match("alo ", "(%w*)$") == "") +assert(string.match("alo ", "(%w+)$") == nil) +assert(string.find("(álo)", "%(á") == 1) +local a, b, c, d, e = string.match("âlo alo", "^(((.).).* (%w*))$") +assert(a == 'âlo alo' and b == 'âl' and c == 'â' and d == 'alo' and e == nil) +a, b, c, d = string.match('0123456789', '(.+(.?)())') +assert(a == '0123456789' and b == '' and c == 11 and d == nil) +print('+') + +assert(string.gsub('ülo ülo', 'ü', 'x') == 'xlo xlo') +assert(string.gsub('alo úlo ', ' +$', '') == 'alo úlo') -- trim +assert(string.gsub(' alo alo ', '^%s*(.-)%s*$', '%1') == 'alo alo') -- double trim +assert(string.gsub('alo alo \n 123\n ', '%s+', ' ') == 'alo alo 123 ') +t = "abç d" +a, b = string.gsub(t, '(.)', '%1@') +assert('@'..a == string.gsub(t, '', '@') and b == 5) +a, b = string.gsub('abçd', '(.)', '%0@', 2) +assert(a == 'a@b@çd' and b == 2) +assert(string.gsub('alo alo', '()[al]', '%1') == '12o 56o') +assert(string.gsub("abc=xyz", "(%w*)(%p)(%w+)", "%3%2%1-%0") == + "xyz=abc-abc=xyz") +assert(string.gsub("abc", "%w", "%1%0") == "aabbcc") +assert(string.gsub("abc", "%w+", "%0%1") == "abcabc") +assert(string.gsub('áéí', '$', '\0óú') == 'áéí\0óú') +assert(string.gsub('', '^', 'r') == 'r') +assert(string.gsub('', '$', 'r') == 'r') +print('+') + +assert(string.gsub("um (dois) tres (quatro)", "(%(%w+%))", string.upper) == + "um (DOIS) tres (QUATRO)") + +do + local function setglobal (n,v) rawset(_G, n, v) end + string.gsub("a=roberto,roberto=a", "(%w+)=(%w%w*)", setglobal) + assert(_G.a=="roberto" and _G.roberto=="a") +end + +function f(a,b) return string.gsub(a,'.',b) end +assert(string.gsub("trocar tudo em |teste|b| é |beleza|al|", "|([^|]*)|([^|]*)|", f) == + "trocar tudo em bbbbb é alalalalalal") + +local function dostring (s) return loadstring(s)() or "" end +assert(string.gsub("alo $a=1$ novamente $return a$", "$([^$]*)%$", dostring) == + "alo novamente 1") + +x = string.gsub("$x=string.gsub('alo', '.', string.upper)$ assim vai para $return x$", + "$([^$]*)%$", dostring) +assert(x == ' assim vai para ALO') + +t = {} +s = 'a alo jose joao' +r = string.gsub(s, '()(%w+)()', function (a,w,b) + assert(string.len(w) == b-a); + t[a] = b-a; + end) +assert(s == r and t[1] == 1 and t[3] == 3 and t[7] == 4 and t[13] == 4) + + +function isbalanced (s) + return string.find(string.gsub(s, "%b()", ""), "[()]") == nil +end + +assert(isbalanced("(9 ((8))(\0) 7) \0\0 a b ()(c)() a")) +assert(not isbalanced("(9 ((8) 7) a b (\0 c) a")) +assert(string.gsub("alo 'oi' alo", "%b''", '"') == 'alo " alo') + + +local t = {"apple", "orange", "lime"; n=0} +assert(string.gsub("x and x and x", "x", function () t.n=t.n+1; return t[t.n] end) + == "apple and orange and lime") + +t = {n=0} +string.gsub("first second word", "%w%w*", function (w) t.n=t.n+1; t[t.n] = w end) +assert(t[1] == "first" and t[2] == "second" and t[3] == "word" and t.n == 3) + +t = {n=0} +assert(string.gsub("first second word", "%w+", + function (w) t.n=t.n+1; t[t.n] = w end, 2) == "first second word") +assert(t[1] == "first" and t[2] == "second" and t[3] == nil) + +assert(not pcall(string.gsub, "alo", "(.", print)) +assert(not pcall(string.gsub, "alo", ".)", print)) +assert(not pcall(string.gsub, "alo", "(.", {})) +assert(not pcall(string.gsub, "alo", "(.)", "%2")) +assert(not pcall(string.gsub, "alo", "(%1)", "a")) +assert(not pcall(string.gsub, "alo", "(%0)", "a")) + +-- big strings +local a = string.rep('a', 300000) +assert(string.find(a, '^a*.?$')) +assert(not string.find(a, '^a*.?b$')) +assert(string.find(a, '^a-.?$')) + +-- deep nest of gsubs +function rev (s) + return string.gsub(s, "(.)(.+)", function (c,s1) return rev(s1)..c end) +end + +local x = string.rep('012345', 10) +assert(rev(rev(x)) == x) + + +-- gsub with tables +assert(string.gsub("alo alo", ".", {}) == "alo alo") +assert(string.gsub("alo alo", "(.)", {a="AA", l=""}) == "AAo AAo") +assert(string.gsub("alo alo", "(.).", {a="AA", l="K"}) == "AAo AAo") +assert(string.gsub("alo alo", "((.)(.?))", {al="AA", o=false}) == "AAo AAo") + +assert(string.gsub("alo alo", "().", {2,5,6}) == "256 alo") + +t = {}; setmetatable(t, {__index = function (t,s) return string.upper(s) end}) +assert(string.gsub("a alo b hi", "%w%w+", t) == "a ALO b HI") + + +-- tests for gmatch +assert(string.gfind == string.gmatch) +local a = 0 +for i in string.gmatch('abcde', '()') do assert(i == a+1); a=i end +assert(a==6) + +t = {n=0} +for w in string.gmatch("first second word", "%w+") do + t.n=t.n+1; t[t.n] = w +end +assert(t[1] == "first" and t[2] == "second" and t[3] == "word") + +t = {3, 6, 9} +for i in string.gmatch ("xuxx uu ppar r", "()(.)%2") do + assert(i == table.remove(t, 1)) +end +assert(table.getn(t) == 0) + +t = {} +for i,j in string.gmatch("13 14 10 = 11, 15= 16, 22=23", "(%d+)%s*=%s*(%d+)") do + t[i] = j +end +a = 0 +for k,v in pairs(t) do assert(k+1 == v+0); a=a+1 end +assert(a == 3) + + +-- tests for `%f' (`frontiers') + +-- assert(string.gsub("aaa aa a aaa a", "%f[%w]a", "x") == "xaa xa x xaa x") +-- assert(string.gsub("[[]] [][] [[[[", "%f[[].", "x") == "x[]] x]x] x[[[") +-- assert(string.gsub("01abc45de3", "%f[%d]", ".") == ".01abc.45de.3") +-- assert(string.gsub("01abc45 de3x", "%f[%D]%w", ".") == "01.bc45 de3.") +-- assert(string.gsub("function", "%f[\1-\255]%w", ".") == ".unction") +-- assert(string.gsub("function", "%f[^\1-\255]", ".") == "function.") +-- +-- local i, e = string.find(" alo aalo allo", "%f[%S].-%f[%s].-%f[%S]") +-- assert(i == 2 and e == 5) +-- local k = string.match(" alo aalo allo", "%f[%S](.-%f[%s].-%f[%S])") +-- assert(k == 'alo ') +-- +-- local a = {1, 5, 9, 14, 17,} +-- for k in string.gmatch("alo alo th02 is 1hat", "()%f[%w%d]") do +-- assert(table.remove(a, 1) == k) +-- end +-- assert(table.getn(a) == 0) + + +print('OK') diff --git a/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/sort.lua b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/sort.lua new file mode 100644 index 0000000000000000000000000000000000000000..8a025583d625136de55678429a1639bcb9e40881 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/sort.lua @@ -0,0 +1,74 @@ +print"testing sort" + + +function check (a, f) + f = f or function (x,y) return x 'alo\0alo\0') +assert('alo' < 'alo\0') +assert('alo\0' > 'alo') +assert('\0' < '\1') +assert('\0\0' < '\0\1') +assert('\1\0a\0a' <= '\1\0a\0a') +assert(not ('\1\0a\0b' <= '\1\0a\0a')) +assert('\0\0\0' < '\0\0\0\0') +assert(not('\0\0\0\0' < '\0\0\0')) +assert('\0\0\0' <= '\0\0\0\0') +assert(not('\0\0\0\0' <= '\0\0\0')) +assert('\0\0\0' <= '\0\0\0') +assert('\0\0\0' >= '\0\0\0') +assert(not ('\0\0b' < '\0\0a\0')) +print('+') +assert(string.sub("123456789",2,4) == "234") +assert(string.sub("123456789",7) == "789") +assert(string.sub("123456789",7,6) == "") +assert(string.sub("123456789",7,7) == "7") +assert(string.sub("123456789",0,0) == "") +assert(string.sub("123456789",-10,10) == "123456789") +assert(string.sub("123456789",1,9) == "123456789") +assert(string.sub("123456789",-10,-20) == "") +assert(string.sub("123456789",-1) == "9") +assert(string.sub("123456789",-4) == "6789") +assert(string.sub("123456789",-6, -4) == "456") +assert(string.sub("\000123456789",3,5) == "234") +assert(("\000123456789"):sub(8) == "789") +print('+') + +assert(string.find("123456789", "345") == 3) +a,b = string.find("123456789", "345") +assert(string.sub("123456789", a, b) == "345") +assert(string.find("1234567890123456789", "345", 3) == 3) +assert(string.find("1234567890123456789", "345", 4) == 13) +assert(string.find("1234567890123456789", "346", 4) == nil) +assert(string.find("1234567890123456789", ".45", -9) == 13) +assert(string.find("abcdefg", "\0", 5, 1) == nil) +assert(string.find("", "") == 1) +assert(string.find('', 'aaa', 1) == nil) +assert(('alo(.)alo'):find('(.)', 1, 1) == 4) + +assert(string.len("") == 0) +assert(string.len("\0\0\0") == 3) +assert(string.len("1234567890") == 10) + +assert(#"" == 0) +assert(#"\0\0\0" == 3) +assert(#"1234567890" == 10) + +assert(string.byte("a") == 97) +assert(string.byte("á") > 127) +assert(string.byte(string.char(255)) == 255) +assert(string.byte(string.char(0)) == 0) +assert(string.byte("\0") == 0) +assert(string.byte("\0\0alo\0x", -1) == string.byte('x')) +assert(string.byte("ba", 2) == 97) +assert(string.byte("\n\n", 2, -1) == 10) +assert(string.byte("\n\n", 2, 2) == 10) +assert(string.byte("") == nil) +assert(string.byte("hi", -3) == nil) +assert(string.byte("hi", 3) == nil) +assert(string.byte("hi", 9, 10) == nil) +assert(string.byte("hi", 2, 1) == nil) +assert(string.char() == "") +assert(string.char(0, 255, 0) == "\0\255\0") +assert(string.char(0, string.byte("á"), 0) == "\0á\0") +assert(string.char(string.byte("ál\0óu", 1, -1)) == "ál\0óu") +assert(string.char(string.byte("ál\0óu", 1, 0)) == "") +assert(string.char(string.byte("ál\0óu", -10, 100)) == "ál\0óu") +print('+') + +assert(string.upper("ab\0c") == "AB\0C") +assert(string.lower("\0ABCc%$") == "\0abcc%$") +assert(string.rep('teste', 0) == '') +assert(string.rep('tés\00tê', 2) == 'tés\0têtés\000tê') +assert(string.rep('', 10) == '') + +assert(string.reverse"" == "") +assert(string.reverse"\0\1\2\3" == "\3\2\1\0") +assert(string.reverse"\0001234" == "4321\0") + +for i=0,30 do assert(string.len(string.rep('a', i)) == i) end + +assert(type(tostring(nil)) == 'string') +assert(type(tostring(12)) == 'string') +assert(''..12 == '12' and type(12 .. '') == 'string') +assert(string.find(tostring{}, 'table:')) +assert(string.find(tostring(print), 'function:')) +assert(tostring(1234567890123) == '1234567890123') +assert(#tostring('\0') == 1) +assert(tostring(true) == "true") +assert(tostring(false) == "false") +print('+') + +x = '"ílo"\n\\' +-- assert(string.format('%q%s', x, x) == '"\\"ílo\\"\\\n\\\\""ílo"\n\\') +-- assert(string.format('%q', "\0") == [["\000"]]) +--assert(string.format("\0%c\0%c%x\0", string.byte("á"), string.byte("b"), 140) == +-- "\0á\0b8c\0") +assert(string.format('') == "") +assert(string.format("%c",34)..string.format("%c",48)..string.format("%c",90)..string.format("%c",100) == + string.format("%c%c%c%c", 34, 48, 90, 100)) +assert(string.format("%s\0 is not \0%s", 'not be', 'be') == 'not be\0 is not \0be') +assert(string.format("%%%d %010d", 10, 23) == "%10 0000000023") +assert(tonumber(string.format("%f", 10.3)) == 10.3) +x = string.format('"%-50s"', 'a') +assert(#x == 52) +assert(string.sub(x, 1, 4) == '"a ') + +assert(string.format("-%.20s.20s", string.rep("%", 2000)) == "-"..string.rep("%", 20)..".20s") +assert(string.format('"-%20s.20s"', string.rep("%", 2000)) == + string.format("%q", "-"..string.rep("%", 2000)..".20s")) + + +-- longest number that can be formated +assert(string.len(string.format('%99.99f', -1e308)) >= 100) + +-- assert(loadstring("return 1\n--comentário sem EOL no final")() == 1) + +assert(table.concat{} == "") +assert(table.concat({}, 'x') == "") +assert(table.concat({'\0', '\0\1', '\0\1\2'}, '.\0.') == "\0.\0.\0\1.\0.\0\1\2") +local a = {}; for i=1,3000 do a[i] = "xuxu" end +assert(table.concat(a, "123").."123" == string.rep("xuxu123", 3000)) +assert(table.concat(a, "b", 20, 20) == "xuxu") +assert(table.concat(a, "", 20, 21) == "xuxuxuxu") +assert(table.concat(a, "", 22, 21) == "") +assert(table.concat(a, "3", 2999) == "xuxu3xuxu") + +a = {"a","b","c"} +assert(table.concat(a, ",", 1, 0) == "") +assert(table.concat(a, ",", 1, 1) == "a") +assert(table.concat(a, ",", 1, 2) == "a,b") +assert(table.concat(a, ",", 2) == "b,c") +assert(table.concat(a, ",", 3) == "c") +assert(table.concat(a, ",", 4) == "") + +local locales = { "ptb", "ISO-8859-1", "pt_BR" } +local function trylocale (w) + for _, l in ipairs(locales) do + if os.setlocale(l, w) then return true end + end + return false +end + +if not trylocale("collate") then + print("locale not supported") +else + assert("alo" < "álo" and "álo" < "amo") +end + +if not trylocale("ctype") then + print("locale not supported") +else + assert(string.gsub("áéíóú", "%a", "x") == "xxxxx") + assert(string.gsub("áÁéÉ", "%l", "x") == "xÁxÉ") + assert(string.gsub("áÁéÉ", "%u", "x") == "áxéx") + assert(string.upper"áÁé{xuxu}ção" == "ÁÁÉ{XUXU}ÇÃO") +end + +-- os.setlocale("C") +-- assert(os.setlocale() == 'C') +-- assert(os.setlocale(nil, "numeric") == 'C') + +print('OK') + + diff --git a/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/vararg.lua b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/vararg.lua new file mode 100644 index 0000000000000000000000000000000000000000..0aa4cb3c93fae770ae6e6c74605794b073932c49 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/vararg.lua @@ -0,0 +1,128 @@ +print('testing vararg') + +_G.arg = nil + +function f(a, ...) + assert(type(arg) == 'table') + assert(type(arg.n) == 'number') + for i=1,arg.n do assert(a[i]==arg[i]) end + return arg.n +end + +function c12 (...) + assert(arg == nil) + local x = {...}; x.n = table.getn(x) + local res = (x.n==2 and x[1] == 1 and x[2] == 2) + if res then res = 55 end + return res, 2 +end + +function vararg (...) return arg end + +local call = function (f, args) return f(unpack(args, 1, args.n)) end + +assert(f() == 0) +assert(f({1,2,3}, 1, 2, 3) == 3) +assert(f({"alo", nil, 45, f, nil}, "alo", nil, 45, f, nil) == 5) + +assert(c12(1,2)==55) +a,b = assert(call(c12, {1,2})) +assert(a == 55 and b == 2) +a = call(c12, {1,2;n=2}) +assert(a == 55 and b == 2) +a = call(c12, {1,2;n=1}) +assert(not a) +assert(c12(1,2,3) == false) +--[[ +local a = vararg(call(next, {_G,nil;n=2})) +local b,c = next(_G) +assert(a[1] == b and a[2] == c and a.n == 2) +a = vararg(call(call, {c12, {1,2}})) +assert(a.n == 2 and a[1] == 55 and a[2] == 2) +a = call(print, {'+'}) +assert(a == nil) +--]] + +local t = {1, 10} +function t:f (...) return self[arg[1]]+arg.n end +assert(t:f(1,4) == 3 and t:f(2) == 11) +print('+') + +lim = 20 +local i, a = 1, {} +while i <= lim do a[i] = i+0.3; i=i+1 end + +function f(a, b, c, d, ...) + local more = {...} + assert(a == 1.3 and more[1] == 5.3 and + more[lim-4] == lim+0.3 and not more[lim-3]) +end + +function g(a,b,c) + assert(a == 1.3 and b == 2.3 and c == 3.3) +end + +call(f, a) +call(g, a) + +a = {} +i = 1 +while i <= lim do a[i] = i; i=i+1 end +assert(call(math.max, a) == lim) + +print("+") + + +-- new-style varargs + +function oneless (a, ...) return ... end + +function f (n, a, ...) + local b + assert(arg == nil) + if n == 0 then + local b, c, d = ... + return a, b, c, d, oneless(oneless(oneless(...))) + else + n, b, a = n-1, ..., a + assert(b == ...) + return f(n, a, ...) + end +end + +a,b,c,d,e = assert(f(10,5,4,3,2,1)) +assert(a==5 and b==4 and c==3 and d==2 and e==1) + +a,b,c,d,e = f(4) +assert(a==nil and b==nil and c==nil and d==nil and e==nil) + + +-- varargs for main chunks +f = loadstring[[ return {...} ]] +x = f(2,3) +assert(x[1] == 2 and x[2] == 3 and x[3] == nil) + + +f = loadstring[[ + local x = {...} + for i=1,select('#', ...) do assert(x[i] == select(i, ...)) end + assert(x[select('#', ...)+1] == nil) + return true +]] + +assert(f("a", "b", nil, {}, assert)) +assert(f()) + +a = {select(3, unpack{10,20,30,40})} +assert(table.getn(a) == 2 and a[1] == 30 and a[2] == 40) +a = {select(1)} +assert(next(a) == nil) +a = {select(-1, 3, 5, 7)} +assert(a[1] == 7 and a[2] == nil) +a = {select(-2, 3, 5, 7)} +assert(a[1] == 5 and a[2] == 7 and a[3] == nil) +pcall(select, 10000) +pcall(select, -10000) + +print('OK') + diff --git a/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/verybig.lua b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/verybig.lua new file mode 100644 index 0000000000000000000000000000000000000000..59e0142a177c0dcfb2d1cc9458ac01bc9cbb19b1 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/_lua5.1-tests/verybig.lua @@ -0,0 +1,100 @@ +if rawget(_G, "_soft") then return 10 end + +print "testing large programs (>64k)" + +-- template to create a very big test file +prog = [[$ + +local a,b + +b = {$1$ + b30009 = 65534, + b30010 = 65535, + b30011 = 65536, + b30012 = 65537, + b30013 = 16777214, + b30014 = 16777215, + b30015 = 16777216, + b30016 = 16777217, + b30017 = 4294967294, + b30018 = 4294967295, + b30019 = 4294967296, + b30020 = 4294967297, + b30021 = -65534, + b30022 = -65535, + b30023 = -65536, + b30024 = -4294967297, + b30025 = 15012.5, + $2$ +}; + +assert(b.a50008 == 25004 and b["a11"] == 5.5) +assert(b.a33007 == 16503.5 and b.a50009 == 25004.5) +assert(b["b"..30024] == -4294967297) + +function b:xxx (a,b) return a+b end +assert(b:xxx(10, 12) == 22) -- pushself with non-constant index +b.xxx = nil + +s = 0; n=0 +for a,b in pairs(b) do s=s+b; n=n+1 end +assert(s==13977183656.5 and n==70001) + +require "checktable" +stat(b) + +a = nil; b = nil +print'+' + +function f(x) b=x end + +a = f{$3$} or 10 + +assert(a==10) +assert(b[1] == "a10" and b[2] == 5 and b[table.getn(b)-1] == "a50009") + + +function xxxx (x) return b[x] end + +assert(xxxx(3) == "a11") + +a = nil; b=nil +xxxx = nil + +return 10 + +]] + +-- functions to fill in the $n$ +F = { +function () -- $1$ + for i=10,50009 do + io.write('a', i, ' = ', 5+((i-10)/2), ',\n') + end +end, + +function () -- $2$ + for i=30026,50009 do + io.write('b', i, ' = ', 15013+((i-30026)/2), ',\n') + end +end, + +function () -- $3$ + for i=10,50009 do + io.write('"a', i, '", ', 5+((i-10)/2), ',\n') + end +end, +} + +file = os.tmpname() +io.output(file) +for s in string.gmatch(prog, "$([^$]+)") do + local n = tonumber(s) + if not n then io.write(s) else F[n]() end +end +io.close() +result = dofile(file) +assert(os.remove(file)) +print'OK' +return result + diff --git a/vendor/github.com/yuin/gopher-lua/_state.go b/vendor/github.com/yuin/gopher-lua/_state.go new file mode 100644 index 0000000000000000000000000000000000000000..aba9f4e5215d8557b469c06eb3330e15db14327e --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/_state.go @@ -0,0 +1,1787 @@ +package lua + +import ( + "context" + "fmt" + "github.com/yuin/gopher-lua/parse" + "io" + "math" + "os" + "runtime" + "strings" + "sync/atomic" + "time" +) + +const MultRet = -1 +const RegistryIndex = -10000 +const EnvironIndex = -10001 +const GlobalsIndex = -10002 + +/* ApiError {{{ */ + +type ApiError struct { + Type ApiErrorType + Object LValue + StackTrace string + // Underlying error. This attribute is set only if the Type is ApiErrorFile or ApiErrorSyntax + Cause error +} + +func newApiError(code ApiErrorType, object LValue) *ApiError { + return &ApiError{code, object, "", nil} +} + +func newApiErrorS(code ApiErrorType, message string) *ApiError { + return newApiError(code, LString(message)) +} + +func newApiErrorE(code ApiErrorType, err error) *ApiError { + return &ApiError{code, LString(err.Error()), "", err} +} + +func (e *ApiError) Error() string { + if len(e.StackTrace) > 0 { + return fmt.Sprintf("%s\n%s", e.Object.String(), e.StackTrace) + } + return e.Object.String() +} + +type ApiErrorType int + +const ( + ApiErrorSyntax ApiErrorType = iota + ApiErrorFile + ApiErrorRun + ApiErrorError + ApiErrorPanic +) + +/* }}} */ + +/* ResumeState {{{ */ + +type ResumeState int + +const ( + ResumeOK ResumeState = iota + ResumeYield + ResumeError +) + +/* }}} */ + +/* P {{{ */ + +type P struct { + Fn LValue + NRet int + Protect bool + Handler *LFunction +} + +/* }}} */ + +/* Options {{{ */ + +// Options is a configuration that is used to create a new LState. +type Options struct { + // Call stack size. This defaults to `lua.CallStackSize`. + CallStackSize int + // Data stack size. This defaults to `lua.RegistrySize`. + RegistrySize int + // Controls whether or not libraries are opened by default + SkipOpenLibs bool + // Tells whether a Go stacktrace should be included in a Lua stacktrace when panics occur. + IncludeGoStackTrace bool +} + +/* }}} */ + +/* Debug {{{ */ + +type Debug struct { + frame *callFrame + Name string + What string + Source string + CurrentLine int + NUpvalues int + LineDefined int + LastLineDefined int +} + +/* }}} */ + +/* callFrame {{{ */ + +type callFrame struct { + Idx int + Fn *LFunction + Parent *callFrame + Pc int + Base int + LocalBase int + ReturnBase int + NArgs int + NRet int + TailCall int +} + +type callFrameStack struct { + array []callFrame + sp int +} + +func newCallFrameStack(size int) *callFrameStack { + return &callFrameStack{ + array: make([]callFrame, size), + sp: 0, + } +} + +func (cs *callFrameStack) IsEmpty() bool { return cs.sp == 0 } + +func (cs *callFrameStack) Clear() { + cs.sp = 0 +} + +func (cs *callFrameStack) Push(v callFrame) { // +inline-start + cs.array[cs.sp] = v + cs.array[cs.sp].Idx = cs.sp + cs.sp++ +} // +inline-end + +func (cs *callFrameStack) Remove(sp int) { + psp := sp - 1 + nsp := sp + 1 + var pre *callFrame + var next *callFrame + if psp > 0 { + pre = &cs.array[psp] + } + if nsp < cs.sp { + next = &cs.array[nsp] + } + if next != nil { + next.Parent = pre + } + for i := sp; i+1 < cs.sp; i++ { + cs.array[i] = cs.array[i+1] + cs.array[i].Idx = i + cs.sp = i + } + cs.sp++ +} + +func (cs *callFrameStack) Sp() int { + return cs.sp +} + +func (cs *callFrameStack) SetSp(sp int) { + cs.sp = sp +} + +func (cs *callFrameStack) Last() *callFrame { + if cs.sp == 0 { + return nil + } + return &cs.array[cs.sp-1] +} + +func (cs *callFrameStack) At(sp int) *callFrame { + return &cs.array[sp] +} + +func (cs *callFrameStack) Pop() *callFrame { + cs.sp-- + return &cs.array[cs.sp] +} + +/* }}} */ + +/* registry {{{ */ + +type registry struct { + array []LValue + top int + alloc *allocator +} + +func newRegistry(size int, alloc *allocator) *registry { + return ®istry{make([]LValue, size), 0, alloc} +} + +func (rg *registry) SetTop(top int) { + oldtop := rg.top + rg.top = top + for i := oldtop; i < rg.top; i++ { + rg.array[i] = LNil + } + for i := rg.top; i < oldtop; i++ { + rg.array[i] = LNil + } +} + +func (rg *registry) Top() int { + return rg.top +} + +func (rg *registry) Push(v LValue) { + rg.array[rg.top] = v + rg.top++ +} + +func (rg *registry) Pop() LValue { + v := rg.array[rg.top-1] + rg.array[rg.top-1] = LNil + rg.top-- + return v +} + +func (rg *registry) Get(reg int) LValue { + return rg.array[reg] +} + +func (rg *registry) CopyRange(regv, start, limit, n int) { // +inline-start + for i := 0; i < n; i++ { + if tidx := start + i; tidx >= rg.top || limit > -1 && tidx >= limit || tidx < 0 { + rg.array[regv+i] = LNil + } else { + rg.array[regv+i] = rg.array[tidx] + } + } + rg.top = regv + n +} // +inline-end + +func (rg *registry) FillNil(regm, n int) { // +inline-start + for i := 0; i < n; i++ { + rg.array[regm+i] = LNil + } + rg.top = regm + n +} // +inline-end + +func (rg *registry) Insert(value LValue, reg int) { + top := rg.Top() + if reg >= top { + rg.Set(reg, value) + return + } + top-- + for ; top >= reg; top-- { + rg.Set(top+1, rg.Get(top)) + } + rg.Set(reg, value) +} + +func (rg *registry) Set(reg int, val LValue) { + rg.array[reg] = val + if reg >= rg.top { + rg.top = reg + 1 + } +} + +func (rg *registry) SetNumber(reg int, val LNumber) { + rg.array[reg] = rg.alloc.LNumber2I(val) + if reg >= rg.top { + rg.top = reg + 1 + } +} /* }}} */ + +/* Global {{{ */ + +func newGlobal() *Global { + return &Global{ + MainThread: nil, + Registry: newLTable(0, 32), + Global: newLTable(0, 64), + builtinMts: make(map[int]LValue), + tempFiles: make([]*os.File, 0, 10), + } +} + +/* }}} */ + +/* package local methods {{{ */ + +func panicWithTraceback(L *LState) { + err := newApiError(ApiErrorRun, L.Get(-1)) + err.StackTrace = L.stackTrace(0) + panic(err) +} + +func panicWithoutTraceback(L *LState) { + err := newApiError(ApiErrorRun, L.Get(-1)) + panic(err) +} + +func newLState(options Options) *LState { + al := newAllocator(32) + ls := &LState{ + G: newGlobal(), + Parent: nil, + Panic: panicWithTraceback, + Dead: false, + Options: options, + + stop: 0, + reg: newRegistry(options.RegistrySize, al), + stack: newCallFrameStack(options.CallStackSize), + alloc: al, + currentFrame: nil, + wrapped: false, + uvcache: nil, + hasErrorFunc: false, + mainLoop: mainLoop, + ctx: nil, + } + ls.Env = ls.G.Global + return ls +} + +func (ls *LState) printReg() { + println("-------------------------") + println("thread:", ls) + println("top:", ls.reg.Top()) + if ls.currentFrame != nil { + println("function base:", ls.currentFrame.Base) + println("return base:", ls.currentFrame.ReturnBase) + } else { + println("(vm not started)") + } + println("local base:", ls.currentLocalBase()) + for i := 0; i < ls.reg.Top(); i++ { + println(i, ls.reg.Get(i).String()) + } + println("-------------------------") +} + +func (ls *LState) printCallStack() { + println("-------------------------") + for i := 0; i < ls.stack.Sp(); i++ { + print(i) + print(" ") + frame := ls.stack.At(i) + if frame == nil { + break + } + if frame.Fn.IsG { + println("IsG:", true, "Frame:", frame, "Fn:", frame.Fn) + } else { + println("IsG:", false, "Frame:", frame, "Fn:", frame.Fn, "pc:", frame.Pc) + } + } + println("-------------------------") +} + +func (ls *LState) closeAllUpvalues() { // +inline-start + for cf := ls.currentFrame; cf != nil; cf = cf.Parent { + if !cf.Fn.IsG { + ls.closeUpvalues(cf.LocalBase) + } + } +} // +inline-end + +func (ls *LState) raiseError(level int, format string, args ...interface{}) { + if !ls.hasErrorFunc { + ls.closeAllUpvalues() + } + message := format + if len(args) > 0 { + message = fmt.Sprintf(format, args...) + } + if level > 0 { + message = fmt.Sprintf("%v %v", ls.where(level-1, true), message) + } + ls.reg.Push(LString(message)) + ls.Panic(ls) +} + +func (ls *LState) findLocal(frame *callFrame, no int) string { + fn := frame.Fn + if !fn.IsG { + if name, ok := fn.LocalName(no, frame.Pc-1); ok { + return name + } + } + var top int + if ls.currentFrame == frame { + top = ls.reg.Top() + } else if frame.Idx+1 < ls.stack.Sp() { + top = ls.stack.At(frame.Idx + 1).Base + } else { + return "" + } + if top-frame.LocalBase >= no { + return "(*temporary)" + } + return "" +} + +func (ls *LState) where(level int, skipg bool) string { + dbg, ok := ls.GetStack(level) + if !ok { + return "" + } + cf := dbg.frame + proto := cf.Fn.Proto + sourcename := "[G]" + if proto != nil { + sourcename = proto.SourceName + } else if skipg { + return ls.where(level+1, skipg) + } + line := "" + if proto != nil { + line = fmt.Sprintf("%v:", proto.DbgSourcePositions[cf.Pc-1]) + } + return fmt.Sprintf("%v:%v", sourcename, line) +} + +func (ls *LState) stackTrace(level int) string { + buf := []string{} + header := "stack traceback:" + if ls.currentFrame != nil { + i := 0 + for dbg, ok := ls.GetStack(i); ok; dbg, ok = ls.GetStack(i) { + cf := dbg.frame + buf = append(buf, fmt.Sprintf("\t%v in %v", ls.Where(i), ls.formattedFrameFuncName(cf))) + if !cf.Fn.IsG && cf.TailCall > 0 { + for tc := cf.TailCall; tc > 0; tc-- { + buf = append(buf, "\t(tailcall): ?") + i++ + } + } + i++ + } + } + buf = append(buf, fmt.Sprintf("\t%v: %v", "[G]", "?")) + buf = buf[intMax(0, intMin(level, len(buf))):len(buf)] + if len(buf) > 20 { + newbuf := make([]string, 0, 20) + newbuf = append(newbuf, buf[0:7]...) + newbuf = append(newbuf, "\t...") + newbuf = append(newbuf, buf[len(buf)-7:len(buf)]...) + buf = newbuf + } + return fmt.Sprintf("%s\n%s", header, strings.Join(buf, "\n")) +} + +func (ls *LState) formattedFrameFuncName(fr *callFrame) string { + name, ischunk := ls.frameFuncName(fr) + if ischunk { + return name + } + if name[0] != '(' && name[0] != '<' { + return fmt.Sprintf("function '%s'", name) + } + return fmt.Sprintf("function %s", name) +} + +func (ls *LState) rawFrameFuncName(fr *callFrame) string { + name, _ := ls.frameFuncName(fr) + return name +} + +func (ls *LState) frameFuncName(fr *callFrame) (string, bool) { + frame := fr.Parent + if frame == nil { + if ls.Parent == nil { + return "main chunk", true + } else { + return "corountine", true + } + } + if !frame.Fn.IsG { + pc := frame.Pc - 1 + for _, call := range frame.Fn.Proto.DbgCalls { + if call.Pc == pc { + name := call.Name + if (name == "?" || fr.TailCall > 0) && !fr.Fn.IsG { + name = fmt.Sprintf("<%v:%v>", fr.Fn.Proto.SourceName, fr.Fn.Proto.LineDefined) + } + return name, false + } + } + } + if !fr.Fn.IsG { + return fmt.Sprintf("<%v:%v>", fr.Fn.Proto.SourceName, fr.Fn.Proto.LineDefined), false + } + return "(anonymous)", false +} + +func (ls *LState) isStarted() bool { + return ls.currentFrame != nil +} + +func (ls *LState) kill() { + ls.Dead = true +} + +func (ls *LState) indexToReg(idx int) int { + base := ls.currentLocalBase() + if idx > 0 { + return base + idx - 1 + } else if idx == 0 { + return -1 + } else { + tidx := ls.reg.Top() + idx + if tidx < base { + return -1 + } + return tidx + } +} + +func (ls *LState) currentLocalBase() int { + base := 0 + if ls.currentFrame != nil { + base = ls.currentFrame.LocalBase + } + return base +} + +func (ls *LState) currentEnv() *LTable { + return ls.Env + /* + if ls.currentFrame == nil { + return ls.Env + } + return ls.currentFrame.Fn.Env + */ +} + +func (ls *LState) rkValue(idx int) LValue { + /* + if OpIsK(idx) { + return ls.currentFrame.Fn.Proto.Constants[opIndexK(idx)] + } + return ls.reg.Get(ls.currentFrame.LocalBase + idx) + */ + if (idx & opBitRk) != 0 { + return ls.currentFrame.Fn.Proto.Constants[idx & ^opBitRk] + } + return ls.reg.array[ls.currentFrame.LocalBase+idx] +} + +func (ls *LState) rkString(idx int) string { + if (idx & opBitRk) != 0 { + return ls.currentFrame.Fn.Proto.stringConstants[idx & ^opBitRk] + } + return string(ls.reg.array[ls.currentFrame.LocalBase+idx].(LString)) +} + +func (ls *LState) closeUpvalues(idx int) { // +inline-start + if ls.uvcache != nil { + var prev *Upvalue + for uv := ls.uvcache; uv != nil; uv = uv.next { + if uv.index >= idx { + if prev != nil { + prev.next = nil + } else { + ls.uvcache = nil + } + uv.Close() + } + prev = uv + } + } +} // +inline-end + +func (ls *LState) findUpvalue(idx int) *Upvalue { + var prev *Upvalue + var next *Upvalue + if ls.uvcache != nil { + for uv := ls.uvcache; uv != nil; uv = uv.next { + if uv.index == idx { + return uv + } + if uv.index > idx { + next = uv + break + } + prev = uv + } + } + uv := &Upvalue{reg: ls.reg, index: idx, closed: false} + if prev != nil { + prev.next = uv + } else { + ls.uvcache = uv + } + if next != nil { + uv.next = next + } + return uv +} + +func (ls *LState) metatable(lvalue LValue, rawget bool) LValue { + var metatable LValue = LNil + switch obj := lvalue.(type) { + case *LTable: + metatable = obj.Metatable + case *LUserData: + metatable = obj.Metatable + default: + if table, ok := ls.G.builtinMts[int(obj.Type())]; ok { + metatable = table + } + } + + if !rawget && metatable != LNil { + oldmt := metatable + if tb, ok := metatable.(*LTable); ok { + metatable = tb.RawGetString("__metatable") + if metatable == LNil { + metatable = oldmt + } + } + } + + return metatable +} + +func (ls *LState) metaOp1(lvalue LValue, event string) LValue { + if mt := ls.metatable(lvalue, true); mt != LNil { + if tb, ok := mt.(*LTable); ok { + return tb.RawGetString(event) + } + } + return LNil +} + +func (ls *LState) metaOp2(value1, value2 LValue, event string) LValue { + if mt := ls.metatable(value1, true); mt != LNil { + if tb, ok := mt.(*LTable); ok { + if ret := tb.RawGetString(event); ret != LNil { + return ret + } + } + } + if mt := ls.metatable(value2, true); mt != LNil { + if tb, ok := mt.(*LTable); ok { + return tb.RawGetString(event) + } + } + return LNil +} + +func (ls *LState) metaCall(lvalue LValue) (*LFunction, bool) { + if fn, ok := lvalue.(*LFunction); ok { + return fn, false + } + if fn, ok := ls.metaOp1(lvalue, "__call").(*LFunction); ok { + return fn, true + } + return nil, false +} + +func (ls *LState) initCallFrame(cf *callFrame) { // +inline-start + if cf.Fn.IsG { + ls.reg.SetTop(cf.LocalBase + cf.NArgs) + } else { + proto := cf.Fn.Proto + nargs := cf.NArgs + np := int(proto.NumParameters) + for i := nargs; i < np; i++ { + ls.reg.array[cf.LocalBase+i] = LNil + nargs = np + } + + if (proto.IsVarArg & VarArgIsVarArg) == 0 { + if nargs < int(proto.NumUsedRegisters) { + nargs = int(proto.NumUsedRegisters) + } + for i := np; i < nargs; i++ { + ls.reg.array[cf.LocalBase+i] = LNil + } + ls.reg.top = cf.LocalBase + int(proto.NumUsedRegisters) + } else { + /* swap vararg positions: + closure + namedparam1 <- lbase + namedparam2 + vararg1 + vararg2 + + TO + + closure + nil + nil + vararg1 + vararg2 + namedparam1 <- lbase + namedparam2 + */ + nvarargs := nargs - np + if nvarargs < 0 { + nvarargs = 0 + } + + ls.reg.SetTop(cf.LocalBase + nargs + np) + for i := 0; i < np; i++ { + //ls.reg.Set(cf.LocalBase+nargs+i, ls.reg.Get(cf.LocalBase+i)) + ls.reg.array[cf.LocalBase+nargs+i] = ls.reg.array[cf.LocalBase+i] + //ls.reg.Set(cf.LocalBase+i, LNil) + ls.reg.array[cf.LocalBase+i] = LNil + } + + if CompatVarArg { + ls.reg.SetTop(cf.LocalBase + nargs + np + 1) + if (proto.IsVarArg & VarArgNeedsArg) != 0 { + argtb := newLTable(nvarargs, 0) + for i := 0; i < nvarargs; i++ { + argtb.RawSetInt(i+1, ls.reg.Get(cf.LocalBase+np+i)) + } + argtb.RawSetString("n", LNumber(nvarargs)) + //ls.reg.Set(cf.LocalBase+nargs+np, argtb) + ls.reg.array[cf.LocalBase+nargs+np] = argtb + } else { + ls.reg.array[cf.LocalBase+nargs+np] = LNil + } + } + cf.LocalBase += nargs + maxreg := cf.LocalBase + int(proto.NumUsedRegisters) + ls.reg.SetTop(maxreg) + } + } +} // +inline-end + +func (ls *LState) pushCallFrame(cf callFrame, fn LValue, meta bool) { // +inline-start + if meta { + cf.NArgs++ + ls.reg.Insert(fn, cf.LocalBase) + } + if cf.Fn == nil { + ls.RaiseError("attempt to call a non-function object") + } + if ls.stack.sp == ls.Options.CallStackSize { + ls.RaiseError("stack overflow") + } + // +inline-call ls.stack.Push cf + newcf := ls.stack.Last() + // +inline-call ls.initCallFrame newcf + ls.currentFrame = newcf +} // +inline-end + +func (ls *LState) callR(nargs, nret, rbase int) { + base := ls.reg.Top() - nargs - 1 + if rbase < 0 { + rbase = base + } + lv := ls.reg.Get(base) + fn, meta := ls.metaCall(lv) + ls.pushCallFrame(callFrame{ + Fn: fn, + Pc: 0, + Base: base, + LocalBase: base + 1, + ReturnBase: rbase, + NArgs: nargs, + NRet: nret, + Parent: ls.currentFrame, + TailCall: 0, + }, lv, meta) + if ls.G.MainThread == nil { + ls.G.MainThread = ls + ls.G.CurrentThread = ls + ls.mainLoop(ls, nil) + } else { + ls.mainLoop(ls, ls.currentFrame) + } + if nret != MultRet { + ls.reg.SetTop(rbase + nret) + } +} + +func (ls *LState) getField(obj LValue, key LValue) LValue { + curobj := obj + for i := 0; i < MaxTableGetLoop; i++ { + tb, istable := curobj.(*LTable) + if istable { + ret := tb.RawGet(key) + if ret != LNil { + return ret + } + } + metaindex := ls.metaOp1(curobj, "__index") + if metaindex == LNil { + if !istable { + ls.RaiseError("attempt to index a non-table object(%v)", curobj.Type().String()) + } + return LNil + } + if metaindex.Type() == LTFunction { + ls.reg.Push(metaindex) + ls.reg.Push(curobj) + ls.reg.Push(key) + ls.Call(2, 1) + return ls.reg.Pop() + } else { + curobj = metaindex + } + } + ls.RaiseError("too many recursions in gettable") + return nil +} + +func (ls *LState) getFieldString(obj LValue, key string) LValue { + curobj := obj + for i := 0; i < MaxTableGetLoop; i++ { + tb, istable := curobj.(*LTable) + if istable { + ret := tb.RawGetString(key) + if ret != LNil { + return ret + } + } + metaindex := ls.metaOp1(curobj, "__index") + if metaindex == LNil { + if !istable { + ls.RaiseError("attempt to index a non-table object(%v)", curobj.Type().String()) + } + return LNil + } + if metaindex.Type() == LTFunction { + ls.reg.Push(metaindex) + ls.reg.Push(curobj) + ls.reg.Push(LString(key)) + ls.Call(2, 1) + return ls.reg.Pop() + } else { + curobj = metaindex + } + } + ls.RaiseError("too many recursions in gettable") + return nil +} + +func (ls *LState) setField(obj LValue, key LValue, value LValue) { + curobj := obj + for i := 0; i < MaxTableGetLoop; i++ { + tb, istable := curobj.(*LTable) + if istable { + if tb.RawGet(key) != LNil { + ls.RawSet(tb, key, value) + return + } + } + metaindex := ls.metaOp1(curobj, "__newindex") + if metaindex == LNil { + if !istable { + ls.RaiseError("attempt to index a non-table object(%v)", curobj.Type().String()) + } + ls.RawSet(tb, key, value) + return + } + if metaindex.Type() == LTFunction { + ls.reg.Push(metaindex) + ls.reg.Push(curobj) + ls.reg.Push(key) + ls.reg.Push(value) + ls.Call(3, 0) + return + } else { + curobj = metaindex + } + } + ls.RaiseError("too many recursions in settable") +} + +func (ls *LState) setFieldString(obj LValue, key string, value LValue) { + curobj := obj + for i := 0; i < MaxTableGetLoop; i++ { + tb, istable := curobj.(*LTable) + if istable { + if tb.RawGetString(key) != LNil { + tb.RawSetString(key, value) + return + } + } + metaindex := ls.metaOp1(curobj, "__newindex") + if metaindex == LNil { + if !istable { + ls.RaiseError("attempt to index a non-table object(%v)", curobj.Type().String()) + } + tb.RawSetString(key, value) + return + } + if metaindex.Type() == LTFunction { + ls.reg.Push(metaindex) + ls.reg.Push(curobj) + ls.reg.Push(LString(key)) + ls.reg.Push(value) + ls.Call(3, 0) + return + } else { + curobj = metaindex + } + } + ls.RaiseError("too many recursions in settable") +} + +/* }}} */ + +/* api methods {{{ */ + +func NewState(opts ...Options) *LState { + var ls *LState + if len(opts) == 0 { + ls = newLState(Options{ + CallStackSize: CallStackSize, + RegistrySize: RegistrySize, + }) + ls.OpenLibs() + } else { + if opts[0].CallStackSize < 1 { + opts[0].CallStackSize = CallStackSize + } + if opts[0].RegistrySize < 128 { + opts[0].RegistrySize = RegistrySize + } + ls = newLState(opts[0]) + if !opts[0].SkipOpenLibs { + ls.OpenLibs() + } + } + return ls +} + +func (ls *LState) Close() { + atomic.AddInt32(&ls.stop, 1) + for _, file := range ls.G.tempFiles { + // ignore errors in these operations + file.Close() + os.Remove(file.Name()) + } +} + +/* registry operations {{{ */ + +func (ls *LState) GetTop() int { + return ls.reg.Top() - ls.currentLocalBase() +} + +func (ls *LState) SetTop(idx int) { + base := ls.currentLocalBase() + newtop := ls.indexToReg(idx) + 1 + if newtop < base { + ls.reg.SetTop(base) + } else { + ls.reg.SetTop(newtop) + } +} + +func (ls *LState) Replace(idx int, value LValue) { + base := ls.currentLocalBase() + if idx > 0 { + reg := base + idx - 1 + if reg < ls.reg.Top() { + ls.reg.Set(reg, value) + } + } else if idx == 0 { + } else if idx > RegistryIndex { + if tidx := ls.reg.Top() + idx; tidx >= base { + ls.reg.Set(tidx, value) + } + } else { + switch idx { + case RegistryIndex: + if tb, ok := value.(*LTable); ok { + ls.G.Registry = tb + } else { + ls.RaiseError("registry must be a table(%v)", value.Type().String()) + } + case EnvironIndex: + if ls.currentFrame == nil { + ls.RaiseError("no calling environment") + } + if tb, ok := value.(*LTable); ok { + ls.currentFrame.Fn.Env = tb + } else { + ls.RaiseError("environment must be a table(%v)", value.Type().String()) + } + case GlobalsIndex: + if tb, ok := value.(*LTable); ok { + ls.G.Global = tb + } else { + ls.RaiseError("_G must be a table(%v)", value.Type().String()) + } + default: + fn := ls.currentFrame.Fn + index := GlobalsIndex - idx - 1 + if index < len(fn.Upvalues) { + fn.Upvalues[index].SetValue(value) + } + } + } +} + +func (ls *LState) Get(idx int) LValue { + base := ls.currentLocalBase() + if idx > 0 { + reg := base + idx - 1 + if reg < ls.reg.Top() { + return ls.reg.Get(reg) + } + return LNil + } else if idx == 0 { + return LNil + } else if idx > RegistryIndex { + tidx := ls.reg.Top() + idx + if tidx < base { + return LNil + } + return ls.reg.Get(tidx) + } else { + switch idx { + case RegistryIndex: + return ls.G.Registry + case EnvironIndex: + if ls.currentFrame == nil { + return ls.Env + } + return ls.currentFrame.Fn.Env + case GlobalsIndex: + return ls.G.Global + default: + fn := ls.currentFrame.Fn + index := GlobalsIndex - idx - 1 + if index < len(fn.Upvalues) { + return fn.Upvalues[index].Value() + } + return LNil + } + } + return LNil +} + +func (ls *LState) Push(value LValue) { + ls.reg.Push(value) +} + +func (ls *LState) Pop(n int) { + for i := 0; i < n; i++ { + if ls.GetTop() == 0 { + ls.RaiseError("register underflow") + } + ls.reg.Pop() + } +} + +func (ls *LState) Insert(value LValue, index int) { + reg := ls.indexToReg(index) + top := ls.reg.Top() + if reg >= top { + ls.reg.Set(reg, value) + return + } + if reg <= ls.currentLocalBase() { + reg = ls.currentLocalBase() + } + top-- + for ; top >= reg; top-- { + ls.reg.Set(top+1, ls.reg.Get(top)) + } + ls.reg.Set(reg, value) +} + +func (ls *LState) Remove(index int) { + reg := ls.indexToReg(index) + top := ls.reg.Top() + switch { + case reg >= top: + return + case reg < ls.currentLocalBase(): + return + case reg == top-1: + ls.Pop(1) + return + } + for i := reg; i < top-1; i++ { + ls.reg.Set(i, ls.reg.Get(i+1)) + } + ls.reg.SetTop(top - 1) +} + +/* }}} */ + +/* object allocation {{{ */ + +func (ls *LState) NewTable() *LTable { + return newLTable(defaultArrayCap, defaultHashCap) +} + +func (ls *LState) CreateTable(acap, hcap int) *LTable { + return newLTable(acap, hcap) +} + +// NewThread returns a new LState that shares with the original state all global objects. +// If the original state has context.Context, the new state has a new child context of the original state and this function returns its cancel function. +func (ls *LState) NewThread() (*LState, context.CancelFunc) { + thread := newLState(ls.Options) + thread.G = ls.G + thread.Env = ls.Env + var f context.CancelFunc = nil + if ls.ctx != nil { + thread.mainLoop = mainLoopWithContext + thread.ctx, f = context.WithCancel(ls.ctx) + } + return thread, f +} + +func (ls *LState) NewUserData() *LUserData { + return &LUserData{ + Env: ls.currentEnv(), + Metatable: LNil, + } +} + +func (ls *LState) NewFunction(fn LGFunction) *LFunction { + return newLFunctionG(fn, ls.currentEnv(), 0) +} + +func (ls *LState) NewClosure(fn LGFunction, upvalues ...LValue) *LFunction { + cl := newLFunctionG(fn, ls.currentEnv(), len(upvalues)) + for i, lv := range upvalues { + cl.Upvalues[i] = &Upvalue{} + cl.Upvalues[i].Close() + cl.Upvalues[i].SetValue(lv) + } + return cl +} + +/* }}} */ + +/* toType {{{ */ + +func (ls *LState) ToBool(n int) bool { + return LVAsBool(ls.Get(n)) +} + +func (ls *LState) ToInt(n int) int { + if lv, ok := ls.Get(n).(LNumber); ok { + return int(lv) + } + if lv, ok := ls.Get(n).(LString); ok { + if num, err := parseNumber(string(lv)); err == nil { + return int(num) + } + } + return 0 +} + +func (ls *LState) ToInt64(n int) int64 { + if lv, ok := ls.Get(n).(LNumber); ok { + return int64(lv) + } + if lv, ok := ls.Get(n).(LString); ok { + if num, err := parseNumber(string(lv)); err == nil { + return int64(num) + } + } + return 0 +} + +func (ls *LState) ToNumber(n int) LNumber { + return LVAsNumber(ls.Get(n)) +} + +func (ls *LState) ToString(n int) string { + return LVAsString(ls.Get(n)) +} + +func (ls *LState) ToTable(n int) *LTable { + if lv, ok := ls.Get(n).(*LTable); ok { + return lv + } + return nil +} + +func (ls *LState) ToFunction(n int) *LFunction { + if lv, ok := ls.Get(n).(*LFunction); ok { + return lv + } + return nil +} + +func (ls *LState) ToUserData(n int) *LUserData { + if lv, ok := ls.Get(n).(*LUserData); ok { + return lv + } + return nil +} + +func (ls *LState) ToThread(n int) *LState { + if lv, ok := ls.Get(n).(*LState); ok { + return lv + } + return nil +} + +/* }}} */ + +/* error & debug operations {{{ */ + +// This function is equivalent to luaL_error( http://www.lua.org/manual/5.1/manual.html#luaL_error ). +func (ls *LState) RaiseError(format string, args ...interface{}) { + ls.raiseError(1, format, args...) +} + +// This function is equivalent to lua_error( http://www.lua.org/manual/5.1/manual.html#lua_error ). +func (ls *LState) Error(lv LValue, level int) { + if str, ok := lv.(LString); ok { + ls.raiseError(level, string(str)) + } else { + if !ls.hasErrorFunc { + ls.closeAllUpvalues() + } + ls.Push(lv) + ls.Panic(ls) + } +} + +func (ls *LState) GetInfo(what string, dbg *Debug, fn LValue) (LValue, error) { + if !strings.HasPrefix(what, ">") { + fn = dbg.frame.Fn + } else { + what = what[1:] + } + f, ok := fn.(*LFunction) + if !ok { + return LNil, newApiErrorS(ApiErrorRun, "can not get debug info(an object in not a function)") + } + + retfn := false + for _, c := range what { + switch c { + case 'f': + retfn = true + case 'S': + if dbg.frame != nil && dbg.frame.Parent == nil { + dbg.What = "main" + } else if f.IsG { + dbg.What = "G" + } else if dbg.frame != nil && dbg.frame.TailCall > 0 { + dbg.What = "tail" + } else { + dbg.What = "Lua" + } + if !f.IsG { + dbg.Source = f.Proto.SourceName + dbg.LineDefined = f.Proto.LineDefined + dbg.LastLineDefined = f.Proto.LastLineDefined + } + case 'l': + if !f.IsG && dbg.frame != nil { + if dbg.frame.Pc > 0 { + dbg.CurrentLine = f.Proto.DbgSourcePositions[dbg.frame.Pc-1] + } + } else { + dbg.CurrentLine = -1 + } + case 'u': + dbg.NUpvalues = len(f.Upvalues) + case 'n': + if dbg.frame != nil { + dbg.Name = ls.rawFrameFuncName(dbg.frame) + } + default: + return LNil, newApiErrorS(ApiErrorRun, "invalid what: "+string(c)) + } + } + + if retfn { + return f, nil + } + return LNil, nil + +} + +func (ls *LState) GetStack(level int) (*Debug, bool) { + frame := ls.currentFrame + for ; level > 0 && frame != nil; frame = frame.Parent { + level-- + if !frame.Fn.IsG { + level -= frame.TailCall + } + } + + if level == 0 && frame != nil { + return &Debug{frame: frame}, true + } else if level < 0 && ls.stack.Sp() > 0 { + return &Debug{frame: ls.stack.At(0)}, true + } + return &Debug{}, false +} + +func (ls *LState) GetLocal(dbg *Debug, no int) (string, LValue) { + frame := dbg.frame + if name := ls.findLocal(frame, no); len(name) > 0 { + return name, ls.reg.Get(frame.LocalBase + no - 1) + } + return "", LNil +} + +func (ls *LState) SetLocal(dbg *Debug, no int, lv LValue) string { + frame := dbg.frame + if name := ls.findLocal(frame, no); len(name) > 0 { + ls.reg.Set(frame.LocalBase+no-1, lv) + return name + } + return "" +} + +func (ls *LState) GetUpvalue(fn *LFunction, no int) (string, LValue) { + if fn.IsG { + return "", LNil + } + + no-- + if no >= 0 && no < len(fn.Upvalues) { + return fn.Proto.DbgUpvalues[no], fn.Upvalues[no].Value() + } + return "", LNil +} + +func (ls *LState) SetUpvalue(fn *LFunction, no int, lv LValue) string { + if fn.IsG { + return "" + } + + no-- + if no >= 0 && no < len(fn.Upvalues) { + fn.Upvalues[no].SetValue(lv) + return fn.Proto.DbgUpvalues[no] + } + return "" +} + +/* }}} */ + +/* env operations {{{ */ + +func (ls *LState) GetFEnv(obj LValue) LValue { + switch lv := obj.(type) { + case *LFunction: + return lv.Env + case *LUserData: + return lv.Env + case *LState: + return lv.Env + } + return LNil +} + +func (ls *LState) SetFEnv(obj LValue, env LValue) { + tb, ok := env.(*LTable) + if !ok { + ls.RaiseError("cannot use %v as an environment", env.Type().String()) + } + + switch lv := obj.(type) { + case *LFunction: + lv.Env = tb + case *LUserData: + lv.Env = tb + case *LState: + lv.Env = tb + } + /* do nothing */ +} + +/* }}} */ + +/* table operations {{{ */ + +func (ls *LState) RawGet(tb *LTable, key LValue) LValue { + return tb.RawGet(key) +} + +func (ls *LState) RawGetInt(tb *LTable, key int) LValue { + return tb.RawGetInt(key) +} + +func (ls *LState) GetField(obj LValue, skey string) LValue { + return ls.getFieldString(obj, skey) +} + +func (ls *LState) GetTable(obj LValue, key LValue) LValue { + return ls.getField(obj, key) +} + +func (ls *LState) RawSet(tb *LTable, key LValue, value LValue) { + if n, ok := key.(LNumber); ok && math.IsNaN(float64(n)) { + ls.RaiseError("table index is NaN") + } else if key == LNil { + ls.RaiseError("table index is nil") + } + tb.RawSet(key, value) +} + +func (ls *LState) RawSetInt(tb *LTable, key int, value LValue) { + tb.RawSetInt(key, value) +} + +func (ls *LState) SetField(obj LValue, key string, value LValue) { + ls.setFieldString(obj, key, value) +} + +func (ls *LState) SetTable(obj LValue, key LValue, value LValue) { + ls.setField(obj, key, value) +} + +func (ls *LState) ForEach(tb *LTable, cb func(LValue, LValue)) { + tb.ForEach(cb) +} + +func (ls *LState) GetGlobal(name string) LValue { + return ls.GetField(ls.Get(GlobalsIndex), name) +} + +func (ls *LState) SetGlobal(name string, value LValue) { + ls.SetField(ls.Get(GlobalsIndex), name, value) +} + +func (ls *LState) Next(tb *LTable, key LValue) (LValue, LValue) { + return tb.Next(key) +} + +/* }}} */ + +/* unary operations {{{ */ + +func (ls *LState) ObjLen(v1 LValue) int { + if v1.Type() == LTString { + return len(string(v1.(LString))) + } + op := ls.metaOp1(v1, "__len") + if op.Type() == LTFunction { + ls.Push(op) + ls.Push(v1) + ls.Call(1, 1) + ret := ls.reg.Pop() + if ret.Type() == LTNumber { + return int(ret.(LNumber)) + } + } else if v1.Type() == LTTable { + return v1.(*LTable).Len() + } + return 0 +} + +/* }}} */ + +/* binary operations {{{ */ + +func (ls *LState) Concat(values ...LValue) string { + top := ls.reg.Top() + for _, value := range values { + ls.reg.Push(value) + } + ret := stringConcat(ls, len(values), ls.reg.Top()-1) + ls.reg.SetTop(top) + return LVAsString(ret) +} + +func (ls *LState) LessThan(lhs, rhs LValue) bool { + return lessThan(ls, lhs, rhs) +} + +func (ls *LState) Equal(lhs, rhs LValue) bool { + return equals(ls, lhs, rhs, false) +} + +func (ls *LState) RawEqual(lhs, rhs LValue) bool { + return equals(ls, lhs, rhs, true) +} + +/* }}} */ + +/* register operations {{{ */ + +func (ls *LState) Register(name string, fn LGFunction) { + ls.SetGlobal(name, ls.NewFunction(fn)) +} + +/* }}} */ + +/* load and function call operations {{{ */ + +func (ls *LState) Load(reader io.Reader, name string) (*LFunction, error) { + chunk, err := parse.Parse(reader, name) + if err != nil { + return nil, newApiErrorE(ApiErrorSyntax, err) + } + proto, err := Compile(chunk, name) + if err != nil { + return nil, newApiErrorE(ApiErrorSyntax, err) + } + return newLFunctionL(proto, ls.currentEnv(), 0), nil +} + +func (ls *LState) Call(nargs, nret int) { + ls.callR(nargs, nret, -1) +} + +func (ls *LState) PCall(nargs, nret int, errfunc *LFunction) (err error) { + err = nil + sp := ls.stack.Sp() + base := ls.reg.Top() - nargs - 1 + oldpanic := ls.Panic + ls.Panic = panicWithoutTraceback + if errfunc != nil { + ls.hasErrorFunc = true + } + defer func() { + ls.Panic = oldpanic + ls.hasErrorFunc = false + rcv := recover() + if rcv != nil { + if _, ok := rcv.(*ApiError); !ok { + err = newApiErrorS(ApiErrorPanic, fmt.Sprint(rcv)) + if ls.Options.IncludeGoStackTrace { + buf := make([]byte, 4096) + runtime.Stack(buf, false) + err.(*ApiError).StackTrace = strings.Trim(string(buf), "\000") + "\n" + ls.stackTrace(0) + } + } else { + err = rcv.(*ApiError) + } + if errfunc != nil { + ls.Push(errfunc) + ls.Push(err.(*ApiError).Object) + ls.Panic = panicWithoutTraceback + defer func() { + ls.Panic = oldpanic + rcv := recover() + if rcv != nil { + if _, ok := rcv.(*ApiError); !ok { + err = newApiErrorS(ApiErrorPanic, fmt.Sprint(rcv)) + if ls.Options.IncludeGoStackTrace { + buf := make([]byte, 4096) + runtime.Stack(buf, false) + err.(*ApiError).StackTrace = strings.Trim(string(buf), "\000") + ls.stackTrace(0) + } + } else { + err = rcv.(*ApiError) + err.(*ApiError).StackTrace = ls.stackTrace(0) + } + } + }() + ls.Call(1, 1) + err = newApiError(ApiErrorError, ls.Get(-1)) + } else if len(err.(*ApiError).StackTrace) == 0 { + err.(*ApiError).StackTrace = ls.stackTrace(0) + } + ls.stack.SetSp(sp) + ls.currentFrame = ls.stack.Last() + ls.reg.SetTop(base) + } + ls.stack.SetSp(sp) + if sp == 0 { + ls.currentFrame = nil + } + }() + + ls.Call(nargs, nret) + + return +} + +func (ls *LState) GPCall(fn LGFunction, data LValue) error { + ls.Push(newLFunctionG(fn, ls.currentEnv(), 0)) + ls.Push(data) + return ls.PCall(1, MultRet, nil) +} + +func (ls *LState) CallByParam(cp P, args ...LValue) error { + ls.Push(cp.Fn) + for _, arg := range args { + ls.Push(arg) + } + + if cp.Protect { + return ls.PCall(len(args), cp.NRet, cp.Handler) + } + ls.Call(len(args), cp.NRet) + return nil +} + +/* }}} */ + +/* metatable operations {{{ */ + +func (ls *LState) GetMetatable(obj LValue) LValue { + return ls.metatable(obj, false) +} + +func (ls *LState) SetMetatable(obj LValue, mt LValue) { + switch mt.(type) { + case *LNilType, *LTable: + default: + ls.RaiseError("metatable must be a table or nil, but got %v", mt.Type().String()) + } + + switch v := obj.(type) { + case *LTable: + v.Metatable = mt + case *LUserData: + v.Metatable = mt + default: + ls.G.builtinMts[int(obj.Type())] = mt + } +} + +/* }}} */ + +/* coroutine operations {{{ */ + +func (ls *LState) Status(th *LState) string { + status := "suspended" + if th.Dead { + status = "dead" + } else if ls.G.CurrentThread == th { + status = "running" + } else if ls.Parent == th { + status = "normal" + } + return status +} + +func (ls *LState) Resume(th *LState, fn *LFunction, args ...LValue) (ResumeState, error, []LValue) { + isstarted := th.isStarted() + if !isstarted { + base := 0 + th.stack.Push(callFrame{ + Fn: fn, + Pc: 0, + Base: base, + LocalBase: base + 1, + ReturnBase: base, + NArgs: 0, + NRet: MultRet, + Parent: nil, + TailCall: 0, + }) + } + + if ls.G.CurrentThread == th { + return ResumeError, newApiErrorS(ApiErrorRun, "can not resume a running thread"), nil + } + if th.Dead { + return ResumeError, newApiErrorS(ApiErrorRun, "can not resume a dead thread"), nil + } + th.Parent = ls + ls.G.CurrentThread = th + if !isstarted { + cf := th.stack.Last() + th.currentFrame = cf + th.SetTop(0) + for _, arg := range args { + th.Push(arg) + } + cf.NArgs = len(args) + th.initCallFrame(cf) + th.Panic = panicWithoutTraceback + } else { + for _, arg := range args { + th.Push(arg) + } + } + top := ls.GetTop() + threadRun(th) + haserror := LVIsFalse(ls.Get(top + 1)) + ret := make([]LValue, 0, ls.GetTop()) + for idx := top + 2; idx <= ls.GetTop(); idx++ { + ret = append(ret, ls.Get(idx)) + } + if len(ret) == 0 { + ret = append(ret, LNil) + } + ls.SetTop(top) + + if haserror { + return ResumeError, newApiError(ApiErrorRun, ret[0]), nil + } else if th.stack.IsEmpty() { + return ResumeOK, nil, ret + } + return ResumeYield, nil, ret +} + +func (ls *LState) Yield(values ...LValue) int { + ls.SetTop(0) + for _, lv := range values { + ls.Push(lv) + } + return -1 +} + +func (ls *LState) XMoveTo(other *LState, n int) { + if ls == other { + return + } + top := ls.GetTop() + n = intMin(n, top) + for i := n; i > 0; i-- { + other.Push(ls.Get(top - i + 1)) + } + ls.SetTop(top - n) +} + +/* }}} */ + +/* GopherLua original APIs {{{ */ + +// Set maximum memory size. This function can only be called from the main thread. +func (ls *LState) SetMx(mx int) { + if ls.Parent != nil { + ls.RaiseError("sub threads are not allowed to set a memory limit") + } + go func() { + limit := uint64(mx * 1024 * 1024) //MB + var s runtime.MemStats + for ls.stop == 0 { + runtime.ReadMemStats(&s) + if s.Alloc >= limit { + fmt.Println("out of memory") + os.Exit(3) + } + time.Sleep(100 * time.Millisecond) + } + }() +} + +// SetContext set a context ctx to this LState. The provided ctx must be non-nil. +func (ls *LState) SetContext(ctx context.Context) { + ls.mainLoop = mainLoopWithContext + ls.ctx = ctx +} + +// Context returns the LState's context. To change the context, use WithContext. +func (ls *LState) Context() context.Context { + return ls.ctx +} + +// RemoveContext removes the context associated with this LState and returns this context. +func (ls *LState) RemoveContext() context.Context { + oldctx := ls.ctx + ls.mainLoop = mainLoop + ls.ctx = nil + return oldctx +} + +// Converts the Lua value at the given acceptable index to the chan LValue. +func (ls *LState) ToChannel(n int) chan LValue { + if lv, ok := ls.Get(n).(LChannel); ok { + return (chan LValue)(lv) + } + return nil +} + +/* }}} */ + +/* }}} */ + +// diff --git a/vendor/github.com/yuin/gopher-lua/_tools/go-inline b/vendor/github.com/yuin/gopher-lua/_tools/go-inline new file mode 100755 index 0000000000000000000000000000000000000000..0fb97299462a83ca21e9a4a38c5c00a8ce3796ab --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/_tools/go-inline @@ -0,0 +1,82 @@ +#!/usr/bin/env python +# Simple and indolent text processor to do inline go function calling + +import sys, re + + +files = sys.argv +class inline(object): + def __init__(self, name): + self.name = name + self.receiver = "" + self.args = [] + self.contents = [] + self.file = "" + self.original = "" + +inlines = {} +for file in sorted(files, reverse=True): + contents = open(file).read().splitlines() + i = 0 + name = "" + while i < len(contents): + line = contents[i] + m = re.match(".*\/\/ \+inline-start", line) + if m: + m2 = re.match("^func\s*(\([\*\s\w]+\))?\s*(\w+)\(([^\)]*)\)", line) + name = m2.group(2) + tinline = inline(name) + tinline.original = line.split("//")[0].strip().rstrip("{") + tinline.file = file + if m2.group(1): + tinline.receiver = m2.group(1).split("(")[1].split(" ")[0] + tinline.args = [arg.strip().split(" ")[0] for arg in m2.group(3).split(",")] + inlines[name] = tinline + else: + if re.match(".*\/\/\s*\+inline-end", line): + inlines[name].contents = "\n".join(inlines[name].contents) + name = "" + elif len(name) > 0: + inlines[name].contents.append(line) + i += 1 + +def do_inlining(text): + contents = text.splitlines() + buf = [] + i = 0 + while i < len(contents): + line = contents[i] + m = re.match("\s*\/\/\s*\+inline-call\s+([\w\.]+)\s+(.*)", line) + if m: + inlinet = inlines[m.group(1).split(".")[-1]] + buf.append("// this section is inlined by go-inline") + buf.append("// source function is '{}' in '{}'".format(inlinet.original, inlinet.file)) + buf.append("{") + if len(inlinet.receiver) > 0 and inlinet.receiver != m.group(1).split(".")[0]: + buf.append("{} := {}".format(inlinet.receiver, ".".join(m.group(1).split(".")[0:-1]))) + + callargs = [arg.strip() for arg in m.group(2).split(" ")] + for j in range(len(callargs)): + if inlinet.args[j] != callargs[j]: + buf.append("{} := {}".format(inlinet.args[j], callargs[j])) + buf.append(do_inlining(inlinet.contents)) + buf.append("}") + else: + buf.append(line) + i += 1 + return "\n".join(buf) + +for file in files: + if not file.startswith("_"): + continue + contents = open(file).read() + with open(file.lstrip("_"), "w") as io: + inlined = do_inlining(contents).split("\n") + for i in range(len(inlined)): + if i == 1: + io.write("////////////////////////////////////////////////////////\n") + io.write("// This file was generated by go-inline. DO NOT EDIT. //\n") + io.write("////////////////////////////////////////////////////////\n") + io.write(inlined[i]) + io.write("\n") + io.write("\n") diff --git a/vendor/github.com/yuin/gopher-lua/_vm.go b/vendor/github.com/yuin/gopher-lua/_vm.go new file mode 100644 index 0000000000000000000000000000000000000000..cef43808d5f29b3a30c45a81fb6225559c937514 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/_vm.go @@ -0,0 +1,1024 @@ +package lua + +import ( + "fmt" + "math" + "strings" +) + +func mainLoop(L *LState, baseframe *callFrame) { + var inst uint32 + var cf *callFrame + + if L.stack.IsEmpty() { + return + } + + L.currentFrame = L.stack.Last() + if L.currentFrame.Fn.IsG { + callGFunction(L, false) + return + } + + for { + cf = L.currentFrame + inst = cf.Fn.Proto.Code[cf.Pc] + cf.Pc++ + if jumpTable[int(inst>>26)](L, inst, baseframe) == 1 { + return + } + } +} + +func mainLoopWithContext(L *LState, baseframe *callFrame) { + var inst uint32 + var cf *callFrame + + if L.stack.IsEmpty() { + return + } + + L.currentFrame = L.stack.Last() + if L.currentFrame.Fn.IsG { + callGFunction(L, false) + return + } + + for { + cf = L.currentFrame + inst = cf.Fn.Proto.Code[cf.Pc] + cf.Pc++ + select { + case <-L.ctx.Done(): + L.RaiseError(L.ctx.Err().Error()) + return + default: + if jumpTable[int(inst>>26)](L, inst, baseframe) == 1 { + return + } + } + } +} + +func copyReturnValues(L *LState, regv, start, n, b int) { // +inline-start + if b == 1 { + // +inline-call L.reg.FillNil regv n + } else { + // +inline-call L.reg.CopyRange regv start -1 n + } +} // +inline-end + +func switchToParentThread(L *LState, nargs int, haserror bool, kill bool) { + parent := L.Parent + if parent == nil { + L.RaiseError("can not yield from outside of a coroutine") + } + L.G.CurrentThread = parent + L.Parent = nil + if !L.wrapped { + if haserror { + parent.Push(LFalse) + } else { + parent.Push(LTrue) + } + } + L.XMoveTo(parent, nargs) + L.stack.Pop() + offset := L.currentFrame.LocalBase - L.currentFrame.ReturnBase + L.currentFrame = L.stack.Last() + L.reg.SetTop(L.reg.Top() - offset) // remove 'yield' function(including tailcalled functions) + if kill { + L.kill() + } +} + +func callGFunction(L *LState, tailcall bool) bool { + frame := L.currentFrame + gfnret := frame.Fn.GFunction(L) + if tailcall { + L.stack.Remove(L.stack.Sp() - 2) // remove caller lua function frame + L.currentFrame = L.stack.Last() + } + + if gfnret < 0 { + switchToParentThread(L, L.GetTop(), false, false) + return true + } + + wantret := frame.NRet + if wantret == MultRet { + wantret = gfnret + } + + if tailcall && L.Parent != nil && L.stack.Sp() == 1 { + switchToParentThread(L, wantret, false, true) + return true + } + + // +inline-call L.reg.CopyRange frame.ReturnBase L.reg.Top()-gfnret -1 wantret + L.stack.Pop() + L.currentFrame = L.stack.Last() + return false +} + +func threadRun(L *LState) { + if L.stack.IsEmpty() { + return + } + + defer func() { + if rcv := recover(); rcv != nil { + var lv LValue + if v, ok := rcv.(*ApiError); ok { + lv = v.Object + } else { + lv = LString(fmt.Sprint(rcv)) + } + if parent := L.Parent; parent != nil { + if L.wrapped { + L.Push(lv) + parent.Panic(L) + } else { + L.SetTop(0) + L.Push(lv) + switchToParentThread(L, 1, true, true) + } + } else { + panic(rcv) + } + } + }() + L.mainLoop(L, nil) +} + +type instFunc func(*LState, uint32, *callFrame) int + +var jumpTable [opCodeMax + 1]instFunc + +func init() { + jumpTable = [opCodeMax + 1]instFunc{ + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_MOVE + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + reg.Set(RA, reg.Get(lbase+B)) + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_MOVEN + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + B := int(inst & 0x1ff) //GETB + C := int(inst>>9) & 0x1ff //GETC + reg.Set(lbase+A, reg.Get(lbase+B)) + code := cf.Fn.Proto.Code + pc := cf.Pc + for i := 0; i < C; i++ { + inst = code[pc] + pc++ + A = int(inst>>18) & 0xff //GETA + B = int(inst & 0x1ff) //GETB + reg.Set(lbase+A, reg.Get(lbase+B)) + } + cf.Pc = pc + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LOADK + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + Bx := int(inst & 0x3ffff) //GETBX + reg.Set(RA, cf.Fn.Proto.Constants[Bx]) + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LOADBOOL + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + C := int(inst>>9) & 0x1ff //GETC + if B != 0 { + reg.Set(RA, LTrue) + } else { + reg.Set(RA, LFalse) + } + if C != 0 { + cf.Pc++ + } + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LOADNIL + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + for i := RA; i <= lbase+B; i++ { + reg.Set(i, LNil) + } + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETUPVAL + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + reg.Set(RA, cf.Fn.Upvalues[B].Value()) + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETGLOBAL + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + Bx := int(inst & 0x3ffff) //GETBX + //reg.Set(RA, L.getField(cf.Fn.Env, cf.Fn.Proto.Constants[Bx])) + reg.Set(RA, L.getFieldString(cf.Fn.Env, cf.Fn.Proto.stringConstants[Bx])) + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETTABLE + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + C := int(inst>>9) & 0x1ff //GETC + reg.Set(RA, L.getField(reg.Get(lbase+B), L.rkValue(C))) + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETTABLEKS + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + C := int(inst>>9) & 0x1ff //GETC + reg.Set(RA, L.getFieldString(reg.Get(lbase+B), L.rkString(C))) + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETGLOBAL + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + Bx := int(inst & 0x3ffff) //GETBX + //L.setField(cf.Fn.Env, cf.Fn.Proto.Constants[Bx], reg.Get(RA)) + L.setFieldString(cf.Fn.Env, cf.Fn.Proto.stringConstants[Bx], reg.Get(RA)) + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETUPVAL + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + cf.Fn.Upvalues[B].SetValue(reg.Get(RA)) + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETTABLE + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + C := int(inst>>9) & 0x1ff //GETC + L.setField(reg.Get(RA), L.rkValue(B), L.rkValue(C)) + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETTABLEKS + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + C := int(inst>>9) & 0x1ff //GETC + L.setFieldString(reg.Get(RA), L.rkString(B), L.rkValue(C)) + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_NEWTABLE + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + C := int(inst>>9) & 0x1ff //GETC + reg.Set(RA, newLTable(B, C)) + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SELF + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + C := int(inst>>9) & 0x1ff //GETC + selfobj := reg.Get(lbase + B) + reg.Set(RA, L.getFieldString(selfobj, L.rkString(C))) + reg.Set(RA+1, selfobj) + return 0 + }, + opArith, // OP_ADD + opArith, // OP_SUB + opArith, // OP_MUL + opArith, // OP_DIV + opArith, // OP_MOD + opArith, // OP_POW + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_UNM + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + unaryv := L.rkValue(B) + if nm, ok := unaryv.(LNumber); ok { + reg.SetNumber(RA, -nm) + } else { + op := L.metaOp1(unaryv, "__unm") + if op.Type() == LTFunction { + reg.Push(op) + reg.Push(unaryv) + L.Call(1, 1) + reg.Set(RA, reg.Pop()) + } else if str, ok1 := unaryv.(LString); ok1 { + if num, err := parseNumber(string(str)); err == nil { + reg.Set(RA, -num) + } else { + L.RaiseError("__unm undefined") + } + } else { + L.RaiseError("__unm undefined") + } + } + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_NOT + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + if LVIsFalse(reg.Get(lbase + B)) { + reg.Set(RA, LTrue) + } else { + reg.Set(RA, LFalse) + } + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LEN + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + switch lv := L.rkValue(B).(type) { + case LString: + reg.SetNumber(RA, LNumber(len(lv))) + default: + op := L.metaOp1(lv, "__len") + if op.Type() == LTFunction { + reg.Push(op) + reg.Push(lv) + L.Call(1, 1) + ret := reg.Pop() + if ret.Type() == LTNumber { + reg.SetNumber(RA, ret.(LNumber)) + } else { + reg.SetNumber(RA, LNumber(0)) + } + } else if lv.Type() == LTTable { + reg.SetNumber(RA, LNumber(lv.(*LTable).Len())) + } else { + L.RaiseError("__len undefined") + } + } + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CONCAT + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + C := int(inst>>9) & 0x1ff //GETC + RC := lbase + C + RB := lbase + B + reg.Set(RA, stringConcat(L, RC-RB+1, RC)) + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_JMP + cf := L.currentFrame + Sbx := int(inst&0x3ffff) - opMaxArgSbx //GETSBX + cf.Pc += Sbx + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_EQ + cf := L.currentFrame + A := int(inst>>18) & 0xff //GETA + B := int(inst & 0x1ff) //GETB + C := int(inst>>9) & 0x1ff //GETC + ret := equals(L, L.rkValue(B), L.rkValue(C), false) + v := 1 + if ret { + v = 0 + } + if v == A { + cf.Pc++ + } + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LT + cf := L.currentFrame + A := int(inst>>18) & 0xff //GETA + B := int(inst & 0x1ff) //GETB + C := int(inst>>9) & 0x1ff //GETC + ret := lessThan(L, L.rkValue(B), L.rkValue(C)) + v := 1 + if ret { + v = 0 + } + if v == A { + cf.Pc++ + } + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LE + cf := L.currentFrame + A := int(inst>>18) & 0xff //GETA + B := int(inst & 0x1ff) //GETB + C := int(inst>>9) & 0x1ff //GETC + lhs := L.rkValue(B) + rhs := L.rkValue(C) + ret := false + + if v1, ok1 := lhs.assertFloat64(); ok1 { + if v2, ok2 := rhs.assertFloat64(); ok2 { + ret = v1 <= v2 + } else { + L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String()) + } + } else { + if lhs.Type() != rhs.Type() { + L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String()) + } + switch lhs.Type() { + case LTString: + ret = strCmp(string(lhs.(LString)), string(rhs.(LString))) <= 0 + default: + switch objectRational(L, lhs, rhs, "__le") { + case 1: + ret = true + case 0: + ret = false + default: + ret = !objectRationalWithError(L, rhs, lhs, "__lt") + } + } + } + + v := 1 + if ret { + v = 0 + } + if v == A { + cf.Pc++ + } + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TEST + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + C := int(inst>>9) & 0x1ff //GETC + if LVAsBool(reg.Get(RA)) == (C == 0) { + cf.Pc++ + } + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TESTSET + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + C := int(inst>>9) & 0x1ff //GETC + if value := reg.Get(lbase + B); LVAsBool(value) != (C == 0) { + reg.Set(RA, value) + } else { + cf.Pc++ + } + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CALL + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + C := int(inst>>9) & 0x1ff //GETC + nargs := B - 1 + if B == 0 { + nargs = reg.Top() - (RA + 1) + } + lv := reg.Get(RA) + nret := C - 1 + var callable *LFunction + var meta bool + if fn, ok := lv.assertFunction(); ok { + callable = fn + meta = false + } else { + callable, meta = L.metaCall(lv) + } + // +inline-call L.pushCallFrame callFrame{Fn:callable,Pc:0,Base:RA,LocalBase:RA+1,ReturnBase:RA,NArgs:nargs,NRet:nret,Parent:cf,TailCall:0} lv meta + if callable.IsG && callGFunction(L, false) { + return 1 + } + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TAILCALL + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + nargs := B - 1 + if B == 0 { + nargs = reg.Top() - (RA + 1) + } + lv := reg.Get(RA) + var callable *LFunction + var meta bool + if fn, ok := lv.assertFunction(); ok { + callable = fn + meta = false + } else { + callable, meta = L.metaCall(lv) + } + if callable == nil { + L.RaiseError("attempt to call a non-function object") + } + // +inline-call L.closeUpvalues lbase + if callable.IsG { + luaframe := cf + L.pushCallFrame(callFrame{ + Fn: callable, + Pc: 0, + Base: RA, + LocalBase: RA + 1, + ReturnBase: cf.ReturnBase, + NArgs: nargs, + NRet: cf.NRet, + Parent: cf, + TailCall: 0, + }, lv, meta) + if callGFunction(L, true) { + return 1 + } + if L.currentFrame == nil || L.currentFrame.Fn.IsG || luaframe == baseframe { + return 1 + } + } else { + base := cf.Base + cf.Fn = callable + cf.Pc = 0 + cf.Base = RA + cf.LocalBase = RA + 1 + cf.ReturnBase = cf.ReturnBase + cf.NArgs = nargs + cf.NRet = cf.NRet + cf.TailCall++ + lbase := cf.LocalBase + if meta { + cf.NArgs++ + L.reg.Insert(lv, cf.LocalBase) + } + // +inline-call L.initCallFrame cf + // +inline-call L.reg.CopyRange base RA -1 reg.Top()-RA-1 + cf.Base = base + cf.LocalBase = base + (cf.LocalBase - lbase + 1) + } + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_RETURN + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + // +inline-call L.closeUpvalues lbase + nret := B - 1 + if B == 0 { + nret = reg.Top() - RA + } + n := cf.NRet + if cf.NRet == MultRet { + n = nret + } + + if L.Parent != nil && L.stack.Sp() == 1 { + // +inline-call copyReturnValues L reg.Top() RA n B + switchToParentThread(L, n, false, true) + return 1 + } + islast := baseframe == L.stack.Pop() || L.stack.IsEmpty() + // +inline-call copyReturnValues L cf.ReturnBase RA n B + L.currentFrame = L.stack.Last() + if islast || L.currentFrame == nil || L.currentFrame.Fn.IsG { + return 1 + } + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_FORLOOP + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + if init, ok1 := reg.Get(RA).assertFloat64(); ok1 { + if limit, ok2 := reg.Get(RA + 1).assertFloat64(); ok2 { + if step, ok3 := reg.Get(RA + 2).assertFloat64(); ok3 { + init += step + reg.SetNumber(RA, LNumber(init)) + if (step > 0 && init <= limit) || (step <= 0 && init >= limit) { + Sbx := int(inst&0x3ffff) - opMaxArgSbx //GETSBX + cf.Pc += Sbx + reg.SetNumber(RA+3, LNumber(init)) + } else { + reg.SetTop(RA + 1) + } + } else { + L.RaiseError("for statement step must be a number") + } + } else { + L.RaiseError("for statement limit must be a number") + } + } else { + L.RaiseError("for statement init must be a number") + } + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_FORPREP + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + Sbx := int(inst&0x3ffff) - opMaxArgSbx //GETSBX + if init, ok1 := reg.Get(RA).assertFloat64(); ok1 { + if step, ok2 := reg.Get(RA + 2).assertFloat64(); ok2 { + reg.SetNumber(RA, LNumber(init-step)) + } else { + L.RaiseError("for statement step must be a number") + } + } else { + L.RaiseError("for statement init must be a number") + } + cf.Pc += Sbx + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TFORLOOP + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + C := int(inst>>9) & 0x1ff //GETC + nret := C + reg.SetTop(RA + 3 + 2) + reg.Set(RA+3+2, reg.Get(RA+2)) + reg.Set(RA+3+1, reg.Get(RA+1)) + reg.Set(RA+3, reg.Get(RA)) + L.callR(2, nret, RA+3) + if value := reg.Get(RA + 3); value != LNil { + reg.Set(RA+2, value) + pc := cf.Fn.Proto.Code[cf.Pc] + cf.Pc += int(pc&0x3ffff) - opMaxArgSbx + } + cf.Pc++ + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETLIST + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + C := int(inst>>9) & 0x1ff //GETC + if C == 0 { + C = int(cf.Fn.Proto.Code[cf.Pc]) + cf.Pc++ + } + offset := (C - 1) * FieldsPerFlush + table := reg.Get(RA).(*LTable) + nelem := B + if B == 0 { + nelem = reg.Top() - RA - 1 + } + for i := 1; i <= nelem; i++ { + table.RawSetInt(offset+i, reg.Get(RA+i)) + } + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CLOSE + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + // +inline-call L.closeUpvalues RA + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CLOSURE + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + Bx := int(inst & 0x3ffff) //GETBX + proto := cf.Fn.Proto.FunctionPrototypes[Bx] + closure := newLFunctionL(proto, cf.Fn.Env, int(proto.NumUpvalues)) + reg.Set(RA, closure) + for i := 0; i < int(proto.NumUpvalues); i++ { + inst = cf.Fn.Proto.Code[cf.Pc] + cf.Pc++ + B := opGetArgB(inst) + switch opGetOpCode(inst) { + case OP_MOVE: + closure.Upvalues[i] = L.findUpvalue(lbase + B) + case OP_GETUPVAL: + closure.Upvalues[i] = cf.Fn.Upvalues[B] + } + } + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_VARARG + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + nparams := int(cf.Fn.Proto.NumParameters) + nvarargs := cf.NArgs - nparams + if nvarargs < 0 { + nvarargs = 0 + } + nwant := B - 1 + if B == 0 { + nwant = nvarargs + } + // +inline-call reg.CopyRange RA cf.Base+nparams+1 cf.LocalBase nwant + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_NOP + return 0 + }, + } +} + +func opArith(L *LState, inst uint32, baseframe *callFrame) int { //OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_MOD, OP_POW + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + opcode := int(inst >> 26) //GETOPCODE + B := int(inst & 0x1ff) //GETB + C := int(inst>>9) & 0x1ff //GETC + lhs := L.rkValue(B) + rhs := L.rkValue(C) + v1, ok1 := lhs.assertFloat64() + v2, ok2 := rhs.assertFloat64() + if ok1 && ok2 { + reg.SetNumber(RA, numberArith(L, opcode, LNumber(v1), LNumber(v2))) + } else { + reg.Set(RA, objectArith(L, opcode, lhs, rhs)) + } + return 0 +} + +func luaModulo(lhs, rhs LNumber) LNumber { + flhs := float64(lhs) + frhs := float64(rhs) + v := math.Mod(flhs, frhs) + if flhs < 0 || frhs < 0 && !(flhs < 0 && frhs < 0) { + v += frhs + } + return LNumber(v) +} + +func numberArith(L *LState, opcode int, lhs, rhs LNumber) LNumber { + switch opcode { + case OP_ADD: + return lhs + rhs + case OP_SUB: + return lhs - rhs + case OP_MUL: + return lhs * rhs + case OP_DIV: + return lhs / rhs + case OP_MOD: + return luaModulo(lhs, rhs) + case OP_POW: + flhs := float64(lhs) + frhs := float64(rhs) + return LNumber(math.Pow(flhs, frhs)) + } + panic("should not reach here") + return LNumber(0) +} + +func objectArith(L *LState, opcode int, lhs, rhs LValue) LValue { + event := "" + switch opcode { + case OP_ADD: + event = "__add" + case OP_SUB: + event = "__sub" + case OP_MUL: + event = "__mul" + case OP_DIV: + event = "__div" + case OP_MOD: + event = "__mod" + case OP_POW: + event = "__pow" + } + op := L.metaOp2(lhs, rhs, event) + if op.Type() == LTFunction { + L.reg.Push(op) + L.reg.Push(lhs) + L.reg.Push(rhs) + L.Call(2, 1) + return L.reg.Pop() + } + if str, ok := lhs.(LString); ok { + if lnum, err := parseNumber(string(str)); err == nil { + lhs = lnum + } + } + if str, ok := rhs.(LString); ok { + if rnum, err := parseNumber(string(str)); err == nil { + rhs = rnum + } + } + if v1, ok1 := lhs.assertFloat64(); ok1 { + if v2, ok2 := rhs.assertFloat64(); ok2 { + return numberArith(L, opcode, LNumber(v1), LNumber(v2)) + } + } + L.RaiseError(fmt.Sprintf("cannot perform %v operation between %v and %v", + strings.TrimLeft(event, "_"), lhs.Type().String(), rhs.Type().String())) + + return LNil +} + +func stringConcat(L *LState, total, last int) LValue { + rhs := L.reg.Get(last) + total-- + for i := last - 1; total > 0; { + lhs := L.reg.Get(i) + if !(LVCanConvToString(lhs) && LVCanConvToString(rhs)) { + op := L.metaOp2(lhs, rhs, "__concat") + if op.Type() == LTFunction { + L.reg.Push(op) + L.reg.Push(lhs) + L.reg.Push(rhs) + L.Call(2, 1) + rhs = L.reg.Pop() + total-- + i-- + } else { + L.RaiseError("cannot perform concat operation between %v and %v", lhs.Type().String(), rhs.Type().String()) + return LNil + } + } else { + buf := make([]string, total+1) + buf[total] = LVAsString(rhs) + for total > 0 { + lhs = L.reg.Get(i) + if !LVCanConvToString(lhs) { + break + } + buf[total-1] = LVAsString(lhs) + i-- + total-- + } + rhs = LString(strings.Join(buf, "")) + } + } + return rhs +} + +func lessThan(L *LState, lhs, rhs LValue) bool { + // optimization for numbers + if v1, ok1 := lhs.assertFloat64(); ok1 { + if v2, ok2 := rhs.assertFloat64(); ok2 { + return v1 < v2 + } + L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String()) + } + if lhs.Type() != rhs.Type() { + L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String()) + return false + } + ret := false + switch lhs.Type() { + case LTString: + ret = strCmp(string(lhs.(LString)), string(rhs.(LString))) < 0 + default: + ret = objectRationalWithError(L, lhs, rhs, "__lt") + } + return ret +} + +func equals(L *LState, lhs, rhs LValue, raw bool) bool { + if lhs.Type() != rhs.Type() { + return false + } + + ret := false + switch lhs.Type() { + case LTNil: + ret = true + case LTNumber: + v1, _ := lhs.assertFloat64() + v2, _ := rhs.assertFloat64() + ret = v1 == v2 + case LTBool: + ret = bool(lhs.(LBool)) == bool(rhs.(LBool)) + case LTString: + ret = string(lhs.(LString)) == string(rhs.(LString)) + case LTUserData, LTTable: + if lhs == rhs { + ret = true + } else if !raw { + switch objectRational(L, lhs, rhs, "__eq") { + case 1: + ret = true + default: + ret = false + } + } + default: + ret = lhs == rhs + } + return ret +} + +func objectRationalWithError(L *LState, lhs, rhs LValue, event string) bool { + switch objectRational(L, lhs, rhs, event) { + case 1: + return true + case 0: + return false + } + L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String()) + return false +} + +func objectRational(L *LState, lhs, rhs LValue, event string) int { + m1 := L.metaOp1(lhs, event) + m2 := L.metaOp1(rhs, event) + if m1.Type() == LTFunction && m1 == m2 { + L.reg.Push(m1) + L.reg.Push(lhs) + L.reg.Push(rhs) + L.Call(2, 1) + if LVAsBool(L.reg.Pop()) { + return 1 + } + return 0 + } + return -1 +} diff --git a/vendor/github.com/yuin/gopher-lua/alloc.go b/vendor/github.com/yuin/gopher-lua/alloc.go new file mode 100644 index 0000000000000000000000000000000000000000..4db466090aed810a9f5e6bc0f1f32e2e3cd0ae03 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/alloc.go @@ -0,0 +1,73 @@ +package lua + +import ( + "reflect" + "unsafe" +) + +// iface is an internal representation of the go-interface. +type iface struct { + itab unsafe.Pointer + word unsafe.Pointer +} + +const preloadLimit LNumber = 128 + +var _fv float64 +var _uv uintptr + +// allocator is a fast bulk memory allocator for the LValue. +type allocator struct { + top int + size int + nptrs []LValue + nheader *reflect.SliceHeader + fptrs []float64 + fheader *reflect.SliceHeader + itabLNumber unsafe.Pointer + preloads [int(preloadLimit)]LValue +} + +func newAllocator(size int) *allocator { + al := &allocator{ + top: 0, + size: size, + nptrs: make([]LValue, size), + nheader: nil, + fptrs: make([]float64, size), + fheader: nil, + itabLNumber: unsafe.Pointer(nil), + } + al.nheader = (*reflect.SliceHeader)(unsafe.Pointer(&al.nptrs)) + al.fheader = (*reflect.SliceHeader)(unsafe.Pointer(&al.fptrs)) + + var v LValue = LNumber(0) + vp := (*iface)(unsafe.Pointer(&v)) + al.itabLNumber = vp.itab + for i := 0; i < int(preloadLimit); i++ { + al.preloads[i] = LNumber(i) + } + return al +} + +func (al *allocator) LNumber2I(v LNumber) LValue { + if v >= 0 && v < preloadLimit && float64(v) == float64(int64(v)) { + return al.preloads[int(v)] + } + if al.top == len(al.nptrs)-1 { + al.top = 0 + al.nptrs = make([]LValue, al.size) + al.nheader = (*reflect.SliceHeader)(unsafe.Pointer(&al.nptrs)) + al.fptrs = make([]float64, al.size) + al.fheader = (*reflect.SliceHeader)(unsafe.Pointer(&al.fptrs)) + } + fptr := (*float64)(unsafe.Pointer(al.fheader.Data + uintptr(al.top)*unsafe.Sizeof(_fv))) + e := *(*LValue)(unsafe.Pointer(al.nheader.Data + uintptr(al.top)*unsafe.Sizeof(_uv))) + al.top++ + + ep := (*iface)(unsafe.Pointer(&e)) + ep.itab = al.itabLNumber + *fptr = float64(v) + ep.word = unsafe.Pointer(fptr) + return e +} diff --git a/vendor/github.com/yuin/gopher-lua/ast/ast.go b/vendor/github.com/yuin/gopher-lua/ast/ast.go new file mode 100644 index 0000000000000000000000000000000000000000..f337a2947322eca363c3f5ea140d9e3cd559fa9c --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/ast/ast.go @@ -0,0 +1,29 @@ +package ast + +type PositionHolder interface { + Line() int + SetLine(int) + LastLine() int + SetLastLine(int) +} + +type Node struct { + line int + lastline int +} + +func (self *Node) Line() int { + return self.line +} + +func (self *Node) SetLine(line int) { + self.line = line +} + +func (self *Node) LastLine() int { + return self.lastline +} + +func (self *Node) SetLastLine(line int) { + self.lastline = line +} diff --git a/vendor/github.com/yuin/gopher-lua/ast/expr.go b/vendor/github.com/yuin/gopher-lua/ast/expr.go new file mode 100644 index 0000000000000000000000000000000000000000..ccda3279101f0f00247f0587deb413405d646bbb --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/ast/expr.go @@ -0,0 +1,137 @@ +package ast + +type Expr interface { + PositionHolder + exprMarker() +} + +type ExprBase struct { + Node +} + +func (expr *ExprBase) exprMarker() {} + +/* ConstExprs {{{ */ + +type ConstExpr interface { + Expr + constExprMarker() +} + +type ConstExprBase struct { + ExprBase +} + +func (expr *ConstExprBase) constExprMarker() {} + +type TrueExpr struct { + ConstExprBase +} + +type FalseExpr struct { + ConstExprBase +} + +type NilExpr struct { + ConstExprBase +} + +type NumberExpr struct { + ConstExprBase + + Value string +} + +type StringExpr struct { + ConstExprBase + + Value string +} + +/* ConstExprs }}} */ + +type Comma3Expr struct { + ExprBase +} + +type IdentExpr struct { + ExprBase + + Value string +} + +type AttrGetExpr struct { + ExprBase + + Object Expr + Key Expr +} + +type TableExpr struct { + ExprBase + + Fields []*Field +} + +type FuncCallExpr struct { + ExprBase + + Func Expr + Receiver Expr + Method string + Args []Expr + AdjustRet bool +} + +type LogicalOpExpr struct { + ExprBase + + Operator string + Lhs Expr + Rhs Expr +} + +type RelationalOpExpr struct { + ExprBase + + Operator string + Lhs Expr + Rhs Expr +} + +type StringConcatOpExpr struct { + ExprBase + + Lhs Expr + Rhs Expr +} + +type ArithmeticOpExpr struct { + ExprBase + + Operator string + Lhs Expr + Rhs Expr +} + +type UnaryMinusOpExpr struct { + ExprBase + Expr Expr +} + +type UnaryNotOpExpr struct { + ExprBase + Expr Expr +} + +type UnaryLenOpExpr struct { + ExprBase + Expr Expr +} + +type FunctionExpr struct { + ExprBase + + ParList *ParList + Stmts []Stmt +} diff --git a/vendor/github.com/yuin/gopher-lua/ast/misc.go b/vendor/github.com/yuin/gopher-lua/ast/misc.go new file mode 100644 index 0000000000000000000000000000000000000000..d811c042aa0ec403ceb5f44f795ec6d7d9eea8e4 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/ast/misc.go @@ -0,0 +1,17 @@ +package ast + +type Field struct { + Key Expr + Value Expr +} + +type ParList struct { + HasVargs bool + Names []string +} + +type FuncName struct { + Func Expr + Receiver Expr + Method string +} diff --git a/vendor/github.com/yuin/gopher-lua/ast/stmt.go b/vendor/github.com/yuin/gopher-lua/ast/stmt.go new file mode 100644 index 0000000000000000000000000000000000000000..56ea6d1a23afe3d2638408b4fb729534dcf44127 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/ast/stmt.go @@ -0,0 +1,95 @@ +package ast + +type Stmt interface { + PositionHolder + stmtMarker() +} + +type StmtBase struct { + Node +} + +func (stmt *StmtBase) stmtMarker() {} + +type AssignStmt struct { + StmtBase + + Lhs []Expr + Rhs []Expr +} + +type LocalAssignStmt struct { + StmtBase + + Names []string + Exprs []Expr +} + +type FuncCallStmt struct { + StmtBase + + Expr Expr +} + +type DoBlockStmt struct { + StmtBase + + Stmts []Stmt +} + +type WhileStmt struct { + StmtBase + + Condition Expr + Stmts []Stmt +} + +type RepeatStmt struct { + StmtBase + + Condition Expr + Stmts []Stmt +} + +type IfStmt struct { + StmtBase + + Condition Expr + Then []Stmt + Else []Stmt +} + +type NumberForStmt struct { + StmtBase + + Name string + Init Expr + Limit Expr + Step Expr + Stmts []Stmt +} + +type GenericForStmt struct { + StmtBase + + Names []string + Exprs []Expr + Stmts []Stmt +} + +type FuncDefStmt struct { + StmtBase + + Name *FuncName + Func *FunctionExpr +} + +type ReturnStmt struct { + StmtBase + + Exprs []Expr +} + +type BreakStmt struct { + StmtBase +} diff --git a/vendor/github.com/yuin/gopher-lua/ast/token.go b/vendor/github.com/yuin/gopher-lua/ast/token.go new file mode 100644 index 0000000000000000000000000000000000000000..820467c9a86bcdeda84ef49fcb1dc75099a77f3a --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/ast/token.go @@ -0,0 +1,22 @@ +package ast + +import ( + "fmt" +) + +type Position struct { + Source string + Line int + Column int +} + +type Token struct { + Type int + Name string + Str string + Pos Position +} + +func (self *Token) String() string { + return fmt.Sprintf("", self.Name, self.Str) +} diff --git a/vendor/github.com/yuin/gopher-lua/auxlib.go b/vendor/github.com/yuin/gopher-lua/auxlib.go new file mode 100644 index 0000000000000000000000000000000000000000..15199390cc505911d18774a67d85f72ab42c6f51 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/auxlib.go @@ -0,0 +1,458 @@ +package lua + +import ( + "bufio" + "fmt" + "io" + "os" + "strings" +) + +/* checkType {{{ */ + +func (ls *LState) CheckAny(n int) LValue { + if n > ls.GetTop() { + ls.ArgError(n, "value expected") + } + return ls.Get(n) +} + +func (ls *LState) CheckInt(n int) int { + v := ls.Get(n) + if intv, ok := v.(LNumber); ok { + return int(intv) + } + ls.TypeError(n, LTNumber) + return 0 +} + +func (ls *LState) CheckInt64(n int) int64 { + v := ls.Get(n) + if intv, ok := v.(LNumber); ok { + return int64(intv) + } + ls.TypeError(n, LTNumber) + return 0 +} + +func (ls *LState) CheckNumber(n int) LNumber { + v := ls.Get(n) + if lv, ok := v.(LNumber); ok { + return lv + } + ls.TypeError(n, LTNumber) + return 0 +} + +func (ls *LState) CheckString(n int) string { + v := ls.Get(n) + if lv, ok := v.(LString); ok { + return string(lv) + } + ls.TypeError(n, LTString) + return "" +} + +func (ls *LState) CheckBool(n int) bool { + v := ls.Get(n) + if lv, ok := v.(LBool); ok { + return bool(lv) + } + ls.TypeError(n, LTBool) + return false +} + +func (ls *LState) CheckTable(n int) *LTable { + v := ls.Get(n) + if lv, ok := v.(*LTable); ok { + return lv + } + ls.TypeError(n, LTTable) + return nil +} + +func (ls *LState) CheckFunction(n int) *LFunction { + v := ls.Get(n) + if lv, ok := v.(*LFunction); ok { + return lv + } + ls.TypeError(n, LTFunction) + return nil +} + +func (ls *LState) CheckUserData(n int) *LUserData { + v := ls.Get(n) + if lv, ok := v.(*LUserData); ok { + return lv + } + ls.TypeError(n, LTUserData) + return nil +} + +func (ls *LState) CheckThread(n int) *LState { + v := ls.Get(n) + if lv, ok := v.(*LState); ok { + return lv + } + ls.TypeError(n, LTThread) + return nil +} + +func (ls *LState) CheckType(n int, typ LValueType) { + v := ls.Get(n) + if v.Type() != typ { + ls.TypeError(n, typ) + } +} + +func (ls *LState) CheckTypes(n int, typs ...LValueType) { + vt := ls.Get(n).Type() + for _, typ := range typs { + if vt == typ { + return + } + } + buf := []string{} + for _, typ := range typs { + buf = append(buf, typ.String()) + } + ls.ArgError(n, strings.Join(buf, " or ")+" expected, got "+ls.Get(n).Type().String()) +} + +func (ls *LState) CheckOption(n int, options []string) int { + str := ls.CheckString(n) + for i, v := range options { + if v == str { + return i + } + } + ls.ArgError(n, fmt.Sprintf("invalid option: %s (must be one of %s)", str, strings.Join(options, ","))) + return 0 +} + +/* }}} */ + +/* optType {{{ */ + +func (ls *LState) OptInt(n int, d int) int { + v := ls.Get(n) + if v == LNil { + return d + } + if intv, ok := v.(LNumber); ok { + return int(intv) + } + ls.TypeError(n, LTNumber) + return 0 +} + +func (ls *LState) OptInt64(n int, d int64) int64 { + v := ls.Get(n) + if v == LNil { + return d + } + if intv, ok := v.(LNumber); ok { + return int64(intv) + } + ls.TypeError(n, LTNumber) + return 0 +} + +func (ls *LState) OptNumber(n int, d LNumber) LNumber { + v := ls.Get(n) + if v == LNil { + return d + } + if lv, ok := v.(LNumber); ok { + return lv + } + ls.TypeError(n, LTNumber) + return 0 +} + +func (ls *LState) OptString(n int, d string) string { + v := ls.Get(n) + if v == LNil { + return d + } + if lv, ok := v.(LString); ok { + return string(lv) + } + ls.TypeError(n, LTString) + return "" +} + +func (ls *LState) OptBool(n int, d bool) bool { + v := ls.Get(n) + if v == LNil { + return d + } + if lv, ok := v.(LBool); ok { + return bool(lv) + } + ls.TypeError(n, LTBool) + return false +} + +func (ls *LState) OptTable(n int, d *LTable) *LTable { + v := ls.Get(n) + if v == LNil { + return d + } + if lv, ok := v.(*LTable); ok { + return lv + } + ls.TypeError(n, LTTable) + return nil +} + +func (ls *LState) OptFunction(n int, d *LFunction) *LFunction { + v := ls.Get(n) + if v == LNil { + return d + } + if lv, ok := v.(*LFunction); ok { + return lv + } + ls.TypeError(n, LTFunction) + return nil +} + +func (ls *LState) OptUserData(n int, d *LUserData) *LUserData { + v := ls.Get(n) + if v == LNil { + return d + } + if lv, ok := v.(*LUserData); ok { + return lv + } + ls.TypeError(n, LTUserData) + return nil +} + +/* }}} */ + +/* error operations {{{ */ + +func (ls *LState) ArgError(n int, message string) { + ls.RaiseError("bad argument #%v to %v (%v)", n, ls.rawFrameFuncName(ls.currentFrame), message) +} + +func (ls *LState) TypeError(n int, typ LValueType) { + ls.RaiseError("bad argument #%v to %v (%v expected, got %v)", n, ls.rawFrameFuncName(ls.currentFrame), typ.String(), ls.Get(n).Type().String()) +} + +/* }}} */ + +/* debug operations {{{ */ + +func (ls *LState) Where(level int) string { + return ls.where(level, false) +} + +/* }}} */ + +/* table operations {{{ */ + +func (ls *LState) FindTable(obj *LTable, n string, size int) LValue { + names := strings.Split(n, ".") + curobj := obj + for _, name := range names { + if curobj.Type() != LTTable { + return LNil + } + nextobj := ls.RawGet(curobj, LString(name)) + if nextobj == LNil { + tb := ls.CreateTable(0, size) + ls.RawSet(curobj, LString(name), tb) + curobj = tb + } else if nextobj.Type() != LTTable { + return LNil + } else { + curobj = nextobj.(*LTable) + } + } + return curobj +} + +/* }}} */ + +/* register operations {{{ */ + +func (ls *LState) RegisterModule(name string, funcs map[string]LGFunction) LValue { + tb := ls.FindTable(ls.Get(RegistryIndex).(*LTable), "_LOADED", 1) + mod := ls.GetField(tb, name) + if mod.Type() != LTTable { + newmod := ls.FindTable(ls.Get(GlobalsIndex).(*LTable), name, len(funcs)) + if newmodtb, ok := newmod.(*LTable); !ok { + ls.RaiseError("name conflict for module(%v)", name) + } else { + for fname, fn := range funcs { + newmodtb.RawSetString(fname, ls.NewFunction(fn)) + } + ls.SetField(tb, name, newmodtb) + return newmodtb + } + } + return mod +} + +func (ls *LState) SetFuncs(tb *LTable, funcs map[string]LGFunction, upvalues ...LValue) *LTable { + for fname, fn := range funcs { + tb.RawSetString(fname, ls.NewClosure(fn, upvalues...)) + } + return tb +} + +/* }}} */ + +/* metatable operations {{{ */ + +func (ls *LState) NewTypeMetatable(typ string) *LTable { + regtable := ls.Get(RegistryIndex) + mt := ls.GetField(regtable, typ) + if tb, ok := mt.(*LTable); ok { + return tb + } + mtnew := ls.NewTable() + ls.SetField(regtable, typ, mtnew) + return mtnew +} + +func (ls *LState) GetMetaField(obj LValue, event string) LValue { + return ls.metaOp1(obj, event) +} + +func (ls *LState) GetTypeMetatable(typ string) LValue { + return ls.GetField(ls.Get(RegistryIndex), typ) +} + +func (ls *LState) CallMeta(obj LValue, event string) LValue { + op := ls.metaOp1(obj, event) + if op.Type() == LTFunction { + ls.reg.Push(op) + ls.reg.Push(obj) + ls.Call(1, 1) + return ls.reg.Pop() + } + return LNil +} + +/* }}} */ + +/* load and function call operations {{{ */ + +func (ls *LState) LoadFile(path string) (*LFunction, error) { + var file *os.File + var err error + if len(path) == 0 { + file = os.Stdin + } else { + file, err = os.Open(path) + defer file.Close() + if err != nil { + return nil, newApiErrorE(ApiErrorFile, err) + } + } + + reader := bufio.NewReader(file) + // get the first character. + c, err := reader.ReadByte() + if err != nil && err != io.EOF { + return nil, newApiErrorE(ApiErrorFile, err) + } + if c == byte('#') { + // Unix exec. file? + // skip first line + _, err, _ = readBufioLine(reader) + if err != nil { + return nil, newApiErrorE(ApiErrorFile, err) + } + } + + if err != io.EOF { + // if the file is not empty, + // unread the first character of the file or newline character(readBufioLine's last byte). + err = reader.UnreadByte() + if err != nil { + return nil, newApiErrorE(ApiErrorFile, err) + } + } + + return ls.Load(reader, path) +} + +func (ls *LState) LoadString(source string) (*LFunction, error) { + return ls.Load(strings.NewReader(source), "") +} + +func (ls *LState) DoFile(path string) error { + if fn, err := ls.LoadFile(path); err != nil { + return err + } else { + ls.Push(fn) + return ls.PCall(0, MultRet, nil) + } +} + +func (ls *LState) DoString(source string) error { + if fn, err := ls.LoadString(source); err != nil { + return err + } else { + ls.Push(fn) + return ls.PCall(0, MultRet, nil) + } +} + +/* }}} */ + +/* GopherLua original APIs {{{ */ + +// ToStringMeta returns string representation of given LValue. +// This method calls the `__tostring` meta method if defined. +func (ls *LState) ToStringMeta(lv LValue) LValue { + if fn, ok := ls.metaOp1(lv, "__tostring").assertFunction(); ok { + ls.Push(fn) + ls.Push(lv) + ls.Call(1, 1) + return ls.reg.Pop() + } else { + return LString(lv.String()) + } +} + +// Set a module loader to the package.preload table. +func (ls *LState) PreloadModule(name string, loader LGFunction) { + preload := ls.GetField(ls.GetField(ls.Get(EnvironIndex), "package"), "preload") + if _, ok := preload.(*LTable); !ok { + ls.RaiseError("package.preload must be a table") + } + ls.SetField(preload, name, ls.NewFunction(loader)) +} + +// Checks whether the given index is an LChannel and returns this channel. +func (ls *LState) CheckChannel(n int) chan LValue { + v := ls.Get(n) + if ch, ok := v.(LChannel); ok { + return (chan LValue)(ch) + } + ls.TypeError(n, LTChannel) + return nil +} + +// If the given index is a LChannel, returns this channel. If this argument is absent or is nil, returns ch. Otherwise, raises an error. +func (ls *LState) OptChannel(n int, ch chan LValue) chan LValue { + v := ls.Get(n) + if v == LNil { + return ch + } + if ch, ok := v.(LChannel); ok { + return (chan LValue)(ch) + } + ls.TypeError(n, LTChannel) + return nil +} + +/* }}} */ + +// diff --git a/vendor/github.com/yuin/gopher-lua/auxlib_test.go b/vendor/github.com/yuin/gopher-lua/auxlib_test.go new file mode 100644 index 0000000000000000000000000000000000000000..ac8356d0b169b6a4d8c6c71f923c5c6559d0dcdf --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/auxlib_test.go @@ -0,0 +1,333 @@ +package lua + +import ( + "io/ioutil" + "os" + "testing" +) + +func TestCheckInt(t *testing.T) { + L := NewState() + defer L.Close() + errorIfGFuncNotFail(t, L, func(L *LState) int { + L.Push(LNumber(10)) + errorIfNotEqual(t, 10, L.CheckInt(2)) + L.Push(LString("aaa")) + L.CheckInt(3) + return 0 + }, "number expected, got string") +} + +func TestCheckInt64(t *testing.T) { + L := NewState() + defer L.Close() + errorIfGFuncNotFail(t, L, func(L *LState) int { + L.Push(LNumber(10)) + errorIfNotEqual(t, int64(10), L.CheckInt64(2)) + L.Push(LString("aaa")) + L.CheckInt64(3) + return 0 + }, "number expected, got string") +} + +func TestCheckNumber(t *testing.T) { + L := NewState() + defer L.Close() + errorIfGFuncNotFail(t, L, func(L *LState) int { + L.Push(LNumber(10)) + errorIfNotEqual(t, LNumber(10), L.CheckNumber(2)) + L.Push(LString("aaa")) + L.CheckNumber(3) + return 0 + }, "number expected, got string") +} + +func TestCheckString(t *testing.T) { + L := NewState() + defer L.Close() + errorIfGFuncNotFail(t, L, func(L *LState) int { + L.Push(LString("aaa")) + errorIfNotEqual(t, "aaa", L.CheckString(2)) + L.Push(LNumber(10)) + L.CheckString(3) + return 0 + }, "string expected, got number") +} + +func TestCheckBool(t *testing.T) { + L := NewState() + defer L.Close() + errorIfGFuncNotFail(t, L, func(L *LState) int { + L.Push(LTrue) + errorIfNotEqual(t, true, L.CheckBool(2)) + L.Push(LNumber(10)) + L.CheckBool(3) + return 0 + }, "boolean expected, got number") +} + +func TestCheckTable(t *testing.T) { + L := NewState() + defer L.Close() + errorIfGFuncNotFail(t, L, func(L *LState) int { + tbl := L.NewTable() + L.Push(tbl) + errorIfNotEqual(t, tbl, L.CheckTable(2)) + L.Push(LNumber(10)) + L.CheckTable(3) + return 0 + }, "table expected, got number") +} + +func TestCheckFunction(t *testing.T) { + L := NewState() + defer L.Close() + errorIfGFuncNotFail(t, L, func(L *LState) int { + fn := L.NewFunction(func(l *LState) int { return 0 }) + L.Push(fn) + errorIfNotEqual(t, fn, L.CheckFunction(2)) + L.Push(LNumber(10)) + L.CheckFunction(3) + return 0 + }, "function expected, got number") +} + +func TestCheckUserData(t *testing.T) { + L := NewState() + defer L.Close() + errorIfGFuncNotFail(t, L, func(L *LState) int { + ud := L.NewUserData() + L.Push(ud) + errorIfNotEqual(t, ud, L.CheckUserData(2)) + L.Push(LNumber(10)) + L.CheckUserData(3) + return 0 + }, "userdata expected, got number") +} + +func TestCheckThread(t *testing.T) { + L := NewState() + defer L.Close() + errorIfGFuncNotFail(t, L, func(L *LState) int { + th, _ := L.NewThread() + L.Push(th) + errorIfNotEqual(t, th, L.CheckThread(2)) + L.Push(LNumber(10)) + L.CheckThread(3) + return 0 + }, "thread expected, got number") +} + +func TestCheckChannel(t *testing.T) { + L := NewState() + defer L.Close() + errorIfGFuncNotFail(t, L, func(L *LState) int { + ch := make(chan LValue) + L.Push(LChannel(ch)) + errorIfNotEqual(t, ch, L.CheckChannel(2)) + L.Push(LString("aaa")) + L.CheckChannel(3) + return 0 + }, "channel expected, got string") +} + +func TestCheckType(t *testing.T) { + L := NewState() + defer L.Close() + errorIfGFuncNotFail(t, L, func(L *LState) int { + L.Push(LNumber(10)) + L.CheckType(2, LTNumber) + L.CheckType(2, LTString) + return 0 + }, "string expected, got number") +} + +func TestCheckTypes(t *testing.T) { + L := NewState() + defer L.Close() + errorIfGFuncNotFail(t, L, func(L *LState) int { + L.Push(LNumber(10)) + L.CheckTypes(2, LTString, LTBool, LTNumber) + L.CheckTypes(2, LTString, LTBool) + return 0 + }, "string or boolean expected, got number") +} + +func TestCheckOption(t *testing.T) { + opts := []string{ + "opt1", + "opt2", + "opt3", + } + L := NewState() + defer L.Close() + errorIfGFuncNotFail(t, L, func(L *LState) int { + L.Push(LString("opt1")) + errorIfNotEqual(t, 0, L.CheckOption(2, opts)) + L.Push(LString("opt5")) + L.CheckOption(3, opts) + return 0 + }, "invalid option: opt5 \\(must be one of opt1,opt2,opt3\\)") +} + +func TestOptInt(t *testing.T) { + L := NewState() + defer L.Close() + errorIfGFuncNotFail(t, L, func(L *LState) int { + errorIfNotEqual(t, 99, L.OptInt(1, 99)) + L.Push(LNumber(10)) + errorIfNotEqual(t, 10, L.OptInt(2, 99)) + L.Push(LString("aaa")) + L.OptInt(3, 99) + return 0 + }, "number expected, got string") +} + +func TestOptInt64(t *testing.T) { + L := NewState() + defer L.Close() + errorIfGFuncNotFail(t, L, func(L *LState) int { + errorIfNotEqual(t, int64(99), L.OptInt64(1, int64(99))) + L.Push(LNumber(10)) + errorIfNotEqual(t, int64(10), L.OptInt64(2, int64(99))) + L.Push(LString("aaa")) + L.OptInt64(3, int64(99)) + return 0 + }, "number expected, got string") +} + +func TestOptNumber(t *testing.T) { + L := NewState() + defer L.Close() + errorIfGFuncNotFail(t, L, func(L *LState) int { + errorIfNotEqual(t, LNumber(99), L.OptNumber(1, LNumber(99))) + L.Push(LNumber(10)) + errorIfNotEqual(t, LNumber(10), L.OptNumber(2, LNumber(99))) + L.Push(LString("aaa")) + L.OptNumber(3, LNumber(99)) + return 0 + }, "number expected, got string") +} + +func TestOptString(t *testing.T) { + L := NewState() + defer L.Close() + errorIfGFuncNotFail(t, L, func(L *LState) int { + errorIfNotEqual(t, "bbb", L.OptString(1, "bbb")) + L.Push(LString("aaa")) + errorIfNotEqual(t, "aaa", L.OptString(2, "bbb")) + L.Push(LNumber(10)) + L.OptString(3, "bbb") + return 0 + }, "string expected, got number") +} + +func TestOptBool(t *testing.T) { + L := NewState() + defer L.Close() + errorIfGFuncNotFail(t, L, func(L *LState) int { + errorIfNotEqual(t, true, L.OptBool(1, true)) + L.Push(LTrue) + errorIfNotEqual(t, true, L.OptBool(2, false)) + L.Push(LNumber(10)) + L.OptBool(3, false) + return 0 + }, "boolean expected, got number") +} + +func TestOptTable(t *testing.T) { + L := NewState() + defer L.Close() + errorIfGFuncNotFail(t, L, func(L *LState) int { + deftbl := L.NewTable() + errorIfNotEqual(t, deftbl, L.OptTable(1, deftbl)) + tbl := L.NewTable() + L.Push(tbl) + errorIfNotEqual(t, tbl, L.OptTable(2, deftbl)) + L.Push(LNumber(10)) + L.OptTable(3, deftbl) + return 0 + }, "table expected, got number") +} + +func TestOptFunction(t *testing.T) { + L := NewState() + defer L.Close() + errorIfGFuncNotFail(t, L, func(L *LState) int { + deffn := L.NewFunction(func(l *LState) int { return 0 }) + errorIfNotEqual(t, deffn, L.OptFunction(1, deffn)) + fn := L.NewFunction(func(l *LState) int { return 0 }) + L.Push(fn) + errorIfNotEqual(t, fn, L.OptFunction(2, deffn)) + L.Push(LNumber(10)) + L.OptFunction(3, deffn) + return 0 + }, "function expected, got number") +} + +func TestOptUserData(t *testing.T) { + L := NewState() + defer L.Close() + errorIfGFuncNotFail(t, L, func(L *LState) int { + defud := L.NewUserData() + errorIfNotEqual(t, defud, L.OptUserData(1, defud)) + ud := L.NewUserData() + L.Push(ud) + errorIfNotEqual(t, ud, L.OptUserData(2, defud)) + L.Push(LNumber(10)) + L.OptUserData(3, defud) + return 0 + }, "userdata expected, got number") +} + +func TestOptChannel(t *testing.T) { + L := NewState() + defer L.Close() + errorIfGFuncNotFail(t, L, func(L *LState) int { + defch := make(chan LValue) + errorIfNotEqual(t, defch, L.OptChannel(1, defch)) + ch := make(chan LValue) + L.Push(LChannel(ch)) + errorIfNotEqual(t, ch, L.OptChannel(2, defch)) + L.Push(LString("aaa")) + L.OptChannel(3, defch) + return 0 + }, "channel expected, got string") +} + +func TestLoadFileForShebang(t *testing.T) { + tmpFile, err := ioutil.TempFile("", "") + errorIfNotNil(t, err) + + err = ioutil.WriteFile(tmpFile.Name(), []byte(`#!/path/to/lua +print("hello") +`), 0644) + errorIfNotNil(t, err) + + defer func() { + tmpFile.Close() + os.Remove(tmpFile.Name()) + }() + + L := NewState() + defer L.Close() + + _, err = L.LoadFile(tmpFile.Name()) + errorIfNotNil(t, err) +} + +func TestLoadFileForEmptyFile(t *testing.T) { + tmpFile, err := ioutil.TempFile("", "") + errorIfNotNil(t, err) + + defer func() { + tmpFile.Close() + os.Remove(tmpFile.Name()) + }() + + L := NewState() + defer L.Close() + + _, err = L.LoadFile(tmpFile.Name()) + errorIfNotNil(t, err) +} diff --git a/vendor/github.com/yuin/gopher-lua/baselib.go b/vendor/github.com/yuin/gopher-lua/baselib.go new file mode 100644 index 0000000000000000000000000000000000000000..2868d419d370be0e7311690cb008f192203827a8 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/baselib.go @@ -0,0 +1,586 @@ +package lua + +import ( + "fmt" + "io" + "os" + "runtime" + "strconv" + "strings" +) + +/* basic functions {{{ */ + +func OpenBase(L *LState) int { + global := L.Get(GlobalsIndex).(*LTable) + L.SetGlobal("_G", global) + L.SetGlobal("_VERSION", LString(LuaVersion)) + L.SetGlobal("_GOPHER_LUA_VERSION", LString(PackageName+" "+PackageVersion)) + basemod := L.RegisterModule("_G", baseFuncs) + global.RawSetString("ipairs", L.NewClosure(baseIpairs, L.NewFunction(ipairsaux))) + global.RawSetString("pairs", L.NewClosure(basePairs, L.NewFunction(pairsaux))) + L.Push(basemod) + return 1 +} + +var baseFuncs = map[string]LGFunction{ + "assert": baseAssert, + "collectgarbage": baseCollectGarbage, + "dofile": baseDoFile, + "error": baseError, + "getfenv": baseGetFEnv, + "getmetatable": baseGetMetatable, + "load": baseLoad, + "loadfile": baseLoadFile, + "loadstring": baseLoadString, + "next": baseNext, + "pcall": basePCall, + "print": basePrint, + "rawequal": baseRawEqual, + "rawget": baseRawGet, + "rawset": baseRawSet, + "select": baseSelect, + "_printregs": base_PrintRegs, + "setfenv": baseSetFEnv, + "setmetatable": baseSetMetatable, + "tonumber": baseToNumber, + "tostring": baseToString, + "type": baseType, + "unpack": baseUnpack, + "xpcall": baseXPCall, + // loadlib + "module": loModule, + "require": loRequire, + // hidden features + "newproxy": baseNewProxy, +} + +func baseAssert(L *LState) int { + if !L.ToBool(1) { + L.RaiseError(L.OptString(2, "assertion failed!")) + return 0 + } + return L.GetTop() +} + +func baseCollectGarbage(L *LState) int { + runtime.GC() + return 0 +} + +func baseDoFile(L *LState) int { + src := L.ToString(1) + top := L.GetTop() + fn, err := L.LoadFile(src) + if err != nil { + L.Push(LString(err.Error())) + L.Panic(L) + } + L.Push(fn) + L.Call(0, MultRet) + return L.GetTop() - top +} + +func baseError(L *LState) int { + obj := L.CheckAny(1) + level := L.OptInt(2, 1) + L.Error(obj, level) + return 0 +} + +func baseGetFEnv(L *LState) int { + var value LValue + if L.GetTop() == 0 { + value = LNumber(1) + } else { + value = L.Get(1) + } + + if fn, ok := value.(*LFunction); ok { + if !fn.IsG { + L.Push(fn.Env) + } else { + L.Push(L.G.Global) + } + return 1 + } + + if number, ok := value.(LNumber); ok { + level := int(float64(number)) + if level <= 0 { + L.Push(L.Env) + } else { + cf := L.currentFrame + for i := 0; i < level && cf != nil; i++ { + cf = cf.Parent + } + if cf == nil || cf.Fn.IsG { + L.Push(L.G.Global) + } else { + L.Push(cf.Fn.Env) + } + } + return 1 + } + + L.Push(L.G.Global) + return 1 +} + +func baseGetMetatable(L *LState) int { + L.Push(L.GetMetatable(L.CheckAny(1))) + return 1 +} + +func ipairsaux(L *LState) int { + tb := L.CheckTable(1) + i := L.CheckInt(2) + i++ + v := tb.RawGetInt(i) + if v == LNil { + return 0 + } else { + L.Pop(1) + L.Push(LNumber(i)) + L.Push(LNumber(i)) + L.Push(v) + return 2 + } +} + +func baseIpairs(L *LState) int { + tb := L.CheckTable(1) + L.Push(L.Get(UpvalueIndex(1))) + L.Push(tb) + L.Push(LNumber(0)) + return 3 +} + +func loadaux(L *LState, reader io.Reader, chunkname string) int { + if fn, err := L.Load(reader, chunkname); err != nil { + L.Push(LNil) + L.Push(LString(err.Error())) + return 2 + } else { + L.Push(fn) + return 1 + } +} + +func baseLoad(L *LState) int { + fn := L.CheckFunction(1) + chunkname := L.OptString(2, "?") + top := L.GetTop() + buf := []string{} + for { + L.SetTop(top) + L.Push(fn) + L.Call(0, 1) + ret := L.reg.Pop() + if ret == LNil { + break + } else if LVCanConvToString(ret) { + str := ret.String() + if len(str) > 0 { + buf = append(buf, string(str)) + } else { + break + } + } else { + L.Push(LNil) + L.Push(LString("reader function must return a string")) + return 2 + } + } + return loadaux(L, strings.NewReader(strings.Join(buf, "")), chunkname) +} + +func baseLoadFile(L *LState) int { + var reader io.Reader + var chunkname string + var err error + if L.GetTop() < 1 { + reader = os.Stdin + chunkname = "" + } else { + chunkname = L.CheckString(1) + reader, err = os.Open(chunkname) + if err != nil { + L.Push(LNil) + L.Push(LString(fmt.Sprintf("can not open file: %v", chunkname))) + return 2 + } + defer reader.(*os.File).Close() + } + return loadaux(L, reader, chunkname) +} + +func baseLoadString(L *LState) int { + return loadaux(L, strings.NewReader(L.CheckString(1)), L.OptString(2, "")) +} + +func baseNext(L *LState) int { + tb := L.CheckTable(1) + index := LNil + if L.GetTop() >= 2 { + index = L.Get(2) + } + key, value := tb.Next(index) + if key == LNil { + L.Push(LNil) + return 1 + } + L.Push(key) + L.Push(value) + return 2 +} + +func pairsaux(L *LState) int { + tb := L.CheckTable(1) + key, value := tb.Next(L.Get(2)) + if key == LNil { + return 0 + } else { + L.Pop(1) + L.Push(key) + L.Push(key) + L.Push(value) + return 2 + } +} + +func basePairs(L *LState) int { + tb := L.CheckTable(1) + L.Push(L.Get(UpvalueIndex(1))) + L.Push(tb) + L.Push(LNil) + return 3 +} + +func basePCall(L *LState) int { + L.CheckFunction(1) + nargs := L.GetTop() - 1 + if err := L.PCall(nargs, MultRet, nil); err != nil { + L.Push(LFalse) + if aerr, ok := err.(*ApiError); ok { + L.Push(aerr.Object) + } else { + L.Push(LString(err.Error())) + } + return 2 + } else { + L.Insert(LTrue, 1) + return L.GetTop() + } +} + +func basePrint(L *LState) int { + top := L.GetTop() + for i := 1; i <= top; i++ { + fmt.Print(L.ToStringMeta(L.Get(i)).String()) + if i != top { + fmt.Print("\t") + } + } + fmt.Println("") + return 0 +} + +func base_PrintRegs(L *LState) int { + L.printReg() + return 0 +} + +func baseRawEqual(L *LState) int { + if L.CheckAny(1) == L.CheckAny(2) { + L.Push(LTrue) + } else { + L.Push(LFalse) + } + return 1 +} + +func baseRawGet(L *LState) int { + L.Push(L.RawGet(L.CheckTable(1), L.CheckAny(2))) + return 1 +} + +func baseRawSet(L *LState) int { + L.RawSet(L.CheckTable(1), L.CheckAny(2), L.CheckAny(3)) + return 0 +} + +func baseSelect(L *LState) int { + L.CheckTypes(1, LTNumber, LTString) + switch lv := L.Get(1).(type) { + case LNumber: + idx := int(lv) + num := L.reg.Top() - L.indexToReg(int(lv)) - 1 + if idx < 0 { + num++ + } + return num + case LString: + if string(lv) != "#" { + L.ArgError(1, "invalid string '"+string(lv)+"'") + } + L.Push(LNumber(L.GetTop() - 1)) + return 1 + } + return 0 +} + +func baseSetFEnv(L *LState) int { + var value LValue + if L.GetTop() == 0 { + value = LNumber(1) + } else { + value = L.Get(1) + } + env := L.CheckTable(2) + + if fn, ok := value.(*LFunction); ok { + if fn.IsG { + L.RaiseError("cannot change the environment of given object") + } else { + fn.Env = env + L.Push(fn) + return 1 + } + } + + if number, ok := value.(LNumber); ok { + level := int(float64(number)) + if level <= 0 { + L.Env = env + return 0 + } + + cf := L.currentFrame + for i := 0; i < level && cf != nil; i++ { + cf = cf.Parent + } + if cf == nil || cf.Fn.IsG { + L.RaiseError("cannot change the environment of given object") + } else { + cf.Fn.Env = env + L.Push(cf.Fn) + return 1 + } + } + + L.RaiseError("cannot change the environment of given object") + return 0 +} + +func baseSetMetatable(L *LState) int { + L.CheckTypes(2, LTNil, LTTable) + obj := L.Get(1) + if obj == LNil { + L.RaiseError("cannot set metatable to a nil object.") + } + mt := L.Get(2) + if m := L.metatable(obj, true); m != LNil { + if tb, ok := m.(*LTable); ok && tb.RawGetString("__metatable") != LNil { + L.RaiseError("cannot change a protected metatable") + } + } + L.SetMetatable(obj, mt) + L.SetTop(1) + return 1 +} + +func baseToNumber(L *LState) int { + base := L.OptInt(2, 10) + noBase := L.Get(2) == LNil + + switch lv := L.CheckAny(1).(type) { + case LNumber: + L.Push(lv) + case LString: + str := strings.Trim(string(lv), " \n\t") + if strings.Index(str, ".") > -1 { + if v, err := strconv.ParseFloat(str, LNumberBit); err != nil { + L.Push(LNil) + } else { + L.Push(LNumber(v)) + } + } else { + if noBase && strings.HasPrefix(strings.ToLower(str), "0x") { + base, str = 16, str[2:] // Hex number + } + if v, err := strconv.ParseInt(str, base, LNumberBit); err != nil { + L.Push(LNil) + } else { + L.Push(LNumber(v)) + } + } + default: + L.Push(LNil) + } + return 1 +} + +func baseToString(L *LState) int { + v1 := L.CheckAny(1) + L.Push(L.ToStringMeta(v1)) + return 1 +} + +func baseType(L *LState) int { + L.Push(LString(L.CheckAny(1).Type().String())) + return 1 +} + +func baseUnpack(L *LState) int { + tb := L.CheckTable(1) + start := L.OptInt(2, 1) + end := L.OptInt(3, tb.Len()) + for i := start; i <= end; i++ { + L.Push(tb.RawGetInt(i)) + } + ret := end - start + 1 + if ret < 0 { + return 0 + } + return ret +} + +func baseXPCall(L *LState) int { + fn := L.CheckFunction(1) + errfunc := L.CheckFunction(2) + + top := L.GetTop() + L.Push(fn) + if err := L.PCall(0, MultRet, errfunc); err != nil { + L.Push(LFalse) + if aerr, ok := err.(*ApiError); ok { + L.Push(aerr.Object) + } else { + L.Push(LString(err.Error())) + } + return 2 + } else { + L.Insert(LTrue, top+1) + return L.GetTop() - top + } +} + +/* }}} */ + +/* load lib {{{ */ + +func loModule(L *LState) int { + name := L.CheckString(1) + loaded := L.GetField(L.Get(RegistryIndex), "_LOADED") + tb := L.GetField(loaded, name) + if _, ok := tb.(*LTable); !ok { + tb = L.FindTable(L.Get(GlobalsIndex).(*LTable), name, 1) + if tb == LNil { + L.RaiseError("name conflict for module: %v", name) + } + L.SetField(loaded, name, tb) + } + if L.GetField(tb, "_NAME") == LNil { + L.SetField(tb, "_M", tb) + L.SetField(tb, "_NAME", LString(name)) + names := strings.Split(name, ".") + pname := "" + if len(names) > 1 { + pname = strings.Join(names[:len(names)-1], ".") + "." + } + L.SetField(tb, "_PACKAGE", LString(pname)) + } + + caller := L.currentFrame.Parent + if caller == nil { + L.RaiseError("no calling stack.") + } else if caller.Fn.IsG { + L.RaiseError("module() can not be called from GFunctions.") + } + L.SetFEnv(caller.Fn, tb) + + top := L.GetTop() + for i := 2; i <= top; i++ { + L.Push(L.Get(i)) + L.Push(tb) + L.Call(1, 0) + } + L.Push(tb) + return 1 +} + +var loopdetection = &LUserData{} + +func loRequire(L *LState) int { + name := L.CheckString(1) + loaded := L.GetField(L.Get(RegistryIndex), "_LOADED") + lv := L.GetField(loaded, name) + if LVAsBool(lv) { + if lv == loopdetection { + L.RaiseError("loop or previous error loading module: %s", name) + } + L.Push(lv) + return 1 + } + loaders, ok := L.GetField(L.Get(RegistryIndex), "_LOADERS").(*LTable) + if !ok { + L.RaiseError("package.loaders must be a table") + } + messages := []string{} + var modasfunc LValue + for i := 1; ; i++ { + loader := L.RawGetInt(loaders, i) + if loader == LNil { + L.RaiseError("module %s not found:\n\t%s, ", name, strings.Join(messages, "\n\t")) + } + L.Push(loader) + L.Push(LString(name)) + L.Call(1, 1) + ret := L.reg.Pop() + switch retv := ret.(type) { + case *LFunction: + modasfunc = retv + goto loopbreak + case LString: + messages = append(messages, string(retv)) + } + } +loopbreak: + L.SetField(loaded, name, loopdetection) + L.Push(modasfunc) + L.Push(LString(name)) + L.Call(1, 1) + ret := L.reg.Pop() + modv := L.GetField(loaded, name) + if ret != LNil && modv == loopdetection { + L.SetField(loaded, name, ret) + L.Push(ret) + } else if modv == loopdetection { + L.SetField(loaded, name, LTrue) + L.Push(LTrue) + } else { + L.Push(modv) + } + return 1 +} + +/* }}} */ + +/* hidden features {{{ */ + +func baseNewProxy(L *LState) int { + ud := L.NewUserData() + L.SetTop(1) + if L.Get(1) == LTrue { + L.SetMetatable(ud, L.NewTable()) + } else if d, ok := L.Get(1).(*LUserData); ok { + L.SetMetatable(ud, L.GetMetatable(d)) + } + L.Push(ud) + return 1 +} + +/* }}} */ + +// diff --git a/vendor/github.com/yuin/gopher-lua/channellib.go b/vendor/github.com/yuin/gopher-lua/channellib.go new file mode 100644 index 0000000000000000000000000000000000000000..6df3e889a1ee7460fc45d38b91d2ac526305904c --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/channellib.go @@ -0,0 +1,152 @@ +package lua + +import ( + "reflect" +) + +func checkChannel(L *LState, idx int) reflect.Value { + ch := L.CheckChannel(idx) + return reflect.ValueOf(ch) +} + +func checkGoroutineSafe(L *LState, idx int) LValue { + v := L.CheckAny(2) + if !isGoroutineSafe(v) { + L.ArgError(2, "can not send a function, userdata, thread or table that has a metatable") + } + return v +} + +func OpenChannel(L *LState) int { + var mod LValue + //_, ok := L.G.builtinMts[int(LTChannel)] + // if !ok { + mod = L.RegisterModule(ChannelLibName, channelFuncs) + mt := L.SetFuncs(L.NewTable(), channelMethods) + mt.RawSetString("__index", mt) + L.G.builtinMts[int(LTChannel)] = mt + // } + L.Push(mod) + return 1 +} + +var channelFuncs = map[string]LGFunction{ + "make": channelMake, + "select": channelSelect, +} + +func channelMake(L *LState) int { + buffer := L.OptInt(1, 0) + L.Push(LChannel(make(chan LValue, buffer))) + return 1 +} + +func channelSelect(L *LState) int { + //TODO check case table size + cases := make([]reflect.SelectCase, L.GetTop()) + top := L.GetTop() + for i := 0; i < top; i++ { + cas := reflect.SelectCase{reflect.SelectSend, reflect.ValueOf(nil), reflect.ValueOf(nil)} + tbl := L.CheckTable(i + 1) + dir, ok1 := tbl.RawGetInt(1).(LString) + if !ok1 { + L.ArgError(i+1, "invalid select case") + } + switch string(dir) { + case "<-|": + ch, ok := tbl.RawGetInt(2).(LChannel) + if !ok { + L.ArgError(i+1, "invalid select case") + } + cas.Chan = reflect.ValueOf((chan LValue)(ch)) + v := tbl.RawGetInt(3) + if !isGoroutineSafe(v) { + L.ArgError(i+1, "can not send a function, userdata, thread or table that has a metatable") + } + cas.Send = reflect.ValueOf(v) + case "|<-": + ch, ok := tbl.RawGetInt(2).(LChannel) + if !ok { + L.ArgError(i+1, "invalid select case") + } + cas.Chan = reflect.ValueOf((chan LValue)(ch)) + cas.Dir = reflect.SelectRecv + case "default": + cas.Dir = reflect.SelectDefault + default: + L.ArgError(i+1, "invalid channel direction:"+string(dir)) + } + cases[i] = cas + } + + pos, recv, rok := reflect.Select(cases) + lv := LNil + if recv.Kind() != 0 { + lv, _ = recv.Interface().(LValue) + if lv == nil { + lv = LNil + } + } + tbl := L.Get(pos + 1).(*LTable) + last := tbl.RawGetInt(tbl.Len()) + if last.Type() == LTFunction { + L.Push(last) + switch cases[pos].Dir { + case reflect.SelectRecv: + if rok { + L.Push(LTrue) + } else { + L.Push(LFalse) + } + L.Push(lv) + L.Call(2, 0) + case reflect.SelectSend: + L.Push(tbl.RawGetInt(3)) + L.Call(1, 0) + case reflect.SelectDefault: + L.Call(0, 0) + } + } + L.Push(LNumber(pos + 1)) + L.Push(lv) + if rok { + L.Push(LTrue) + } else { + L.Push(LFalse) + } + return 3 +} + +var channelMethods = map[string]LGFunction{ + "receive": channelReceive, + "send": channelSend, + "close": channelClose, +} + +func channelReceive(L *LState) int { + rch := checkChannel(L, 1) + v, ok := rch.Recv() + if ok { + L.Push(LTrue) + L.Push(v.Interface().(LValue)) + } else { + L.Push(LFalse) + L.Push(LNil) + } + return 2 +} + +func channelSend(L *LState) int { + rch := checkChannel(L, 1) + v := checkGoroutineSafe(L, 2) + rch.Send(reflect.ValueOf(v)) + return 0 +} + +func channelClose(L *LState) int { + rch := checkChannel(L, 1) + rch.Close() + return 0 +} + +// diff --git a/vendor/github.com/yuin/gopher-lua/channellib_test.go b/vendor/github.com/yuin/gopher-lua/channellib_test.go new file mode 100644 index 0000000000000000000000000000000000000000..a7fbffce7e9978a771266257596550cf20d251d5 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/channellib_test.go @@ -0,0 +1,261 @@ +package lua + +import ( + "reflect" + "sync" + "testing" + "time" +) + +func TestChannelMake(t *testing.T) { + L := NewState() + defer L.Close() + errorIfScriptFail(t, L, ` + ch = channel.make() + `) + obj := L.GetGlobal("ch") + ch, ok := obj.(LChannel) + errorIfFalse(t, ok, "channel expected") + errorIfNotEqual(t, 0, reflect.ValueOf(ch).Cap()) + close(ch) + + errorIfScriptFail(t, L, ` + ch = channel.make(10) + `) + obj = L.GetGlobal("ch") + ch, _ = obj.(LChannel) + errorIfNotEqual(t, 10, reflect.ValueOf(ch).Cap()) + close(ch) +} + +func TestChannelSelectError(t *testing.T) { + L := NewState() + defer L.Close() + errorIfScriptFail(t, L, `ch = channel.make()`) + errorIfScriptNotFail(t, L, `channel.select({1,2,3})`, "invalid select case") + errorIfScriptNotFail(t, L, `channel.select({"<-|", 1, 3})`, "invalid select case") + errorIfScriptNotFail(t, L, `channel.select({"<-|", ch, function() end})`, "can not send a function") + errorIfScriptNotFail(t, L, `channel.select({"|<-", 1, 3})`, "invalid select case") + errorIfScriptNotFail(t, L, `channel.select({"<-->", 1, 3})`, "invalid channel direction") + errorIfScriptFail(t, L, `ch:close()`) +} + +func TestChannelSelect1(t *testing.T) { + var result LValue + var wg sync.WaitGroup + receiver := func(ch, quit chan LValue) { + defer wg.Done() + L := NewState() + defer L.Close() + L.SetGlobal("ch", LChannel(ch)) + L.SetGlobal("quit", LChannel(quit)) + if err := L.DoString(` + buf = "" + local exit = false + while not exit do + channel.select( + {"|<-", ch, function(ok, v) + if not ok then + buf = buf .. "channel closed" + exit = true + else + buf = buf .. "received:" .. v + end + end}, + {"|<-", quit, function(ok, v) + buf = buf .. "quit" + end} + ) + end + `); err != nil { + panic(err) + } + result = L.GetGlobal("buf") + } + + sender := func(ch, quit chan LValue) { + defer wg.Done() + L := NewState() + defer L.Close() + L.SetGlobal("ch", LChannel(ch)) + L.SetGlobal("quit", LChannel(quit)) + if err := L.DoString(` + ch:send("1") + ch:send("2") + `); err != nil { + panic(err) + } + ch <- LString("3") + quit <- LTrue + time.Sleep(1 * time.Second) + close(ch) + } + + ch := make(chan LValue) + quit := make(chan LValue) + wg.Add(2) + go receiver(ch, quit) + go sender(ch, quit) + wg.Wait() + lstr, ok := result.(LString) + errorIfFalse(t, ok, "must be string") + str := string(lstr) + errorIfNotEqual(t, "received:1received:2received:3quitchannel closed", str) + +} + +func TestChannelSelect2(t *testing.T) { + var wg sync.WaitGroup + receiver := func(ch, quit chan LValue) { + defer wg.Done() + L := NewState() + defer L.Close() + L.SetGlobal("ch", LChannel(ch)) + L.SetGlobal("quit", LChannel(quit)) + errorIfScriptFail(t, L, ` + idx, rcv, ok = channel.select( + {"|<-", ch}, + {"|<-", quit} + ) + assert(idx == 1) + assert(rcv == "1") + assert(ok) + idx, rcv, ok = channel.select( + {"|<-", ch}, + {"|<-", quit} + ) + assert(idx == 1) + assert(rcv == nil) + assert(not ok) + `) + } + + sender := func(ch, quit chan LValue) { + defer wg.Done() + L := NewState() + defer L.Close() + L.SetGlobal("ch", LChannel(ch)) + L.SetGlobal("quit", LChannel(quit)) + errorIfScriptFail(t, L, `ch:send("1")`) + errorIfScriptFail(t, L, `ch:close()`) + } + + ch := make(chan LValue) + quit := make(chan LValue) + wg.Add(2) + go receiver(ch, quit) + go sender(ch, quit) + wg.Wait() +} + +func TestChannelSelect3(t *testing.T) { + var wg sync.WaitGroup + receiver := func(ch chan LValue) { + defer wg.Done() + L := NewState() + defer L.Close() + L.SetGlobal("ch", LChannel(ch)) + errorIfScriptFail(t, L, ` + ok = true + while ok do + idx, rcv, ok = channel.select( + {"|<-", ch} + ) + end + `) + } + + sender := func(ch chan LValue) { + defer wg.Done() + L := NewState() + defer L.Close() + L.SetGlobal("ch", LChannel(ch)) + errorIfScriptFail(t, L, ` + ok = false + channel.select( + {"<-|", ch, "1", function(v) + ok = true + end} + ) + assert(ok) + idx, rcv, ok = channel.select( + {"<-|", ch, "1"} + ) + assert(idx == 1) + ch:close() + `) + } + + ch := make(chan LValue) + wg.Add(2) + go receiver(ch) + time.Sleep(1) + go sender(ch) + wg.Wait() +} + +func TestChannelSelect4(t *testing.T) { + var wg sync.WaitGroup + receiver := func(ch chan LValue) { + defer wg.Done() + L := NewState() + defer L.Close() + L.SetGlobal("ch", LChannel(ch)) + errorIfScriptFail(t, L, ` + idx, rcv, ok = channel.select( + {"|<-", ch}, + {"default"} + ) + assert(idx == 2) + called = false + idx, rcv, ok = channel.select( + {"|<-", ch}, + {"default", function() + called = true + end} + ) + assert(called) + ch:close() + `) + } + + ch := make(chan LValue) + wg.Add(1) + go receiver(ch) + wg.Wait() +} + +func TestChannelSendReceive1(t *testing.T) { + var wg sync.WaitGroup + receiver := func(ch chan LValue) { + defer wg.Done() + L := NewState() + defer L.Close() + L.SetGlobal("ch", LChannel(ch)) + errorIfScriptFail(t, L, ` + local ok, v = ch:receive() + assert(ok) + assert(v == "1") + `) + time.Sleep(1 * time.Second) + errorIfScriptFail(t, L, ` + local ok, v = ch:receive() + assert(not ok) + assert(v == nil) + `) + } + sender := func(ch chan LValue) { + defer wg.Done() + L := NewState() + defer L.Close() + L.SetGlobal("ch", LChannel(ch)) + errorIfScriptFail(t, L, `ch:send("1")`) + errorIfScriptNotFail(t, L, `ch:send(function() end)`, "can not send a function") + errorIfScriptFail(t, L, `ch:close()`) + } + ch := make(chan LValue) + wg.Add(2) + go receiver(ch) + go sender(ch) + wg.Wait() +} diff --git a/vendor/github.com/yuin/gopher-lua/cmd/glua/glua.go b/vendor/github.com/yuin/gopher-lua/cmd/glua/glua.go new file mode 100644 index 0000000000000000000000000000000000000000..8b17ad92aa63021f99890fe10b4eb3e07dc3037f --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/cmd/glua/glua.go @@ -0,0 +1,179 @@ +package main + +import ( + "flag" + "fmt" + "github.com/chzyer/readline" + "github.com/yuin/gopher-lua" + "github.com/yuin/gopher-lua/parse" + "os" + "runtime/pprof" +) + +func main() { + os.Exit(mainAux()) +} + +func mainAux() int { + var opt_e, opt_l, opt_p string + var opt_i, opt_v, opt_dt, opt_dc bool + var opt_m int + flag.StringVar(&opt_e, "e", "", "") + flag.StringVar(&opt_l, "l", "", "") + flag.StringVar(&opt_p, "p", "", "") + flag.IntVar(&opt_m, "mx", 0, "") + flag.BoolVar(&opt_i, "i", false, "") + flag.BoolVar(&opt_v, "v", false, "") + flag.BoolVar(&opt_dt, "dt", false, "") + flag.BoolVar(&opt_dc, "dc", false, "") + flag.Usage = func() { + fmt.Println(`Usage: glua [options] [script [args]]. +Available options are: + -e stat execute string 'stat' + -l name require library 'name' + -mx MB memory limit(default: unlimited) + -dt dump AST trees + -dc dump VM codes + -i enter interactive mode after executing 'script' + -p file write cpu profiles to the file + -v show version information +`) + } + flag.Parse() + if len(opt_p) != 0 { + f, err := os.Create(opt_p) + if err != nil { + fmt.Println(err.Error()) + os.Exit(1) + } + pprof.StartCPUProfile(f) + defer pprof.StopCPUProfile() + } + if len(opt_e) == 0 && !opt_i && !opt_v && flag.NArg() == 0 { + opt_i = true + } + + status := 0 + + L := lua.NewState() + defer L.Close() + if opt_m > 0 { + L.SetMx(opt_m) + } + + if opt_v || opt_i { + fmt.Println(lua.PackageCopyRight) + } + + if len(opt_l) > 0 { + if err := L.DoFile(opt_l); err != nil { + fmt.Println(err.Error()) + } + } + + if nargs := flag.NArg(); nargs > 0 { + script := flag.Arg(0) + argtb := L.NewTable() + for i := 1; i < nargs; i++ { + L.RawSet(argtb, lua.LNumber(i), lua.LString(flag.Arg(i))) + } + L.SetGlobal("arg", argtb) + if opt_dt || opt_dc { + file, err := os.Open(script) + if err != nil { + fmt.Println(err.Error()) + return 1 + } + chunk, err2 := parse.Parse(file, script) + if err2 != nil { + fmt.Println(err2.Error()) + return 1 + } + if opt_dt { + fmt.Println(parse.Dump(chunk)) + } + if opt_dc { + proto, err3 := lua.Compile(chunk, script) + if err3 != nil { + fmt.Println(err3.Error()) + return 1 + } + fmt.Println(proto.String()) + } + } + if err := L.DoFile(script); err != nil { + fmt.Println(err.Error()) + status = 1 + } + } + + if len(opt_e) > 0 { + if err := L.DoString(opt_e); err != nil { + fmt.Println(err.Error()) + status = 1 + } + } + + if opt_i { + doREPL(L) + } + return status +} + +// do read/eval/print/loop +func doREPL(L *lua.LState) { + rl, err := readline.New("> ") + if err != nil { + panic(err) + } + defer rl.Close() + for { + if str, err := loadline(rl, L); err == nil { + if err := L.DoString(str); err != nil { + fmt.Println(err) + } + } else { // error on loadline + fmt.Println(err) + return + } + } +} + +func incomplete(err error) bool { + if lerr, ok := err.(*lua.ApiError); ok { + if perr, ok := lerr.Cause.(*parse.Error); ok { + return perr.Pos.Line == parse.EOF + } + } + return false +} + +func loadline(rl *readline.Instance, L *lua.LState) (string, error) { + rl.SetPrompt("> ") + if line, err := rl.Readline(); err == nil { + if _, err := L.LoadString("return " + line); err == nil { // try add return <...> then compile + return line, nil + } else { + return multiline(line, rl, L) + } + } else { + return "", err + } +} + +func multiline(ml string, rl *readline.Instance, L *lua.LState) (string, error) { + for { + if _, err := L.LoadString(ml); err == nil { // try compile + return ml, nil + } else if !incomplete(err) { // syntax error , but not EOF + return ml, nil + } else { + rl.SetPrompt(">> ") + if line, err := rl.Readline(); err == nil { + ml = ml + "\n" + line + } else { + return "", err + } + } + } +} diff --git a/vendor/github.com/yuin/gopher-lua/compile.go b/vendor/github.com/yuin/gopher-lua/compile.go new file mode 100644 index 0000000000000000000000000000000000000000..dd51c0def6b300a4aaefc21de00420771620052e --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/compile.go @@ -0,0 +1,1656 @@ +package lua + +import ( + "fmt" + "github.com/yuin/gopher-lua/ast" + "math" + "reflect" +) + +/* internal constants & structs {{{ */ + +const maxRegisters = 200 + +type expContextType int + +const ( + ecGlobal expContextType = iota + ecUpvalue + ecLocal + ecTable + ecVararg + ecMethod + ecNone +) + +const regNotDefined = opMaxArgsA + 1 +const labelNoJump = 0 + +type expcontext struct { + ctype expContextType + reg int + // varargopt >= 0: wants varargopt+1 results, i.e a = func() + // varargopt = -1: ignore results i.e func() + // varargopt = -2: receive all results i.e a = {func()} + varargopt int +} + +type assigncontext struct { + ec *expcontext + keyrk int + valuerk int + keyks bool + needmove bool +} + +type lblabels struct { + t int + f int + e int + b bool +} + +type constLValueExpr struct { + ast.ExprBase + + Value LValue +} + +// }}} + +/* utilities {{{ */ +var _ecnone0 = &expcontext{ecNone, regNotDefined, 0} +var _ecnonem1 = &expcontext{ecNone, regNotDefined, -1} +var _ecnonem2 = &expcontext{ecNone, regNotDefined, -2} +var ecfuncdef = &expcontext{ecMethod, regNotDefined, 0} + +func ecupdate(ec *expcontext, ctype expContextType, reg, varargopt int) { + ec.ctype = ctype + ec.reg = reg + ec.varargopt = varargopt +} + +func ecnone(varargopt int) *expcontext { + switch varargopt { + case 0: + return _ecnone0 + case -1: + return _ecnonem1 + case -2: + return _ecnonem2 + } + return &expcontext{ecNone, regNotDefined, varargopt} +} + +func sline(pos ast.PositionHolder) int { + return pos.Line() +} + +func eline(pos ast.PositionHolder) int { + return pos.LastLine() +} + +func savereg(ec *expcontext, reg int) int { + if ec.ctype != ecLocal || ec.reg == regNotDefined { + return reg + } + return ec.reg +} + +func raiseCompileError(context *funcContext, line int, format string, args ...interface{}) { + msg := fmt.Sprintf(format, args...) + panic(&CompileError{context: context, Line: line, Message: msg}) +} + +func isVarArgReturnExpr(expr ast.Expr) bool { + switch ex := expr.(type) { + case *ast.FuncCallExpr: + return !ex.AdjustRet + case *ast.Comma3Expr: + return true + } + return false +} + +func lnumberValue(expr ast.Expr) (LNumber, bool) { + if ex, ok := expr.(*ast.NumberExpr); ok { + lv, err := parseNumber(ex.Value) + if err != nil { + lv = LNumber(math.NaN()) + } + return lv, true + } else if ex, ok := expr.(*constLValueExpr); ok { + return ex.Value.(LNumber), true + } + return 0, false +} + +/* utilities }}} */ + +type CompileError struct { // {{{ + context *funcContext + Line int + Message string +} + +func (e *CompileError) Error() string { + return fmt.Sprintf("compile error near line(%v) %v: %v", e.Line, e.context.Proto.SourceName, e.Message) +} // }}} + +type codeStore struct { // {{{ + codes []uint32 + lines []int + pc int +} + +func (cd *codeStore) Add(inst uint32, line int) { + if l := len(cd.codes); l <= 0 || cd.pc == l { + cd.codes = append(cd.codes, inst) + cd.lines = append(cd.lines, line) + } else { + cd.codes[cd.pc] = inst + cd.lines[cd.pc] = line + } + cd.pc++ +} + +func (cd *codeStore) AddABC(op int, a int, b int, c int, line int) { + cd.Add(opCreateABC(op, a, b, c), line) +} + +func (cd *codeStore) AddABx(op int, a int, bx int, line int) { + cd.Add(opCreateABx(op, a, bx), line) +} + +func (cd *codeStore) AddASbx(op int, a int, sbx int, line int) { + cd.Add(opCreateASbx(op, a, sbx), line) +} + +func (cd *codeStore) PropagateKMV(top int, save *int, reg *int, inc int) { + lastinst := cd.Last() + if opGetArgA(lastinst) >= top { + switch opGetOpCode(lastinst) { + case OP_LOADK: + cindex := opGetArgBx(lastinst) + if cindex <= opMaxIndexRk { + cd.Pop() + *save = opRkAsk(cindex) + return + } + case OP_MOVE: + cd.Pop() + *save = opGetArgB(lastinst) + return + } + } + *save = *reg + *reg = *reg + inc +} + +func (cd *codeStore) PropagateMV(top int, save *int, reg *int, inc int) { + lastinst := cd.Last() + if opGetArgA(lastinst) >= top { + switch opGetOpCode(lastinst) { + case OP_MOVE: + cd.Pop() + *save = opGetArgB(lastinst) + return + } + } + *save = *reg + *reg = *reg + inc +} + +func (cd *codeStore) SetOpCode(pc int, v int) { + opSetOpCode(&cd.codes[pc], v) +} + +func (cd *codeStore) SetA(pc int, v int) { + opSetArgA(&cd.codes[pc], v) +} + +func (cd *codeStore) SetB(pc int, v int) { + opSetArgB(&cd.codes[pc], v) +} + +func (cd *codeStore) SetC(pc int, v int) { + opSetArgC(&cd.codes[pc], v) +} + +func (cd *codeStore) SetBx(pc int, v int) { + opSetArgBx(&cd.codes[pc], v) +} + +func (cd *codeStore) SetSbx(pc int, v int) { + opSetArgSbx(&cd.codes[pc], v) +} + +func (cd *codeStore) At(pc int) uint32 { + return cd.codes[pc] +} + +func (cd *codeStore) List() []uint32 { + return cd.codes[:cd.pc] +} + +func (cd *codeStore) PosList() []int { + return cd.lines[:cd.pc] +} + +func (cd *codeStore) LastPC() int { + return cd.pc - 1 +} + +func (cd *codeStore) Last() uint32 { + if cd.pc == 0 { + return opInvalidInstruction + } + return cd.codes[cd.pc-1] +} + +func (cd *codeStore) Pop() { + cd.pc-- +} /* }}} Code */ + +/* {{{ VarNamePool */ + +type varNamePoolValue struct { + Index int + Name string +} + +type varNamePool struct { + names []string + offset int +} + +func newVarNamePool(offset int) *varNamePool { + return &varNamePool{make([]string, 0, 16), offset} +} + +func (vp *varNamePool) Names() []string { + return vp.names +} + +func (vp *varNamePool) List() []varNamePoolValue { + result := make([]varNamePoolValue, len(vp.names), len(vp.names)) + for i, name := range vp.names { + result[i].Index = i + vp.offset + result[i].Name = name + } + return result +} + +func (vp *varNamePool) LastIndex() int { + return vp.offset + len(vp.names) +} + +func (vp *varNamePool) Find(name string) int { + for i := len(vp.names) - 1; i >= 0; i-- { + if vp.names[i] == name { + return i + vp.offset + } + } + return -1 +} + +func (vp *varNamePool) RegisterUnique(name string) int { + index := vp.Find(name) + if index < 0 { + return vp.Register(name) + } + return index +} + +func (vp *varNamePool) Register(name string) int { + vp.names = append(vp.names, name) + return len(vp.names) - 1 + vp.offset +} + +/* }}} VarNamePool */ + +/* FuncContext {{{ */ + +type codeBlock struct { + LocalVars *varNamePool + BreakLabel int + Parent *codeBlock + RefUpvalue bool + LineStart int + LastLine int +} + +func newCodeBlock(localvars *varNamePool, blabel int, parent *codeBlock, pos ast.PositionHolder) *codeBlock { + bl := &codeBlock{localvars, blabel, parent, false, 0, 0} + if pos != nil { + bl.LineStart = pos.Line() + bl.LastLine = pos.LastLine() + } + return bl +} + +type funcContext struct { + Proto *FunctionProto + Code *codeStore + Parent *funcContext + Upvalues *varNamePool + Block *codeBlock + Blocks []*codeBlock + regTop int + labelId int + labelPc map[int]int +} + +func newFuncContext(sourcename string, parent *funcContext) *funcContext { + fc := &funcContext{ + Proto: newFunctionProto(sourcename), + Code: &codeStore{make([]uint32, 0, 1024), make([]int, 0, 1024), 0}, + Parent: parent, + Upvalues: newVarNamePool(0), + Block: newCodeBlock(newVarNamePool(0), labelNoJump, nil, nil), + regTop: 0, + labelId: 1, + labelPc: map[int]int{}, + } + fc.Blocks = []*codeBlock{fc.Block} + return fc +} + +func (fc *funcContext) NewLabel() int { + ret := fc.labelId + fc.labelId++ + return ret +} + +func (fc *funcContext) SetLabelPc(label int, pc int) { + fc.labelPc[label] = pc +} + +func (fc *funcContext) GetLabelPc(label int) int { + return fc.labelPc[label] +} + +func (fc *funcContext) ConstIndex(value LValue) int { + ctype := value.Type() + for i, lv := range fc.Proto.Constants { + if lv.Type() == ctype && lv == value { + return i + } + } + fc.Proto.Constants = append(fc.Proto.Constants, value) + v := len(fc.Proto.Constants) - 1 + if v > opMaxArgBx { + raiseCompileError(fc, fc.Proto.LineDefined, "too many constants") + } + return v +} + +func (fc *funcContext) RegisterLocalVar(name string) int { + ret := fc.Block.LocalVars.Register(name) + fc.Proto.DbgLocals = append(fc.Proto.DbgLocals, &DbgLocalInfo{Name: name, StartPc: fc.Code.LastPC() + 1}) + fc.SetRegTop(fc.RegTop() + 1) + return ret +} + +func (fc *funcContext) FindLocalVarAndBlock(name string) (int, *codeBlock) { + for block := fc.Block; block != nil; block = block.Parent { + if index := block.LocalVars.Find(name); index > -1 { + return index, block + } + } + return -1, nil +} + +func (fc *funcContext) FindLocalVar(name string) int { + idx, _ := fc.FindLocalVarAndBlock(name) + return idx +} + +func (fc *funcContext) LocalVars() []varNamePoolValue { + result := make([]varNamePoolValue, 0, 32) + for _, block := range fc.Blocks { + result = append(result, block.LocalVars.List()...) + } + return result +} + +func (fc *funcContext) EnterBlock(blabel int, pos ast.PositionHolder) { + fc.Block = newCodeBlock(newVarNamePool(fc.RegTop()), blabel, fc.Block, pos) + fc.Blocks = append(fc.Blocks, fc.Block) +} + +func (fc *funcContext) CloseUpvalues() int { + n := -1 + if fc.Block.RefUpvalue { + n = fc.Block.Parent.LocalVars.LastIndex() + fc.Code.AddABC(OP_CLOSE, n, 0, 0, fc.Block.LastLine) + } + return n +} + +func (fc *funcContext) LeaveBlock() int { + closed := fc.CloseUpvalues() + fc.EndScope() + fc.Block = fc.Block.Parent + fc.SetRegTop(fc.Block.LocalVars.LastIndex()) + return closed +} + +func (fc *funcContext) EndScope() { + for _, vr := range fc.Block.LocalVars.List() { + fc.Proto.DbgLocals[vr.Index].EndPc = fc.Code.LastPC() + } +} + +func (fc *funcContext) SetRegTop(top int) { + if top > maxRegisters { + raiseCompileError(fc, fc.Proto.LineDefined, "too many local variables") + } + fc.regTop = top +} + +func (fc *funcContext) RegTop() int { + return fc.regTop +} + +/* FuncContext }}} */ + +func compileChunk(context *funcContext, chunk []ast.Stmt) { // {{{ + for _, stmt := range chunk { + compileStmt(context, stmt) + } +} // }}} + +func compileBlock(context *funcContext, chunk []ast.Stmt) { // {{{ + if len(chunk) == 0 { + return + } + ph := &ast.Node{} + ph.SetLine(sline(chunk[0])) + ph.SetLastLine(eline(chunk[len(chunk)-1])) + context.EnterBlock(labelNoJump, ph) + for _, stmt := range chunk { + compileStmt(context, stmt) + } + context.LeaveBlock() +} // }}} + +func compileStmt(context *funcContext, stmt ast.Stmt) { // {{{ + switch st := stmt.(type) { + case *ast.AssignStmt: + compileAssignStmt(context, st) + case *ast.LocalAssignStmt: + compileLocalAssignStmt(context, st) + case *ast.FuncCallStmt: + compileFuncCallExpr(context, context.RegTop(), st.Expr.(*ast.FuncCallExpr), ecnone(-1)) + case *ast.DoBlockStmt: + context.EnterBlock(labelNoJump, st) + compileChunk(context, st.Stmts) + context.LeaveBlock() + case *ast.WhileStmt: + compileWhileStmt(context, st) + case *ast.RepeatStmt: + compileRepeatStmt(context, st) + case *ast.FuncDefStmt: + compileFuncDefStmt(context, st) + case *ast.ReturnStmt: + compileReturnStmt(context, st) + case *ast.IfStmt: + compileIfStmt(context, st) + case *ast.BreakStmt: + compileBreakStmt(context, st) + case *ast.NumberForStmt: + compileNumberForStmt(context, st) + case *ast.GenericForStmt: + compileGenericForStmt(context, st) + } +} // }}} + +func compileAssignStmtLeft(context *funcContext, stmt *ast.AssignStmt) (int, []*assigncontext) { // {{{ + reg := context.RegTop() + acs := make([]*assigncontext, 0, len(stmt.Lhs)) + for i, lhs := range stmt.Lhs { + islast := i == len(stmt.Lhs)-1 + switch st := lhs.(type) { + case *ast.IdentExpr: + identtype := getIdentRefType(context, context, st) + ec := &expcontext{identtype, regNotDefined, 0} + switch identtype { + case ecGlobal: + context.ConstIndex(LString(st.Value)) + case ecUpvalue: + context.Upvalues.RegisterUnique(st.Value) + case ecLocal: + if islast { + ec.reg = context.FindLocalVar(st.Value) + } + } + acs = append(acs, &assigncontext{ec, 0, 0, false, false}) + case *ast.AttrGetExpr: + ac := &assigncontext{&expcontext{ecTable, regNotDefined, 0}, 0, 0, false, false} + compileExprWithKMVPropagation(context, st.Object, ®, &ac.ec.reg) + ac.keyrk = reg + reg += compileExpr(context, reg, st.Key, ecnone(0)) + if _, ok := st.Key.(*ast.StringExpr); ok { + ac.keyks = true + } + acs = append(acs, ac) + + default: + panic("invalid left expression.") + } + } + return reg, acs +} // }}} + +func compileAssignStmtRight(context *funcContext, stmt *ast.AssignStmt, reg int, acs []*assigncontext) (int, []*assigncontext) { // {{{ + lennames := len(stmt.Lhs) + lenexprs := len(stmt.Rhs) + namesassigned := 0 + + for namesassigned < lennames { + ac := acs[namesassigned] + ec := ac.ec + var expr ast.Expr = nil + if namesassigned >= lenexprs { + expr = &ast.NilExpr{} + expr.SetLine(sline(stmt.Lhs[namesassigned])) + expr.SetLastLine(eline(stmt.Lhs[namesassigned])) + } else if isVarArgReturnExpr(stmt.Rhs[namesassigned]) && (lenexprs-namesassigned-1) <= 0 { + varargopt := lennames - namesassigned - 1 + regstart := reg + reginc := compileExpr(context, reg, stmt.Rhs[namesassigned], ecnone(varargopt)) + reg += reginc + for i := namesassigned; i < namesassigned+int(reginc); i++ { + acs[i].needmove = true + if acs[i].ec.ctype == ecTable { + acs[i].valuerk = regstart + (i - namesassigned) + } + } + namesassigned = lennames + continue + } + + if expr == nil { + expr = stmt.Rhs[namesassigned] + } + idx := reg + reginc := compileExpr(context, reg, expr, ec) + if ec.ctype == ecTable { + if _, ok := expr.(*ast.LogicalOpExpr); !ok { + context.Code.PropagateKMV(context.RegTop(), &ac.valuerk, ®, reginc) + } else { + ac.valuerk = idx + reg += reginc + } + } else { + ac.needmove = reginc != 0 + reg += reginc + } + namesassigned += 1 + } + + rightreg := reg - 1 + + // extra right exprs + for i := namesassigned; i < lenexprs; i++ { + varargopt := -1 + if i != lenexprs-1 { + varargopt = 0 + } + reg += compileExpr(context, reg, stmt.Rhs[i], ecnone(varargopt)) + } + return rightreg, acs +} // }}} + +func compileAssignStmt(context *funcContext, stmt *ast.AssignStmt) { // {{{ + code := context.Code + lennames := len(stmt.Lhs) + reg, acs := compileAssignStmtLeft(context, stmt) + reg, acs = compileAssignStmtRight(context, stmt, reg, acs) + + for i := lennames - 1; i >= 0; i-- { + ex := stmt.Lhs[i] + switch acs[i].ec.ctype { + case ecLocal: + if acs[i].needmove { + code.AddABC(OP_MOVE, context.FindLocalVar(ex.(*ast.IdentExpr).Value), reg, 0, sline(ex)) + reg -= 1 + } + case ecGlobal: + code.AddABx(OP_SETGLOBAL, reg, context.ConstIndex(LString(ex.(*ast.IdentExpr).Value)), sline(ex)) + reg -= 1 + case ecUpvalue: + code.AddABC(OP_SETUPVAL, reg, context.Upvalues.RegisterUnique(ex.(*ast.IdentExpr).Value), 0, sline(ex)) + reg -= 1 + case ecTable: + opcode := OP_SETTABLE + if acs[i].keyks { + opcode = OP_SETTABLEKS + } + code.AddABC(opcode, acs[i].ec.reg, acs[i].keyrk, acs[i].valuerk, sline(ex)) + if !opIsK(acs[i].valuerk) { + reg -= 1 + } + } + } +} // }}} + +func compileRegAssignment(context *funcContext, names []string, exprs []ast.Expr, reg int, nvars int, line int) { // {{{ + lennames := len(names) + lenexprs := len(exprs) + namesassigned := 0 + ec := &expcontext{} + + for namesassigned < lennames && namesassigned < lenexprs { + if isVarArgReturnExpr(exprs[namesassigned]) && (lenexprs-namesassigned-1) <= 0 { + + varargopt := nvars - namesassigned + ecupdate(ec, ecVararg, reg, varargopt-1) + compileExpr(context, reg, exprs[namesassigned], ec) + reg += varargopt + namesassigned = lennames + } else { + ecupdate(ec, ecLocal, reg, 0) + compileExpr(context, reg, exprs[namesassigned], ec) + reg += 1 + namesassigned += 1 + } + } + + // extra left names + if lennames > namesassigned { + restleft := lennames - namesassigned - 1 + context.Code.AddABC(OP_LOADNIL, reg, reg+restleft, 0, line) + reg += restleft + } + + // extra right exprs + for i := namesassigned; i < lenexprs; i++ { + varargopt := -1 + if i != lenexprs-1 { + varargopt = 0 + } + ecupdate(ec, ecNone, reg, varargopt) + reg += compileExpr(context, reg, exprs[i], ec) + } +} // }}} + +func compileLocalAssignStmt(context *funcContext, stmt *ast.LocalAssignStmt) { // {{{ + reg := context.RegTop() + if len(stmt.Names) == 1 && len(stmt.Exprs) == 1 { + if _, ok := stmt.Exprs[0].(*ast.FunctionExpr); ok { + context.RegisterLocalVar(stmt.Names[0]) + compileRegAssignment(context, stmt.Names, stmt.Exprs, reg, len(stmt.Names), sline(stmt)) + return + } + } + + compileRegAssignment(context, stmt.Names, stmt.Exprs, reg, len(stmt.Names), sline(stmt)) + for _, name := range stmt.Names { + context.RegisterLocalVar(name) + } +} // }}} + +func compileReturnStmt(context *funcContext, stmt *ast.ReturnStmt) { // {{{ + lenexprs := len(stmt.Exprs) + code := context.Code + reg := context.RegTop() + a := reg + lastisvaarg := false + + if lenexprs == 1 { + switch ex := stmt.Exprs[0].(type) { + case *ast.IdentExpr: + if idx := context.FindLocalVar(ex.Value); idx > -1 { + code.AddABC(OP_RETURN, idx, 2, 0, sline(stmt)) + return + } + case *ast.FuncCallExpr: + reg += compileExpr(context, reg, ex, ecnone(-2)) + code.SetOpCode(code.LastPC(), OP_TAILCALL) + code.AddABC(OP_RETURN, a, 0, 0, sline(stmt)) + return + } + } + + for i, expr := range stmt.Exprs { + if i == lenexprs-1 && isVarArgReturnExpr(expr) { + compileExpr(context, reg, expr, ecnone(-2)) + lastisvaarg = true + } else { + reg += compileExpr(context, reg, expr, ecnone(0)) + } + } + count := reg - a + 1 + if lastisvaarg { + count = 0 + } + context.Code.AddABC(OP_RETURN, a, count, 0, sline(stmt)) +} // }}} + +func compileIfStmt(context *funcContext, stmt *ast.IfStmt) { // {{{ + thenlabel := context.NewLabel() + elselabel := context.NewLabel() + endlabel := context.NewLabel() + + compileBranchCondition(context, context.RegTop(), stmt.Condition, thenlabel, elselabel, false) + context.SetLabelPc(thenlabel, context.Code.LastPC()) + compileBlock(context, stmt.Then) + if len(stmt.Else) > 0 { + context.Code.AddASbx(OP_JMP, 0, endlabel, sline(stmt)) + } + context.SetLabelPc(elselabel, context.Code.LastPC()) + if len(stmt.Else) > 0 { + compileBlock(context, stmt.Else) + context.SetLabelPc(endlabel, context.Code.LastPC()) + } + +} // }}} + +func compileBranchCondition(context *funcContext, reg int, expr ast.Expr, thenlabel, elselabel int, hasnextcond bool) { // {{{ + // TODO folding constants? + code := context.Code + flip := 0 + jumplabel := elselabel + if hasnextcond { + flip = 1 + jumplabel = thenlabel + } + + switch ex := expr.(type) { + case *ast.FalseExpr, *ast.NilExpr: + if !hasnextcond { + code.AddASbx(OP_JMP, 0, elselabel, sline(expr)) + return + } + case *ast.TrueExpr, *ast.NumberExpr, *ast.StringExpr: + if !hasnextcond { + return + } + case *ast.UnaryNotOpExpr: + compileBranchCondition(context, reg, ex.Expr, elselabel, thenlabel, !hasnextcond) + return + case *ast.LogicalOpExpr: + switch ex.Operator { + case "and": + nextcondlabel := context.NewLabel() + compileBranchCondition(context, reg, ex.Lhs, nextcondlabel, elselabel, false) + context.SetLabelPc(nextcondlabel, context.Code.LastPC()) + compileBranchCondition(context, reg, ex.Rhs, thenlabel, elselabel, hasnextcond) + case "or": + nextcondlabel := context.NewLabel() + compileBranchCondition(context, reg, ex.Lhs, thenlabel, nextcondlabel, true) + context.SetLabelPc(nextcondlabel, context.Code.LastPC()) + compileBranchCondition(context, reg, ex.Rhs, thenlabel, elselabel, hasnextcond) + } + return + case *ast.RelationalOpExpr: + compileRelationalOpExprAux(context, reg, ex, flip, jumplabel) + return + } + + a := reg + compileExprWithMVPropagation(context, expr, ®, &a) + code.AddABC(OP_TEST, a, 0, 0^flip, sline(expr)) + code.AddASbx(OP_JMP, 0, jumplabel, sline(expr)) +} // }}} + +func compileWhileStmt(context *funcContext, stmt *ast.WhileStmt) { // {{{ + thenlabel := context.NewLabel() + elselabel := context.NewLabel() + condlabel := context.NewLabel() + + context.SetLabelPc(condlabel, context.Code.LastPC()) + compileBranchCondition(context, context.RegTop(), stmt.Condition, thenlabel, elselabel, false) + context.SetLabelPc(thenlabel, context.Code.LastPC()) + context.EnterBlock(elselabel, stmt) + compileChunk(context, stmt.Stmts) + context.CloseUpvalues() + context.Code.AddASbx(OP_JMP, 0, condlabel, eline(stmt)) + context.LeaveBlock() + context.SetLabelPc(elselabel, context.Code.LastPC()) +} // }}} + +func compileRepeatStmt(context *funcContext, stmt *ast.RepeatStmt) { // {{{ + initlabel := context.NewLabel() + thenlabel := context.NewLabel() + elselabel := context.NewLabel() + + context.SetLabelPc(initlabel, context.Code.LastPC()) + context.SetLabelPc(elselabel, context.Code.LastPC()) + context.EnterBlock(thenlabel, stmt) + compileChunk(context, stmt.Stmts) + compileBranchCondition(context, context.RegTop(), stmt.Condition, thenlabel, elselabel, false) + + context.SetLabelPc(thenlabel, context.Code.LastPC()) + n := context.LeaveBlock() + + if n > -1 { + label := context.NewLabel() + context.Code.AddASbx(OP_JMP, 0, label, eline(stmt)) + context.SetLabelPc(elselabel, context.Code.LastPC()) + context.Code.AddABC(OP_CLOSE, n, 0, 0, eline(stmt)) + context.Code.AddASbx(OP_JMP, 0, initlabel, eline(stmt)) + context.SetLabelPc(label, context.Code.LastPC()) + } + +} // }}} + +func compileBreakStmt(context *funcContext, stmt *ast.BreakStmt) { // {{{ + for block := context.Block; block != nil; block = block.Parent { + if label := block.BreakLabel; label != labelNoJump { + if block.RefUpvalue { + context.Code.AddABC(OP_CLOSE, block.Parent.LocalVars.LastIndex(), 0, 0, sline(stmt)) + } + context.Code.AddASbx(OP_JMP, 0, label, sline(stmt)) + return + } + } + raiseCompileError(context, sline(stmt), "no loop to break") +} // }}} + +func compileFuncDefStmt(context *funcContext, stmt *ast.FuncDefStmt) { // {{{ + if stmt.Name.Func == nil { + reg := context.RegTop() + var treg, kreg int + compileExprWithKMVPropagation(context, stmt.Name.Receiver, ®, &treg) + kreg = loadRk(context, ®, stmt.Func, LString(stmt.Name.Method)) + compileExpr(context, reg, stmt.Func, ecfuncdef) + context.Code.AddABC(OP_SETTABLE, treg, kreg, reg, sline(stmt.Name.Receiver)) + } else { + astmt := &ast.AssignStmt{Lhs: []ast.Expr{stmt.Name.Func}, Rhs: []ast.Expr{stmt.Func}} + astmt.SetLine(sline(stmt.Func)) + astmt.SetLastLine(eline(stmt.Func)) + compileAssignStmt(context, astmt) + } +} // }}} + +func compileNumberForStmt(context *funcContext, stmt *ast.NumberForStmt) { // {{{ + code := context.Code + endlabel := context.NewLabel() + ec := &expcontext{} + + context.EnterBlock(endlabel, stmt) + reg := context.RegTop() + rindex := context.RegisterLocalVar("(for index)") + ecupdate(ec, ecLocal, rindex, 0) + compileExpr(context, reg, stmt.Init, ec) + + reg = context.RegTop() + rlimit := context.RegisterLocalVar("(for limit)") + ecupdate(ec, ecLocal, rlimit, 0) + compileExpr(context, reg, stmt.Limit, ec) + + reg = context.RegTop() + rstep := context.RegisterLocalVar("(for step)") + if stmt.Step == nil { + stmt.Step = &ast.NumberExpr{Value: "1"} + stmt.Step.SetLine(sline(stmt.Init)) + } + ecupdate(ec, ecLocal, rstep, 0) + compileExpr(context, reg, stmt.Step, ec) + + code.AddASbx(OP_FORPREP, rindex, 0, sline(stmt)) + + context.RegisterLocalVar(stmt.Name) + + bodypc := code.LastPC() + compileChunk(context, stmt.Stmts) + + context.LeaveBlock() + + flpc := code.LastPC() + code.AddASbx(OP_FORLOOP, rindex, bodypc-(flpc+1), sline(stmt)) + + context.SetLabelPc(endlabel, code.LastPC()) + code.SetSbx(bodypc, flpc-bodypc) + +} // }}} + +func compileGenericForStmt(context *funcContext, stmt *ast.GenericForStmt) { // {{{ + code := context.Code + endlabel := context.NewLabel() + bodylabel := context.NewLabel() + fllabel := context.NewLabel() + nnames := len(stmt.Names) + + context.EnterBlock(endlabel, stmt) + rgen := context.RegisterLocalVar("(for generator)") + context.RegisterLocalVar("(for state)") + context.RegisterLocalVar("(for control)") + + compileRegAssignment(context, stmt.Names, stmt.Exprs, context.RegTop()-3, 3, sline(stmt)) + + code.AddASbx(OP_JMP, 0, fllabel, sline(stmt)) + + for _, name := range stmt.Names { + context.RegisterLocalVar(name) + } + + context.SetLabelPc(bodylabel, code.LastPC()) + compileChunk(context, stmt.Stmts) + + context.LeaveBlock() + + context.SetLabelPc(fllabel, code.LastPC()) + code.AddABC(OP_TFORLOOP, rgen, 0, nnames, sline(stmt)) + code.AddASbx(OP_JMP, 0, bodylabel, sline(stmt)) + + context.SetLabelPc(endlabel, code.LastPC()) +} // }}} + +func compileExpr(context *funcContext, reg int, expr ast.Expr, ec *expcontext) int { // {{{ + code := context.Code + sreg := savereg(ec, reg) + sused := 1 + if sreg < reg { + sused = 0 + } + + switch ex := expr.(type) { + case *ast.StringExpr: + code.AddABx(OP_LOADK, sreg, context.ConstIndex(LString(ex.Value)), sline(ex)) + return sused + case *ast.NumberExpr: + num, err := parseNumber(ex.Value) + if err != nil { + num = LNumber(math.NaN()) + } + code.AddABx(OP_LOADK, sreg, context.ConstIndex(num), sline(ex)) + return sused + case *constLValueExpr: + code.AddABx(OP_LOADK, sreg, context.ConstIndex(ex.Value), sline(ex)) + return sused + case *ast.NilExpr: + code.AddABC(OP_LOADNIL, sreg, sreg, 0, sline(ex)) + return sused + case *ast.FalseExpr: + code.AddABC(OP_LOADBOOL, sreg, 0, 0, sline(ex)) + return sused + case *ast.TrueExpr: + code.AddABC(OP_LOADBOOL, sreg, 1, 0, sline(ex)) + return sused + case *ast.IdentExpr: + switch getIdentRefType(context, context, ex) { + case ecGlobal: + code.AddABx(OP_GETGLOBAL, sreg, context.ConstIndex(LString(ex.Value)), sline(ex)) + case ecUpvalue: + code.AddABC(OP_GETUPVAL, sreg, context.Upvalues.RegisterUnique(ex.Value), 0, sline(ex)) + case ecLocal: + b := context.FindLocalVar(ex.Value) + code.AddABC(OP_MOVE, sreg, b, 0, sline(ex)) + } + return sused + case *ast.Comma3Expr: + if context.Proto.IsVarArg == 0 { + raiseCompileError(context, sline(ex), "cannot use '...' outside a vararg function") + } + context.Proto.IsVarArg &= ^VarArgNeedsArg + code.AddABC(OP_VARARG, sreg, 2+ec.varargopt, 0, sline(ex)) + if context.RegTop() > (sreg+2+ec.varargopt) || ec.varargopt < -1 { + return 0 + } + return (sreg + 1 + ec.varargopt) - reg + case *ast.AttrGetExpr: + a := sreg + b := reg + compileExprWithMVPropagation(context, ex.Object, ®, &b) + c := reg + compileExprWithKMVPropagation(context, ex.Key, ®, &c) + opcode := OP_GETTABLE + if _, ok := ex.Key.(*ast.StringExpr); ok { + opcode = OP_GETTABLEKS + } + code.AddABC(opcode, a, b, c, sline(ex)) + return sused + case *ast.TableExpr: + compileTableExpr(context, reg, ex, ec) + return 1 + case *ast.ArithmeticOpExpr: + compileArithmeticOpExpr(context, reg, ex, ec) + return sused + case *ast.StringConcatOpExpr: + compileStringConcatOpExpr(context, reg, ex, ec) + return sused + case *ast.UnaryMinusOpExpr, *ast.UnaryNotOpExpr, *ast.UnaryLenOpExpr: + compileUnaryOpExpr(context, reg, ex, ec) + return sused + case *ast.RelationalOpExpr: + compileRelationalOpExpr(context, reg, ex, ec) + return sused + case *ast.LogicalOpExpr: + compileLogicalOpExpr(context, reg, ex, ec) + return sused + case *ast.FuncCallExpr: + return compileFuncCallExpr(context, reg, ex, ec) + case *ast.FunctionExpr: + childcontext := newFuncContext(context.Proto.SourceName, context) + compileFunctionExpr(childcontext, ex, ec) + protono := len(context.Proto.FunctionPrototypes) + context.Proto.FunctionPrototypes = append(context.Proto.FunctionPrototypes, childcontext.Proto) + code.AddABx(OP_CLOSURE, sreg, protono, sline(ex)) + for _, upvalue := range childcontext.Upvalues.List() { + localidx, block := context.FindLocalVarAndBlock(upvalue.Name) + if localidx > -1 { + code.AddABC(OP_MOVE, 0, localidx, 0, sline(ex)) + block.RefUpvalue = true + } else { + upvalueidx := context.Upvalues.Find(upvalue.Name) + if upvalueidx < 0 { + upvalueidx = context.Upvalues.RegisterUnique(upvalue.Name) + } + code.AddABC(OP_GETUPVAL, 0, upvalueidx, 0, sline(ex)) + } + } + return sused + default: + panic(fmt.Sprintf("expr %v not implemented.", reflect.TypeOf(ex).Elem().Name())) + } + + panic("should not reach here") + return sused +} // }}} + +func compileExprWithPropagation(context *funcContext, expr ast.Expr, reg *int, save *int, propergator func(int, *int, *int, int)) { // {{{ + reginc := compileExpr(context, *reg, expr, ecnone(0)) + if _, ok := expr.(*ast.LogicalOpExpr); ok { + *save = *reg + *reg = *reg + reginc + } else { + propergator(context.RegTop(), save, reg, reginc) + } +} // }}} + +func compileExprWithKMVPropagation(context *funcContext, expr ast.Expr, reg *int, save *int) { // {{{ + compileExprWithPropagation(context, expr, reg, save, context.Code.PropagateKMV) +} // }}} + +func compileExprWithMVPropagation(context *funcContext, expr ast.Expr, reg *int, save *int) { // {{{ + compileExprWithPropagation(context, expr, reg, save, context.Code.PropagateMV) +} // }}} + +func constFold(exp ast.Expr) ast.Expr { // {{{ + switch expr := exp.(type) { + case *ast.ArithmeticOpExpr: + lvalue, lisconst := lnumberValue(expr.Lhs) + rvalue, risconst := lnumberValue(expr.Rhs) + if lisconst && risconst { + switch expr.Operator { + case "+": + return &constLValueExpr{Value: lvalue + rvalue} + case "-": + return &constLValueExpr{Value: lvalue - rvalue} + case "*": + return &constLValueExpr{Value: lvalue * rvalue} + case "/": + return &constLValueExpr{Value: lvalue / rvalue} + case "%": + return &constLValueExpr{Value: luaModulo(lvalue, rvalue)} + case "^": + return &constLValueExpr{Value: LNumber(math.Pow(float64(lvalue), float64(rvalue)))} + default: + panic(fmt.Sprintf("unknown binop: %v", expr.Operator)) + } + } else { + retexpr := *expr + retexpr.Lhs = constFold(expr.Lhs) + retexpr.Rhs = constFold(expr.Rhs) + return &retexpr + } + case *ast.UnaryMinusOpExpr: + expr.Expr = constFold(expr.Expr) + if value, ok := lnumberValue(expr.Expr); ok { + return &constLValueExpr{Value: LNumber(-value)} + } + return expr + default: + + return exp + } + return exp +} // }}} + +func compileFunctionExpr(context *funcContext, funcexpr *ast.FunctionExpr, ec *expcontext) { // {{{ + context.Proto.LineDefined = sline(funcexpr) + context.Proto.LastLineDefined = eline(funcexpr) + if len(funcexpr.ParList.Names) > maxRegisters { + raiseCompileError(context, context.Proto.LineDefined, "register overflow") + } + context.Proto.NumParameters = uint8(len(funcexpr.ParList.Names)) + if ec.ctype == ecMethod { + context.Proto.NumParameters += 1 + context.RegisterLocalVar("self") + } + for _, name := range funcexpr.ParList.Names { + context.RegisterLocalVar(name) + } + if funcexpr.ParList.HasVargs { + if CompatVarArg { + context.Proto.IsVarArg = VarArgHasArg | VarArgNeedsArg + if context.Parent != nil { + context.RegisterLocalVar("arg") + } + } + context.Proto.IsVarArg |= VarArgIsVarArg + } + + compileChunk(context, funcexpr.Stmts) + + context.Code.AddABC(OP_RETURN, 0, 1, 0, eline(funcexpr)) + context.EndScope() + context.Proto.Code = context.Code.List() + context.Proto.DbgSourcePositions = context.Code.PosList() + context.Proto.DbgUpvalues = context.Upvalues.Names() + context.Proto.NumUpvalues = uint8(len(context.Proto.DbgUpvalues)) + for _, clv := range context.Proto.Constants { + sv := "" + if slv, ok := clv.(LString); ok { + sv = string(slv) + } + context.Proto.stringConstants = append(context.Proto.stringConstants, sv) + } + patchCode(context) +} // }}} + +func compileTableExpr(context *funcContext, reg int, ex *ast.TableExpr, ec *expcontext) { // {{{ + code := context.Code + /* + tablereg := savereg(ec, reg) + if tablereg == reg { + reg += 1 + } + */ + tablereg := reg + reg++ + code.AddABC(OP_NEWTABLE, tablereg, 0, 0, sline(ex)) + tablepc := code.LastPC() + regbase := reg + + arraycount := 0 + lastvararg := false + for i, field := range ex.Fields { + islast := i == len(ex.Fields)-1 + if field.Key == nil { + if islast && isVarArgReturnExpr(field.Value) { + reg += compileExpr(context, reg, field.Value, ecnone(-2)) + lastvararg = true + } else { + reg += compileExpr(context, reg, field.Value, ecnone(0)) + arraycount += 1 + } + } else { + regorg := reg + b := reg + compileExprWithKMVPropagation(context, field.Key, ®, &b) + c := reg + compileExprWithKMVPropagation(context, field.Value, ®, &c) + opcode := OP_SETTABLE + if _, ok := field.Key.(*ast.StringExpr); ok { + opcode = OP_SETTABLEKS + } + code.AddABC(opcode, tablereg, b, c, sline(ex)) + reg = regorg + } + flush := arraycount % FieldsPerFlush + if (arraycount != 0 && (flush == 0 || islast)) || lastvararg { + reg = regbase + num := flush + if num == 0 { + num = FieldsPerFlush + } + c := (arraycount-1)/FieldsPerFlush + 1 + b := num + if islast && isVarArgReturnExpr(field.Value) { + b = 0 + } + line := field.Value + if field.Key != nil { + line = field.Key + } + if c > 511 { + c = 0 + } + code.AddABC(OP_SETLIST, tablereg, b, c, sline(line)) + if c == 0 { + code.Add(uint32(c), sline(line)) + } + } + } + code.SetB(tablepc, int2Fb(arraycount)) + code.SetC(tablepc, int2Fb(len(ex.Fields)-arraycount)) + if ec.ctype == ecLocal && ec.reg != tablereg { + code.AddABC(OP_MOVE, ec.reg, tablereg, 0, sline(ex)) + } +} // }}} + +func compileArithmeticOpExpr(context *funcContext, reg int, expr *ast.ArithmeticOpExpr, ec *expcontext) { // {{{ + exp := constFold(expr) + if ex, ok := exp.(*constLValueExpr); ok { + exp.SetLine(sline(expr)) + compileExpr(context, reg, ex, ec) + return + } + expr, _ = exp.(*ast.ArithmeticOpExpr) + a := savereg(ec, reg) + b := reg + compileExprWithKMVPropagation(context, expr.Lhs, ®, &b) + c := reg + compileExprWithKMVPropagation(context, expr.Rhs, ®, &c) + + op := 0 + switch expr.Operator { + case "+": + op = OP_ADD + case "-": + op = OP_SUB + case "*": + op = OP_MUL + case "/": + op = OP_DIV + case "%": + op = OP_MOD + case "^": + op = OP_POW + } + context.Code.AddABC(op, a, b, c, sline(expr)) +} // }}} + +func compileStringConcatOpExpr(context *funcContext, reg int, expr *ast.StringConcatOpExpr, ec *expcontext) { // {{{ + code := context.Code + crange := 1 + for current := expr.Rhs; current != nil; { + if ex, ok := current.(*ast.StringConcatOpExpr); ok { + crange += 1 + current = ex.Rhs + } else { + current = nil + } + } + a := savereg(ec, reg) + basereg := reg + reg += compileExpr(context, reg, expr.Lhs, ecnone(0)) + reg += compileExpr(context, reg, expr.Rhs, ecnone(0)) + for pc := code.LastPC(); pc != 0 && opGetOpCode(code.At(pc)) == OP_CONCAT; pc-- { + code.Pop() + } + code.AddABC(OP_CONCAT, a, basereg, basereg+crange, sline(expr)) +} // }}} + +func compileUnaryOpExpr(context *funcContext, reg int, expr ast.Expr, ec *expcontext) { // {{{ + opcode := 0 + code := context.Code + var operandexpr ast.Expr + switch ex := expr.(type) { + case *ast.UnaryMinusOpExpr: + exp := constFold(ex) + if lvexpr, ok := exp.(*constLValueExpr); ok { + exp.SetLine(sline(expr)) + compileExpr(context, reg, lvexpr, ec) + return + } + ex, _ = exp.(*ast.UnaryMinusOpExpr) + operandexpr = ex.Expr + opcode = OP_UNM + case *ast.UnaryNotOpExpr: + switch ex.Expr.(type) { + case *ast.TrueExpr: + code.AddABC(OP_LOADBOOL, savereg(ec, reg), 0, 0, sline(expr)) + return + case *ast.FalseExpr, *ast.NilExpr: + code.AddABC(OP_LOADBOOL, savereg(ec, reg), 1, 0, sline(expr)) + return + default: + opcode = OP_NOT + operandexpr = ex.Expr + } + case *ast.UnaryLenOpExpr: + opcode = OP_LEN + operandexpr = ex.Expr + } + + a := savereg(ec, reg) + b := reg + compileExprWithMVPropagation(context, operandexpr, ®, &b) + code.AddABC(opcode, a, b, 0, sline(expr)) +} // }}} + +func compileRelationalOpExprAux(context *funcContext, reg int, expr *ast.RelationalOpExpr, flip int, label int) { // {{{ + code := context.Code + b := reg + compileExprWithKMVPropagation(context, expr.Lhs, ®, &b) + c := reg + compileExprWithKMVPropagation(context, expr.Rhs, ®, &c) + switch expr.Operator { + case "<": + code.AddABC(OP_LT, 0^flip, b, c, sline(expr)) + case ">": + code.AddABC(OP_LT, 0^flip, c, b, sline(expr)) + case "<=": + code.AddABC(OP_LE, 0^flip, b, c, sline(expr)) + case ">=": + code.AddABC(OP_LE, 0^flip, c, b, sline(expr)) + case "==": + code.AddABC(OP_EQ, 0^flip, b, c, sline(expr)) + case "~=": + code.AddABC(OP_EQ, 1^flip, b, c, sline(expr)) + } + code.AddASbx(OP_JMP, 0, label, sline(expr)) +} // }}} + +func compileRelationalOpExpr(context *funcContext, reg int, expr *ast.RelationalOpExpr, ec *expcontext) { // {{{ + a := savereg(ec, reg) + code := context.Code + jumplabel := context.NewLabel() + compileRelationalOpExprAux(context, reg, expr, 1, jumplabel) + code.AddABC(OP_LOADBOOL, a, 0, 1, sline(expr)) + context.SetLabelPc(jumplabel, code.LastPC()) + code.AddABC(OP_LOADBOOL, a, 1, 0, sline(expr)) +} // }}} + +func compileLogicalOpExpr(context *funcContext, reg int, expr *ast.LogicalOpExpr, ec *expcontext) { // {{{ + a := savereg(ec, reg) + code := context.Code + endlabel := context.NewLabel() + lb := &lblabels{context.NewLabel(), context.NewLabel(), endlabel, false} + nextcondlabel := context.NewLabel() + if expr.Operator == "and" { + compileLogicalOpExprAux(context, reg, expr.Lhs, ec, nextcondlabel, endlabel, false, lb) + context.SetLabelPc(nextcondlabel, code.LastPC()) + compileLogicalOpExprAux(context, reg, expr.Rhs, ec, endlabel, endlabel, false, lb) + } else { + compileLogicalOpExprAux(context, reg, expr.Lhs, ec, endlabel, nextcondlabel, true, lb) + context.SetLabelPc(nextcondlabel, code.LastPC()) + compileLogicalOpExprAux(context, reg, expr.Rhs, ec, endlabel, endlabel, false, lb) + } + + if lb.b { + context.SetLabelPc(lb.f, code.LastPC()) + code.AddABC(OP_LOADBOOL, a, 0, 1, sline(expr)) + context.SetLabelPc(lb.t, code.LastPC()) + code.AddABC(OP_LOADBOOL, a, 1, 0, sline(expr)) + } + + lastinst := code.Last() + if opGetOpCode(lastinst) == OP_JMP && opGetArgSbx(lastinst) == endlabel { + code.Pop() + } + + context.SetLabelPc(endlabel, code.LastPC()) +} // }}} + +func compileLogicalOpExprAux(context *funcContext, reg int, expr ast.Expr, ec *expcontext, thenlabel, elselabel int, hasnextcond bool, lb *lblabels) { // {{{ + // TODO folding constants? + code := context.Code + flip := 0 + jumplabel := elselabel + if hasnextcond { + flip = 1 + jumplabel = thenlabel + } + + switch ex := expr.(type) { + case *ast.FalseExpr: + if elselabel == lb.e { + code.AddASbx(OP_JMP, 0, lb.f, sline(expr)) + lb.b = true + } else { + code.AddASbx(OP_JMP, 0, elselabel, sline(expr)) + } + return + case *ast.NilExpr: + if elselabel == lb.e { + compileExpr(context, reg, expr, ec) + code.AddASbx(OP_JMP, 0, lb.e, sline(expr)) + } else { + code.AddASbx(OP_JMP, 0, elselabel, sline(expr)) + } + return + case *ast.TrueExpr: + if thenlabel == lb.e { + code.AddASbx(OP_JMP, 0, lb.t, sline(expr)) + lb.b = true + } else { + code.AddASbx(OP_JMP, 0, thenlabel, sline(expr)) + } + return + case *ast.NumberExpr, *ast.StringExpr: + if thenlabel == lb.e { + compileExpr(context, reg, expr, ec) + code.AddASbx(OP_JMP, 0, lb.e, sline(expr)) + } else { + code.AddASbx(OP_JMP, 0, thenlabel, sline(expr)) + } + return + case *ast.LogicalOpExpr: + switch ex.Operator { + case "and": + nextcondlabel := context.NewLabel() + compileLogicalOpExprAux(context, reg, ex.Lhs, ec, nextcondlabel, elselabel, false, lb) + context.SetLabelPc(nextcondlabel, context.Code.LastPC()) + compileLogicalOpExprAux(context, reg, ex.Rhs, ec, thenlabel, elselabel, hasnextcond, lb) + case "or": + nextcondlabel := context.NewLabel() + compileLogicalOpExprAux(context, reg, ex.Lhs, ec, thenlabel, nextcondlabel, true, lb) + context.SetLabelPc(nextcondlabel, context.Code.LastPC()) + compileLogicalOpExprAux(context, reg, ex.Rhs, ec, thenlabel, elselabel, hasnextcond, lb) + } + return + case *ast.RelationalOpExpr: + if thenlabel == elselabel { + flip ^= 1 + jumplabel = lb.t + lb.b = true + } else if thenlabel == lb.e { + jumplabel = lb.t + lb.b = true + } else if elselabel == lb.e { + jumplabel = lb.f + lb.b = true + } + compileRelationalOpExprAux(context, reg, ex, flip, jumplabel) + return + } + + if !hasnextcond && thenlabel == elselabel { + reg += compileExpr(context, reg, expr, ec) + } else { + a := reg + sreg := savereg(ec, a) + reg += compileExpr(context, reg, expr, ecnone(0)) + if sreg == a { + code.AddABC(OP_TEST, a, 0, 0^flip, sline(expr)) + } else { + code.AddABC(OP_TESTSET, sreg, a, 0^flip, sline(expr)) + } + } + code.AddASbx(OP_JMP, 0, jumplabel, sline(expr)) +} // }}} + +func compileFuncCallExpr(context *funcContext, reg int, expr *ast.FuncCallExpr, ec *expcontext) int { // {{{ + funcreg := reg + if ec.ctype == ecLocal && ec.reg == (int(context.Proto.NumParameters)-1) { + funcreg = ec.reg + reg = ec.reg + } + argc := len(expr.Args) + islastvararg := false + name := "(anonymous)" + + if expr.Func != nil { // hoge.func() + reg += compileExpr(context, reg, expr.Func, ecnone(0)) + name = getExprName(context, expr.Func) + } else { // hoge:method() + b := reg + compileExprWithMVPropagation(context, expr.Receiver, ®, &b) + c := loadRk(context, ®, expr, LString(expr.Method)) + context.Code.AddABC(OP_SELF, funcreg, b, c, sline(expr)) + // increments a register for an implicit "self" + reg = b + 1 + reg2 := funcreg + 2 + if reg2 > reg { + reg = reg2 + } + argc += 1 + name = string(expr.Method) + } + + for i, ar := range expr.Args { + islastvararg = (i == len(expr.Args)-1) && isVarArgReturnExpr(ar) + if islastvararg { + compileExpr(context, reg, ar, ecnone(-2)) + } else { + reg += compileExpr(context, reg, ar, ecnone(0)) + } + } + b := argc + 1 + if islastvararg { + b = 0 + } + context.Code.AddABC(OP_CALL, funcreg, b, ec.varargopt+2, sline(expr)) + context.Proto.DbgCalls = append(context.Proto.DbgCalls, DbgCall{Pc: context.Code.LastPC(), Name: name}) + + if ec.varargopt == 0 && ec.ctype == ecLocal && funcreg != ec.reg { + context.Code.AddABC(OP_MOVE, ec.reg, funcreg, 0, sline(expr)) + return 1 + } + if context.RegTop() > (funcreg+2+ec.varargopt) || ec.varargopt < -1 { + return 0 + } + return ec.varargopt + 1 +} // }}} + +func loadRk(context *funcContext, reg *int, expr ast.Expr, cnst LValue) int { // {{{ + cindex := context.ConstIndex(cnst) + if cindex <= opMaxIndexRk { + return opRkAsk(cindex) + } else { + ret := *reg + *reg++ + context.Code.AddABx(OP_LOADK, ret, cindex, sline(expr)) + return ret + } +} // }}} + +func getIdentRefType(context *funcContext, current *funcContext, expr *ast.IdentExpr) expContextType { // {{{ + if current == nil { + return ecGlobal + } else if current.FindLocalVar(expr.Value) > -1 { + if current == context { + return ecLocal + } + return ecUpvalue + } + return getIdentRefType(context, current.Parent, expr) +} // }}} + +func getExprName(context *funcContext, expr ast.Expr) string { // {{{ + switch ex := expr.(type) { + case *ast.IdentExpr: + return ex.Value + case *ast.AttrGetExpr: + switch kex := ex.Key.(type) { + case *ast.StringExpr: + return kex.Value + } + return "?" + } + return "?" +} // }}} + +func patchCode(context *funcContext) { // {{{ + maxreg := 1 + if np := int(context.Proto.NumParameters); np > 1 { + maxreg = np + } + moven := 0 + code := context.Code.List() + for pc := 0; pc < len(code); pc++ { + inst := code[pc] + curop := opGetOpCode(inst) + switch curop { + case OP_CLOSURE: + pc += int(context.Proto.FunctionPrototypes[opGetArgBx(inst)].NumUpvalues) + moven = 0 + continue + case OP_SETGLOBAL, OP_SETUPVAL, OP_EQ, OP_LT, OP_LE, OP_TEST, + OP_TAILCALL, OP_RETURN, OP_FORPREP, OP_FORLOOP, OP_TFORLOOP, + OP_SETLIST, OP_CLOSE: + /* nothing to do */ + case OP_CALL: + if reg := opGetArgA(inst) + opGetArgC(inst) - 2; reg > maxreg { + maxreg = reg + } + case OP_VARARG: + if reg := opGetArgA(inst) + opGetArgB(inst) - 1; reg > maxreg { + maxreg = reg + } + case OP_SELF: + if reg := opGetArgA(inst) + 1; reg > maxreg { + maxreg = reg + } + case OP_LOADNIL: + if reg := opGetArgB(inst); reg > maxreg { + maxreg = reg + } + case OP_JMP: // jump to jump optimization + distance := 0 + count := 0 // avoiding infinite loops + for jmp := inst; opGetOpCode(jmp) == OP_JMP && count < 5; jmp = context.Code.At(pc + distance + 1) { + d := context.GetLabelPc(opGetArgSbx(jmp)) - pc + if d > opMaxArgSbx { + if distance == 0 { + raiseCompileError(context, context.Proto.LineDefined, "too long to jump.") + } + break + } + distance = d + count++ + } + if distance == 0 { + context.Code.SetOpCode(pc, OP_NOP) + } else { + context.Code.SetSbx(pc, distance) + } + default: + if reg := opGetArgA(inst); reg > maxreg { + maxreg = reg + } + } + + // bulk move optimization(reducing op dipatch costs) + if curop == OP_MOVE { + moven++ + } else { + if moven > 1 { + context.Code.SetOpCode(pc-moven, OP_MOVEN) + context.Code.SetC(pc-moven, intMin(moven-1, opMaxArgsC)) + } + moven = 0 + } + } + maxreg++ + if maxreg > maxRegisters { + raiseCompileError(context, context.Proto.LineDefined, "register overflow(too many local variables)") + } + context.Proto.NumUsedRegisters = uint8(maxreg) +} // }}} + +func Compile(chunk []ast.Stmt, name string) (proto *FunctionProto, err error) { // {{{ + defer func() { + if rcv := recover(); rcv != nil { + if _, ok := rcv.(*CompileError); ok { + err = rcv.(error) + } else { + panic(rcv) + } + } + }() + err = nil + parlist := &ast.ParList{HasVargs: true, Names: []string{}} + funcexpr := &ast.FunctionExpr{ParList: parlist, Stmts: chunk} + context := newFuncContext(name, nil) + compileFunctionExpr(context, funcexpr, ecnone(0)) + proto = context.Proto + return +} // }}} diff --git a/vendor/github.com/yuin/gopher-lua/config.go b/vendor/github.com/yuin/gopher-lua/config.go new file mode 100644 index 0000000000000000000000000000000000000000..96c2ad3e1577f44b6dfcea305112a9c651069012 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/config.go @@ -0,0 +1,35 @@ +package lua + +import ( + "os" +) + +var CompatVarArg = true +var FieldsPerFlush = 50 +var RegistrySize = 256 * 20 +var CallStackSize = 256 +var MaxTableGetLoop = 100 +var MaxArrayIndex = 67108864 + +type LNumber float64 + +const LNumberBit = 64 +const LNumberScanFormat = "%f" +const LuaVersion = "Lua 5.1" + +var LuaPath = "LUA_PATH" +var LuaLDir string +var LuaPathDefault string +var LuaOS string + +func init() { + if os.PathSeparator == '/' { // unix-like + LuaOS = "unix" + LuaLDir = "/usr/local/share/lua/5.1" + LuaPathDefault = "./?.lua;" + LuaLDir + "/?.lua;" + LuaLDir + "/?/init.lua" + } else { // windows + LuaOS = "windows" + LuaLDir = "!\\lua" + LuaPathDefault = ".\\?.lua;" + LuaLDir + "\\?.lua;" + LuaLDir + "\\?\\init.lua" + } +} diff --git a/vendor/github.com/yuin/gopher-lua/coroutinelib.go b/vendor/github.com/yuin/gopher-lua/coroutinelib.go new file mode 100644 index 0000000000000000000000000000000000000000..d42c41a1dfc57f7d7050cb8fc546e8b926719d73 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/coroutinelib.go @@ -0,0 +1,112 @@ +package lua + +func OpenCoroutine(L *LState) int { + // TODO: Tie module name to contents of linit.go? + mod := L.RegisterModule(CoroutineLibName, coFuncs) + L.Push(mod) + return 1 +} + +var coFuncs = map[string]LGFunction{ + "create": coCreate, + "yield": coYield, + "resume": coResume, + "running": coRunning, + "status": coStatus, + "wrap": coWrap, +} + +func coCreate(L *LState) int { + fn := L.CheckFunction(1) + newthread, _ := L.NewThread() + base := 0 + newthread.stack.Push(callFrame{ + Fn: fn, + Pc: 0, + Base: base, + LocalBase: base + 1, + ReturnBase: base, + NArgs: 0, + NRet: MultRet, + Parent: nil, + TailCall: 0, + }) + L.Push(newthread) + return 1 +} + +func coYield(L *LState) int { + return -1 +} + +func coResume(L *LState) int { + th := L.CheckThread(1) + if L.G.CurrentThread == th { + msg := "can not resume a running thread" + if th.wrapped { + L.RaiseError(msg) + return 0 + } + L.Push(LFalse) + L.Push(LString(msg)) + return 2 + } + if th.Dead { + msg := "can not resume a dead thread" + if th.wrapped { + L.RaiseError(msg) + return 0 + } + L.Push(LFalse) + L.Push(LString(msg)) + return 2 + } + th.Parent = L + L.G.CurrentThread = th + if !th.isStarted() { + cf := th.stack.Last() + th.currentFrame = cf + th.SetTop(0) + nargs := L.GetTop() - 1 + L.XMoveTo(th, nargs) + cf.NArgs = nargs + th.initCallFrame(cf) + th.Panic = panicWithoutTraceback + } else { + nargs := L.GetTop() - 1 + L.XMoveTo(th, nargs) + } + top := L.GetTop() + threadRun(th) + return L.GetTop() - top +} + +func coRunning(L *LState) int { + if L.G.MainThread == L { + L.Push(LNil) + return 1 + } + L.Push(L.G.CurrentThread) + return 1 +} + +func coStatus(L *LState) int { + L.Push(LString(L.Status(L.CheckThread(1)))) + return 1 +} + +func wrapaux(L *LState) int { + L.Insert(L.ToThread(UpvalueIndex(1)), 1) + return coResume(L) +} + +func coWrap(L *LState) int { + coCreate(L) + L.CheckThread(L.GetTop()).wrapped = true + v := L.Get(L.GetTop()) + L.Pop(1) + L.Push(L.NewClosure(wrapaux, v)) + return 1 +} + +// diff --git a/vendor/github.com/yuin/gopher-lua/debuglib.go b/vendor/github.com/yuin/gopher-lua/debuglib.go new file mode 100644 index 0000000000000000000000000000000000000000..41f883f1d067c1992e52a8ceb37b9215e8f19643 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/debuglib.go @@ -0,0 +1,173 @@ +package lua + +import ( + "fmt" + "strings" +) + +func OpenDebug(L *LState) int { + dbgmod := L.RegisterModule(DebugLibName, debugFuncs) + L.Push(dbgmod) + return 1 +} + +var debugFuncs = map[string]LGFunction{ + "getfenv": debugGetFEnv, + "getinfo": debugGetInfo, + "getlocal": debugGetLocal, + "getmetatable": debugGetMetatable, + "getupvalue": debugGetUpvalue, + "setfenv": debugSetFEnv, + "setlocal": debugSetLocal, + "setmetatable": debugSetMetatable, + "setupvalue": debugSetUpvalue, + "traceback": debugTraceback, +} + +func debugGetFEnv(L *LState) int { + L.Push(L.GetFEnv(L.CheckAny(1))) + return 1 +} + +func debugGetInfo(L *LState) int { + L.CheckTypes(1, LTFunction, LTNumber) + arg1 := L.Get(1) + what := L.OptString(2, "Slunf") + var dbg *Debug + var fn LValue + var err error + var ok bool + switch lv := arg1.(type) { + case *LFunction: + dbg = &Debug{} + fn, err = L.GetInfo(">"+what, dbg, lv) + case LNumber: + dbg, ok = L.GetStack(int(lv)) + if !ok { + L.Push(LNil) + return 1 + } + fn, err = L.GetInfo(what, dbg, LNil) + } + + if err != nil { + L.Push(LNil) + return 1 + } + tbl := L.NewTable() + if len(dbg.Name) > 0 { + tbl.RawSetString("name", LString(dbg.Name)) + } else { + tbl.RawSetString("name", LNil) + } + tbl.RawSetString("what", LString(dbg.What)) + tbl.RawSetString("source", LString(dbg.Source)) + tbl.RawSetString("currentline", LNumber(dbg.CurrentLine)) + tbl.RawSetString("nups", LNumber(dbg.NUpvalues)) + tbl.RawSetString("linedefined", LNumber(dbg.LineDefined)) + tbl.RawSetString("lastlinedefined", LNumber(dbg.LastLineDefined)) + tbl.RawSetString("func", fn) + L.Push(tbl) + return 1 +} + +func debugGetLocal(L *LState) int { + level := L.CheckInt(1) + idx := L.CheckInt(2) + dbg, ok := L.GetStack(level) + if !ok { + L.ArgError(1, "level out of range") + } + name, value := L.GetLocal(dbg, idx) + if len(name) > 0 { + L.Push(LString(name)) + L.Push(value) + return 2 + } + L.Push(LNil) + return 1 +} + +func debugGetMetatable(L *LState) int { + L.Push(L.GetMetatable(L.CheckAny(1))) + return 1 +} + +func debugGetUpvalue(L *LState) int { + fn := L.CheckFunction(1) + idx := L.CheckInt(2) + name, value := L.GetUpvalue(fn, idx) + if len(name) > 0 { + L.Push(LString(name)) + L.Push(value) + return 2 + } + L.Push(LNil) + return 1 +} + +func debugSetFEnv(L *LState) int { + L.SetFEnv(L.CheckAny(1), L.CheckAny(2)) + return 0 +} + +func debugSetLocal(L *LState) int { + level := L.CheckInt(1) + idx := L.CheckInt(2) + value := L.CheckAny(3) + dbg, ok := L.GetStack(level) + if !ok { + L.ArgError(1, "level out of range") + } + name := L.SetLocal(dbg, idx, value) + if len(name) > 0 { + L.Push(LString(name)) + } else { + L.Push(LNil) + } + return 1 +} + +func debugSetMetatable(L *LState) int { + L.CheckTypes(2, LTNil, LTTable) + obj := L.Get(1) + mt := L.Get(2) + L.SetMetatable(obj, mt) + L.SetTop(1) + return 1 +} + +func debugSetUpvalue(L *LState) int { + fn := L.CheckFunction(1) + idx := L.CheckInt(2) + value := L.CheckAny(3) + name := L.SetUpvalue(fn, idx, value) + if len(name) > 0 { + L.Push(LString(name)) + } else { + L.Push(LNil) + } + return 1 +} + +func debugTraceback(L *LState) int { + msg := "" + level := L.OptInt(2, 1) + ls := L + if L.GetTop() > 0 { + if s, ok := L.Get(1).assertString(); ok { + msg = s + } + if l, ok := L.Get(1).(*LState); ok { + ls = l + msg = "" + } + } + + traceback := strings.TrimSpace(ls.stackTrace(level)) + if len(msg) > 0 { + traceback = fmt.Sprintf("%s\n%s", msg, traceback) + } + L.Push(LString(traceback)) + return 1 +} diff --git a/vendor/github.com/yuin/gopher-lua/function.go b/vendor/github.com/yuin/gopher-lua/function.go new file mode 100644 index 0000000000000000000000000000000000000000..169e5407cac47082db64a8e5cb9fca9b64f59dca --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/function.go @@ -0,0 +1,193 @@ +package lua + +import ( + "fmt" + "strings" +) + +const ( + VarArgHasArg uint8 = 1 + VarArgIsVarArg uint8 = 2 + VarArgNeedsArg uint8 = 4 +) + +type DbgLocalInfo struct { + Name string + StartPc int + EndPc int +} + +type DbgCall struct { + Name string + Pc int +} + +type FunctionProto struct { + SourceName string + LineDefined int + LastLineDefined int + NumUpvalues uint8 + NumParameters uint8 + IsVarArg uint8 + NumUsedRegisters uint8 + Code []uint32 + Constants []LValue + FunctionPrototypes []*FunctionProto + + DbgSourcePositions []int + DbgLocals []*DbgLocalInfo + DbgCalls []DbgCall + DbgUpvalues []string + + stringConstants []string +} + +/* Upvalue {{{ */ + +type Upvalue struct { + next *Upvalue + reg *registry + index int + value LValue + closed bool +} + +func (uv *Upvalue) Value() LValue { + //if uv.IsClosed() { + if uv.closed || uv.reg == nil { + return uv.value + } + //return uv.reg.Get(uv.index) + return uv.reg.array[uv.index] +} + +func (uv *Upvalue) SetValue(value LValue) { + if uv.IsClosed() { + uv.value = value + } else { + uv.reg.Set(uv.index, value) + } +} + +func (uv *Upvalue) Close() { + value := uv.Value() + uv.closed = true + uv.value = value +} + +func (uv *Upvalue) IsClosed() bool { + return uv.closed || uv.reg == nil +} + +func UpvalueIndex(i int) int { + return GlobalsIndex - i +} + +/* }}} */ + +/* FunctionProto {{{ */ + +func newFunctionProto(name string) *FunctionProto { + return &FunctionProto{ + SourceName: name, + LineDefined: 0, + LastLineDefined: 0, + NumUpvalues: 0, + NumParameters: 0, + IsVarArg: 0, + NumUsedRegisters: 2, + Code: make([]uint32, 0, 128), + Constants: make([]LValue, 0, 32), + FunctionPrototypes: make([]*FunctionProto, 0, 16), + + DbgSourcePositions: make([]int, 0, 128), + DbgLocals: make([]*DbgLocalInfo, 0, 16), + DbgCalls: make([]DbgCall, 0, 128), + DbgUpvalues: make([]string, 0, 16), + + stringConstants: make([]string, 0, 32), + } +} + +func (fp *FunctionProto) String() string { + return fp.str(1, 0) +} + +func (fp *FunctionProto) str(level int, count int) string { + indent := strings.Repeat(" ", level-1) + buf := []string{} + buf = append(buf, fmt.Sprintf("%v; function [%v] definition (level %v)\n", + indent, count, level)) + buf = append(buf, fmt.Sprintf("%v; %v upvalues, %v params, %v stacks\n", + indent, fp.NumUpvalues, fp.NumParameters, fp.NumUsedRegisters)) + for reg, linfo := range fp.DbgLocals { + buf = append(buf, fmt.Sprintf("%v.local %v ; %v\n", indent, linfo.Name, reg)) + } + for reg, upvalue := range fp.DbgUpvalues { + buf = append(buf, fmt.Sprintf("%v.upvalue %v ; %v\n", indent, upvalue, reg)) + } + for reg, conzt := range fp.Constants { + buf = append(buf, fmt.Sprintf("%v.const %v ; %v\n", indent, conzt.String(), reg)) + } + buf = append(buf, "\n") + + protono := 0 + for no, code := range fp.Code { + inst := opGetOpCode(code) + if inst == OP_CLOSURE { + buf = append(buf, "\n") + buf = append(buf, fp.FunctionPrototypes[protono].str(level+1, protono)) + buf = append(buf, "\n") + protono++ + } + buf = append(buf, fmt.Sprintf("%v[%03d] %v (line:%v)\n", + indent, no+1, opToString(code), fp.DbgSourcePositions[no])) + + } + buf = append(buf, fmt.Sprintf("%v; end of function\n", indent)) + return strings.Join(buf, "") +} + +/* }}} */ + +/* LFunction {{{ */ + +func newLFunctionL(proto *FunctionProto, env *LTable, nupvalue int) *LFunction { + return &LFunction{ + IsG: false, + Env: env, + + Proto: proto, + GFunction: nil, + Upvalues: make([]*Upvalue, nupvalue), + } +} + +func newLFunctionG(gfunc LGFunction, env *LTable, nupvalue int) *LFunction { + return &LFunction{ + IsG: true, + Env: env, + + Proto: nil, + GFunction: gfunc, + Upvalues: make([]*Upvalue, nupvalue), + } +} + +func (fn *LFunction) LocalName(regno, pc int) (string, bool) { + if fn.IsG { + return "", false + } + p := fn.Proto + for i := 0; i < len(p.DbgLocals) && p.DbgLocals[i].StartPc < pc; i++ { + if pc < p.DbgLocals[i].EndPc { + regno-- + if regno == 0 { + return p.DbgLocals[i].Name, true + } + } + } + return "", false +} + +/* }}} */ diff --git a/vendor/github.com/yuin/gopher-lua/iolib.go b/vendor/github.com/yuin/gopher-lua/iolib.go new file mode 100644 index 0000000000000000000000000000000000000000..b0c2f569b2905389a562d8f791e4490f8c066879 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/iolib.go @@ -0,0 +1,743 @@ +package lua + +import ( + "bufio" + "errors" + "fmt" + "io" + "io/ioutil" + "os" + "os/exec" + "syscall" +) + +var ioFuncs = map[string]LGFunction{ + "close": ioClose, + "flush": ioFlush, + "lines": ioLines, + "input": ioInput, + "output": ioOutput, + "open": ioOpenFile, + "popen": ioPopen, + "read": ioRead, + "type": ioType, + "tmpfile": ioTmpFile, + "write": ioWrite, +} + +const lFileClass = "FILE*" + +type lFile struct { + fp *os.File + pp *exec.Cmd + writer io.Writer + reader *bufio.Reader + closed bool +} + +type lFileType int + +const ( + lFileFile lFileType = iota + lFileProcess +) + +const fileDefOutIndex = 1 +const fileDefInIndex = 2 +const fileDefaultWriteBuffer = 4096 +const fileDefaultReadBuffer = 4096 + +func checkFile(L *LState) *lFile { + ud := L.CheckUserData(1) + if file, ok := ud.Value.(*lFile); ok { + return file + } + L.ArgError(1, "file expected") + return nil +} + +func errorIfFileIsClosed(L *LState, file *lFile) { + if file.closed { + L.ArgError(1, "file is closed") + } +} + +func newFile(L *LState, file *os.File, path string, flag int, perm os.FileMode, writable, readable bool) (*LUserData, error) { + ud := L.NewUserData() + var err error + if file == nil { + file, err = os.OpenFile(path, flag, perm) + if err != nil { + return nil, err + } + } + lfile := &lFile{fp: file, pp: nil, writer: nil, reader: nil, closed: false} + ud.Value = lfile + if writable { + lfile.writer = file + } + if readable { + lfile.reader = bufio.NewReaderSize(file, fileDefaultReadBuffer) + } + L.SetMetatable(ud, L.GetTypeMetatable(lFileClass)) + return ud, nil +} + +func newProcess(L *LState, cmd string, writable, readable bool) (*LUserData, error) { + ud := L.NewUserData() + c, args := popenArgs(cmd) + pp := exec.Command(c, args...) + lfile := &lFile{fp: nil, pp: pp, writer: nil, reader: nil, closed: false} + ud.Value = lfile + + var err error + if writable { + lfile.writer, err = pp.StdinPipe() + } + if readable { + var reader io.Reader + reader, err = pp.StdoutPipe() + lfile.reader = bufio.NewReaderSize(reader, fileDefaultReadBuffer) + } + if err != nil { + return nil, err + } + err = pp.Start() + if err != nil { + return nil, err + } + + L.SetMetatable(ud, L.GetTypeMetatable(lFileClass)) + return ud, nil +} + +func (file *lFile) Type() lFileType { + if file.fp == nil { + return lFileProcess + } + return lFileFile +} + +func (file *lFile) Name() string { + switch file.Type() { + case lFileFile: + return fmt.Sprintf("file %s", file.fp.Name()) + case lFileProcess: + return fmt.Sprintf("process %s", file.pp.Path) + } + return "" +} + +func (file *lFile) AbandonReadBuffer() error { + if file.Type() == lFileFile && file.reader != nil { + _, err := file.fp.Seek(-int64(file.reader.Buffered()), 1) + if err != nil { + return err + } + file.reader = bufio.NewReaderSize(file.fp, fileDefaultReadBuffer) + } + return nil +} + +func fileDefOut(L *LState) *LUserData { + return L.Get(UpvalueIndex(1)).(*LTable).RawGetInt(fileDefOutIndex).(*LUserData) +} + +func fileDefIn(L *LState) *LUserData { + return L.Get(UpvalueIndex(1)).(*LTable).RawGetInt(fileDefInIndex).(*LUserData) +} + +func fileIsWritable(L *LState, file *lFile) int { + if file.writer == nil { + L.Push(LNil) + L.Push(LString(fmt.Sprintf("%s is opened for only reading.", file.Name()))) + L.Push(LNumber(1)) // C-Lua compatibility: Original Lua pushes errno to the stack + return 3 + } + return 0 +} + +func fileIsReadable(L *LState, file *lFile) int { + if file.reader == nil { + L.Push(LNil) + L.Push(LString(fmt.Sprintf("%s is opened for only writing.", file.Name()))) + L.Push(LNumber(1)) // C-Lua compatibility: Original Lua pushes errno to the stack + return 3 + } + return 0 +} + +var stdFiles = []struct { + name string + file *os.File + writable bool + readable bool +}{ + {"stdout", os.Stdout, true, false}, + {"stdin", os.Stdin, false, true}, + {"stderr", os.Stderr, true, false}, +} + +func OpenIo(L *LState) int { + mod := L.RegisterModule(IoLibName, map[string]LGFunction{}).(*LTable) + mt := L.NewTypeMetatable(lFileClass) + mt.RawSetString("__index", mt) + L.SetFuncs(mt, fileMethods) + mt.RawSetString("lines", L.NewClosure(fileLines, L.NewFunction(fileLinesIter))) + + for _, finfo := range stdFiles { + file, _ := newFile(L, finfo.file, "", 0, os.FileMode(0), finfo.writable, finfo.readable) + mod.RawSetString(finfo.name, file) + } + uv := L.CreateTable(2, 0) + uv.RawSetInt(fileDefOutIndex, mod.RawGetString("stdout")) + uv.RawSetInt(fileDefInIndex, mod.RawGetString("stdin")) + for name, fn := range ioFuncs { + mod.RawSetString(name, L.NewClosure(fn, uv)) + } + mod.RawSetString("lines", L.NewClosure(ioLines, uv, L.NewClosure(ioLinesIter, uv))) + // Modifications are being made in-place rather than returned? + L.Push(mod) + return 1 +} + +var fileMethods = map[string]LGFunction{ + "__tostring": fileToString, + "write": fileWrite, + "close": fileClose, + "flush": fileFlush, + "lines": fileLines, + "read": fileRead, + "seek": fileSeek, + "setvbuf": fileSetVBuf, +} + +func fileToString(L *LState) int { + file := checkFile(L) + if file.Type() == lFileFile { + if file.closed { + L.Push(LString("file (closed)")) + } else { + L.Push(LString("file")) + } + } else { + if file.closed { + L.Push(LString("process (closed)")) + } else { + L.Push(LString("process")) + } + } + return 1 +} + +func fileWriteAux(L *LState, file *lFile, idx int) int { + if n := fileIsWritable(L, file); n != 0 { + return n + } + errorIfFileIsClosed(L, file) + top := L.GetTop() + out := file.writer + var err error + for i := idx; i <= top; i++ { + L.CheckTypes(i, LTNumber, LTString) + s := LVAsString(L.Get(i)) + if _, err = out.Write(unsafeFastStringToReadOnlyBytes(s)); err != nil { + goto errreturn + } + } + + file.AbandonReadBuffer() + L.Push(LTrue) + return 1 +errreturn: + + file.AbandonReadBuffer() + L.Push(LNil) + L.Push(LString(err.Error())) + L.Push(LNumber(1)) // C-Lua compatibility: Original Lua pushes errno to the stack + return 3 +} + +func fileCloseAux(L *LState, file *lFile) int { + file.closed = true + var err error + if file.writer != nil { + if bwriter, ok := file.writer.(*bufio.Writer); ok { + if err = bwriter.Flush(); err != nil { + goto errreturn + } + } + } + file.AbandonReadBuffer() + + switch file.Type() { + case lFileFile: + if err = file.fp.Close(); err != nil { + goto errreturn + } + L.Push(LTrue) + return 1 + case lFileProcess: + err = file.pp.Wait() + var exitStatus int // Initialised to zero value = 0 + if err != nil { + if e2, ok := err.(*exec.ExitError); ok { + if s, ok := e2.Sys().(syscall.WaitStatus); ok { + exitStatus = s.ExitStatus() + } else { + err = errors.New("Unimplemented for system where exec.ExitError.Sys() is not syscall.WaitStatus.") + } + } + } else { + exitStatus = 0 + } + L.Push(LNumber(exitStatus)) + return 1 + } + +errreturn: + L.RaiseError(err.Error()) + return 0 +} + +func fileFlushAux(L *LState, file *lFile) int { + if n := fileIsWritable(L, file); n != 0 { + return n + } + errorIfFileIsClosed(L, file) + + if bwriter, ok := file.writer.(*bufio.Writer); ok { + if err := bwriter.Flush(); err != nil { + L.Push(LNil) + L.Push(LString(err.Error())) + return 2 + } + } + L.Push(LTrue) + return 1 +} + +func fileReadAux(L *LState, file *lFile, idx int) int { + if n := fileIsReadable(L, file); n != 0 { + return n + } + errorIfFileIsClosed(L, file) + if L.GetTop() == idx-1 { + L.Push(LString("*l")) + } + var err error + top := L.GetTop() + for i := idx; i <= top; i++ { + switch lv := L.Get(i).(type) { + case LNumber: + size := int64(lv) + if size == 0 { + _, err = file.reader.ReadByte() + if err == io.EOF { + L.Push(LNil) + goto normalreturn + } + file.reader.UnreadByte() + } + var buf []byte + var iseof bool + buf, err, iseof = readBufioSize(file.reader, size) + if iseof { + L.Push(LNil) + goto normalreturn + } + if err != nil { + goto errreturn + } + L.Push(LString(string(buf))) + case LString: + options := L.CheckString(i) + if len(options) > 0 && options[0] != '*' { + L.ArgError(2, "invalid options:"+options) + } + for _, opt := range options[1:] { + switch opt { + case 'n': + var v LNumber + _, err = fmt.Fscanf(file.reader, LNumberScanFormat, &v) + if err == io.EOF { + L.Push(LNil) + goto normalreturn + } + if err != nil { + goto errreturn + } + L.Push(v) + case 'a': + var buf []byte + buf, err = ioutil.ReadAll(file.reader) + if err == io.EOF { + L.Push(emptyLString) + goto normalreturn + } + if err != nil { + goto errreturn + } + L.Push(LString(string(buf))) + case 'l': + var buf []byte + var iseof bool + buf, err, iseof = readBufioLine(file.reader) + if iseof { + L.Push(LNil) + goto normalreturn + } + if err != nil { + goto errreturn + } + L.Push(LString(string(buf))) + default: + L.ArgError(2, "invalid options:"+string(opt)) + } + } + } + } +normalreturn: + return L.GetTop() - top + +errreturn: + L.RaiseError(err.Error()) + //L.Push(LNil) + //L.Push(LString(err.Error())) + return 2 +} + +var fileSeekOptions = []string{"set", "cur", "end"} + +func fileSeek(L *LState) int { + file := checkFile(L) + if file.Type() != lFileFile { + L.Push(LNil) + L.Push(LString("can not seek a process.")) + return 2 + } + + top := L.GetTop() + if top == 1 { + L.Push(LString("cur")) + L.Push(LNumber(0)) + } else if top == 2 { + L.Push(LNumber(0)) + } + + var pos int64 + var err error + + err = file.AbandonReadBuffer() + if err != nil { + goto errreturn + } + + pos, err = file.fp.Seek(L.CheckInt64(3), L.CheckOption(2, fileSeekOptions)) + if err != nil { + goto errreturn + } + + L.Push(LNumber(pos)) + return 1 + +errreturn: + L.Push(LNil) + L.Push(LString(err.Error())) + return 2 +} + +func fileWrite(L *LState) int { + return fileWriteAux(L, checkFile(L), 2) +} + +func fileClose(L *LState) int { + return fileCloseAux(L, checkFile(L)) +} + +func fileFlush(L *LState) int { + return fileFlushAux(L, checkFile(L)) +} + +func fileLinesIter(L *LState) int { + var file *lFile + if ud, ok := L.Get(1).(*LUserData); ok { + file = ud.Value.(*lFile) + } else { + file = L.Get(UpvalueIndex(2)).(*LUserData).Value.(*lFile) + } + buf, _, err := file.reader.ReadLine() + if err != nil { + if err == io.EOF { + L.Push(LNil) + return 1 + } + L.RaiseError(err.Error()) + } + L.Push(LString(string(buf))) + return 1 +} + +func fileLines(L *LState) int { + file := checkFile(L) + ud := L.CheckUserData(1) + if n := fileIsReadable(L, file); n != 0 { + return 0 + } + L.Push(L.NewClosure(fileLinesIter, L.Get(UpvalueIndex(1)), ud)) + return 1 +} + +func fileRead(L *LState) int { + return fileReadAux(L, checkFile(L), 2) +} + +var filebufOptions = []string{"no", "full"} + +func fileSetVBuf(L *LState) int { + var err error + var writer io.Writer + file := checkFile(L) + if n := fileIsWritable(L, file); n != 0 { + return n + } + switch filebufOptions[L.CheckOption(2, filebufOptions)] { + case "no": + switch file.Type() { + case lFileFile: + file.writer = file.fp + case lFileProcess: + file.writer, err = file.pp.StdinPipe() + if err != nil { + goto errreturn + } + } + case "full", "line": // TODO line buffer not supported + bufsize := L.OptInt(3, fileDefaultWriteBuffer) + switch file.Type() { + case lFileFile: + file.writer = bufio.NewWriterSize(file.fp, bufsize) + case lFileProcess: + writer, err = file.pp.StdinPipe() + if err != nil { + goto errreturn + } + file.writer = bufio.NewWriterSize(writer, bufsize) + } + } + L.Push(LTrue) + return 1 +errreturn: + L.Push(LNil) + L.Push(LString(err.Error())) + return 2 +} + +func ioInput(L *LState) int { + if L.GetTop() == 0 { + L.Push(fileDefIn(L)) + return 1 + } + switch lv := L.Get(1).(type) { + case LString: + file, err := newFile(L, nil, string(lv), os.O_RDONLY, 0600, false, true) + if err != nil { + L.RaiseError(err.Error()) + } + L.Get(UpvalueIndex(1)).(*LTable).RawSetInt(fileDefInIndex, file) + L.Push(file) + return 1 + case *LUserData: + if _, ok := lv.Value.(*lFile); ok { + L.Get(UpvalueIndex(1)).(*LTable).RawSetInt(fileDefInIndex, lv) + L.Push(lv) + return 1 + } + + } + L.ArgError(1, "string or file expedted, but got "+L.Get(1).Type().String()) + return 0 +} + +func ioClose(L *LState) int { + if L.GetTop() == 0 { + return fileCloseAux(L, fileDefOut(L).Value.(*lFile)) + } + return fileClose(L) +} + +func ioFlush(L *LState) int { + return fileFlushAux(L, fileDefOut(L).Value.(*lFile)) +} + +func ioLinesIter(L *LState) int { + var file *lFile + toclose := false + if ud, ok := L.Get(1).(*LUserData); ok { + file = ud.Value.(*lFile) + } else { + file = L.Get(UpvalueIndex(2)).(*LUserData).Value.(*lFile) + toclose = true + } + buf, _, err := file.reader.ReadLine() + if err != nil { + if err == io.EOF { + if toclose { + fileCloseAux(L, file) + } + L.Push(LNil) + return 1 + } + L.RaiseError(err.Error()) + } + L.Push(LString(string(buf))) + return 1 +} + +func ioLines(L *LState) int { + if L.GetTop() == 0 { + L.Push(L.Get(UpvalueIndex(2))) + L.Push(fileDefIn(L)) + return 2 + } + + path := L.CheckString(1) + ud, err := newFile(L, nil, path, os.O_RDONLY, os.FileMode(0600), false, true) + if err != nil { + return 0 + } + L.Push(L.NewClosure(ioLinesIter, L.Get(UpvalueIndex(1)), ud)) + return 1 +} + +var ioOpenOpions = []string{"r", "rb", "w", "wb", "a", "ab", "r+", "rb+", "w+", "wb+", "a+", "ab+"} + +func ioOpenFile(L *LState) int { + path := L.CheckString(1) + if L.GetTop() == 1 { + L.Push(LString("r")) + } + mode := os.O_RDONLY + perm := 0600 + writable := true + readable := true + switch ioOpenOpions[L.CheckOption(2, ioOpenOpions)] { + case "r", "rb": + mode = os.O_RDONLY + writable = false + case "w", "wb": + mode = os.O_WRONLY | os.O_CREATE + readable = false + case "a", "ab": + mode = os.O_WRONLY | os.O_APPEND | os.O_CREATE + case "r+", "rb+": + mode = os.O_RDWR + case "w+", "wb+": + mode = os.O_RDWR | os.O_TRUNC | os.O_CREATE + case "a+", "ab+": + mode = os.O_APPEND | os.O_RDWR | os.O_CREATE + } + file, err := newFile(L, nil, path, mode, os.FileMode(perm), writable, readable) + if err != nil { + L.Push(LNil) + L.Push(LString(err.Error())) + L.Push(LNumber(1)) // C-Lua compatibility: Original Lua pushes errno to the stack + return 3 + } + L.Push(file) + return 1 + +} + +var ioPopenOptions = []string{"r", "w"} + +func ioPopen(L *LState) int { + cmd := L.CheckString(1) + if L.GetTop() == 1 { + L.Push(LString("r")) + } + var file *LUserData + var err error + + switch ioPopenOptions[L.CheckOption(2, ioPopenOptions)] { + case "r": + file, err = newProcess(L, cmd, false, true) + case "w": + file, err = newProcess(L, cmd, true, false) + } + if err != nil { + L.Push(LNil) + L.Push(LString(err.Error())) + return 2 + } + L.Push(file) + return 1 +} + +func ioRead(L *LState) int { + return fileReadAux(L, fileDefIn(L).Value.(*lFile), 1) +} + +func ioType(L *LState) int { + ud, udok := L.Get(1).(*LUserData) + if !udok { + L.Push(LNil) + return 1 + } + file, ok := ud.Value.(*lFile) + if !ok { + L.Push(LNil) + return 1 + } + if file.closed { + L.Push(LString("closed file")) + return 1 + } + L.Push(LString("file")) + return 1 +} + +func ioTmpFile(L *LState) int { + file, err := ioutil.TempFile("", "") + if err != nil { + L.Push(LNil) + L.Push(LString(err.Error())) + return 2 + } + L.G.tempFiles = append(L.G.tempFiles, file) + ud, _ := newFile(L, file, "", 0, os.FileMode(0), true, true) + L.Push(ud) + return 1 +} + +func ioOutput(L *LState) int { + if L.GetTop() == 0 { + L.Push(fileDefOut(L)) + return 1 + } + switch lv := L.Get(1).(type) { + case LString: + file, err := newFile(L, nil, string(lv), os.O_WRONLY|os.O_CREATE, 0600, true, false) + if err != nil { + L.RaiseError(err.Error()) + } + L.Get(UpvalueIndex(1)).(*LTable).RawSetInt(fileDefOutIndex, file) + L.Push(file) + return 1 + case *LUserData: + if _, ok := lv.Value.(*lFile); ok { + L.Get(UpvalueIndex(1)).(*LTable).RawSetInt(fileDefOutIndex, lv) + L.Push(lv) + return 1 + } + + } + L.ArgError(1, "string or file expedted, but got "+L.Get(1).Type().String()) + return 0 +} + +func ioWrite(L *LState) int { + return fileWriteAux(L, fileDefOut(L).Value.(*lFile), 1) +} + +// diff --git a/vendor/github.com/yuin/gopher-lua/linit.go b/vendor/github.com/yuin/gopher-lua/linit.go new file mode 100644 index 0000000000000000000000000000000000000000..cd96d660151e4019b5be759eb30edebeeb20701e --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/linit.go @@ -0,0 +1,54 @@ +package lua + +const ( + // BaseLibName is here for consistency; the base functions have no namespace/library. + BaseLibName = "" + // LoadLibName is here for consistency; the loading system has no namespace/library. + LoadLibName = "package" + // TabLibName is the name of the table Library. + TabLibName = "table" + // IoLibName is the name of the io Library. + IoLibName = "io" + // OsLibName is the name of the os Library. + OsLibName = "os" + // StringLibName is the name of the string Library. + StringLibName = "string" + // MathLibName is the name of the math Library. + MathLibName = "math" + // DebugLibName is the name of the debug Library. + DebugLibName = "debug" + // ChannelLibName is the name of the channel Library. + ChannelLibName = "channel" + // CoroutineLibName is the name of the coroutine Library. + CoroutineLibName = "coroutine" +) + +type luaLib struct { + libName string + libFunc LGFunction +} + +var luaLibs = []luaLib{ + luaLib{LoadLibName, OpenPackage}, + luaLib{BaseLibName, OpenBase}, + luaLib{TabLibName, OpenTable}, + luaLib{IoLibName, OpenIo}, + luaLib{OsLibName, OpenOs}, + luaLib{StringLibName, OpenString}, + luaLib{MathLibName, OpenMath}, + luaLib{DebugLibName, OpenDebug}, + luaLib{ChannelLibName, OpenChannel}, + luaLib{CoroutineLibName, OpenCoroutine}, +} + +// OpenLibs loads the built-in libraries. It is equivalent to running OpenLoad, +// then OpenBase, then iterating over the other OpenXXX functions in any order. +func (ls *LState) OpenLibs() { + // NB: Map iteration order in Go is deliberately randomised, so must open Load/Base + // prior to iterating. + for _, lib := range luaLibs { + ls.Push(ls.NewFunction(lib.libFunc)) + ls.Push(LString(lib.libName)) + ls.Call(1, 0) + } +} diff --git a/vendor/github.com/yuin/gopher-lua/loadlib.go b/vendor/github.com/yuin/gopher-lua/loadlib.go new file mode 100644 index 0000000000000000000000000000000000000000..772bb04ad8800fcc098246e8cce11b7c41e66c4b --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/loadlib.go @@ -0,0 +1,125 @@ +package lua + +import ( + "fmt" + "os" + "path/filepath" + "strings" +) + +/* load lib {{{ */ + +var loLoaders = []LGFunction{loLoaderPreload, loLoaderLua} + +func loGetPath(env string, defpath string) string { + path := os.Getenv(env) + if len(path) == 0 { + path = defpath + } + path = strings.Replace(path, ";;", ";"+defpath+";", -1) + if os.PathSeparator != '/' { + dir, err := filepath.Abs(filepath.Dir(os.Args[0])) + if err != nil { + panic(err) + } + path = strings.Replace(path, "!", dir, -1) + } + return path +} + +func loFindFile(L *LState, name, pname string) (string, string) { + name = strings.Replace(name, ".", string(os.PathSeparator), -1) + lv := L.GetField(L.GetField(L.Get(EnvironIndex), "package"), pname) + path, ok := lv.(LString) + if !ok { + L.RaiseError("package.%s must be a string", pname) + } + messages := []string{} + for _, pattern := range strings.Split(string(path), ";") { + luapath := strings.Replace(pattern, "?", name, -1) + if _, err := os.Stat(luapath); err == nil { + return luapath, "" + } else { + messages = append(messages, err.Error()) + } + } + return "", strings.Join(messages, "\n\t") +} + +func OpenPackage(L *LState) int { + packagemod := L.RegisterModule(LoadLibName, loFuncs) + + L.SetField(packagemod, "preload", L.NewTable()) + + loaders := L.CreateTable(len(loLoaders), 0) + for i, loader := range loLoaders { + L.RawSetInt(loaders, i+1, L.NewFunction(loader)) + } + L.SetField(packagemod, "loaders", loaders) + L.SetField(L.Get(RegistryIndex), "_LOADERS", loaders) + + loaded := L.NewTable() + L.SetField(packagemod, "loaded", loaded) + L.SetField(L.Get(RegistryIndex), "_LOADED", loaded) + + L.SetField(packagemod, "path", LString(loGetPath(LuaPath, LuaPathDefault))) + L.SetField(packagemod, "cpath", emptyLString) + + L.Push(packagemod) + return 1 +} + +var loFuncs = map[string]LGFunction{ + "loadlib": loLoadLib, + "seeall": loSeeAll, +} + +func loLoaderPreload(L *LState) int { + name := L.CheckString(1) + preload := L.GetField(L.GetField(L.Get(EnvironIndex), "package"), "preload") + if _, ok := preload.(*LTable); !ok { + L.RaiseError("package.preload must be a table") + } + lv := L.GetField(preload, name) + if lv == LNil { + L.Push(LString(fmt.Sprintf("no field package.preload['%s']", name))) + return 1 + } + L.Push(lv) + return 1 +} + +func loLoaderLua(L *LState) int { + name := L.CheckString(1) + path, msg := loFindFile(L, name, "path") + if len(path) == 0 { + L.Push(LString(msg)) + return 1 + } + fn, err1 := L.LoadFile(path) + if err1 != nil { + L.RaiseError(err1.Error()) + } + L.Push(fn) + return 1 +} + +func loLoadLib(L *LState) int { + L.RaiseError("loadlib is not supported") + return 0 +} + +func loSeeAll(L *LState) int { + mod := L.CheckTable(1) + mt := L.GetMetatable(mod) + if mt == LNil { + mt = L.CreateTable(0, 1) + L.SetMetatable(mod, mt) + } + L.SetField(mt, "__index", L.Get(GlobalsIndex)) + return 0 +} + +/* }}} */ + +// diff --git a/vendor/github.com/yuin/gopher-lua/mathlib.go b/vendor/github.com/yuin/gopher-lua/mathlib.go new file mode 100644 index 0000000000000000000000000000000000000000..0771a48f5a7d74cd9893eae9c2f05d1a58b27b20 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/mathlib.go @@ -0,0 +1,231 @@ +package lua + +import ( + "math" + "math/rand" +) + +func OpenMath(L *LState) int { + mod := L.RegisterModule(MathLibName, mathFuncs).(*LTable) + mod.RawSetString("pi", LNumber(math.Pi)) + mod.RawSetString("huge", LNumber(math.MaxFloat64)) + L.Push(mod) + return 1 +} + +var mathFuncs = map[string]LGFunction{ + "abs": mathAbs, + "acos": mathAcos, + "asin": mathAsin, + "atan": mathAtan, + "atan2": mathAtan2, + "ceil": mathCeil, + "cos": mathCos, + "cosh": mathCosh, + "deg": mathDeg, + "exp": mathExp, + "floor": mathFloor, + "fmod": mathFmod, + "frexp": mathFrexp, + "ldexp": mathLdexp, + "log": mathLog, + "log10": mathLog10, + "max": mathMax, + "min": mathMin, + "mod": mathMod, + "modf": mathModf, + "pow": mathPow, + "rad": mathRad, + "random": mathRandom, + "randomseed": mathRandomseed, + "sin": mathSin, + "sinh": mathSinh, + "sqrt": mathSqrt, + "tan": mathTan, + "tanh": mathTanh, +} + +func mathAbs(L *LState) int { + L.Push(LNumber(math.Abs(float64(L.CheckNumber(1))))) + return 1 +} + +func mathAcos(L *LState) int { + L.Push(LNumber(math.Acos(float64(L.CheckNumber(1))))) + return 1 +} + +func mathAsin(L *LState) int { + L.Push(LNumber(math.Asin(float64(L.CheckNumber(1))))) + return 1 +} + +func mathAtan(L *LState) int { + L.Push(LNumber(math.Atan(float64(L.CheckNumber(1))))) + return 1 +} + +func mathAtan2(L *LState) int { + L.Push(LNumber(math.Atan2(float64(L.CheckNumber(1)), float64(L.CheckNumber(2))))) + return 1 +} + +func mathCeil(L *LState) int { + L.Push(LNumber(math.Ceil(float64(L.CheckNumber(1))))) + return 1 +} + +func mathCos(L *LState) int { + L.Push(LNumber(math.Cos(float64(L.CheckNumber(1))))) + return 1 +} + +func mathCosh(L *LState) int { + L.Push(LNumber(math.Cosh(float64(L.CheckNumber(1))))) + return 1 +} + +func mathDeg(L *LState) int { + L.Push(LNumber(float64(L.CheckNumber(1)) * 180 / math.Pi)) + return 1 +} + +func mathExp(L *LState) int { + L.Push(LNumber(math.Exp(float64(L.CheckNumber(1))))) + return 1 +} + +func mathFloor(L *LState) int { + L.Push(LNumber(math.Floor(float64(L.CheckNumber(1))))) + return 1 +} + +func mathFmod(L *LState) int { + L.Push(LNumber(math.Mod(float64(L.CheckNumber(1)), float64(L.CheckNumber(2))))) + return 1 +} + +func mathFrexp(L *LState) int { + v1, v2 := math.Frexp(float64(L.CheckNumber(1))) + L.Push(LNumber(v1)) + L.Push(LNumber(v2)) + return 2 +} + +func mathLdexp(L *LState) int { + L.Push(LNumber(math.Ldexp(float64(L.CheckNumber(1)), L.CheckInt(2)))) + return 1 +} + +func mathLog(L *LState) int { + L.Push(LNumber(math.Log(float64(L.CheckNumber(1))))) + return 1 +} + +func mathLog10(L *LState) int { + L.Push(LNumber(math.Log10(float64(L.CheckNumber(1))))) + return 1 +} + +func mathMax(L *LState) int { + if L.GetTop() == 0 { + L.RaiseError("wrong number of arguments") + } + max := L.CheckNumber(1) + top := L.GetTop() + for i := 2; i <= top; i++ { + v := L.CheckNumber(i) + if v > max { + max = v + } + } + L.Push(max) + return 1 +} + +func mathMin(L *LState) int { + if L.GetTop() == 0 { + L.RaiseError("wrong number of arguments") + } + min := L.CheckNumber(1) + top := L.GetTop() + for i := 2; i <= top; i++ { + v := L.CheckNumber(i) + if v < min { + min = v + } + } + L.Push(min) + return 1 +} + +func mathMod(L *LState) int { + lhs := L.CheckNumber(1) + rhs := L.CheckNumber(2) + L.Push(luaModulo(lhs, rhs)) + return 1 +} + +func mathModf(L *LState) int { + v1, v2 := math.Modf(float64(L.CheckNumber(1))) + L.Push(LNumber(v1)) + L.Push(LNumber(v2)) + return 2 +} + +func mathPow(L *LState) int { + L.Push(LNumber(math.Pow(float64(L.CheckNumber(1)), float64(L.CheckNumber(2))))) + return 1 +} + +func mathRad(L *LState) int { + L.Push(LNumber(float64(L.CheckNumber(1)) * math.Pi / 180)) + return 1 +} + +func mathRandom(L *LState) int { + switch L.GetTop() { + case 0: + L.Push(LNumber(rand.Float64())) + case 1: + n := L.CheckInt(1) + L.Push(LNumber(rand.Intn(n-1) + 1)) + default: + min := L.CheckInt(1) + max := L.CheckInt(2) + 1 + L.Push(LNumber(rand.Intn(max-min) + min)) + } + return 1 +} + +func mathRandomseed(L *LState) int { + rand.Seed(L.CheckInt64(1)) + return 0 +} + +func mathSin(L *LState) int { + L.Push(LNumber(math.Sin(float64(L.CheckNumber(1))))) + return 1 +} + +func mathSinh(L *LState) int { + L.Push(LNumber(math.Sinh(float64(L.CheckNumber(1))))) + return 1 +} + +func mathSqrt(L *LState) int { + L.Push(LNumber(math.Sqrt(float64(L.CheckNumber(1))))) + return 1 +} + +func mathTan(L *LState) int { + L.Push(LNumber(math.Tan(float64(L.CheckNumber(1))))) + return 1 +} + +func mathTanh(L *LState) int { + L.Push(LNumber(math.Tanh(float64(L.CheckNumber(1))))) + return 1 +} + +// diff --git a/vendor/github.com/yuin/gopher-lua/opcode.go b/vendor/github.com/yuin/gopher-lua/opcode.go new file mode 100644 index 0000000000000000000000000000000000000000..91fff1c9b4157c9d77ee47fef66d3cd7319a6a9b --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/opcode.go @@ -0,0 +1,371 @@ +package lua + +import ( + "fmt" +) + +/* + gopherlua uses Lua 5.1.4's opcodes. + Lua 5.1.4 opcodes layout: + + instruction = 32bit(fixed length) + + +---------------------------------------------+ + |0-5(6bits)|6-13(8bit)|14-22(9bit)|23-31(9bit)| + |==========+==========+===========+===========| + | opcode | A | C | B | + |----------+----------+-----------+-----------| + | opcode | A | Bx(unsigned) | + |----------+----------+-----------+-----------| + | opcode | A | sBx(signed) | + +---------------------------------------------+ +*/ + +const opInvalidInstruction = ^uint32(0) + +const opSizeCode = 6 +const opSizeA = 8 +const opSizeB = 9 +const opSizeC = 9 +const opSizeBx = 18 +const opSizesBx = 18 + +const opMaxArgsA = (1 << opSizeA) - 1 +const opMaxArgsB = (1 << opSizeB) - 1 +const opMaxArgsC = (1 << opSizeC) - 1 +const opMaxArgBx = (1 << opSizeBx) - 1 +const opMaxArgSbx = opMaxArgBx >> 1 + +const ( + OP_MOVE int = iota /* A B R(A) := R(B) */ + OP_MOVEN /* A B R(A) := R(B); followed by R(C) MOVE ops */ + OP_LOADK /* A Bx R(A) := Kst(Bx) */ + OP_LOADBOOL /* A B C R(A) := (Bool)B; if (C) pc++ */ + OP_LOADNIL /* A B R(A) := ... := R(B) := nil */ + OP_GETUPVAL /* A B R(A) := UpValue[B] */ + + OP_GETGLOBAL /* A Bx R(A) := Gbl[Kst(Bx)] */ + OP_GETTABLE /* A B C R(A) := R(B)[RK(C)] */ + OP_GETTABLEKS /* A B C R(A) := R(B)[RK(C)] ; RK(C) is constant string */ + + OP_SETGLOBAL /* A Bx Gbl[Kst(Bx)] := R(A) */ + OP_SETUPVAL /* A B UpValue[B] := R(A) */ + OP_SETTABLE /* A B C R(A)[RK(B)] := RK(C) */ + OP_SETTABLEKS /* A B C R(A)[RK(B)] := RK(C) ; RK(B) is constant string */ + + OP_NEWTABLE /* A B C R(A) := {} (size = BC) */ + + OP_SELF /* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */ + + OP_ADD /* A B C R(A) := RK(B) + RK(C) */ + OP_SUB /* A B C R(A) := RK(B) - RK(C) */ + OP_MUL /* A B C R(A) := RK(B) * RK(C) */ + OP_DIV /* A B C R(A) := RK(B) / RK(C) */ + OP_MOD /* A B C R(A) := RK(B) % RK(C) */ + OP_POW /* A B C R(A) := RK(B) ^ RK(C) */ + OP_UNM /* A B R(A) := -R(B) */ + OP_NOT /* A B R(A) := not R(B) */ + OP_LEN /* A B R(A) := length of R(B) */ + + OP_CONCAT /* A B C R(A) := R(B).. ... ..R(C) */ + + OP_JMP /* sBx pc+=sBx */ + + OP_EQ /* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */ + OP_LT /* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ + OP_LE /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ + + OP_TEST /* A C if not (R(A) <=> C) then pc++ */ + OP_TESTSET /* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ + + OP_CALL /* A B C R(A) ... R(A+C-2) := R(A)(R(A+1) ... R(A+B-1)) */ + OP_TAILCALL /* A B C return R(A)(R(A+1) ... R(A+B-1)) */ + OP_RETURN /* A B return R(A) ... R(A+B-2) (see note) */ + + OP_FORLOOP /* A sBx R(A)+=R(A+2); + if R(A) =) R(A)*/ + OP_CLOSURE /* A Bx R(A) := closure(KPROTO[Bx] R(A) ... R(A+n)) */ + + OP_VARARG /* A B R(A) R(A+1) ... R(A+B-1) = vararg */ + + OP_NOP /* NOP */ +) +const opCodeMax = OP_NOP + +type opArgMode int + +const ( + opArgModeN opArgMode = iota + opArgModeU + opArgModeR + opArgModeK +) + +type opType int + +const ( + opTypeABC = iota + opTypeABx + opTypeASbx +) + +type opProp struct { + Name string + IsTest bool + SetRegA bool + ModeArgB opArgMode + ModeArgC opArgMode + Type opType +} + +var opProps = []opProp{ + opProp{"MOVE", false, true, opArgModeR, opArgModeN, opTypeABC}, + opProp{"MOVEN", false, true, opArgModeR, opArgModeN, opTypeABC}, + opProp{"LOADK", false, true, opArgModeK, opArgModeN, opTypeABx}, + opProp{"LOADBOOL", false, true, opArgModeU, opArgModeU, opTypeABC}, + opProp{"LOADNIL", false, true, opArgModeR, opArgModeN, opTypeABC}, + opProp{"GETUPVAL", false, true, opArgModeU, opArgModeN, opTypeABC}, + opProp{"GETGLOBAL", false, true, opArgModeK, opArgModeN, opTypeABx}, + opProp{"GETTABLE", false, true, opArgModeR, opArgModeK, opTypeABC}, + opProp{"GETTABLEKS", false, true, opArgModeR, opArgModeK, opTypeABC}, + opProp{"SETGLOBAL", false, false, opArgModeK, opArgModeN, opTypeABx}, + opProp{"SETUPVAL", false, false, opArgModeU, opArgModeN, opTypeABC}, + opProp{"SETTABLE", false, false, opArgModeK, opArgModeK, opTypeABC}, + opProp{"SETTABLEKS", false, false, opArgModeK, opArgModeK, opTypeABC}, + opProp{"NEWTABLE", false, true, opArgModeU, opArgModeU, opTypeABC}, + opProp{"SELF", false, true, opArgModeR, opArgModeK, opTypeABC}, + opProp{"ADD", false, true, opArgModeK, opArgModeK, opTypeABC}, + opProp{"SUB", false, true, opArgModeK, opArgModeK, opTypeABC}, + opProp{"MUL", false, true, opArgModeK, opArgModeK, opTypeABC}, + opProp{"DIV", false, true, opArgModeK, opArgModeK, opTypeABC}, + opProp{"MOD", false, true, opArgModeK, opArgModeK, opTypeABC}, + opProp{"POW", false, true, opArgModeK, opArgModeK, opTypeABC}, + opProp{"UNM", false, true, opArgModeR, opArgModeN, opTypeABC}, + opProp{"NOT", false, true, opArgModeR, opArgModeN, opTypeABC}, + opProp{"LEN", false, true, opArgModeR, opArgModeN, opTypeABC}, + opProp{"CONCAT", false, true, opArgModeR, opArgModeR, opTypeABC}, + opProp{"JMP", false, false, opArgModeR, opArgModeN, opTypeASbx}, + opProp{"EQ", true, false, opArgModeK, opArgModeK, opTypeABC}, + opProp{"LT", true, false, opArgModeK, opArgModeK, opTypeABC}, + opProp{"LE", true, false, opArgModeK, opArgModeK, opTypeABC}, + opProp{"TEST", true, true, opArgModeR, opArgModeU, opTypeABC}, + opProp{"TESTSET", true, true, opArgModeR, opArgModeU, opTypeABC}, + opProp{"CALL", false, true, opArgModeU, opArgModeU, opTypeABC}, + opProp{"TAILCALL", false, true, opArgModeU, opArgModeU, opTypeABC}, + opProp{"RETURN", false, false, opArgModeU, opArgModeN, opTypeABC}, + opProp{"FORLOOP", false, true, opArgModeR, opArgModeN, opTypeASbx}, + opProp{"FORPREP", false, true, opArgModeR, opArgModeN, opTypeASbx}, + opProp{"TFORLOOP", true, false, opArgModeN, opArgModeU, opTypeABC}, + opProp{"SETLIST", false, false, opArgModeU, opArgModeU, opTypeABC}, + opProp{"CLOSE", false, false, opArgModeN, opArgModeN, opTypeABC}, + opProp{"CLOSURE", false, true, opArgModeU, opArgModeN, opTypeABx}, + opProp{"VARARG", false, true, opArgModeU, opArgModeN, opTypeABC}, + opProp{"NOP", false, false, opArgModeR, opArgModeN, opTypeASbx}, +} + +func opGetOpCode(inst uint32) int { + return int(inst >> 26) +} + +func opSetOpCode(inst *uint32, opcode int) { + *inst = (*inst & 0x3ffffff) | uint32(opcode<<26) +} + +func opGetArgA(inst uint32) int { + return int(inst>>18) & 0xff +} + +func opSetArgA(inst *uint32, arg int) { + *inst = (*inst & 0xfc03ffff) | uint32((arg&0xff)<<18) +} + +func opGetArgB(inst uint32) int { + return int(inst & 0x1ff) +} + +func opSetArgB(inst *uint32, arg int) { + *inst = (*inst & 0xfffffe00) | uint32(arg&0x1ff) +} + +func opGetArgC(inst uint32) int { + return int(inst>>9) & 0x1ff +} + +func opSetArgC(inst *uint32, arg int) { + *inst = (*inst & 0xfffc01ff) | uint32((arg&0x1ff)<<9) +} + +func opGetArgBx(inst uint32) int { + return int(inst & 0x3ffff) +} + +func opSetArgBx(inst *uint32, arg int) { + *inst = (*inst & 0xfffc0000) | uint32(arg&0x3ffff) +} + +func opGetArgSbx(inst uint32) int { + return opGetArgBx(inst) - opMaxArgSbx +} + +func opSetArgSbx(inst *uint32, arg int) { + opSetArgBx(inst, arg+opMaxArgSbx) +} + +func opCreateABC(op int, a int, b int, c int) uint32 { + var inst uint32 = 0 + opSetOpCode(&inst, op) + opSetArgA(&inst, a) + opSetArgB(&inst, b) + opSetArgC(&inst, c) + return inst +} + +func opCreateABx(op int, a int, bx int) uint32 { + var inst uint32 = 0 + opSetOpCode(&inst, op) + opSetArgA(&inst, a) + opSetArgBx(&inst, bx) + return inst +} + +func opCreateASbx(op int, a int, sbx int) uint32 { + var inst uint32 = 0 + opSetOpCode(&inst, op) + opSetArgA(&inst, a) + opSetArgSbx(&inst, sbx) + return inst +} + +const opBitRk = 1 << (opSizeB - 1) +const opMaxIndexRk = opBitRk - 1 + +func opIsK(value int) bool { + return bool((value & opBitRk) != 0) +} + +func opIndexK(value int) int { + return value & ^opBitRk +} + +func opRkAsk(value int) int { + return value | opBitRk +} + +func opToString(inst uint32) string { + op := opGetOpCode(inst) + if op > opCodeMax { + return "" + } + prop := &(opProps[op]) + + arga := opGetArgA(inst) + argb := opGetArgB(inst) + argc := opGetArgC(inst) + argbx := opGetArgBx(inst) + argsbx := opGetArgSbx(inst) + + buf := "" + switch prop.Type { + case opTypeABC: + buf = fmt.Sprintf("%s | %d, %d, %d", prop.Name, arga, argb, argc) + case opTypeABx: + buf = fmt.Sprintf("%s | %d, %d", prop.Name, arga, argbx) + case opTypeASbx: + buf = fmt.Sprintf("%s | %d, %d", prop.Name, arga, argsbx) + } + + switch op { + case OP_MOVE: + buf += fmt.Sprintf("; R(%v) := R(%v)", arga, argb) + case OP_MOVEN: + buf += fmt.Sprintf("; R(%v) := R(%v); followed by %v MOVE ops", arga, argb, argc) + case OP_LOADK: + buf += fmt.Sprintf("; R(%v) := Kst(%v)", arga, argbx) + case OP_LOADBOOL: + buf += fmt.Sprintf("; R(%v) := (Bool)%v; if (%v) pc++", arga, argb, argc) + case OP_LOADNIL: + buf += fmt.Sprintf("; R(%v) := ... := R(%v) := nil", arga, argb) + case OP_GETUPVAL: + buf += fmt.Sprintf("; R(%v) := UpValue[%v]", arga, argb) + case OP_GETGLOBAL: + buf += fmt.Sprintf("; R(%v) := Gbl[Kst(%v)]", arga, argbx) + case OP_GETTABLE: + buf += fmt.Sprintf("; R(%v) := R(%v)[RK(%v)]", arga, argb, argc) + case OP_GETTABLEKS: + buf += fmt.Sprintf("; R(%v) := R(%v)[RK(%v)] ; RK(%v) is constant string", arga, argb, argc, argc) + case OP_SETGLOBAL: + buf += fmt.Sprintf("; Gbl[Kst(%v)] := R(%v)", argbx, arga) + case OP_SETUPVAL: + buf += fmt.Sprintf("; UpValue[%v] := R(%v)", argb, arga) + case OP_SETTABLE: + buf += fmt.Sprintf("; R(%v)[RK(%v)] := RK(%v)", arga, argb, argc) + case OP_SETTABLEKS: + buf += fmt.Sprintf("; R(%v)[RK(%v)] := RK(%v) ; RK(%v) is constant string", arga, argb, argc, argb) + case OP_NEWTABLE: + buf += fmt.Sprintf("; R(%v) := {} (size = BC)", arga) + case OP_SELF: + buf += fmt.Sprintf("; R(%v+1) := R(%v); R(%v) := R(%v)[RK(%v)]", arga, argb, arga, argb, argc) + case OP_ADD: + buf += fmt.Sprintf("; R(%v) := RK(%v) + RK(%v)", arga, argb, argc) + case OP_SUB: + buf += fmt.Sprintf("; R(%v) := RK(%v) - RK(%v)", arga, argb, argc) + case OP_MUL: + buf += fmt.Sprintf("; R(%v) := RK(%v) * RK(%v)", arga, argb, argc) + case OP_DIV: + buf += fmt.Sprintf("; R(%v) := RK(%v) / RK(%v)", arga, argb, argc) + case OP_MOD: + buf += fmt.Sprintf("; R(%v) := RK(%v) %% RK(%v)", arga, argb, argc) + case OP_POW: + buf += fmt.Sprintf("; R(%v) := RK(%v) ^ RK(%v)", arga, argb, argc) + case OP_UNM: + buf += fmt.Sprintf("; R(%v) := -R(%v)", arga, argb) + case OP_NOT: + buf += fmt.Sprintf("; R(%v) := not R(%v)", arga, argb) + case OP_LEN: + buf += fmt.Sprintf("; R(%v) := length of R(%v)", arga, argb) + case OP_CONCAT: + buf += fmt.Sprintf("; R(%v) := R(%v).. ... ..R(%v)", arga, argb, argc) + case OP_JMP: + buf += fmt.Sprintf("; pc+=%v", argsbx) + case OP_EQ: + buf += fmt.Sprintf("; if ((RK(%v) == RK(%v)) ~= %v) then pc++", argb, argc, arga) + case OP_LT: + buf += fmt.Sprintf("; if ((RK(%v) < RK(%v)) ~= %v) then pc++", argb, argc, arga) + case OP_LE: + buf += fmt.Sprintf("; if ((RK(%v) <= RK(%v)) ~= %v) then pc++", argb, argc, arga) + case OP_TEST: + buf += fmt.Sprintf("; if not (R(%v) <=> %v) then pc++", arga, argc) + case OP_TESTSET: + buf += fmt.Sprintf("; if (R(%v) <=> %v) then R(%v) := R(%v) else pc++", argb, argc, arga, argb) + case OP_CALL: + buf += fmt.Sprintf("; R(%v) ... R(%v+%v-2) := R(%v)(R(%v+1) ... R(%v+%v-1))", arga, arga, argc, arga, arga, arga, argb) + case OP_TAILCALL: + buf += fmt.Sprintf("; return R(%v)(R(%v+1) ... R(%v+%v-1))", arga, arga, arga, argb) + case OP_RETURN: + buf += fmt.Sprintf("; return R(%v) ... R(%v+%v-2)", arga, arga, argb) + case OP_FORLOOP: + buf += fmt.Sprintf("; R(%v)+=R(%v+2); if R(%v) =) R(%v)", arga) + case OP_CLOSURE: + buf += fmt.Sprintf("; R(%v) := closure(KPROTO[%v] R(%v) ... R(%v+n))", arga, argbx, arga, arga) + case OP_VARARG: + buf += fmt.Sprintf("; R(%v) R(%v+1) ... R(%v+%v-1) = vararg", arga, arga, arga, argb) + case OP_NOP: + /* nothing to do */ + } + return buf +} diff --git a/vendor/github.com/yuin/gopher-lua/oslib.go b/vendor/github.com/yuin/gopher-lua/oslib.go new file mode 100644 index 0000000000000000000000000000000000000000..e18656894f14b94c2bd176e8dd96ceb046b73b16 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/oslib.go @@ -0,0 +1,206 @@ +package lua + +import ( + "io/ioutil" + "os" + "strings" + "time" +) + +var startedAt time.Time + +func init() { + startedAt = time.Now() +} + +func getIntField(L *LState, tb *LTable, key string, v int) int { + ret := tb.RawGetString(key) + if ln, ok := ret.(LNumber); ok { + return int(ln) + } + return v +} + +func getBoolField(L *LState, tb *LTable, key string, v bool) bool { + ret := tb.RawGetString(key) + if lb, ok := ret.(LBool); ok { + return bool(lb) + } + return v +} + +func OpenOs(L *LState) int { + osmod := L.RegisterModule(OsLibName, osFuncs) + L.Push(osmod) + return 1 +} + +var osFuncs = map[string]LGFunction{ + "clock": osClock, + "difftime": osDiffTime, + "execute": osExecute, + "exit": osExit, + "date": osDate, + "getenv": osGetEnv, + "remove": osRemove, + "rename": osRename, + "setenv": osSetEnv, + "setlocale": osSetLocale, + "time": osTime, + "tmpname": osTmpname, +} + +func osClock(L *LState) int { + L.Push(LNumber(float64(time.Now().Sub(startedAt)) / float64(time.Second))) + return 1 +} + +func osDiffTime(L *LState) int { + L.Push(LNumber(L.CheckInt64(1) - L.CheckInt64(2))) + return 1 +} + +func osExecute(L *LState) int { + var procAttr os.ProcAttr + procAttr.Files = []*os.File{os.Stdin, os.Stdout, os.Stderr} + cmd, args := popenArgs(L.CheckString(1)) + args = append([]string{cmd}, args...) + process, err := os.StartProcess(cmd, args, &procAttr) + if err != nil { + L.Push(LNumber(1)) + return 1 + } + + ps, err := process.Wait() + if err != nil || !ps.Success() { + L.Push(LNumber(1)) + return 1 + } + L.Push(LNumber(0)) + return 1 +} + +func osExit(L *LState) int { + L.Close() + os.Exit(L.OptInt(1, 0)) + return 1 +} + +func osDate(L *LState) int { + t := time.Now() + cfmt := "%c" + if L.GetTop() >= 1 { + cfmt = L.CheckString(1) + if strings.HasPrefix(cfmt, "!") { + t = time.Now().UTC() + cfmt = strings.TrimLeft(cfmt, "!") + } + if L.GetTop() >= 2 { + t = time.Unix(L.CheckInt64(2), 0) + } + if strings.HasPrefix(cfmt, "*t") { + ret := L.NewTable() + ret.RawSetString("year", LNumber(t.Year())) + ret.RawSetString("month", LNumber(t.Month())) + ret.RawSetString("day", LNumber(t.Day())) + ret.RawSetString("hour", LNumber(t.Hour())) + ret.RawSetString("min", LNumber(t.Minute())) + ret.RawSetString("sec", LNumber(t.Second())) + ret.RawSetString("wday", LNumber(t.Weekday()+1)) + // TODO yday & dst + ret.RawSetString("yday", LNumber(0)) + ret.RawSetString("isdst", LFalse) + L.Push(ret) + return 1 + } + } + L.Push(LString(strftime(t, cfmt))) + return 1 +} + +func osGetEnv(L *LState) int { + v := os.Getenv(L.CheckString(1)) + if len(v) == 0 { + L.Push(LNil) + } else { + L.Push(LString(v)) + } + return 1 +} + +func osRemove(L *LState) int { + err := os.Remove(L.CheckString(1)) + if err != nil { + L.Push(LNil) + L.Push(LString(err.Error())) + return 2 + } else { + L.Push(LTrue) + return 1 + } +} + +func osRename(L *LState) int { + err := os.Rename(L.CheckString(1), L.CheckString(2)) + if err != nil { + L.Push(LNil) + L.Push(LString(err.Error())) + return 2 + } else { + L.Push(LTrue) + return 1 + } +} + +func osSetLocale(L *LState) int { + // setlocale is not supported + L.Push(LFalse) + return 1 +} + +func osSetEnv(L *LState) int { + err := os.Setenv(L.CheckString(1), L.CheckString(2)) + if err != nil { + L.Push(LNil) + L.Push(LString(err.Error())) + return 2 + } else { + L.Push(LTrue) + return 1 + } +} + +func osTime(L *LState) int { + if L.GetTop() == 0 { + L.Push(LNumber(time.Now().Unix())) + } else { + tbl := L.CheckTable(1) + sec := getIntField(L, tbl, "sec", 0) + min := getIntField(L, tbl, "min", 0) + hour := getIntField(L, tbl, "hour", 12) + day := getIntField(L, tbl, "day", -1) + month := getIntField(L, tbl, "month", -1) + year := getIntField(L, tbl, "year", -1) + isdst := getBoolField(L, tbl, "isdst", false) + t := time.Date(year, time.Month(month), day, hour, min, sec, 0, time.Local) + // TODO dst + if false { + print(isdst) + } + L.Push(LNumber(t.Unix())) + } + return 1 +} + +func osTmpname(L *LState) int { + file, err := ioutil.TempFile("", "") + if err != nil { + L.RaiseError("unable to generate a unique filename") + } + file.Close() + os.Remove(file.Name()) // ignore errors + L.Push(LString(file.Name())) + return 1 +} + +// diff --git a/vendor/github.com/yuin/gopher-lua/package.go b/vendor/github.com/yuin/gopher-lua/package.go new file mode 100644 index 0000000000000000000000000000000000000000..9fde3f0c2156867dceff4440c918a1bea68a24a7 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/package.go @@ -0,0 +1,7 @@ +// GopherLua: VM and compiler for Lua in Go +package lua + +const PackageName = "GopherLua" +const PackageVersion = "0.1" +const PackageAuthors = "Yusuke Inuzuka" +const PackageCopyRight = PackageName + " " + PackageVersion + " Copyright (C) 2015 -2017 " + PackageAuthors diff --git a/vendor/github.com/yuin/gopher-lua/parse/Makefile b/vendor/github.com/yuin/gopher-lua/parse/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..6dd048c165ff7dc0bf04908071edb0e052f44811 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/parse/Makefile @@ -0,0 +1,4 @@ +all : parser.go + +parser.go : parser.go.y + goyacc -o $@ parser.go.y; [ -f y.output ] && ( rm -f y.output ) diff --git a/vendor/github.com/yuin/gopher-lua/parse/lexer.go b/vendor/github.com/yuin/gopher-lua/parse/lexer.go new file mode 100644 index 0000000000000000000000000000000000000000..4e54b7c5d09111269dd42fbac20940c56bfcc68b --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/parse/lexer.go @@ -0,0 +1,537 @@ +package parse + +import ( + "bufio" + "bytes" + "fmt" + "github.com/yuin/gopher-lua/ast" + "io" + "reflect" + "strconv" + "strings" +) + +const EOF = -1 +const whitespace1 = 1<<'\t' | 1<<' ' +const whitespace2 = 1<<'\t' | 1<<'\n' | 1<<'\r' | 1<<' ' + +type Error struct { + Pos ast.Position + Message string + Token string +} + +func (e *Error) Error() string { + pos := e.Pos + if pos.Line == EOF { + return fmt.Sprintf("%v at EOF: %s\n", pos.Source, e.Message) + } else { + return fmt.Sprintf("%v line:%d(column:%d) near '%v': %s\n", pos.Source, pos.Line, pos.Column, e.Token, e.Message) + } +} + +func writeChar(buf *bytes.Buffer, c int) { buf.WriteByte(byte(c)) } + +func isDecimal(ch int) bool { return '0' <= ch && ch <= '9' } + +func isIdent(ch int, pos int) bool { + return ch == '_' || 'A' <= ch && ch <= 'Z' || 'a' <= ch && ch <= 'z' || isDecimal(ch) && pos > 0 +} + +func isDigit(ch int) bool { + return '0' <= ch && ch <= '9' || 'a' <= ch && ch <= 'f' || 'A' <= ch && ch <= 'F' +} + +type Scanner struct { + Pos ast.Position + reader *bufio.Reader +} + +func NewScanner(reader io.Reader, source string) *Scanner { + return &Scanner{ + Pos: ast.Position{source, 1, 0}, + reader: bufio.NewReaderSize(reader, 4096), + } +} + +func (sc *Scanner) Error(tok string, msg string) *Error { return &Error{sc.Pos, msg, tok} } + +func (sc *Scanner) TokenError(tok ast.Token, msg string) *Error { return &Error{tok.Pos, msg, tok.Str} } + +func (sc *Scanner) readNext() int { + ch, err := sc.reader.ReadByte() + if err == io.EOF { + return EOF + } + return int(ch) +} + +func (sc *Scanner) Newline(ch int) { + if ch < 0 { + return + } + sc.Pos.Line += 1 + sc.Pos.Column = 0 + next := sc.Peek() + if ch == '\n' && next == '\r' || ch == '\r' && next == '\n' { + sc.reader.ReadByte() + } +} + +func (sc *Scanner) Next() int { + ch := sc.readNext() + switch ch { + case '\n', '\r': + sc.Newline(ch) + ch = int('\n') + case EOF: + sc.Pos.Line = EOF + sc.Pos.Column = 0 + default: + sc.Pos.Column++ + } + return ch +} + +func (sc *Scanner) Peek() int { + ch := sc.readNext() + if ch != EOF { + sc.reader.UnreadByte() + } + return ch +} + +func (sc *Scanner) skipWhiteSpace(whitespace int64) int { + ch := sc.Next() + for ; whitespace&(1<': + if sc.Peek() == '=' { + tok.Type = TGte + tok.Str = ">=" + sc.Next() + } else { + tok.Type = ch + tok.Str = string(ch) + } + case '.': + ch2 := sc.Peek() + switch { + case isDecimal(ch2): + tok.Type = TNumber + err = sc.scanNumber(ch, buf) + tok.Str = buf.String() + case ch2 == '.': + writeChar(buf, ch) + writeChar(buf, sc.Next()) + if sc.Peek() == '.' { + writeChar(buf, sc.Next()) + tok.Type = T3Comma + } else { + tok.Type = T2Comma + } + default: + tok.Type = '.' + } + tok.Str = buf.String() + case '+', '*', '/', '%', '^', '#', '(', ')', '{', '}', ']', ';', ':', ',': + tok.Type = ch + tok.Str = string(ch) + default: + writeChar(buf, ch) + err = sc.Error(buf.String(), "Invalid token") + goto finally + } + } + +finally: + tok.Name = TokenName(int(tok.Type)) + return tok, err +} + +// yacc interface {{{ + +type Lexer struct { + scanner *Scanner + Stmts []ast.Stmt + PNewLine bool + Token ast.Token + PrevTokenType int +} + +func (lx *Lexer) Lex(lval *yySymType) int { + lx.PrevTokenType = lx.Token.Type + tok, err := lx.scanner.Scan(lx) + if err != nil { + panic(err) + } + if tok.Type < 0 { + return 0 + } + lval.token = tok + lx.Token = tok + return int(tok.Type) +} + +func (lx *Lexer) Error(message string) { + panic(lx.scanner.Error(lx.Token.Str, message)) +} + +func (lx *Lexer) TokenError(tok ast.Token, message string) { + panic(lx.scanner.TokenError(tok, message)) +} + +func Parse(reader io.Reader, name string) (chunk []ast.Stmt, err error) { + lexer := &Lexer{NewScanner(reader, name), nil, false, ast.Token{Str: ""}, TNil} + chunk = nil + defer func() { + if e := recover(); e != nil { + err, _ = e.(error) + } + }() + yyParse(lexer) + chunk = lexer.Stmts + return +} + +// }}} + +// Dump {{{ + +func isInlineDumpNode(rv reflect.Value) bool { + switch rv.Kind() { + case reflect.Struct, reflect.Slice, reflect.Interface, reflect.Ptr: + return false + default: + return true + } +} + +func dump(node interface{}, level int, s string) string { + rt := reflect.TypeOf(node) + if fmt.Sprint(rt) == "" { + return strings.Repeat(s, level) + "" + } + + rv := reflect.ValueOf(node) + buf := []string{} + switch rt.Kind() { + case reflect.Slice: + if rv.Len() == 0 { + return strings.Repeat(s, level) + "" + } + for i := 0; i < rv.Len(); i++ { + buf = append(buf, dump(rv.Index(i).Interface(), level, s)) + } + case reflect.Ptr: + vt := rv.Elem() + tt := rt.Elem() + indicies := []int{} + for i := 0; i < tt.NumField(); i++ { + if strings.Index(tt.Field(i).Name, "Base") > -1 { + continue + } + indicies = append(indicies, i) + } + switch { + case len(indicies) == 0: + return strings.Repeat(s, level) + "" + case len(indicies) == 1 && isInlineDumpNode(vt.Field(indicies[0])): + for _, i := range indicies { + buf = append(buf, strings.Repeat(s, level)+"- Node$"+tt.Name()+": "+dump(vt.Field(i).Interface(), 0, s)) + } + default: + buf = append(buf, strings.Repeat(s, level)+"- Node$"+tt.Name()) + for _, i := range indicies { + if isInlineDumpNode(vt.Field(i)) { + inf := dump(vt.Field(i).Interface(), 0, s) + buf = append(buf, strings.Repeat(s, level+1)+tt.Field(i).Name+": "+inf) + } else { + buf = append(buf, strings.Repeat(s, level+1)+tt.Field(i).Name+": ") + buf = append(buf, dump(vt.Field(i).Interface(), level+2, s)) + } + } + } + default: + buf = append(buf, strings.Repeat(s, level)+fmt.Sprint(node)) + } + return strings.Join(buf, "\n") +} + +func Dump(chunk []ast.Stmt) string { + return dump(chunk, 0, " ") +} + +// }} diff --git a/vendor/github.com/yuin/gopher-lua/parse/parser.go b/vendor/github.com/yuin/gopher-lua/parse/parser.go new file mode 100644 index 0000000000000000000000000000000000000000..f8f59b36154c1008699bf50b6a36628ae4584853 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/parse/parser.go @@ -0,0 +1,1137 @@ +//line parser.go.y:2 +package parse + +import __yyfmt__ "fmt" + +//line parser.go.y:2 +import ( + "github.com/yuin/gopher-lua/ast" +) + +//line parser.go.y:34 +type yySymType struct { + yys int + token ast.Token + + stmts []ast.Stmt + stmt ast.Stmt + + funcname *ast.FuncName + funcexpr *ast.FunctionExpr + + exprlist []ast.Expr + expr ast.Expr + + fieldlist []*ast.Field + field *ast.Field + fieldsep string + + namelist []string + parlist *ast.ParList +} + +const TAnd = 57346 +const TBreak = 57347 +const TDo = 57348 +const TElse = 57349 +const TElseIf = 57350 +const TEnd = 57351 +const TFalse = 57352 +const TFor = 57353 +const TFunction = 57354 +const TIf = 57355 +const TIn = 57356 +const TLocal = 57357 +const TNil = 57358 +const TNot = 57359 +const TOr = 57360 +const TReturn = 57361 +const TRepeat = 57362 +const TThen = 57363 +const TTrue = 57364 +const TUntil = 57365 +const TWhile = 57366 +const TEqeq = 57367 +const TNeq = 57368 +const TLte = 57369 +const TGte = 57370 +const T2Comma = 57371 +const T3Comma = 57372 +const TIdent = 57373 +const TNumber = 57374 +const TString = 57375 +const UNARY = 57376 + +var yyToknames = []string{ + "TAnd", + "TBreak", + "TDo", + "TElse", + "TElseIf", + "TEnd", + "TFalse", + "TFor", + "TFunction", + "TIf", + "TIn", + "TLocal", + "TNil", + "TNot", + "TOr", + "TReturn", + "TRepeat", + "TThen", + "TTrue", + "TUntil", + "TWhile", + "TEqeq", + "TNeq", + "TLte", + "TGte", + "T2Comma", + "T3Comma", + "TIdent", + "TNumber", + "TString", + " {", + " (", + " >", + " <", + " +", + " -", + " *", + " /", + " %", + "UNARY", + " ^", +} +var yyStatenames = []string{} + +const yyEofCode = 1 +const yyErrCode = 2 +const yyMaxDepth = 200 + +//line parser.go.y:514 +func TokenName(c int) string { + if c >= TAnd && c-TAnd < len(yyToknames) { + if yyToknames[c-TAnd] != "" { + return yyToknames[c-TAnd] + } + } + return string([]byte{byte(c)}) +} + +//line yacctab:1 +var yyExca = []int{ + -1, 1, + 1, -1, + -2, 0, + -1, 17, + 46, 31, + 47, 31, + -2, 68, + -1, 93, + 46, 32, + 47, 32, + -2, 68, +} + +const yyNprod = 95 +const yyPrivate = 57344 + +var yyTokenNames []string +var yyStates []string + +const yyLast = 579 + +var yyAct = []int{ + + 24, 88, 50, 23, 45, 84, 56, 65, 137, 153, + 136, 113, 52, 142, 54, 53, 33, 134, 65, 132, + 62, 63, 32, 61, 108, 109, 48, 111, 106, 41, + 42, 105, 49, 155, 166, 81, 82, 83, 138, 104, + 22, 91, 131, 80, 95, 92, 162, 74, 48, 85, + 150, 99, 165, 148, 49, 149, 75, 76, 77, 78, + 79, 67, 80, 107, 106, 148, 114, 115, 116, 117, + 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, + 128, 129, 72, 73, 71, 70, 74, 65, 39, 40, + 47, 139, 133, 68, 69, 75, 76, 77, 78, 79, + 60, 80, 141, 144, 143, 146, 145, 31, 67, 147, + 9, 48, 110, 97, 48, 152, 151, 49, 38, 62, + 49, 17, 66, 77, 78, 79, 96, 80, 59, 72, + 73, 71, 70, 74, 154, 102, 91, 156, 55, 157, + 68, 69, 75, 76, 77, 78, 79, 21, 80, 187, + 94, 20, 26, 184, 37, 179, 163, 112, 25, 35, + 178, 93, 170, 172, 27, 171, 164, 173, 19, 159, + 175, 174, 29, 89, 28, 39, 40, 20, 182, 181, + 100, 34, 135, 183, 67, 39, 40, 47, 186, 64, + 51, 1, 90, 87, 36, 130, 86, 30, 66, 18, + 46, 44, 43, 8, 58, 72, 73, 71, 70, 74, + 57, 67, 168, 169, 167, 3, 68, 69, 75, 76, + 77, 78, 79, 160, 80, 66, 4, 2, 0, 0, + 0, 158, 72, 73, 71, 70, 74, 0, 0, 0, + 0, 0, 0, 68, 69, 75, 76, 77, 78, 79, + 26, 80, 37, 0, 0, 0, 25, 35, 140, 0, + 0, 0, 27, 0, 0, 0, 0, 0, 0, 0, + 29, 21, 28, 39, 40, 20, 26, 0, 37, 34, + 0, 0, 25, 35, 0, 0, 0, 0, 27, 0, + 0, 0, 36, 98, 0, 0, 29, 89, 28, 39, + 40, 20, 26, 0, 37, 34, 0, 0, 25, 35, + 0, 0, 0, 0, 27, 67, 90, 176, 36, 0, + 0, 0, 29, 21, 28, 39, 40, 20, 0, 66, + 0, 34, 0, 0, 0, 0, 72, 73, 71, 70, + 74, 0, 67, 0, 36, 0, 0, 68, 69, 75, + 76, 77, 78, 79, 0, 80, 66, 0, 177, 0, + 0, 0, 0, 72, 73, 71, 70, 74, 0, 67, + 0, 185, 0, 0, 68, 69, 75, 76, 77, 78, + 79, 0, 80, 66, 0, 161, 0, 0, 0, 0, + 72, 73, 71, 70, 74, 0, 67, 0, 0, 0, + 0, 68, 69, 75, 76, 77, 78, 79, 0, 80, + 66, 0, 0, 180, 0, 0, 0, 72, 73, 71, + 70, 74, 0, 67, 0, 0, 0, 0, 68, 69, + 75, 76, 77, 78, 79, 0, 80, 66, 0, 0, + 103, 0, 0, 0, 72, 73, 71, 70, 74, 0, + 67, 0, 101, 0, 0, 68, 69, 75, 76, 77, + 78, 79, 0, 80, 66, 0, 0, 0, 0, 0, + 0, 72, 73, 71, 70, 74, 0, 67, 0, 0, + 0, 0, 68, 69, 75, 76, 77, 78, 79, 0, + 80, 66, 0, 0, 0, 0, 0, 0, 72, 73, + 71, 70, 74, 0, 0, 0, 0, 0, 0, 68, + 69, 75, 76, 77, 78, 79, 0, 80, 72, 73, + 71, 70, 74, 0, 0, 0, 0, 0, 0, 68, + 69, 75, 76, 77, 78, 79, 0, 80, 7, 10, + 0, 0, 0, 0, 14, 15, 13, 0, 16, 0, + 0, 0, 6, 12, 0, 0, 0, 11, 0, 0, + 0, 0, 0, 0, 21, 0, 0, 0, 20, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 5, +} +var yyPact = []int{ + + -1000, -1000, 533, -5, -1000, -1000, 292, -1000, -17, 152, + -1000, 292, -1000, 292, 107, 97, 88, -1000, -1000, -1000, + 292, -1000, -1000, -29, 473, -1000, -1000, -1000, -1000, -1000, + -1000, 152, -1000, -1000, 292, 292, 292, 14, -1000, -1000, + 142, 292, 116, 292, 95, -1000, 82, 240, -1000, -1000, + 171, -1000, 446, 112, 419, -7, 17, 14, -24, -1000, + 81, -19, -1000, 104, -42, 292, 292, 292, 292, 292, + 292, 292, 292, 292, 292, 292, 292, 292, 292, 292, + 292, -1, -1, -1, -1000, -11, -1000, -37, -1000, -8, + 292, 473, -29, -1000, 152, 207, -1000, 55, -1000, -40, + -1000, -1000, 292, -1000, 292, 292, 34, -1000, 24, 19, + 14, 292, -1000, -1000, 473, 57, 493, 18, 18, 18, + 18, 18, 18, 18, 83, 83, -1, -1, -1, -1, + -44, -1000, -1000, -14, -1000, 266, -1000, -1000, 292, 180, + -1000, -1000, -1000, 160, 473, -1000, 338, 40, -1000, -1000, + -1000, -1000, -29, -1000, 157, 22, -1000, 473, -12, -1000, + 205, 292, -1000, 154, -1000, -1000, 292, -1000, -1000, 292, + 311, 151, -1000, 473, 146, 392, -1000, 292, -1000, -1000, + -1000, 144, 365, -1000, -1000, -1000, 140, -1000, +} +var yyPgo = []int{ + + 0, 190, 227, 2, 226, 223, 215, 210, 204, 203, + 118, 6, 3, 0, 22, 107, 168, 199, 4, 197, + 5, 195, 16, 193, 1, 182, +} +var yyR1 = []int{ + + 0, 1, 1, 1, 2, 2, 2, 3, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 5, 5, 6, 6, 6, 7, 7, 8, + 8, 9, 9, 10, 10, 10, 11, 11, 12, 12, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 14, 15, 15, + 15, 15, 17, 16, 16, 18, 18, 18, 18, 19, + 20, 20, 21, 21, 21, 22, 22, 23, 23, 23, + 24, 24, 24, 25, 25, +} +var yyR2 = []int{ + + 0, 1, 2, 3, 0, 2, 2, 1, 3, 1, + 3, 5, 4, 6, 8, 9, 11, 7, 3, 4, + 4, 2, 0, 5, 1, 2, 1, 1, 3, 1, + 3, 1, 3, 1, 4, 3, 1, 3, 1, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 2, 2, 2, 1, 1, 1, + 1, 3, 3, 2, 4, 2, 3, 1, 1, 2, + 5, 4, 1, 1, 3, 2, 3, 1, 3, 2, + 3, 5, 1, 1, 1, +} +var yyChk = []int{ + + -1000, -1, -2, -6, -4, 45, 19, 5, -9, -15, + 6, 24, 20, 13, 11, 12, 15, -10, -17, -16, + 35, 31, 45, -12, -13, 16, 10, 22, 32, 30, + -19, -15, -14, -22, 39, 17, 52, 12, -10, 33, + 34, 46, 47, 50, 49, -18, 48, 35, -22, -14, + -3, -1, -13, -3, -13, 31, -11, -7, -8, 31, + 12, -11, 31, -13, -16, 47, 18, 4, 36, 37, + 28, 27, 25, 26, 29, 38, 39, 40, 41, 42, + 44, -13, -13, -13, -20, 35, 54, -23, -24, 31, + 50, -13, -12, -10, -15, -13, 31, 31, 53, -12, + 9, 6, 23, 21, 46, 14, 47, -20, 48, 49, + 31, 46, 53, 53, -13, -13, -13, -13, -13, -13, + -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, + -21, 53, 30, -11, 54, -25, 47, 45, 46, -13, + 51, -18, 53, -3, -13, -3, -13, -12, 31, 31, + 31, -20, -12, 53, -3, 47, -24, -13, 51, 9, + -5, 47, 6, -3, 9, 30, 46, 9, 7, 8, + -13, -3, 9, -13, -3, -13, 6, 47, 9, 9, + 21, -3, -13, -3, 9, 6, -3, 9, +} +var yyDef = []int{ + + 4, -2, 1, 2, 5, 6, 24, 26, 0, 9, + 4, 0, 4, 0, 0, 0, 0, -2, 69, 70, + 0, 33, 3, 25, 38, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 0, 0, 0, 0, 68, 67, + 0, 0, 0, 0, 0, 73, 0, 0, 77, 78, + 0, 7, 0, 0, 0, 36, 0, 0, 27, 29, + 0, 21, 36, 0, 70, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 64, 65, 66, 79, 0, 85, 0, 87, 33, + 0, 92, 8, -2, 0, 0, 35, 0, 75, 0, + 10, 4, 0, 4, 0, 0, 0, 18, 0, 0, + 0, 0, 71, 72, 39, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 0, 4, 82, 83, 86, 89, 93, 94, 0, 0, + 34, 74, 76, 0, 12, 22, 0, 0, 37, 28, + 30, 19, 20, 4, 0, 0, 88, 90, 0, 11, + 0, 0, 4, 0, 81, 84, 0, 13, 4, 0, + 0, 0, 80, 91, 0, 0, 4, 0, 17, 14, + 4, 0, 0, 23, 15, 4, 0, 16, +} +var yyTok1 = []int{ + + 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 52, 3, 42, 3, 3, + 35, 53, 40, 38, 47, 39, 49, 41, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 48, 45, + 37, 46, 36, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 50, 3, 51, 44, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 34, 3, 54, +} +var yyTok2 = []int{ + + 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 43, +} +var yyTok3 = []int{ + 0, +} + +//line yaccpar:1 + +/* parser for yacc output */ + +var yyDebug = 0 + +type yyLexer interface { + Lex(lval *yySymType) int + Error(s string) +} + +const yyFlag = -1000 + +func yyTokname(c int) string { + // 4 is TOKSTART above + if c >= 4 && c-4 < len(yyToknames) { + if yyToknames[c-4] != "" { + return yyToknames[c-4] + } + } + return __yyfmt__.Sprintf("tok-%v", c) +} + +func yyStatname(s int) string { + if s >= 0 && s < len(yyStatenames) { + if yyStatenames[s] != "" { + return yyStatenames[s] + } + } + return __yyfmt__.Sprintf("state-%v", s) +} + +func yylex1(lex yyLexer, lval *yySymType) int { + c := 0 + char := lex.Lex(lval) + if char <= 0 { + c = yyTok1[0] + goto out + } + if char < len(yyTok1) { + c = yyTok1[char] + goto out + } + if char >= yyPrivate { + if char < yyPrivate+len(yyTok2) { + c = yyTok2[char-yyPrivate] + goto out + } + } + for i := 0; i < len(yyTok3); i += 2 { + c = yyTok3[i+0] + if c == char { + c = yyTok3[i+1] + goto out + } + } + +out: + if c == 0 { + c = yyTok2[1] /* unknown char */ + } + if yyDebug >= 3 { + __yyfmt__.Printf("lex %s(%d)\n", yyTokname(c), uint(char)) + } + return c +} + +func yyParse(yylex yyLexer) int { + var yyn int + var yylval yySymType + var yyVAL yySymType + yyS := make([]yySymType, yyMaxDepth) + + Nerrs := 0 /* number of errors */ + Errflag := 0 /* error recovery flag */ + yystate := 0 + yychar := -1 + yyp := -1 + goto yystack + +ret0: + return 0 + +ret1: + return 1 + +yystack: + /* put a state and value onto the stack */ + if yyDebug >= 4 { + __yyfmt__.Printf("char %v in %v\n", yyTokname(yychar), yyStatname(yystate)) + } + + yyp++ + if yyp >= len(yyS) { + nyys := make([]yySymType, len(yyS)*2) + copy(nyys, yyS) + yyS = nyys + } + yyS[yyp] = yyVAL + yyS[yyp].yys = yystate + +yynewstate: + yyn = yyPact[yystate] + if yyn <= yyFlag { + goto yydefault /* simple state */ + } + if yychar < 0 { + yychar = yylex1(yylex, &yylval) + } + yyn += yychar + if yyn < 0 || yyn >= yyLast { + goto yydefault + } + yyn = yyAct[yyn] + if yyChk[yyn] == yychar { /* valid shift */ + yychar = -1 + yyVAL = yylval + yystate = yyn + if Errflag > 0 { + Errflag-- + } + goto yystack + } + +yydefault: + /* default state action */ + yyn = yyDef[yystate] + if yyn == -2 { + if yychar < 0 { + yychar = yylex1(yylex, &yylval) + } + + /* look through exception table */ + xi := 0 + for { + if yyExca[xi+0] == -1 && yyExca[xi+1] == yystate { + break + } + xi += 2 + } + for xi += 2; ; xi += 2 { + yyn = yyExca[xi+0] + if yyn < 0 || yyn == yychar { + break + } + } + yyn = yyExca[xi+1] + if yyn < 0 { + goto ret0 + } + } + if yyn == 0 { + /* error ... attempt to resume parsing */ + switch Errflag { + case 0: /* brand new error */ + yylex.Error("syntax error") + Nerrs++ + if yyDebug >= 1 { + __yyfmt__.Printf("%s", yyStatname(yystate)) + __yyfmt__.Printf(" saw %s\n", yyTokname(yychar)) + } + fallthrough + + case 1, 2: /* incompletely recovered error ... try again */ + Errflag = 3 + + /* find a state where "error" is a legal shift action */ + for yyp >= 0 { + yyn = yyPact[yyS[yyp].yys] + yyErrCode + if yyn >= 0 && yyn < yyLast { + yystate = yyAct[yyn] /* simulate a shift of "error" */ + if yyChk[yystate] == yyErrCode { + goto yystack + } + } + + /* the current p has no shift on "error", pop stack */ + if yyDebug >= 2 { + __yyfmt__.Printf("error recovery pops state %d\n", yyS[yyp].yys) + } + yyp-- + } + /* there is no state on the stack with an error shift ... abort */ + goto ret1 + + case 3: /* no shift yet; clobber input char */ + if yyDebug >= 2 { + __yyfmt__.Printf("error recovery discards %s\n", yyTokname(yychar)) + } + if yychar == yyEofCode { + goto ret1 + } + yychar = -1 + goto yynewstate /* try again in the same state */ + } + } + + /* reduction by production yyn */ + if yyDebug >= 2 { + __yyfmt__.Printf("reduce %v in:\n\t%v\n", yyn, yyStatname(yystate)) + } + + yynt := yyn + yypt := yyp + _ = yypt // guard against "declared and not used" + + yyp -= yyR2[yyn] + yyVAL = yyS[yyp+1] + + /* consult goto table to find next state */ + yyn = yyR1[yyn] + yyg := yyPgo[yyn] + yyj := yyg + yyS[yyp].yys + 1 + + if yyj >= yyLast { + yystate = yyAct[yyg] + } else { + yystate = yyAct[yyj] + if yyChk[yystate] != -yyn { + yystate = yyAct[yyg] + } + } + // dummy call; replaced with literal code + switch yynt { + + case 1: + //line parser.go.y:73 + { + yyVAL.stmts = yyS[yypt-0].stmts + if l, ok := yylex.(*Lexer); ok { + l.Stmts = yyVAL.stmts + } + } + case 2: + //line parser.go.y:79 + { + yyVAL.stmts = append(yyS[yypt-1].stmts, yyS[yypt-0].stmt) + if l, ok := yylex.(*Lexer); ok { + l.Stmts = yyVAL.stmts + } + } + case 3: + //line parser.go.y:85 + { + yyVAL.stmts = append(yyS[yypt-2].stmts, yyS[yypt-1].stmt) + if l, ok := yylex.(*Lexer); ok { + l.Stmts = yyVAL.stmts + } + } + case 4: + //line parser.go.y:93 + { + yyVAL.stmts = []ast.Stmt{} + } + case 5: + //line parser.go.y:96 + { + yyVAL.stmts = append(yyS[yypt-1].stmts, yyS[yypt-0].stmt) + } + case 6: + //line parser.go.y:99 + { + yyVAL.stmts = yyS[yypt-1].stmts + } + case 7: + //line parser.go.y:104 + { + yyVAL.stmts = yyS[yypt-0].stmts + } + case 8: + //line parser.go.y:109 + { + yyVAL.stmt = &ast.AssignStmt{Lhs: yyS[yypt-2].exprlist, Rhs: yyS[yypt-0].exprlist} + yyVAL.stmt.SetLine(yyS[yypt-2].exprlist[0].Line()) + } + case 9: + //line parser.go.y:114 + { + if _, ok := yyS[yypt-0].expr.(*ast.FuncCallExpr); !ok { + yylex.(*Lexer).Error("parse error") + } else { + yyVAL.stmt = &ast.FuncCallStmt{Expr: yyS[yypt-0].expr} + yyVAL.stmt.SetLine(yyS[yypt-0].expr.Line()) + } + } + case 10: + //line parser.go.y:122 + { + yyVAL.stmt = &ast.DoBlockStmt{Stmts: yyS[yypt-1].stmts} + yyVAL.stmt.SetLine(yyS[yypt-2].token.Pos.Line) + yyVAL.stmt.SetLastLine(yyS[yypt-0].token.Pos.Line) + } + case 11: + //line parser.go.y:127 + { + yyVAL.stmt = &ast.WhileStmt{Condition: yyS[yypt-3].expr, Stmts: yyS[yypt-1].stmts} + yyVAL.stmt.SetLine(yyS[yypt-4].token.Pos.Line) + yyVAL.stmt.SetLastLine(yyS[yypt-0].token.Pos.Line) + } + case 12: + //line parser.go.y:132 + { + yyVAL.stmt = &ast.RepeatStmt{Condition: yyS[yypt-0].expr, Stmts: yyS[yypt-2].stmts} + yyVAL.stmt.SetLine(yyS[yypt-3].token.Pos.Line) + yyVAL.stmt.SetLastLine(yyS[yypt-0].expr.Line()) + } + case 13: + //line parser.go.y:137 + { + yyVAL.stmt = &ast.IfStmt{Condition: yyS[yypt-4].expr, Then: yyS[yypt-2].stmts} + cur := yyVAL.stmt + for _, elseif := range yyS[yypt-1].stmts { + cur.(*ast.IfStmt).Else = []ast.Stmt{elseif} + cur = elseif + } + yyVAL.stmt.SetLine(yyS[yypt-5].token.Pos.Line) + yyVAL.stmt.SetLastLine(yyS[yypt-0].token.Pos.Line) + } + case 14: + //line parser.go.y:147 + { + yyVAL.stmt = &ast.IfStmt{Condition: yyS[yypt-6].expr, Then: yyS[yypt-4].stmts} + cur := yyVAL.stmt + for _, elseif := range yyS[yypt-3].stmts { + cur.(*ast.IfStmt).Else = []ast.Stmt{elseif} + cur = elseif + } + cur.(*ast.IfStmt).Else = yyS[yypt-1].stmts + yyVAL.stmt.SetLine(yyS[yypt-7].token.Pos.Line) + yyVAL.stmt.SetLastLine(yyS[yypt-0].token.Pos.Line) + } + case 15: + //line parser.go.y:158 + { + yyVAL.stmt = &ast.NumberForStmt{Name: yyS[yypt-7].token.Str, Init: yyS[yypt-5].expr, Limit: yyS[yypt-3].expr, Stmts: yyS[yypt-1].stmts} + yyVAL.stmt.SetLine(yyS[yypt-8].token.Pos.Line) + yyVAL.stmt.SetLastLine(yyS[yypt-0].token.Pos.Line) + } + case 16: + //line parser.go.y:163 + { + yyVAL.stmt = &ast.NumberForStmt{Name: yyS[yypt-9].token.Str, Init: yyS[yypt-7].expr, Limit: yyS[yypt-5].expr, Step: yyS[yypt-3].expr, Stmts: yyS[yypt-1].stmts} + yyVAL.stmt.SetLine(yyS[yypt-10].token.Pos.Line) + yyVAL.stmt.SetLastLine(yyS[yypt-0].token.Pos.Line) + } + case 17: + //line parser.go.y:168 + { + yyVAL.stmt = &ast.GenericForStmt{Names: yyS[yypt-5].namelist, Exprs: yyS[yypt-3].exprlist, Stmts: yyS[yypt-1].stmts} + yyVAL.stmt.SetLine(yyS[yypt-6].token.Pos.Line) + yyVAL.stmt.SetLastLine(yyS[yypt-0].token.Pos.Line) + } + case 18: + //line parser.go.y:173 + { + yyVAL.stmt = &ast.FuncDefStmt{Name: yyS[yypt-1].funcname, Func: yyS[yypt-0].funcexpr} + yyVAL.stmt.SetLine(yyS[yypt-2].token.Pos.Line) + yyVAL.stmt.SetLastLine(yyS[yypt-0].funcexpr.LastLine()) + } + case 19: + //line parser.go.y:178 + { + yyVAL.stmt = &ast.LocalAssignStmt{Names: []string{yyS[yypt-1].token.Str}, Exprs: []ast.Expr{yyS[yypt-0].funcexpr}} + yyVAL.stmt.SetLine(yyS[yypt-3].token.Pos.Line) + yyVAL.stmt.SetLastLine(yyS[yypt-0].funcexpr.LastLine()) + } + case 20: + //line parser.go.y:183 + { + yyVAL.stmt = &ast.LocalAssignStmt{Names: yyS[yypt-2].namelist, Exprs: yyS[yypt-0].exprlist} + yyVAL.stmt.SetLine(yyS[yypt-3].token.Pos.Line) + } + case 21: + //line parser.go.y:187 + { + yyVAL.stmt = &ast.LocalAssignStmt{Names: yyS[yypt-0].namelist, Exprs: []ast.Expr{}} + yyVAL.stmt.SetLine(yyS[yypt-1].token.Pos.Line) + } + case 22: + //line parser.go.y:193 + { + yyVAL.stmts = []ast.Stmt{} + } + case 23: + //line parser.go.y:196 + { + yyVAL.stmts = append(yyS[yypt-4].stmts, &ast.IfStmt{Condition: yyS[yypt-2].expr, Then: yyS[yypt-0].stmts}) + yyVAL.stmts[len(yyVAL.stmts)-1].SetLine(yyS[yypt-3].token.Pos.Line) + } + case 24: + //line parser.go.y:202 + { + yyVAL.stmt = &ast.ReturnStmt{Exprs: nil} + yyVAL.stmt.SetLine(yyS[yypt-0].token.Pos.Line) + } + case 25: + //line parser.go.y:206 + { + yyVAL.stmt = &ast.ReturnStmt{Exprs: yyS[yypt-0].exprlist} + yyVAL.stmt.SetLine(yyS[yypt-1].token.Pos.Line) + } + case 26: + //line parser.go.y:210 + { + yyVAL.stmt = &ast.BreakStmt{} + yyVAL.stmt.SetLine(yyS[yypt-0].token.Pos.Line) + } + case 27: + //line parser.go.y:216 + { + yyVAL.funcname = yyS[yypt-0].funcname + } + case 28: + //line parser.go.y:219 + { + yyVAL.funcname = &ast.FuncName{Func: nil, Receiver: yyS[yypt-2].funcname.Func, Method: yyS[yypt-0].token.Str} + } + case 29: + //line parser.go.y:224 + { + yyVAL.funcname = &ast.FuncName{Func: &ast.IdentExpr{Value: yyS[yypt-0].token.Str}} + yyVAL.funcname.Func.SetLine(yyS[yypt-0].token.Pos.Line) + } + case 30: + //line parser.go.y:228 + { + key := &ast.StringExpr{Value: yyS[yypt-0].token.Str} + key.SetLine(yyS[yypt-0].token.Pos.Line) + fn := &ast.AttrGetExpr{Object: yyS[yypt-2].funcname.Func, Key: key} + fn.SetLine(yyS[yypt-0].token.Pos.Line) + yyVAL.funcname = &ast.FuncName{Func: fn} + } + case 31: + //line parser.go.y:237 + { + yyVAL.exprlist = []ast.Expr{yyS[yypt-0].expr} + } + case 32: + //line parser.go.y:240 + { + yyVAL.exprlist = append(yyS[yypt-2].exprlist, yyS[yypt-0].expr) + } + case 33: + //line parser.go.y:245 + { + yyVAL.expr = &ast.IdentExpr{Value: yyS[yypt-0].token.Str} + yyVAL.expr.SetLine(yyS[yypt-0].token.Pos.Line) + } + case 34: + //line parser.go.y:249 + { + yyVAL.expr = &ast.AttrGetExpr{Object: yyS[yypt-3].expr, Key: yyS[yypt-1].expr} + yyVAL.expr.SetLine(yyS[yypt-3].expr.Line()) + } + case 35: + //line parser.go.y:253 + { + key := &ast.StringExpr{Value: yyS[yypt-0].token.Str} + key.SetLine(yyS[yypt-0].token.Pos.Line) + yyVAL.expr = &ast.AttrGetExpr{Object: yyS[yypt-2].expr, Key: key} + yyVAL.expr.SetLine(yyS[yypt-2].expr.Line()) + } + case 36: + //line parser.go.y:261 + { + yyVAL.namelist = []string{yyS[yypt-0].token.Str} + } + case 37: + //line parser.go.y:264 + { + yyVAL.namelist = append(yyS[yypt-2].namelist, yyS[yypt-0].token.Str) + } + case 38: + //line parser.go.y:269 + { + yyVAL.exprlist = []ast.Expr{yyS[yypt-0].expr} + } + case 39: + //line parser.go.y:272 + { + yyVAL.exprlist = append(yyS[yypt-2].exprlist, yyS[yypt-0].expr) + } + case 40: + //line parser.go.y:277 + { + yyVAL.expr = &ast.NilExpr{} + yyVAL.expr.SetLine(yyS[yypt-0].token.Pos.Line) + } + case 41: + //line parser.go.y:281 + { + yyVAL.expr = &ast.FalseExpr{} + yyVAL.expr.SetLine(yyS[yypt-0].token.Pos.Line) + } + case 42: + //line parser.go.y:285 + { + yyVAL.expr = &ast.TrueExpr{} + yyVAL.expr.SetLine(yyS[yypt-0].token.Pos.Line) + } + case 43: + //line parser.go.y:289 + { + yyVAL.expr = &ast.NumberExpr{Value: yyS[yypt-0].token.Str} + yyVAL.expr.SetLine(yyS[yypt-0].token.Pos.Line) + } + case 44: + //line parser.go.y:293 + { + yyVAL.expr = &ast.Comma3Expr{} + yyVAL.expr.SetLine(yyS[yypt-0].token.Pos.Line) + } + case 45: + //line parser.go.y:297 + { + yyVAL.expr = yyS[yypt-0].expr + } + case 46: + //line parser.go.y:300 + { + yyVAL.expr = yyS[yypt-0].expr + } + case 47: + //line parser.go.y:303 + { + yyVAL.expr = yyS[yypt-0].expr + } + case 48: + //line parser.go.y:306 + { + yyVAL.expr = yyS[yypt-0].expr + } + case 49: + //line parser.go.y:309 + { + yyVAL.expr = &ast.LogicalOpExpr{Lhs: yyS[yypt-2].expr, Operator: "or", Rhs: yyS[yypt-0].expr} + yyVAL.expr.SetLine(yyS[yypt-2].expr.Line()) + } + case 50: + //line parser.go.y:313 + { + yyVAL.expr = &ast.LogicalOpExpr{Lhs: yyS[yypt-2].expr, Operator: "and", Rhs: yyS[yypt-0].expr} + yyVAL.expr.SetLine(yyS[yypt-2].expr.Line()) + } + case 51: + //line parser.go.y:317 + { + yyVAL.expr = &ast.RelationalOpExpr{Lhs: yyS[yypt-2].expr, Operator: ">", Rhs: yyS[yypt-0].expr} + yyVAL.expr.SetLine(yyS[yypt-2].expr.Line()) + } + case 52: + //line parser.go.y:321 + { + yyVAL.expr = &ast.RelationalOpExpr{Lhs: yyS[yypt-2].expr, Operator: "<", Rhs: yyS[yypt-0].expr} + yyVAL.expr.SetLine(yyS[yypt-2].expr.Line()) + } + case 53: + //line parser.go.y:325 + { + yyVAL.expr = &ast.RelationalOpExpr{Lhs: yyS[yypt-2].expr, Operator: ">=", Rhs: yyS[yypt-0].expr} + yyVAL.expr.SetLine(yyS[yypt-2].expr.Line()) + } + case 54: + //line parser.go.y:329 + { + yyVAL.expr = &ast.RelationalOpExpr{Lhs: yyS[yypt-2].expr, Operator: "<=", Rhs: yyS[yypt-0].expr} + yyVAL.expr.SetLine(yyS[yypt-2].expr.Line()) + } + case 55: + //line parser.go.y:333 + { + yyVAL.expr = &ast.RelationalOpExpr{Lhs: yyS[yypt-2].expr, Operator: "==", Rhs: yyS[yypt-0].expr} + yyVAL.expr.SetLine(yyS[yypt-2].expr.Line()) + } + case 56: + //line parser.go.y:337 + { + yyVAL.expr = &ast.RelationalOpExpr{Lhs: yyS[yypt-2].expr, Operator: "~=", Rhs: yyS[yypt-0].expr} + yyVAL.expr.SetLine(yyS[yypt-2].expr.Line()) + } + case 57: + //line parser.go.y:341 + { + yyVAL.expr = &ast.StringConcatOpExpr{Lhs: yyS[yypt-2].expr, Rhs: yyS[yypt-0].expr} + yyVAL.expr.SetLine(yyS[yypt-2].expr.Line()) + } + case 58: + //line parser.go.y:345 + { + yyVAL.expr = &ast.ArithmeticOpExpr{Lhs: yyS[yypt-2].expr, Operator: "+", Rhs: yyS[yypt-0].expr} + yyVAL.expr.SetLine(yyS[yypt-2].expr.Line()) + } + case 59: + //line parser.go.y:349 + { + yyVAL.expr = &ast.ArithmeticOpExpr{Lhs: yyS[yypt-2].expr, Operator: "-", Rhs: yyS[yypt-0].expr} + yyVAL.expr.SetLine(yyS[yypt-2].expr.Line()) + } + case 60: + //line parser.go.y:353 + { + yyVAL.expr = &ast.ArithmeticOpExpr{Lhs: yyS[yypt-2].expr, Operator: "*", Rhs: yyS[yypt-0].expr} + yyVAL.expr.SetLine(yyS[yypt-2].expr.Line()) + } + case 61: + //line parser.go.y:357 + { + yyVAL.expr = &ast.ArithmeticOpExpr{Lhs: yyS[yypt-2].expr, Operator: "/", Rhs: yyS[yypt-0].expr} + yyVAL.expr.SetLine(yyS[yypt-2].expr.Line()) + } + case 62: + //line parser.go.y:361 + { + yyVAL.expr = &ast.ArithmeticOpExpr{Lhs: yyS[yypt-2].expr, Operator: "%", Rhs: yyS[yypt-0].expr} + yyVAL.expr.SetLine(yyS[yypt-2].expr.Line()) + } + case 63: + //line parser.go.y:365 + { + yyVAL.expr = &ast.ArithmeticOpExpr{Lhs: yyS[yypt-2].expr, Operator: "^", Rhs: yyS[yypt-0].expr} + yyVAL.expr.SetLine(yyS[yypt-2].expr.Line()) + } + case 64: + //line parser.go.y:369 + { + yyVAL.expr = &ast.UnaryMinusOpExpr{Expr: yyS[yypt-0].expr} + yyVAL.expr.SetLine(yyS[yypt-0].expr.Line()) + } + case 65: + //line parser.go.y:373 + { + yyVAL.expr = &ast.UnaryNotOpExpr{Expr: yyS[yypt-0].expr} + yyVAL.expr.SetLine(yyS[yypt-0].expr.Line()) + } + case 66: + //line parser.go.y:377 + { + yyVAL.expr = &ast.UnaryLenOpExpr{Expr: yyS[yypt-0].expr} + yyVAL.expr.SetLine(yyS[yypt-0].expr.Line()) + } + case 67: + //line parser.go.y:383 + { + yyVAL.expr = &ast.StringExpr{Value: yyS[yypt-0].token.Str} + yyVAL.expr.SetLine(yyS[yypt-0].token.Pos.Line) + } + case 68: + //line parser.go.y:389 + { + yyVAL.expr = yyS[yypt-0].expr + } + case 69: + //line parser.go.y:392 + { + yyVAL.expr = yyS[yypt-0].expr + } + case 70: + //line parser.go.y:395 + { + yyVAL.expr = yyS[yypt-0].expr + } + case 71: + //line parser.go.y:398 + { + yyVAL.expr = yyS[yypt-1].expr + yyVAL.expr.SetLine(yyS[yypt-2].token.Pos.Line) + } + case 72: + //line parser.go.y:404 + { + yyS[yypt-1].expr.(*ast.FuncCallExpr).AdjustRet = true + yyVAL.expr = yyS[yypt-1].expr + } + case 73: + //line parser.go.y:410 + { + yyVAL.expr = &ast.FuncCallExpr{Func: yyS[yypt-1].expr, Args: yyS[yypt-0].exprlist} + yyVAL.expr.SetLine(yyS[yypt-1].expr.Line()) + } + case 74: + //line parser.go.y:414 + { + yyVAL.expr = &ast.FuncCallExpr{Method: yyS[yypt-1].token.Str, Receiver: yyS[yypt-3].expr, Args: yyS[yypt-0].exprlist} + yyVAL.expr.SetLine(yyS[yypt-3].expr.Line()) + } + case 75: + //line parser.go.y:420 + { + if yylex.(*Lexer).PNewLine { + yylex.(*Lexer).TokenError(yyS[yypt-1].token, "ambiguous syntax (function call x new statement)") + } + yyVAL.exprlist = []ast.Expr{} + } + case 76: + //line parser.go.y:426 + { + if yylex.(*Lexer).PNewLine { + yylex.(*Lexer).TokenError(yyS[yypt-2].token, "ambiguous syntax (function call x new statement)") + } + yyVAL.exprlist = yyS[yypt-1].exprlist + } + case 77: + //line parser.go.y:432 + { + yyVAL.exprlist = []ast.Expr{yyS[yypt-0].expr} + } + case 78: + //line parser.go.y:435 + { + yyVAL.exprlist = []ast.Expr{yyS[yypt-0].expr} + } + case 79: + //line parser.go.y:440 + { + yyVAL.expr = &ast.FunctionExpr{ParList: yyS[yypt-0].funcexpr.ParList, Stmts: yyS[yypt-0].funcexpr.Stmts} + yyVAL.expr.SetLine(yyS[yypt-1].token.Pos.Line) + yyVAL.expr.SetLastLine(yyS[yypt-0].funcexpr.LastLine()) + } + case 80: + //line parser.go.y:447 + { + yyVAL.funcexpr = &ast.FunctionExpr{ParList: yyS[yypt-3].parlist, Stmts: yyS[yypt-1].stmts} + yyVAL.funcexpr.SetLine(yyS[yypt-4].token.Pos.Line) + yyVAL.funcexpr.SetLastLine(yyS[yypt-0].token.Pos.Line) + } + case 81: + //line parser.go.y:452 + { + yyVAL.funcexpr = &ast.FunctionExpr{ParList: &ast.ParList{HasVargs: false, Names: []string{}}, Stmts: yyS[yypt-1].stmts} + yyVAL.funcexpr.SetLine(yyS[yypt-3].token.Pos.Line) + yyVAL.funcexpr.SetLastLine(yyS[yypt-0].token.Pos.Line) + } + case 82: + //line parser.go.y:459 + { + yyVAL.parlist = &ast.ParList{HasVargs: true, Names: []string{}} + } + case 83: + //line parser.go.y:462 + { + yyVAL.parlist = &ast.ParList{HasVargs: false, Names: []string{}} + yyVAL.parlist.Names = append(yyVAL.parlist.Names, yyS[yypt-0].namelist...) + } + case 84: + //line parser.go.y:466 + { + yyVAL.parlist = &ast.ParList{HasVargs: true, Names: []string{}} + yyVAL.parlist.Names = append(yyVAL.parlist.Names, yyS[yypt-2].namelist...) + } + case 85: + //line parser.go.y:473 + { + yyVAL.expr = &ast.TableExpr{Fields: []*ast.Field{}} + yyVAL.expr.SetLine(yyS[yypt-1].token.Pos.Line) + } + case 86: + //line parser.go.y:477 + { + yyVAL.expr = &ast.TableExpr{Fields: yyS[yypt-1].fieldlist} + yyVAL.expr.SetLine(yyS[yypt-2].token.Pos.Line) + } + case 87: + //line parser.go.y:484 + { + yyVAL.fieldlist = []*ast.Field{yyS[yypt-0].field} + } + case 88: + //line parser.go.y:487 + { + yyVAL.fieldlist = append(yyS[yypt-2].fieldlist, yyS[yypt-0].field) + } + case 89: + //line parser.go.y:490 + { + yyVAL.fieldlist = yyS[yypt-1].fieldlist + } + case 90: + //line parser.go.y:495 + { + yyVAL.field = &ast.Field{Key: &ast.StringExpr{Value: yyS[yypt-2].token.Str}, Value: yyS[yypt-0].expr} + yyVAL.field.Key.SetLine(yyS[yypt-2].token.Pos.Line) + } + case 91: + //line parser.go.y:499 + { + yyVAL.field = &ast.Field{Key: yyS[yypt-3].expr, Value: yyS[yypt-0].expr} + } + case 92: + //line parser.go.y:502 + { + yyVAL.field = &ast.Field{Value: yyS[yypt-0].expr} + } + case 93: + //line parser.go.y:507 + { + yyVAL.fieldsep = "," + } + case 94: + //line parser.go.y:510 + { + yyVAL.fieldsep = ";" + } + } + goto yystack /* stack new state and value */ +} diff --git a/vendor/github.com/yuin/gopher-lua/parse/parser.go.y b/vendor/github.com/yuin/gopher-lua/parse/parser.go.y new file mode 100644 index 0000000000000000000000000000000000000000..956133db29242ffbcc220f52fef46bada25bed7b --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/parse/parser.go.y @@ -0,0 +1,524 @@ +%{ +package parse + +import ( + "github.com/yuin/gopher-lua/ast" +) +%} +%type chunk +%type chunk1 +%type block +%type stat +%type elseifs +%type laststat +%type funcname +%type funcname1 +%type varlist +%type var +%type namelist +%type exprlist +%type expr +%type string +%type prefixexp +%type functioncall +%type afunctioncall +%type args +%type function +%type funcbody +%type parlist +%type tableconstructor +%type fieldlist +%type field +%type fieldsep + +%union { + token ast.Token + + stmts []ast.Stmt + stmt ast.Stmt + + funcname *ast.FuncName + funcexpr *ast.FunctionExpr + + exprlist []ast.Expr + expr ast.Expr + + fieldlist []*ast.Field + field *ast.Field + fieldsep string + + namelist []string + parlist *ast.ParList +} + +/* Reserved words */ +%token TAnd TBreak TDo TElse TElseIf TEnd TFalse TFor TFunction TIf TIn TLocal TNil TNot TOr TReturn TRepeat TThen TTrue TUntil TWhile + +/* Literals */ +%token TEqeq TNeq TLte TGte T2Comma T3Comma TIdent TNumber TString '{' '(' + +/* Operators */ +%left TOr +%left TAnd +%left '>' '<' TGte TLte TEqeq TNeq +%right T2Comma +%left '+' '-' +%left '*' '/' '%' +%right UNARY /* not # -(unary) */ +%right '^' + +%% + +chunk: + chunk1 { + $$ = $1 + if l, ok := yylex.(*Lexer); ok { + l.Stmts = $$ + } + } | + chunk1 laststat { + $$ = append($1, $2) + if l, ok := yylex.(*Lexer); ok { + l.Stmts = $$ + } + } | + chunk1 laststat ';' { + $$ = append($1, $2) + if l, ok := yylex.(*Lexer); ok { + l.Stmts = $$ + } + } + +chunk1: + { + $$ = []ast.Stmt{} + } | + chunk1 stat { + $$ = append($1, $2) + } | + chunk1 ';' { + $$ = $1 + } + +block: + chunk { + $$ = $1 + } + +stat: + varlist '=' exprlist { + $$ = &ast.AssignStmt{Lhs: $1, Rhs: $3} + $$.SetLine($1[0].Line()) + } | + /* 'stat = functioncal' causes a reduce/reduce conflict */ + prefixexp { + if _, ok := $1.(*ast.FuncCallExpr); !ok { + yylex.(*Lexer).Error("parse error") + } else { + $$ = &ast.FuncCallStmt{Expr: $1} + $$.SetLine($1.Line()) + } + } | + TDo block TEnd { + $$ = &ast.DoBlockStmt{Stmts: $2} + $$.SetLine($1.Pos.Line) + $$.SetLastLine($3.Pos.Line) + } | + TWhile expr TDo block TEnd { + $$ = &ast.WhileStmt{Condition: $2, Stmts: $4} + $$.SetLine($1.Pos.Line) + $$.SetLastLine($5.Pos.Line) + } | + TRepeat block TUntil expr { + $$ = &ast.RepeatStmt{Condition: $4, Stmts: $2} + $$.SetLine($1.Pos.Line) + $$.SetLastLine($4.Line()) + } | + TIf expr TThen block elseifs TEnd { + $$ = &ast.IfStmt{Condition: $2, Then: $4} + cur := $$ + for _, elseif := range $5 { + cur.(*ast.IfStmt).Else = []ast.Stmt{elseif} + cur = elseif + } + $$.SetLine($1.Pos.Line) + $$.SetLastLine($6.Pos.Line) + } | + TIf expr TThen block elseifs TElse block TEnd { + $$ = &ast.IfStmt{Condition: $2, Then: $4} + cur := $$ + for _, elseif := range $5 { + cur.(*ast.IfStmt).Else = []ast.Stmt{elseif} + cur = elseif + } + cur.(*ast.IfStmt).Else = $7 + $$.SetLine($1.Pos.Line) + $$.SetLastLine($8.Pos.Line) + } | + TFor TIdent '=' expr ',' expr TDo block TEnd { + $$ = &ast.NumberForStmt{Name: $2.Str, Init: $4, Limit: $6, Stmts: $8} + $$.SetLine($1.Pos.Line) + $$.SetLastLine($9.Pos.Line) + } | + TFor TIdent '=' expr ',' expr ',' expr TDo block TEnd { + $$ = &ast.NumberForStmt{Name: $2.Str, Init: $4, Limit: $6, Step:$8, Stmts: $10} + $$.SetLine($1.Pos.Line) + $$.SetLastLine($11.Pos.Line) + } | + TFor namelist TIn exprlist TDo block TEnd { + $$ = &ast.GenericForStmt{Names:$2, Exprs:$4, Stmts: $6} + $$.SetLine($1.Pos.Line) + $$.SetLastLine($7.Pos.Line) + } | + TFunction funcname funcbody { + $$ = &ast.FuncDefStmt{Name: $2, Func: $3} + $$.SetLine($1.Pos.Line) + $$.SetLastLine($3.LastLine()) + } | + TLocal TFunction TIdent funcbody { + $$ = &ast.LocalAssignStmt{Names:[]string{$3.Str}, Exprs: []ast.Expr{$4}} + $$.SetLine($1.Pos.Line) + $$.SetLastLine($4.LastLine()) + } | + TLocal namelist '=' exprlist { + $$ = &ast.LocalAssignStmt{Names: $2, Exprs:$4} + $$.SetLine($1.Pos.Line) + } | + TLocal namelist { + $$ = &ast.LocalAssignStmt{Names: $2, Exprs:[]ast.Expr{}} + $$.SetLine($1.Pos.Line) + } + +elseifs: + { + $$ = []ast.Stmt{} + } | + elseifs TElseIf expr TThen block { + $$ = append($1, &ast.IfStmt{Condition: $3, Then: $5}) + $$[len($$)-1].SetLine($2.Pos.Line) + } + +laststat: + TReturn { + $$ = &ast.ReturnStmt{Exprs:nil} + $$.SetLine($1.Pos.Line) + } | + TReturn exprlist { + $$ = &ast.ReturnStmt{Exprs:$2} + $$.SetLine($1.Pos.Line) + } | + TBreak { + $$ = &ast.BreakStmt{} + $$.SetLine($1.Pos.Line) + } + +funcname: + funcname1 { + $$ = $1 + } | + funcname1 ':' TIdent { + $$ = &ast.FuncName{Func:nil, Receiver:$1.Func, Method: $3.Str} + } + +funcname1: + TIdent { + $$ = &ast.FuncName{Func: &ast.IdentExpr{Value:$1.Str}} + $$.Func.SetLine($1.Pos.Line) + } | + funcname1 '.' TIdent { + key:= &ast.StringExpr{Value:$3.Str} + key.SetLine($3.Pos.Line) + fn := &ast.AttrGetExpr{Object: $1.Func, Key: key} + fn.SetLine($3.Pos.Line) + $$ = &ast.FuncName{Func: fn} + } + +varlist: + var { + $$ = []ast.Expr{$1} + } | + varlist ',' var { + $$ = append($1, $3) + } + +var: + TIdent { + $$ = &ast.IdentExpr{Value:$1.Str} + $$.SetLine($1.Pos.Line) + } | + prefixexp '[' expr ']' { + $$ = &ast.AttrGetExpr{Object: $1, Key: $3} + $$.SetLine($1.Line()) + } | + prefixexp '.' TIdent { + key := &ast.StringExpr{Value:$3.Str} + key.SetLine($3.Pos.Line) + $$ = &ast.AttrGetExpr{Object: $1, Key: key} + $$.SetLine($1.Line()) + } + +namelist: + TIdent { + $$ = []string{$1.Str} + } | + namelist ',' TIdent { + $$ = append($1, $3.Str) + } + +exprlist: + expr { + $$ = []ast.Expr{$1} + } | + exprlist ',' expr { + $$ = append($1, $3) + } + +expr: + TNil { + $$ = &ast.NilExpr{} + $$.SetLine($1.Pos.Line) + } | + TFalse { + $$ = &ast.FalseExpr{} + $$.SetLine($1.Pos.Line) + } | + TTrue { + $$ = &ast.TrueExpr{} + $$.SetLine($1.Pos.Line) + } | + TNumber { + $$ = &ast.NumberExpr{Value: $1.Str} + $$.SetLine($1.Pos.Line) + } | + T3Comma { + $$ = &ast.Comma3Expr{} + $$.SetLine($1.Pos.Line) + } | + function { + $$ = $1 + } | + prefixexp { + $$ = $1 + } | + string { + $$ = $1 + } | + tableconstructor { + $$ = $1 + } | + expr TOr expr { + $$ = &ast.LogicalOpExpr{Lhs: $1, Operator: "or", Rhs: $3} + $$.SetLine($1.Line()) + } | + expr TAnd expr { + $$ = &ast.LogicalOpExpr{Lhs: $1, Operator: "and", Rhs: $3} + $$.SetLine($1.Line()) + } | + expr '>' expr { + $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: ">", Rhs: $3} + $$.SetLine($1.Line()) + } | + expr '<' expr { + $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: "<", Rhs: $3} + $$.SetLine($1.Line()) + } | + expr TGte expr { + $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: ">=", Rhs: $3} + $$.SetLine($1.Line()) + } | + expr TLte expr { + $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: "<=", Rhs: $3} + $$.SetLine($1.Line()) + } | + expr TEqeq expr { + $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: "==", Rhs: $3} + $$.SetLine($1.Line()) + } | + expr TNeq expr { + $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: "~=", Rhs: $3} + $$.SetLine($1.Line()) + } | + expr T2Comma expr { + $$ = &ast.StringConcatOpExpr{Lhs: $1, Rhs: $3} + $$.SetLine($1.Line()) + } | + expr '+' expr { + $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "+", Rhs: $3} + $$.SetLine($1.Line()) + } | + expr '-' expr { + $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "-", Rhs: $3} + $$.SetLine($1.Line()) + } | + expr '*' expr { + $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "*", Rhs: $3} + $$.SetLine($1.Line()) + } | + expr '/' expr { + $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "/", Rhs: $3} + $$.SetLine($1.Line()) + } | + expr '%' expr { + $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "%", Rhs: $3} + $$.SetLine($1.Line()) + } | + expr '^' expr { + $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "^", Rhs: $3} + $$.SetLine($1.Line()) + } | + '-' expr %prec UNARY { + $$ = &ast.UnaryMinusOpExpr{Expr: $2} + $$.SetLine($2.Line()) + } | + TNot expr %prec UNARY { + $$ = &ast.UnaryNotOpExpr{Expr: $2} + $$.SetLine($2.Line()) + } | + '#' expr %prec UNARY { + $$ = &ast.UnaryLenOpExpr{Expr: $2} + $$.SetLine($2.Line()) + } + +string: + TString { + $$ = &ast.StringExpr{Value: $1.Str} + $$.SetLine($1.Pos.Line) + } + +prefixexp: + var { + $$ = $1 + } | + afunctioncall { + $$ = $1 + } | + functioncall { + $$ = $1 + } | + '(' expr ')' { + $$ = $2 + $$.SetLine($1.Pos.Line) + } + +afunctioncall: + '(' functioncall ')' { + $2.(*ast.FuncCallExpr).AdjustRet = true + $$ = $2 + } + +functioncall: + prefixexp args { + $$ = &ast.FuncCallExpr{Func: $1, Args: $2} + $$.SetLine($1.Line()) + } | + prefixexp ':' TIdent args { + $$ = &ast.FuncCallExpr{Method: $3.Str, Receiver: $1, Args: $4} + $$.SetLine($1.Line()) + } + +args: + '(' ')' { + if yylex.(*Lexer).PNewLine { + yylex.(*Lexer).TokenError($1, "ambiguous syntax (function call x new statement)") + } + $$ = []ast.Expr{} + } | + '(' exprlist ')' { + if yylex.(*Lexer).PNewLine { + yylex.(*Lexer).TokenError($1, "ambiguous syntax (function call x new statement)") + } + $$ = $2 + } | + tableconstructor { + $$ = []ast.Expr{$1} + } | + string { + $$ = []ast.Expr{$1} + } + +function: + TFunction funcbody { + $$ = &ast.FunctionExpr{ParList:$2.ParList, Stmts: $2.Stmts} + $$.SetLine($1.Pos.Line) + $$.SetLastLine($2.LastLine()) + } + +funcbody: + '(' parlist ')' block TEnd { + $$ = &ast.FunctionExpr{ParList: $2, Stmts: $4} + $$.SetLine($1.Pos.Line) + $$.SetLastLine($5.Pos.Line) + } | + '(' ')' block TEnd { + $$ = &ast.FunctionExpr{ParList: &ast.ParList{HasVargs: false, Names: []string{}}, Stmts: $3} + $$.SetLine($1.Pos.Line) + $$.SetLastLine($4.Pos.Line) + } + +parlist: + T3Comma { + $$ = &ast.ParList{HasVargs: true, Names: []string{}} + } | + namelist { + $$ = &ast.ParList{HasVargs: false, Names: []string{}} + $$.Names = append($$.Names, $1...) + } | + namelist ',' T3Comma { + $$ = &ast.ParList{HasVargs: true, Names: []string{}} + $$.Names = append($$.Names, $1...) + } + + +tableconstructor: + '{' '}' { + $$ = &ast.TableExpr{Fields: []*ast.Field{}} + $$.SetLine($1.Pos.Line) + } | + '{' fieldlist '}' { + $$ = &ast.TableExpr{Fields: $2} + $$.SetLine($1.Pos.Line) + } + + +fieldlist: + field { + $$ = []*ast.Field{$1} + } | + fieldlist fieldsep field { + $$ = append($1, $3) + } | + fieldlist fieldsep { + $$ = $1 + } + +field: + TIdent '=' expr { + $$ = &ast.Field{Key: &ast.StringExpr{Value:$1.Str}, Value: $3} + $$.Key.SetLine($1.Pos.Line) + } | + '[' expr ']' '=' expr { + $$ = &ast.Field{Key: $2, Value: $5} + } | + expr { + $$ = &ast.Field{Value: $1} + } + +fieldsep: + ',' { + $$ = "," + } | + ';' { + $$ = ";" + } + +%% + +func TokenName(c int) string { + if c >= TAnd && c-TAnd < len(yyToknames) { + if yyToknames[c-TAnd] != "" { + return yyToknames[c-TAnd] + } + } + return string([]byte{byte(c)}) +} + diff --git a/vendor/github.com/yuin/gopher-lua/pm/pm.go b/vendor/github.com/yuin/gopher-lua/pm/pm.go new file mode 100644 index 0000000000000000000000000000000000000000..cd13bbde1b68abb04be30a6d721af5526cadb372 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/pm/pm.go @@ -0,0 +1,639 @@ +// Lua pattern match functions for Go +package pm + +import ( + "fmt" +) + +const EOS = -1 +const _UNKNOWN = -2 + +/* Error {{{ */ + +type Error struct { + Pos int + Message string +} + +func newError(pos int, message string, args ...interface{}) *Error { + if len(args) == 0 { + return &Error{pos, message} + } + return &Error{pos, fmt.Sprintf(message, args...)} +} + +func (e *Error) Error() string { + switch e.Pos { + case EOS: + return fmt.Sprintf("%s at EOS", e.Message) + case _UNKNOWN: + return fmt.Sprintf("%s", e.Message) + default: + return fmt.Sprintf("%s at %d", e.Message, e.Pos) + } +} + +/* }}} */ + +/* MatchData {{{ */ + +type MatchData struct { + // captured positions + // layout + // xxxx xxxx xxxx xxx0 : caputured positions + // xxxx xxxx xxxx xxx1 : position captured positions + captures []uint32 +} + +func newMatchState() *MatchData { return &MatchData{[]uint32{}} } + +func (st *MatchData) addPosCapture(s, pos int) { + for s+1 >= len(st.captures) { + st.captures = append(st.captures, 0) + } + st.captures[s] = (uint32(pos) << 1) | 1 + st.captures[s+1] = (uint32(pos) << 1) | 1 +} + +func (st *MatchData) setCapture(s, pos int) uint32 { + for s >= len(st.captures) { + st.captures = append(st.captures, 0) + } + v := st.captures[s] + st.captures[s] = (uint32(pos) << 1) + return v +} + +func (st *MatchData) restoreCapture(s int, pos uint32) { st.captures[s] = pos } + +func (st *MatchData) CaptureLength() int { return len(st.captures) } + +func (st *MatchData) IsPosCapture(idx int) bool { return (st.captures[idx] & 1) == 1 } + +func (st *MatchData) Capture(idx int) int { return int(st.captures[idx] >> 1) } + +/* }}} */ + +/* scanner {{{ */ + +type scannerState struct { + Pos int + started bool +} + +type scanner struct { + src []byte + State scannerState + saved scannerState +} + +func newScanner(src []byte) *scanner { + return &scanner{ + src: src, + State: scannerState{ + Pos: 0, + started: false, + }, + saved: scannerState{}, + } +} + +func (sc *scanner) Length() int { return len(sc.src) } + +func (sc *scanner) Next() int { + if !sc.State.started { + sc.State.started = true + if len(sc.src) == 0 { + sc.State.Pos = EOS + } + } else { + sc.State.Pos = sc.NextPos() + } + if sc.State.Pos == EOS { + return EOS + } + return int(sc.src[sc.State.Pos]) +} + +func (sc *scanner) CurrentPos() int { + return sc.State.Pos +} + +func (sc *scanner) NextPos() int { + if sc.State.Pos == EOS || sc.State.Pos >= len(sc.src)-1 { + return EOS + } + if !sc.State.started { + return 0 + } else { + return sc.State.Pos + 1 + } +} + +func (sc *scanner) Peek() int { + cureof := sc.State.Pos == EOS + ch := sc.Next() + if !cureof { + if sc.State.Pos == EOS { + sc.State.Pos = len(sc.src) - 1 + } else { + sc.State.Pos-- + if sc.State.Pos < 0 { + sc.State.Pos = 0 + sc.State.started = false + } + } + } + return ch +} + +func (sc *scanner) Save() { sc.saved = sc.State } + +func (sc *scanner) Restore() { sc.State = sc.saved } + +/* }}} */ + +/* bytecode {{{ */ + +type opCode int + +const ( + opChar opCode = iota + opMatch + opTailMatch + opJmp + opSplit + opSave + opPSave + opBrace + opNumber +) + +type inst struct { + OpCode opCode + Class class + Operand1 int + Operand2 int +} + +/* }}} */ + +/* classes {{{ */ + +type class interface { + Matches(ch int) bool +} + +type dotClass struct{} + +func (pn *dotClass) Matches(ch int) bool { return true } + +type charClass struct { + Ch int +} + +func (pn *charClass) Matches(ch int) bool { return pn.Ch == ch } + +type singleClass struct { + Class int +} + +func (pn *singleClass) Matches(ch int) bool { + ret := false + switch pn.Class { + case 'a', 'A': + ret = 'A' <= ch && ch <= 'Z' || 'a' <= ch && ch <= 'z' + case 'c', 'C': + ret = (0x00 <= ch && ch <= 0x1F) || ch == 0x7F + case 'd', 'D': + ret = '0' <= ch && ch <= '9' + case 'l', 'L': + ret = 'a' <= ch && ch <= 'z' + case 'p', 'P': + ret = (0x21 <= ch && ch <= 0x2f) || (0x30 <= ch && ch <= 0x40) || (0x5b <= ch && ch <= 0x60) || (0x7b <= ch && ch <= 0x7e) + case 's', 'S': + switch ch { + case ' ', '\f', '\n', '\r', '\t', '\v': + ret = true + } + case 'u', 'U': + ret = 'A' <= ch && ch <= 'Z' + case 'w', 'W': + ret = '0' <= ch && ch <= '9' || 'A' <= ch && ch <= 'Z' || 'a' <= ch && ch <= 'z' + case 'x', 'X': + ret = '0' <= ch && ch <= '9' || 'a' <= ch && ch <= 'f' || 'A' <= ch && ch <= 'F' + case 'z', 'Z': + ret = ch == 0 + default: + return ch == pn.Class + } + if 'A' <= pn.Class && pn.Class <= 'Z' { + return !ret + } + return ret +} + +type setClass struct { + IsNot bool + Classes []class +} + +func (pn *setClass) Matches(ch int) bool { + for _, class := range pn.Classes { + if class.Matches(ch) { + return !pn.IsNot + } + } + return pn.IsNot +} + +type rangeClass struct { + Begin class + End class +} + +func (pn *rangeClass) Matches(ch int) bool { + switch begin := pn.Begin.(type) { + case *charClass: + end, ok := pn.End.(*charClass) + if !ok { + return false + } + return begin.Ch <= ch && ch <= end.Ch + } + return false +} + +// }}} + +// patterns {{{ + +type pattern interface{} + +type singlePattern struct { + Class class +} + +type seqPattern struct { + MustHead bool + MustTail bool + Patterns []pattern +} + +type repeatPattern struct { + Type int + Class class +} + +type posCapPattern struct{} + +type capPattern struct { + Pattern pattern +} + +type numberPattern struct { + N int +} + +type bracePattern struct { + Begin int + End int +} + +// }}} + +/* parse {{{ */ + +func parseClass(sc *scanner, allowset bool) class { + ch := sc.Next() + switch ch { + case '%': + return &singleClass{sc.Next()} + case '.': + if allowset { + return &dotClass{} + } + return &charClass{ch} + case '[': + if allowset { + return parseClassSet(sc) + } + return &charClass{ch} + //case '^' '$', '(', ')', ']', '*', '+', '-', '?': + // panic(newError(sc.CurrentPos(), "invalid %c", ch)) + case EOS: + panic(newError(sc.CurrentPos(), "unexpected EOS")) + default: + return &charClass{ch} + } +} + +func parseClassSet(sc *scanner) class { + set := &setClass{false, []class{}} + if sc.Peek() == '^' { + set.IsNot = true + sc.Next() + } + isrange := false + for { + ch := sc.Peek() + switch ch { + // case '[': + // panic(newError(sc.CurrentPos(), "'[' can not be nested")) + case EOS: + panic(newError(sc.CurrentPos(), "unexpected EOS")) + case ']': + if len(set.Classes) > 0 { + sc.Next() + goto exit + } + fallthrough + case '-': + if len(set.Classes) > 0 { + sc.Next() + isrange = true + continue + } + fallthrough + default: + set.Classes = append(set.Classes, parseClass(sc, false)) + } + if isrange { + begin := set.Classes[len(set.Classes)-2] + end := set.Classes[len(set.Classes)-1] + set.Classes = set.Classes[0 : len(set.Classes)-2] + set.Classes = append(set.Classes, &rangeClass{begin, end}) + isrange = false + } + } +exit: + if isrange { + set.Classes = append(set.Classes, &charClass{'-'}) + } + + return set +} + +func parsePattern(sc *scanner, toplevel bool) *seqPattern { + pat := &seqPattern{} + if toplevel { + if sc.Peek() == '^' { + sc.Next() + pat.MustHead = true + } + } + for { + ch := sc.Peek() + switch ch { + case '%': + sc.Save() + sc.Next() + switch sc.Peek() { + case '0': + panic(newError(sc.CurrentPos(), "invalid capture index")) + case '1', '2', '3', '4', '5', '6', '7', '8', '9': + pat.Patterns = append(pat.Patterns, &numberPattern{sc.Next() - 48}) + case 'b': + sc.Next() + pat.Patterns = append(pat.Patterns, &bracePattern{sc.Next(), sc.Next()}) + default: + sc.Restore() + pat.Patterns = append(pat.Patterns, &singlePattern{parseClass(sc, true)}) + } + case '.', '[', ']': + pat.Patterns = append(pat.Patterns, &singlePattern{parseClass(sc, true)}) + //case ']': + // panic(newError(sc.CurrentPos(), "invalid ']'")) + case ')': + if toplevel { + panic(newError(sc.CurrentPos(), "invalid ')'")) + } + return pat + case '(': + sc.Next() + if sc.Peek() == ')' { + sc.Next() + pat.Patterns = append(pat.Patterns, &posCapPattern{}) + } else { + ret := &capPattern{parsePattern(sc, false)} + if sc.Peek() != ')' { + panic(newError(sc.CurrentPos(), "unfinished capture")) + } + sc.Next() + pat.Patterns = append(pat.Patterns, ret) + } + case '*', '+', '-', '?': + sc.Next() + if len(pat.Patterns) > 0 { + spat, ok := pat.Patterns[len(pat.Patterns)-1].(*singlePattern) + if ok { + pat.Patterns = pat.Patterns[0 : len(pat.Patterns)-1] + pat.Patterns = append(pat.Patterns, &repeatPattern{ch, spat.Class}) + continue + } + } + pat.Patterns = append(pat.Patterns, &singlePattern{&charClass{ch}}) + case '$': + if toplevel && (sc.NextPos() == sc.Length()-1 || sc.NextPos() == EOS) { + pat.MustTail = true + } else { + pat.Patterns = append(pat.Patterns, &singlePattern{&charClass{ch}}) + } + sc.Next() + case EOS: + sc.Next() + goto exit + default: + sc.Next() + pat.Patterns = append(pat.Patterns, &singlePattern{&charClass{ch}}) + } + } +exit: + return pat +} + +type iptr struct { + insts []inst + capture int +} + +func compilePattern(p pattern, ps ...*iptr) []inst { + var ptr *iptr + toplevel := false + if len(ps) == 0 { + toplevel = true + ptr = &iptr{[]inst{inst{opSave, nil, 0, -1}}, 2} + } else { + ptr = ps[0] + } + switch pat := p.(type) { + case *singlePattern: + ptr.insts = append(ptr.insts, inst{opChar, pat.Class, -1, -1}) + case *seqPattern: + for _, cp := range pat.Patterns { + compilePattern(cp, ptr) + } + case *repeatPattern: + idx := len(ptr.insts) + switch pat.Type { + case '*': + ptr.insts = append(ptr.insts, + inst{opSplit, nil, idx + 1, idx + 3}, + inst{opChar, pat.Class, -1, -1}, + inst{opJmp, nil, idx, -1}) + case '+': + ptr.insts = append(ptr.insts, + inst{opChar, pat.Class, -1, -1}, + inst{opSplit, nil, idx, idx + 2}) + case '-': + ptr.insts = append(ptr.insts, + inst{opSplit, nil, idx + 3, idx + 1}, + inst{opChar, pat.Class, -1, -1}, + inst{opJmp, nil, idx, -1}) + case '?': + ptr.insts = append(ptr.insts, + inst{opSplit, nil, idx + 1, idx + 2}, + inst{opChar, pat.Class, -1, -1}) + } + case *posCapPattern: + ptr.insts = append(ptr.insts, inst{opPSave, nil, ptr.capture, -1}) + ptr.capture += 2 + case *capPattern: + c0, c1 := ptr.capture, ptr.capture+1 + ptr.capture += 2 + ptr.insts = append(ptr.insts, inst{opSave, nil, c0, -1}) + compilePattern(pat.Pattern, ptr) + ptr.insts = append(ptr.insts, inst{opSave, nil, c1, -1}) + case *bracePattern: + ptr.insts = append(ptr.insts, inst{opBrace, nil, pat.Begin, pat.End}) + case *numberPattern: + ptr.insts = append(ptr.insts, inst{opNumber, nil, pat.N, -1}) + } + if toplevel { + if p.(*seqPattern).MustTail { + ptr.insts = append(ptr.insts, inst{opSave, nil, 1, -1}, inst{opTailMatch, nil, -1, -1}) + } + ptr.insts = append(ptr.insts, inst{opSave, nil, 1, -1}, inst{opMatch, nil, -1, -1}) + } + return ptr.insts +} + +/* }}} parse */ + +/* VM {{{ */ + +// Simple recursive virtual machine based on the +// "Regular Expression Matching: the Virtual Machine Approach" (https://swtch.com/~rsc/regexp/regexp2.html) +func recursiveVM(src []byte, insts []inst, pc, sp int, ms ...*MatchData) (bool, int, *MatchData) { + var m *MatchData + if len(ms) == 0 { + m = newMatchState() + } else { + m = ms[0] + } +redo: + inst := insts[pc] + switch inst.OpCode { + case opChar: + if sp >= len(src) || !inst.Class.Matches(int(src[sp])) { + return false, sp, m + } + pc++ + sp++ + goto redo + case opMatch: + return true, sp, m + case opTailMatch: + return sp >= len(src), sp, m + case opJmp: + pc = inst.Operand1 + goto redo + case opSplit: + if ok, nsp, _ := recursiveVM(src, insts, inst.Operand1, sp, m); ok { + return true, nsp, m + } + pc = inst.Operand2 + goto redo + case opSave: + s := m.setCapture(inst.Operand1, sp) + if ok, nsp, _ := recursiveVM(src, insts, pc+1, sp, m); ok { + return true, nsp, m + } + m.restoreCapture(inst.Operand1, s) + return false, sp, m + case opPSave: + m.addPosCapture(inst.Operand1, sp+1) + pc++ + goto redo + case opBrace: + if sp >= len(src) || int(src[sp]) != inst.Operand1 { + return false, sp, m + } + count := 1 + for sp = sp + 1; sp < len(src); sp++ { + if int(src[sp]) == inst.Operand2 { + count-- + } + if count == 0 { + pc++ + sp++ + goto redo + } + if int(src[sp]) == inst.Operand1 { + count++ + } + } + return false, sp, m + case opNumber: + idx := inst.Operand1 * 2 + if idx >= m.CaptureLength()-1 { + panic(newError(_UNKNOWN, "invalid capture index")) + } + capture := src[m.Capture(idx):m.Capture(idx+1)] + for i := 0; i < len(capture); i++ { + if i+sp >= len(src) || capture[i] != src[i+sp] { + return false, sp, m + } + } + pc++ + sp += len(capture) + goto redo + } + panic("should not reach here") + return false, sp, m +} + +/* }}} */ + +/* API {{{ */ + +func Find(p string, src []byte, offset, limit int) (matches []*MatchData, err error) { + defer func() { + if v := recover(); v != nil { + if perr, ok := v.(*Error); ok { + err = perr + } else { + panic(v) + } + } + }() + pat := parsePattern(newScanner([]byte(p)), true) + insts := compilePattern(pat) + matches = []*MatchData{} + for sp := offset; sp <= len(src); { + ok, nsp, ms := recursiveVM(src, insts, 0, sp) + sp++ + if ok { + if sp < nsp { + sp = nsp + } + matches = append(matches, ms) + } + if len(matches) == limit || pat.MustHead { + break + } + } + return +} + +/* }}} */ diff --git a/vendor/github.com/yuin/gopher-lua/script_test.go b/vendor/github.com/yuin/gopher-lua/script_test.go new file mode 100644 index 0000000000000000000000000000000000000000..a98ae5e0336c1a4496df55c683f6dc2d24eb638e --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/script_test.go @@ -0,0 +1,87 @@ +package lua + +import ( + "fmt" + "github.com/yuin/gopher-lua/parse" + "os" + "testing" +) + +const maxMemory = 40 + +var gluaTests []string = []string{ + "base.lua", + "coroutine.lua", + "db.lua", + "issues.lua", + "os.lua", + "table.lua", + "vm.lua", + "math.lua", + "strings.lua", +} + +var luaTests []string = []string{ + "attrib.lua", + "calls.lua", + "closure.lua", + "constructs.lua", + "events.lua", + "literals.lua", + "locals.lua", + "math.lua", + "sort.lua", + "strings.lua", + "vararg.lua", + "pm.lua", + "files.lua", +} + +func testScriptCompile(t *testing.T, script string) { + file, err := os.Open(script) + if err != nil { + t.Fatal(err) + return + } + chunk, err2 := parse.Parse(file, script) + if err2 != nil { + t.Fatal(err2) + return + } + parse.Dump(chunk) + proto, err3 := Compile(chunk, script) + if err3 != nil { + t.Fatal(err3) + return + } + proto.String() +} + +func testScriptDir(t *testing.T, tests []string, directory string) { + if err := os.Chdir(directory); err != nil { + t.Error(err) + } + defer os.Chdir("..") + for _, script := range tests { + fmt.Printf("testing %s/%s\n", directory, script) + testScriptCompile(t, script) + L := NewState(Options{ + RegistrySize: 1024 * 20, + CallStackSize: 1024, + IncludeGoStackTrace: true, + }) + L.SetMx(maxMemory) + if err := L.DoFile(script); err != nil { + t.Error(err) + } + L.Close() + } +} + +func TestGlua(t *testing.T) { + testScriptDir(t, gluaTests, "_glua-tests") +} + +func TestLua(t *testing.T) { + testScriptDir(t, luaTests, "_lua5.1-tests") +} diff --git a/vendor/github.com/yuin/gopher-lua/state.go b/vendor/github.com/yuin/gopher-lua/state.go new file mode 100644 index 0000000000000000000000000000000000000000..b6ea313de535ea528541354bbd3ce0b418ae0969 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/state.go @@ -0,0 +1,1872 @@ +package lua + +//////////////////////////////////////////////////////// +// This file was generated by go-inline. DO NOT EDIT. // +//////////////////////////////////////////////////////// + +import ( + "context" + "fmt" + "github.com/yuin/gopher-lua/parse" + "io" + "math" + "os" + "runtime" + "strings" + "sync/atomic" + "time" +) + +const MultRet = -1 +const RegistryIndex = -10000 +const EnvironIndex = -10001 +const GlobalsIndex = -10002 + +/* ApiError {{{ */ + +type ApiError struct { + Type ApiErrorType + Object LValue + StackTrace string + // Underlying error. This attribute is set only if the Type is ApiErrorFile or ApiErrorSyntax + Cause error +} + +func newApiError(code ApiErrorType, object LValue) *ApiError { + return &ApiError{code, object, "", nil} +} + +func newApiErrorS(code ApiErrorType, message string) *ApiError { + return newApiError(code, LString(message)) +} + +func newApiErrorE(code ApiErrorType, err error) *ApiError { + return &ApiError{code, LString(err.Error()), "", err} +} + +func (e *ApiError) Error() string { + if len(e.StackTrace) > 0 { + return fmt.Sprintf("%s\n%s", e.Object.String(), e.StackTrace) + } + return e.Object.String() +} + +type ApiErrorType int + +const ( + ApiErrorSyntax ApiErrorType = iota + ApiErrorFile + ApiErrorRun + ApiErrorError + ApiErrorPanic +) + +/* }}} */ + +/* ResumeState {{{ */ + +type ResumeState int + +const ( + ResumeOK ResumeState = iota + ResumeYield + ResumeError +) + +/* }}} */ + +/* P {{{ */ + +type P struct { + Fn LValue + NRet int + Protect bool + Handler *LFunction +} + +/* }}} */ + +/* Options {{{ */ + +// Options is a configuration that is used to create a new LState. +type Options struct { + // Call stack size. This defaults to `lua.CallStackSize`. + CallStackSize int + // Data stack size. This defaults to `lua.RegistrySize`. + RegistrySize int + // Controls whether or not libraries are opened by default + SkipOpenLibs bool + // Tells whether a Go stacktrace should be included in a Lua stacktrace when panics occur. + IncludeGoStackTrace bool +} + +/* }}} */ + +/* Debug {{{ */ + +type Debug struct { + frame *callFrame + Name string + What string + Source string + CurrentLine int + NUpvalues int + LineDefined int + LastLineDefined int +} + +/* }}} */ + +/* callFrame {{{ */ + +type callFrame struct { + Idx int + Fn *LFunction + Parent *callFrame + Pc int + Base int + LocalBase int + ReturnBase int + NArgs int + NRet int + TailCall int +} + +type callFrameStack struct { + array []callFrame + sp int +} + +func newCallFrameStack(size int) *callFrameStack { + return &callFrameStack{ + array: make([]callFrame, size), + sp: 0, + } +} + +func (cs *callFrameStack) IsEmpty() bool { return cs.sp == 0 } + +func (cs *callFrameStack) Clear() { + cs.sp = 0 +} + +func (cs *callFrameStack) Push(v callFrame) { // +inline-start + cs.array[cs.sp] = v + cs.array[cs.sp].Idx = cs.sp + cs.sp++ +} // +inline-end + +func (cs *callFrameStack) Remove(sp int) { + psp := sp - 1 + nsp := sp + 1 + var pre *callFrame + var next *callFrame + if psp > 0 { + pre = &cs.array[psp] + } + if nsp < cs.sp { + next = &cs.array[nsp] + } + if next != nil { + next.Parent = pre + } + for i := sp; i+1 < cs.sp; i++ { + cs.array[i] = cs.array[i+1] + cs.array[i].Idx = i + cs.sp = i + } + cs.sp++ +} + +func (cs *callFrameStack) Sp() int { + return cs.sp +} + +func (cs *callFrameStack) SetSp(sp int) { + cs.sp = sp +} + +func (cs *callFrameStack) Last() *callFrame { + if cs.sp == 0 { + return nil + } + return &cs.array[cs.sp-1] +} + +func (cs *callFrameStack) At(sp int) *callFrame { + return &cs.array[sp] +} + +func (cs *callFrameStack) Pop() *callFrame { + cs.sp-- + return &cs.array[cs.sp] +} + +/* }}} */ + +/* registry {{{ */ + +type registry struct { + array []LValue + top int + alloc *allocator +} + +func newRegistry(size int, alloc *allocator) *registry { + return ®istry{make([]LValue, size), 0, alloc} +} + +func (rg *registry) SetTop(top int) { + oldtop := rg.top + rg.top = top + for i := oldtop; i < rg.top; i++ { + rg.array[i] = LNil + } + for i := rg.top; i < oldtop; i++ { + rg.array[i] = LNil + } +} + +func (rg *registry) Top() int { + return rg.top +} + +func (rg *registry) Push(v LValue) { + rg.array[rg.top] = v + rg.top++ +} + +func (rg *registry) Pop() LValue { + v := rg.array[rg.top-1] + rg.array[rg.top-1] = LNil + rg.top-- + return v +} + +func (rg *registry) Get(reg int) LValue { + return rg.array[reg] +} + +func (rg *registry) CopyRange(regv, start, limit, n int) { // +inline-start + for i := 0; i < n; i++ { + if tidx := start + i; tidx >= rg.top || limit > -1 && tidx >= limit || tidx < 0 { + rg.array[regv+i] = LNil + } else { + rg.array[regv+i] = rg.array[tidx] + } + } + rg.top = regv + n +} // +inline-end + +func (rg *registry) FillNil(regm, n int) { // +inline-start + for i := 0; i < n; i++ { + rg.array[regm+i] = LNil + } + rg.top = regm + n +} // +inline-end + +func (rg *registry) Insert(value LValue, reg int) { + top := rg.Top() + if reg >= top { + rg.Set(reg, value) + return + } + top-- + for ; top >= reg; top-- { + rg.Set(top+1, rg.Get(top)) + } + rg.Set(reg, value) +} + +func (rg *registry) Set(reg int, val LValue) { + rg.array[reg] = val + if reg >= rg.top { + rg.top = reg + 1 + } +} + +func (rg *registry) SetNumber(reg int, val LNumber) { + rg.array[reg] = rg.alloc.LNumber2I(val) + if reg >= rg.top { + rg.top = reg + 1 + } +} /* }}} */ + +/* Global {{{ */ + +func newGlobal() *Global { + return &Global{ + MainThread: nil, + Registry: newLTable(0, 32), + Global: newLTable(0, 64), + builtinMts: make(map[int]LValue), + tempFiles: make([]*os.File, 0, 10), + } +} + +/* }}} */ + +/* package local methods {{{ */ + +func panicWithTraceback(L *LState) { + err := newApiError(ApiErrorRun, L.Get(-1)) + err.StackTrace = L.stackTrace(0) + panic(err) +} + +func panicWithoutTraceback(L *LState) { + err := newApiError(ApiErrorRun, L.Get(-1)) + panic(err) +} + +func newLState(options Options) *LState { + al := newAllocator(32) + ls := &LState{ + G: newGlobal(), + Parent: nil, + Panic: panicWithTraceback, + Dead: false, + Options: options, + + stop: 0, + reg: newRegistry(options.RegistrySize, al), + stack: newCallFrameStack(options.CallStackSize), + alloc: al, + currentFrame: nil, + wrapped: false, + uvcache: nil, + hasErrorFunc: false, + mainLoop: mainLoop, + ctx: nil, + } + ls.Env = ls.G.Global + return ls +} + +func (ls *LState) printReg() { + println("-------------------------") + println("thread:", ls) + println("top:", ls.reg.Top()) + if ls.currentFrame != nil { + println("function base:", ls.currentFrame.Base) + println("return base:", ls.currentFrame.ReturnBase) + } else { + println("(vm not started)") + } + println("local base:", ls.currentLocalBase()) + for i := 0; i < ls.reg.Top(); i++ { + println(i, ls.reg.Get(i).String()) + } + println("-------------------------") +} + +func (ls *LState) printCallStack() { + println("-------------------------") + for i := 0; i < ls.stack.Sp(); i++ { + print(i) + print(" ") + frame := ls.stack.At(i) + if frame == nil { + break + } + if frame.Fn.IsG { + println("IsG:", true, "Frame:", frame, "Fn:", frame.Fn) + } else { + println("IsG:", false, "Frame:", frame, "Fn:", frame.Fn, "pc:", frame.Pc) + } + } + println("-------------------------") +} + +func (ls *LState) closeAllUpvalues() { // +inline-start + for cf := ls.currentFrame; cf != nil; cf = cf.Parent { + if !cf.Fn.IsG { + ls.closeUpvalues(cf.LocalBase) + } + } +} // +inline-end + +func (ls *LState) raiseError(level int, format string, args ...interface{}) { + if !ls.hasErrorFunc { + ls.closeAllUpvalues() + } + message := format + if len(args) > 0 { + message = fmt.Sprintf(format, args...) + } + if level > 0 { + message = fmt.Sprintf("%v %v", ls.where(level-1, true), message) + } + ls.reg.Push(LString(message)) + ls.Panic(ls) +} + +func (ls *LState) findLocal(frame *callFrame, no int) string { + fn := frame.Fn + if !fn.IsG { + if name, ok := fn.LocalName(no, frame.Pc-1); ok { + return name + } + } + var top int + if ls.currentFrame == frame { + top = ls.reg.Top() + } else if frame.Idx+1 < ls.stack.Sp() { + top = ls.stack.At(frame.Idx + 1).Base + } else { + return "" + } + if top-frame.LocalBase >= no { + return "(*temporary)" + } + return "" +} + +func (ls *LState) where(level int, skipg bool) string { + dbg, ok := ls.GetStack(level) + if !ok { + return "" + } + cf := dbg.frame + proto := cf.Fn.Proto + sourcename := "[G]" + if proto != nil { + sourcename = proto.SourceName + } else if skipg { + return ls.where(level+1, skipg) + } + line := "" + if proto != nil { + line = fmt.Sprintf("%v:", proto.DbgSourcePositions[cf.Pc-1]) + } + return fmt.Sprintf("%v:%v", sourcename, line) +} + +func (ls *LState) stackTrace(level int) string { + buf := []string{} + header := "stack traceback:" + if ls.currentFrame != nil { + i := 0 + for dbg, ok := ls.GetStack(i); ok; dbg, ok = ls.GetStack(i) { + cf := dbg.frame + buf = append(buf, fmt.Sprintf("\t%v in %v", ls.Where(i), ls.formattedFrameFuncName(cf))) + if !cf.Fn.IsG && cf.TailCall > 0 { + for tc := cf.TailCall; tc > 0; tc-- { + buf = append(buf, "\t(tailcall): ?") + i++ + } + } + i++ + } + } + buf = append(buf, fmt.Sprintf("\t%v: %v", "[G]", "?")) + buf = buf[intMax(0, intMin(level, len(buf))):len(buf)] + if len(buf) > 20 { + newbuf := make([]string, 0, 20) + newbuf = append(newbuf, buf[0:7]...) + newbuf = append(newbuf, "\t...") + newbuf = append(newbuf, buf[len(buf)-7:len(buf)]...) + buf = newbuf + } + return fmt.Sprintf("%s\n%s", header, strings.Join(buf, "\n")) +} + +func (ls *LState) formattedFrameFuncName(fr *callFrame) string { + name, ischunk := ls.frameFuncName(fr) + if ischunk { + return name + } + if name[0] != '(' && name[0] != '<' { + return fmt.Sprintf("function '%s'", name) + } + return fmt.Sprintf("function %s", name) +} + +func (ls *LState) rawFrameFuncName(fr *callFrame) string { + name, _ := ls.frameFuncName(fr) + return name +} + +func (ls *LState) frameFuncName(fr *callFrame) (string, bool) { + frame := fr.Parent + if frame == nil { + if ls.Parent == nil { + return "main chunk", true + } else { + return "corountine", true + } + } + if !frame.Fn.IsG { + pc := frame.Pc - 1 + for _, call := range frame.Fn.Proto.DbgCalls { + if call.Pc == pc { + name := call.Name + if (name == "?" || fr.TailCall > 0) && !fr.Fn.IsG { + name = fmt.Sprintf("<%v:%v>", fr.Fn.Proto.SourceName, fr.Fn.Proto.LineDefined) + } + return name, false + } + } + } + if !fr.Fn.IsG { + return fmt.Sprintf("<%v:%v>", fr.Fn.Proto.SourceName, fr.Fn.Proto.LineDefined), false + } + return "(anonymous)", false +} + +func (ls *LState) isStarted() bool { + return ls.currentFrame != nil +} + +func (ls *LState) kill() { + ls.Dead = true +} + +func (ls *LState) indexToReg(idx int) int { + base := ls.currentLocalBase() + if idx > 0 { + return base + idx - 1 + } else if idx == 0 { + return -1 + } else { + tidx := ls.reg.Top() + idx + if tidx < base { + return -1 + } + return tidx + } +} + +func (ls *LState) currentLocalBase() int { + base := 0 + if ls.currentFrame != nil { + base = ls.currentFrame.LocalBase + } + return base +} + +func (ls *LState) currentEnv() *LTable { + return ls.Env + /* + if ls.currentFrame == nil { + return ls.Env + } + return ls.currentFrame.Fn.Env + */ +} + +func (ls *LState) rkValue(idx int) LValue { + /* + if OpIsK(idx) { + return ls.currentFrame.Fn.Proto.Constants[opIndexK(idx)] + } + return ls.reg.Get(ls.currentFrame.LocalBase + idx) + */ + if (idx & opBitRk) != 0 { + return ls.currentFrame.Fn.Proto.Constants[idx & ^opBitRk] + } + return ls.reg.array[ls.currentFrame.LocalBase+idx] +} + +func (ls *LState) rkString(idx int) string { + if (idx & opBitRk) != 0 { + return ls.currentFrame.Fn.Proto.stringConstants[idx & ^opBitRk] + } + return string(ls.reg.array[ls.currentFrame.LocalBase+idx].(LString)) +} + +func (ls *LState) closeUpvalues(idx int) { // +inline-start + if ls.uvcache != nil { + var prev *Upvalue + for uv := ls.uvcache; uv != nil; uv = uv.next { + if uv.index >= idx { + if prev != nil { + prev.next = nil + } else { + ls.uvcache = nil + } + uv.Close() + } + prev = uv + } + } +} // +inline-end + +func (ls *LState) findUpvalue(idx int) *Upvalue { + var prev *Upvalue + var next *Upvalue + if ls.uvcache != nil { + for uv := ls.uvcache; uv != nil; uv = uv.next { + if uv.index == idx { + return uv + } + if uv.index > idx { + next = uv + break + } + prev = uv + } + } + uv := &Upvalue{reg: ls.reg, index: idx, closed: false} + if prev != nil { + prev.next = uv + } else { + ls.uvcache = uv + } + if next != nil { + uv.next = next + } + return uv +} + +func (ls *LState) metatable(lvalue LValue, rawget bool) LValue { + var metatable LValue = LNil + switch obj := lvalue.(type) { + case *LTable: + metatable = obj.Metatable + case *LUserData: + metatable = obj.Metatable + default: + if table, ok := ls.G.builtinMts[int(obj.Type())]; ok { + metatable = table + } + } + + if !rawget && metatable != LNil { + oldmt := metatable + if tb, ok := metatable.(*LTable); ok { + metatable = tb.RawGetString("__metatable") + if metatable == LNil { + metatable = oldmt + } + } + } + + return metatable +} + +func (ls *LState) metaOp1(lvalue LValue, event string) LValue { + if mt := ls.metatable(lvalue, true); mt != LNil { + if tb, ok := mt.(*LTable); ok { + return tb.RawGetString(event) + } + } + return LNil +} + +func (ls *LState) metaOp2(value1, value2 LValue, event string) LValue { + if mt := ls.metatable(value1, true); mt != LNil { + if tb, ok := mt.(*LTable); ok { + if ret := tb.RawGetString(event); ret != LNil { + return ret + } + } + } + if mt := ls.metatable(value2, true); mt != LNil { + if tb, ok := mt.(*LTable); ok { + return tb.RawGetString(event) + } + } + return LNil +} + +func (ls *LState) metaCall(lvalue LValue) (*LFunction, bool) { + if fn, ok := lvalue.(*LFunction); ok { + return fn, false + } + if fn, ok := ls.metaOp1(lvalue, "__call").(*LFunction); ok { + return fn, true + } + return nil, false +} + +func (ls *LState) initCallFrame(cf *callFrame) { // +inline-start + if cf.Fn.IsG { + ls.reg.SetTop(cf.LocalBase + cf.NArgs) + } else { + proto := cf.Fn.Proto + nargs := cf.NArgs + np := int(proto.NumParameters) + for i := nargs; i < np; i++ { + ls.reg.array[cf.LocalBase+i] = LNil + nargs = np + } + + if (proto.IsVarArg & VarArgIsVarArg) == 0 { + if nargs < int(proto.NumUsedRegisters) { + nargs = int(proto.NumUsedRegisters) + } + for i := np; i < nargs; i++ { + ls.reg.array[cf.LocalBase+i] = LNil + } + ls.reg.top = cf.LocalBase + int(proto.NumUsedRegisters) + } else { + /* swap vararg positions: + closure + namedparam1 <- lbase + namedparam2 + vararg1 + vararg2 + + TO + + closure + nil + nil + vararg1 + vararg2 + namedparam1 <- lbase + namedparam2 + */ + nvarargs := nargs - np + if nvarargs < 0 { + nvarargs = 0 + } + + ls.reg.SetTop(cf.LocalBase + nargs + np) + for i := 0; i < np; i++ { + //ls.reg.Set(cf.LocalBase+nargs+i, ls.reg.Get(cf.LocalBase+i)) + ls.reg.array[cf.LocalBase+nargs+i] = ls.reg.array[cf.LocalBase+i] + //ls.reg.Set(cf.LocalBase+i, LNil) + ls.reg.array[cf.LocalBase+i] = LNil + } + + if CompatVarArg { + ls.reg.SetTop(cf.LocalBase + nargs + np + 1) + if (proto.IsVarArg & VarArgNeedsArg) != 0 { + argtb := newLTable(nvarargs, 0) + for i := 0; i < nvarargs; i++ { + argtb.RawSetInt(i+1, ls.reg.Get(cf.LocalBase+np+i)) + } + argtb.RawSetString("n", LNumber(nvarargs)) + //ls.reg.Set(cf.LocalBase+nargs+np, argtb) + ls.reg.array[cf.LocalBase+nargs+np] = argtb + } else { + ls.reg.array[cf.LocalBase+nargs+np] = LNil + } + } + cf.LocalBase += nargs + maxreg := cf.LocalBase + int(proto.NumUsedRegisters) + ls.reg.SetTop(maxreg) + } + } +} // +inline-end + +func (ls *LState) pushCallFrame(cf callFrame, fn LValue, meta bool) { // +inline-start + if meta { + cf.NArgs++ + ls.reg.Insert(fn, cf.LocalBase) + } + if cf.Fn == nil { + ls.RaiseError("attempt to call a non-function object") + } + if ls.stack.sp == ls.Options.CallStackSize { + ls.RaiseError("stack overflow") + } + // this section is inlined by go-inline + // source function is 'func (cs *callFrameStack) Push(v callFrame) ' in '_state.go' + { + cs := ls.stack + v := cf + cs.array[cs.sp] = v + cs.array[cs.sp].Idx = cs.sp + cs.sp++ + } + newcf := ls.stack.Last() + // this section is inlined by go-inline + // source function is 'func (ls *LState) initCallFrame(cf *callFrame) ' in '_state.go' + { + cf := newcf + if cf.Fn.IsG { + ls.reg.SetTop(cf.LocalBase + cf.NArgs) + } else { + proto := cf.Fn.Proto + nargs := cf.NArgs + np := int(proto.NumParameters) + for i := nargs; i < np; i++ { + ls.reg.array[cf.LocalBase+i] = LNil + nargs = np + } + + if (proto.IsVarArg & VarArgIsVarArg) == 0 { + if nargs < int(proto.NumUsedRegisters) { + nargs = int(proto.NumUsedRegisters) + } + for i := np; i < nargs; i++ { + ls.reg.array[cf.LocalBase+i] = LNil + } + ls.reg.top = cf.LocalBase + int(proto.NumUsedRegisters) + } else { + /* swap vararg positions: + closure + namedparam1 <- lbase + namedparam2 + vararg1 + vararg2 + + TO + + closure + nil + nil + vararg1 + vararg2 + namedparam1 <- lbase + namedparam2 + */ + nvarargs := nargs - np + if nvarargs < 0 { + nvarargs = 0 + } + + ls.reg.SetTop(cf.LocalBase + nargs + np) + for i := 0; i < np; i++ { + //ls.reg.Set(cf.LocalBase+nargs+i, ls.reg.Get(cf.LocalBase+i)) + ls.reg.array[cf.LocalBase+nargs+i] = ls.reg.array[cf.LocalBase+i] + //ls.reg.Set(cf.LocalBase+i, LNil) + ls.reg.array[cf.LocalBase+i] = LNil + } + + if CompatVarArg { + ls.reg.SetTop(cf.LocalBase + nargs + np + 1) + if (proto.IsVarArg & VarArgNeedsArg) != 0 { + argtb := newLTable(nvarargs, 0) + for i := 0; i < nvarargs; i++ { + argtb.RawSetInt(i+1, ls.reg.Get(cf.LocalBase+np+i)) + } + argtb.RawSetString("n", LNumber(nvarargs)) + //ls.reg.Set(cf.LocalBase+nargs+np, argtb) + ls.reg.array[cf.LocalBase+nargs+np] = argtb + } else { + ls.reg.array[cf.LocalBase+nargs+np] = LNil + } + } + cf.LocalBase += nargs + maxreg := cf.LocalBase + int(proto.NumUsedRegisters) + ls.reg.SetTop(maxreg) + } + } + } + ls.currentFrame = newcf +} // +inline-end + +func (ls *LState) callR(nargs, nret, rbase int) { + base := ls.reg.Top() - nargs - 1 + if rbase < 0 { + rbase = base + } + lv := ls.reg.Get(base) + fn, meta := ls.metaCall(lv) + ls.pushCallFrame(callFrame{ + Fn: fn, + Pc: 0, + Base: base, + LocalBase: base + 1, + ReturnBase: rbase, + NArgs: nargs, + NRet: nret, + Parent: ls.currentFrame, + TailCall: 0, + }, lv, meta) + if ls.G.MainThread == nil { + ls.G.MainThread = ls + ls.G.CurrentThread = ls + ls.mainLoop(ls, nil) + } else { + ls.mainLoop(ls, ls.currentFrame) + } + if nret != MultRet { + ls.reg.SetTop(rbase + nret) + } +} + +func (ls *LState) getField(obj LValue, key LValue) LValue { + curobj := obj + for i := 0; i < MaxTableGetLoop; i++ { + tb, istable := curobj.(*LTable) + if istable { + ret := tb.RawGet(key) + if ret != LNil { + return ret + } + } + metaindex := ls.metaOp1(curobj, "__index") + if metaindex == LNil { + if !istable { + ls.RaiseError("attempt to index a non-table object(%v)", curobj.Type().String()) + } + return LNil + } + if metaindex.Type() == LTFunction { + ls.reg.Push(metaindex) + ls.reg.Push(curobj) + ls.reg.Push(key) + ls.Call(2, 1) + return ls.reg.Pop() + } else { + curobj = metaindex + } + } + ls.RaiseError("too many recursions in gettable") + return nil +} + +func (ls *LState) getFieldString(obj LValue, key string) LValue { + curobj := obj + for i := 0; i < MaxTableGetLoop; i++ { + tb, istable := curobj.(*LTable) + if istable { + ret := tb.RawGetString(key) + if ret != LNil { + return ret + } + } + metaindex := ls.metaOp1(curobj, "__index") + if metaindex == LNil { + if !istable { + ls.RaiseError("attempt to index a non-table object(%v)", curobj.Type().String()) + } + return LNil + } + if metaindex.Type() == LTFunction { + ls.reg.Push(metaindex) + ls.reg.Push(curobj) + ls.reg.Push(LString(key)) + ls.Call(2, 1) + return ls.reg.Pop() + } else { + curobj = metaindex + } + } + ls.RaiseError("too many recursions in gettable") + return nil +} + +func (ls *LState) setField(obj LValue, key LValue, value LValue) { + curobj := obj + for i := 0; i < MaxTableGetLoop; i++ { + tb, istable := curobj.(*LTable) + if istable { + if tb.RawGet(key) != LNil { + ls.RawSet(tb, key, value) + return + } + } + metaindex := ls.metaOp1(curobj, "__newindex") + if metaindex == LNil { + if !istable { + ls.RaiseError("attempt to index a non-table object(%v)", curobj.Type().String()) + } + ls.RawSet(tb, key, value) + return + } + if metaindex.Type() == LTFunction { + ls.reg.Push(metaindex) + ls.reg.Push(curobj) + ls.reg.Push(key) + ls.reg.Push(value) + ls.Call(3, 0) + return + } else { + curobj = metaindex + } + } + ls.RaiseError("too many recursions in settable") +} + +func (ls *LState) setFieldString(obj LValue, key string, value LValue) { + curobj := obj + for i := 0; i < MaxTableGetLoop; i++ { + tb, istable := curobj.(*LTable) + if istable { + if tb.RawGetString(key) != LNil { + tb.RawSetString(key, value) + return + } + } + metaindex := ls.metaOp1(curobj, "__newindex") + if metaindex == LNil { + if !istable { + ls.RaiseError("attempt to index a non-table object(%v)", curobj.Type().String()) + } + tb.RawSetString(key, value) + return + } + if metaindex.Type() == LTFunction { + ls.reg.Push(metaindex) + ls.reg.Push(curobj) + ls.reg.Push(LString(key)) + ls.reg.Push(value) + ls.Call(3, 0) + return + } else { + curobj = metaindex + } + } + ls.RaiseError("too many recursions in settable") +} + +/* }}} */ + +/* api methods {{{ */ + +func NewState(opts ...Options) *LState { + var ls *LState + if len(opts) == 0 { + ls = newLState(Options{ + CallStackSize: CallStackSize, + RegistrySize: RegistrySize, + }) + ls.OpenLibs() + } else { + if opts[0].CallStackSize < 1 { + opts[0].CallStackSize = CallStackSize + } + if opts[0].RegistrySize < 128 { + opts[0].RegistrySize = RegistrySize + } + ls = newLState(opts[0]) + if !opts[0].SkipOpenLibs { + ls.OpenLibs() + } + } + return ls +} + +func (ls *LState) Close() { + atomic.AddInt32(&ls.stop, 1) + for _, file := range ls.G.tempFiles { + // ignore errors in these operations + file.Close() + os.Remove(file.Name()) + } +} + +/* registry operations {{{ */ + +func (ls *LState) GetTop() int { + return ls.reg.Top() - ls.currentLocalBase() +} + +func (ls *LState) SetTop(idx int) { + base := ls.currentLocalBase() + newtop := ls.indexToReg(idx) + 1 + if newtop < base { + ls.reg.SetTop(base) + } else { + ls.reg.SetTop(newtop) + } +} + +func (ls *LState) Replace(idx int, value LValue) { + base := ls.currentLocalBase() + if idx > 0 { + reg := base + idx - 1 + if reg < ls.reg.Top() { + ls.reg.Set(reg, value) + } + } else if idx == 0 { + } else if idx > RegistryIndex { + if tidx := ls.reg.Top() + idx; tidx >= base { + ls.reg.Set(tidx, value) + } + } else { + switch idx { + case RegistryIndex: + if tb, ok := value.(*LTable); ok { + ls.G.Registry = tb + } else { + ls.RaiseError("registry must be a table(%v)", value.Type().String()) + } + case EnvironIndex: + if ls.currentFrame == nil { + ls.RaiseError("no calling environment") + } + if tb, ok := value.(*LTable); ok { + ls.currentFrame.Fn.Env = tb + } else { + ls.RaiseError("environment must be a table(%v)", value.Type().String()) + } + case GlobalsIndex: + if tb, ok := value.(*LTable); ok { + ls.G.Global = tb + } else { + ls.RaiseError("_G must be a table(%v)", value.Type().String()) + } + default: + fn := ls.currentFrame.Fn + index := GlobalsIndex - idx - 1 + if index < len(fn.Upvalues) { + fn.Upvalues[index].SetValue(value) + } + } + } +} + +func (ls *LState) Get(idx int) LValue { + base := ls.currentLocalBase() + if idx > 0 { + reg := base + idx - 1 + if reg < ls.reg.Top() { + return ls.reg.Get(reg) + } + return LNil + } else if idx == 0 { + return LNil + } else if idx > RegistryIndex { + tidx := ls.reg.Top() + idx + if tidx < base { + return LNil + } + return ls.reg.Get(tidx) + } else { + switch idx { + case RegistryIndex: + return ls.G.Registry + case EnvironIndex: + if ls.currentFrame == nil { + return ls.Env + } + return ls.currentFrame.Fn.Env + case GlobalsIndex: + return ls.G.Global + default: + fn := ls.currentFrame.Fn + index := GlobalsIndex - idx - 1 + if index < len(fn.Upvalues) { + return fn.Upvalues[index].Value() + } + return LNil + } + } + return LNil +} + +func (ls *LState) Push(value LValue) { + ls.reg.Push(value) +} + +func (ls *LState) Pop(n int) { + for i := 0; i < n; i++ { + if ls.GetTop() == 0 { + ls.RaiseError("register underflow") + } + ls.reg.Pop() + } +} + +func (ls *LState) Insert(value LValue, index int) { + reg := ls.indexToReg(index) + top := ls.reg.Top() + if reg >= top { + ls.reg.Set(reg, value) + return + } + if reg <= ls.currentLocalBase() { + reg = ls.currentLocalBase() + } + top-- + for ; top >= reg; top-- { + ls.reg.Set(top+1, ls.reg.Get(top)) + } + ls.reg.Set(reg, value) +} + +func (ls *LState) Remove(index int) { + reg := ls.indexToReg(index) + top := ls.reg.Top() + switch { + case reg >= top: + return + case reg < ls.currentLocalBase(): + return + case reg == top-1: + ls.Pop(1) + return + } + for i := reg; i < top-1; i++ { + ls.reg.Set(i, ls.reg.Get(i+1)) + } + ls.reg.SetTop(top - 1) +} + +/* }}} */ + +/* object allocation {{{ */ + +func (ls *LState) NewTable() *LTable { + return newLTable(defaultArrayCap, defaultHashCap) +} + +func (ls *LState) CreateTable(acap, hcap int) *LTable { + return newLTable(acap, hcap) +} + +// NewThread returns a new LState that shares with the original state all global objects. +// If the original state has context.Context, the new state has a new child context of the original state and this function returns its cancel function. +func (ls *LState) NewThread() (*LState, context.CancelFunc) { + thread := newLState(ls.Options) + thread.G = ls.G + thread.Env = ls.Env + var f context.CancelFunc = nil + if ls.ctx != nil { + thread.mainLoop = mainLoopWithContext + thread.ctx, f = context.WithCancel(ls.ctx) + } + return thread, f +} + +func (ls *LState) NewUserData() *LUserData { + return &LUserData{ + Env: ls.currentEnv(), + Metatable: LNil, + } +} + +func (ls *LState) NewFunction(fn LGFunction) *LFunction { + return newLFunctionG(fn, ls.currentEnv(), 0) +} + +func (ls *LState) NewClosure(fn LGFunction, upvalues ...LValue) *LFunction { + cl := newLFunctionG(fn, ls.currentEnv(), len(upvalues)) + for i, lv := range upvalues { + cl.Upvalues[i] = &Upvalue{} + cl.Upvalues[i].Close() + cl.Upvalues[i].SetValue(lv) + } + return cl +} + +/* }}} */ + +/* toType {{{ */ + +func (ls *LState) ToBool(n int) bool { + return LVAsBool(ls.Get(n)) +} + +func (ls *LState) ToInt(n int) int { + if lv, ok := ls.Get(n).(LNumber); ok { + return int(lv) + } + if lv, ok := ls.Get(n).(LString); ok { + if num, err := parseNumber(string(lv)); err == nil { + return int(num) + } + } + return 0 +} + +func (ls *LState) ToInt64(n int) int64 { + if lv, ok := ls.Get(n).(LNumber); ok { + return int64(lv) + } + if lv, ok := ls.Get(n).(LString); ok { + if num, err := parseNumber(string(lv)); err == nil { + return int64(num) + } + } + return 0 +} + +func (ls *LState) ToNumber(n int) LNumber { + return LVAsNumber(ls.Get(n)) +} + +func (ls *LState) ToString(n int) string { + return LVAsString(ls.Get(n)) +} + +func (ls *LState) ToTable(n int) *LTable { + if lv, ok := ls.Get(n).(*LTable); ok { + return lv + } + return nil +} + +func (ls *LState) ToFunction(n int) *LFunction { + if lv, ok := ls.Get(n).(*LFunction); ok { + return lv + } + return nil +} + +func (ls *LState) ToUserData(n int) *LUserData { + if lv, ok := ls.Get(n).(*LUserData); ok { + return lv + } + return nil +} + +func (ls *LState) ToThread(n int) *LState { + if lv, ok := ls.Get(n).(*LState); ok { + return lv + } + return nil +} + +/* }}} */ + +/* error & debug operations {{{ */ + +// This function is equivalent to luaL_error( http://www.lua.org/manual/5.1/manual.html#luaL_error ). +func (ls *LState) RaiseError(format string, args ...interface{}) { + ls.raiseError(1, format, args...) +} + +// This function is equivalent to lua_error( http://www.lua.org/manual/5.1/manual.html#lua_error ). +func (ls *LState) Error(lv LValue, level int) { + if str, ok := lv.(LString); ok { + ls.raiseError(level, string(str)) + } else { + if !ls.hasErrorFunc { + ls.closeAllUpvalues() + } + ls.Push(lv) + ls.Panic(ls) + } +} + +func (ls *LState) GetInfo(what string, dbg *Debug, fn LValue) (LValue, error) { + if !strings.HasPrefix(what, ">") { + fn = dbg.frame.Fn + } else { + what = what[1:] + } + f, ok := fn.(*LFunction) + if !ok { + return LNil, newApiErrorS(ApiErrorRun, "can not get debug info(an object in not a function)") + } + + retfn := false + for _, c := range what { + switch c { + case 'f': + retfn = true + case 'S': + if dbg.frame != nil && dbg.frame.Parent == nil { + dbg.What = "main" + } else if f.IsG { + dbg.What = "G" + } else if dbg.frame != nil && dbg.frame.TailCall > 0 { + dbg.What = "tail" + } else { + dbg.What = "Lua" + } + if !f.IsG { + dbg.Source = f.Proto.SourceName + dbg.LineDefined = f.Proto.LineDefined + dbg.LastLineDefined = f.Proto.LastLineDefined + } + case 'l': + if !f.IsG && dbg.frame != nil { + if dbg.frame.Pc > 0 { + dbg.CurrentLine = f.Proto.DbgSourcePositions[dbg.frame.Pc-1] + } + } else { + dbg.CurrentLine = -1 + } + case 'u': + dbg.NUpvalues = len(f.Upvalues) + case 'n': + if dbg.frame != nil { + dbg.Name = ls.rawFrameFuncName(dbg.frame) + } + default: + return LNil, newApiErrorS(ApiErrorRun, "invalid what: "+string(c)) + } + } + + if retfn { + return f, nil + } + return LNil, nil + +} + +func (ls *LState) GetStack(level int) (*Debug, bool) { + frame := ls.currentFrame + for ; level > 0 && frame != nil; frame = frame.Parent { + level-- + if !frame.Fn.IsG { + level -= frame.TailCall + } + } + + if level == 0 && frame != nil { + return &Debug{frame: frame}, true + } else if level < 0 && ls.stack.Sp() > 0 { + return &Debug{frame: ls.stack.At(0)}, true + } + return &Debug{}, false +} + +func (ls *LState) GetLocal(dbg *Debug, no int) (string, LValue) { + frame := dbg.frame + if name := ls.findLocal(frame, no); len(name) > 0 { + return name, ls.reg.Get(frame.LocalBase + no - 1) + } + return "", LNil +} + +func (ls *LState) SetLocal(dbg *Debug, no int, lv LValue) string { + frame := dbg.frame + if name := ls.findLocal(frame, no); len(name) > 0 { + ls.reg.Set(frame.LocalBase+no-1, lv) + return name + } + return "" +} + +func (ls *LState) GetUpvalue(fn *LFunction, no int) (string, LValue) { + if fn.IsG { + return "", LNil + } + + no-- + if no >= 0 && no < len(fn.Upvalues) { + return fn.Proto.DbgUpvalues[no], fn.Upvalues[no].Value() + } + return "", LNil +} + +func (ls *LState) SetUpvalue(fn *LFunction, no int, lv LValue) string { + if fn.IsG { + return "" + } + + no-- + if no >= 0 && no < len(fn.Upvalues) { + fn.Upvalues[no].SetValue(lv) + return fn.Proto.DbgUpvalues[no] + } + return "" +} + +/* }}} */ + +/* env operations {{{ */ + +func (ls *LState) GetFEnv(obj LValue) LValue { + switch lv := obj.(type) { + case *LFunction: + return lv.Env + case *LUserData: + return lv.Env + case *LState: + return lv.Env + } + return LNil +} + +func (ls *LState) SetFEnv(obj LValue, env LValue) { + tb, ok := env.(*LTable) + if !ok { + ls.RaiseError("cannot use %v as an environment", env.Type().String()) + } + + switch lv := obj.(type) { + case *LFunction: + lv.Env = tb + case *LUserData: + lv.Env = tb + case *LState: + lv.Env = tb + } + /* do nothing */ +} + +/* }}} */ + +/* table operations {{{ */ + +func (ls *LState) RawGet(tb *LTable, key LValue) LValue { + return tb.RawGet(key) +} + +func (ls *LState) RawGetInt(tb *LTable, key int) LValue { + return tb.RawGetInt(key) +} + +func (ls *LState) GetField(obj LValue, skey string) LValue { + return ls.getFieldString(obj, skey) +} + +func (ls *LState) GetTable(obj LValue, key LValue) LValue { + return ls.getField(obj, key) +} + +func (ls *LState) RawSet(tb *LTable, key LValue, value LValue) { + if n, ok := key.(LNumber); ok && math.IsNaN(float64(n)) { + ls.RaiseError("table index is NaN") + } else if key == LNil { + ls.RaiseError("table index is nil") + } + tb.RawSet(key, value) +} + +func (ls *LState) RawSetInt(tb *LTable, key int, value LValue) { + tb.RawSetInt(key, value) +} + +func (ls *LState) SetField(obj LValue, key string, value LValue) { + ls.setFieldString(obj, key, value) +} + +func (ls *LState) SetTable(obj LValue, key LValue, value LValue) { + ls.setField(obj, key, value) +} + +func (ls *LState) ForEach(tb *LTable, cb func(LValue, LValue)) { + tb.ForEach(cb) +} + +func (ls *LState) GetGlobal(name string) LValue { + return ls.GetField(ls.Get(GlobalsIndex), name) +} + +func (ls *LState) SetGlobal(name string, value LValue) { + ls.SetField(ls.Get(GlobalsIndex), name, value) +} + +func (ls *LState) Next(tb *LTable, key LValue) (LValue, LValue) { + return tb.Next(key) +} + +/* }}} */ + +/* unary operations {{{ */ + +func (ls *LState) ObjLen(v1 LValue) int { + if v1.Type() == LTString { + return len(string(v1.(LString))) + } + op := ls.metaOp1(v1, "__len") + if op.Type() == LTFunction { + ls.Push(op) + ls.Push(v1) + ls.Call(1, 1) + ret := ls.reg.Pop() + if ret.Type() == LTNumber { + return int(ret.(LNumber)) + } + } else if v1.Type() == LTTable { + return v1.(*LTable).Len() + } + return 0 +} + +/* }}} */ + +/* binary operations {{{ */ + +func (ls *LState) Concat(values ...LValue) string { + top := ls.reg.Top() + for _, value := range values { + ls.reg.Push(value) + } + ret := stringConcat(ls, len(values), ls.reg.Top()-1) + ls.reg.SetTop(top) + return LVAsString(ret) +} + +func (ls *LState) LessThan(lhs, rhs LValue) bool { + return lessThan(ls, lhs, rhs) +} + +func (ls *LState) Equal(lhs, rhs LValue) bool { + return equals(ls, lhs, rhs, false) +} + +func (ls *LState) RawEqual(lhs, rhs LValue) bool { + return equals(ls, lhs, rhs, true) +} + +/* }}} */ + +/* register operations {{{ */ + +func (ls *LState) Register(name string, fn LGFunction) { + ls.SetGlobal(name, ls.NewFunction(fn)) +} + +/* }}} */ + +/* load and function call operations {{{ */ + +func (ls *LState) Load(reader io.Reader, name string) (*LFunction, error) { + chunk, err := parse.Parse(reader, name) + if err != nil { + return nil, newApiErrorE(ApiErrorSyntax, err) + } + proto, err := Compile(chunk, name) + if err != nil { + return nil, newApiErrorE(ApiErrorSyntax, err) + } + return newLFunctionL(proto, ls.currentEnv(), 0), nil +} + +func (ls *LState) Call(nargs, nret int) { + ls.callR(nargs, nret, -1) +} + +func (ls *LState) PCall(nargs, nret int, errfunc *LFunction) (err error) { + err = nil + sp := ls.stack.Sp() + base := ls.reg.Top() - nargs - 1 + oldpanic := ls.Panic + ls.Panic = panicWithoutTraceback + if errfunc != nil { + ls.hasErrorFunc = true + } + defer func() { + ls.Panic = oldpanic + ls.hasErrorFunc = false + rcv := recover() + if rcv != nil { + if _, ok := rcv.(*ApiError); !ok { + err = newApiErrorS(ApiErrorPanic, fmt.Sprint(rcv)) + if ls.Options.IncludeGoStackTrace { + buf := make([]byte, 4096) + runtime.Stack(buf, false) + err.(*ApiError).StackTrace = strings.Trim(string(buf), "\000") + "\n" + ls.stackTrace(0) + } + } else { + err = rcv.(*ApiError) + } + if errfunc != nil { + ls.Push(errfunc) + ls.Push(err.(*ApiError).Object) + ls.Panic = panicWithoutTraceback + defer func() { + ls.Panic = oldpanic + rcv := recover() + if rcv != nil { + if _, ok := rcv.(*ApiError); !ok { + err = newApiErrorS(ApiErrorPanic, fmt.Sprint(rcv)) + if ls.Options.IncludeGoStackTrace { + buf := make([]byte, 4096) + runtime.Stack(buf, false) + err.(*ApiError).StackTrace = strings.Trim(string(buf), "\000") + ls.stackTrace(0) + } + } else { + err = rcv.(*ApiError) + err.(*ApiError).StackTrace = ls.stackTrace(0) + } + } + }() + ls.Call(1, 1) + err = newApiError(ApiErrorError, ls.Get(-1)) + } else if len(err.(*ApiError).StackTrace) == 0 { + err.(*ApiError).StackTrace = ls.stackTrace(0) + } + ls.stack.SetSp(sp) + ls.currentFrame = ls.stack.Last() + ls.reg.SetTop(base) + } + ls.stack.SetSp(sp) + if sp == 0 { + ls.currentFrame = nil + } + }() + + ls.Call(nargs, nret) + + return +} + +func (ls *LState) GPCall(fn LGFunction, data LValue) error { + ls.Push(newLFunctionG(fn, ls.currentEnv(), 0)) + ls.Push(data) + return ls.PCall(1, MultRet, nil) +} + +func (ls *LState) CallByParam(cp P, args ...LValue) error { + ls.Push(cp.Fn) + for _, arg := range args { + ls.Push(arg) + } + + if cp.Protect { + return ls.PCall(len(args), cp.NRet, cp.Handler) + } + ls.Call(len(args), cp.NRet) + return nil +} + +/* }}} */ + +/* metatable operations {{{ */ + +func (ls *LState) GetMetatable(obj LValue) LValue { + return ls.metatable(obj, false) +} + +func (ls *LState) SetMetatable(obj LValue, mt LValue) { + switch mt.(type) { + case *LNilType, *LTable: + default: + ls.RaiseError("metatable must be a table or nil, but got %v", mt.Type().String()) + } + + switch v := obj.(type) { + case *LTable: + v.Metatable = mt + case *LUserData: + v.Metatable = mt + default: + ls.G.builtinMts[int(obj.Type())] = mt + } +} + +/* }}} */ + +/* coroutine operations {{{ */ + +func (ls *LState) Status(th *LState) string { + status := "suspended" + if th.Dead { + status = "dead" + } else if ls.G.CurrentThread == th { + status = "running" + } else if ls.Parent == th { + status = "normal" + } + return status +} + +func (ls *LState) Resume(th *LState, fn *LFunction, args ...LValue) (ResumeState, error, []LValue) { + isstarted := th.isStarted() + if !isstarted { + base := 0 + th.stack.Push(callFrame{ + Fn: fn, + Pc: 0, + Base: base, + LocalBase: base + 1, + ReturnBase: base, + NArgs: 0, + NRet: MultRet, + Parent: nil, + TailCall: 0, + }) + } + + if ls.G.CurrentThread == th { + return ResumeError, newApiErrorS(ApiErrorRun, "can not resume a running thread"), nil + } + if th.Dead { + return ResumeError, newApiErrorS(ApiErrorRun, "can not resume a dead thread"), nil + } + th.Parent = ls + ls.G.CurrentThread = th + if !isstarted { + cf := th.stack.Last() + th.currentFrame = cf + th.SetTop(0) + for _, arg := range args { + th.Push(arg) + } + cf.NArgs = len(args) + th.initCallFrame(cf) + th.Panic = panicWithoutTraceback + } else { + for _, arg := range args { + th.Push(arg) + } + } + top := ls.GetTop() + threadRun(th) + haserror := LVIsFalse(ls.Get(top + 1)) + ret := make([]LValue, 0, ls.GetTop()) + for idx := top + 2; idx <= ls.GetTop(); idx++ { + ret = append(ret, ls.Get(idx)) + } + if len(ret) == 0 { + ret = append(ret, LNil) + } + ls.SetTop(top) + + if haserror { + return ResumeError, newApiError(ApiErrorRun, ret[0]), nil + } else if th.stack.IsEmpty() { + return ResumeOK, nil, ret + } + return ResumeYield, nil, ret +} + +func (ls *LState) Yield(values ...LValue) int { + ls.SetTop(0) + for _, lv := range values { + ls.Push(lv) + } + return -1 +} + +func (ls *LState) XMoveTo(other *LState, n int) { + if ls == other { + return + } + top := ls.GetTop() + n = intMin(n, top) + for i := n; i > 0; i-- { + other.Push(ls.Get(top - i + 1)) + } + ls.SetTop(top - n) +} + +/* }}} */ + +/* GopherLua original APIs {{{ */ + +// Set maximum memory size. This function can only be called from the main thread. +func (ls *LState) SetMx(mx int) { + if ls.Parent != nil { + ls.RaiseError("sub threads are not allowed to set a memory limit") + } + go func() { + limit := uint64(mx * 1024 * 1024) //MB + var s runtime.MemStats + for ls.stop == 0 { + runtime.ReadMemStats(&s) + if s.Alloc >= limit { + fmt.Println("out of memory") + os.Exit(3) + } + time.Sleep(100 * time.Millisecond) + } + }() +} + +// SetContext set a context ctx to this LState. The provided ctx must be non-nil. +func (ls *LState) SetContext(ctx context.Context) { + ls.mainLoop = mainLoopWithContext + ls.ctx = ctx +} + +// Context returns the LState's context. To change the context, use WithContext. +func (ls *LState) Context() context.Context { + return ls.ctx +} + +// RemoveContext removes the context associated with this LState and returns this context. +func (ls *LState) RemoveContext() context.Context { + oldctx := ls.ctx + ls.mainLoop = mainLoop + ls.ctx = nil + return oldctx +} + +// Converts the Lua value at the given acceptable index to the chan LValue. +func (ls *LState) ToChannel(n int) chan LValue { + if lv, ok := ls.Get(n).(LChannel); ok { + return (chan LValue)(lv) + } + return nil +} + +/* }}} */ + +/* }}} */ + +// diff --git a/vendor/github.com/yuin/gopher-lua/state_test.go b/vendor/github.com/yuin/gopher-lua/state_test.go new file mode 100644 index 0000000000000000000000000000000000000000..46fb5e54fea76fa6c1f1fea772020af3aaeaa2bd --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/state_test.go @@ -0,0 +1,433 @@ +package lua + +import ( + "context" + "strings" + "testing" + "time" +) + +func TestCallStackOverflow(t *testing.T) { + L := NewState(Options{ + CallStackSize: 3, + }) + defer L.Close() + errorIfScriptNotFail(t, L, ` + local function a() + end + local function b() + a() + end + local function c() + print(_printregs()) + b() + end + c() + `, "stack overflow") +} + +func TestSkipOpenLibs(t *testing.T) { + L := NewState(Options{SkipOpenLibs: true}) + defer L.Close() + errorIfScriptNotFail(t, L, `print("")`, + "attempt to call a non-function object") + L2 := NewState() + defer L2.Close() + errorIfScriptFail(t, L2, `print("")`) +} + +func TestGetAndReplace(t *testing.T) { + L := NewState() + defer L.Close() + L.Push(LString("a")) + L.Replace(1, LString("b")) + L.Replace(0, LString("c")) + errorIfNotEqual(t, LNil, L.Get(0)) + errorIfNotEqual(t, LNil, L.Get(-10)) + errorIfNotEqual(t, L.Env, L.Get(EnvironIndex)) + errorIfNotEqual(t, LString("b"), L.Get(1)) + L.Push(LString("c")) + L.Push(LString("d")) + L.Replace(-2, LString("e")) + errorIfNotEqual(t, LString("e"), L.Get(-2)) + registry := L.NewTable() + L.Replace(RegistryIndex, registry) + L.G.Registry = registry + errorIfGFuncNotFail(t, L, func(L *LState) int { + L.Replace(RegistryIndex, LNil) + return 0 + }, "registry must be a table") + errorIfGFuncFail(t, L, func(L *LState) int { + env := L.NewTable() + L.Replace(EnvironIndex, env) + errorIfNotEqual(t, env, L.Get(EnvironIndex)) + return 0 + }) + errorIfGFuncNotFail(t, L, func(L *LState) int { + L.Replace(EnvironIndex, LNil) + return 0 + }, "environment must be a table") + errorIfGFuncFail(t, L, func(L *LState) int { + gbl := L.NewTable() + L.Replace(GlobalsIndex, gbl) + errorIfNotEqual(t, gbl, L.G.Global) + return 0 + }) + errorIfGFuncNotFail(t, L, func(L *LState) int { + L.Replace(GlobalsIndex, LNil) + return 0 + }, "_G must be a table") + + L2 := NewState() + defer L2.Close() + clo := L2.NewClosure(func(L2 *LState) int { + L2.Replace(UpvalueIndex(1), LNumber(3)) + errorIfNotEqual(t, LNumber(3), L2.Get(UpvalueIndex(1))) + return 0 + }, LNumber(1), LNumber(2)) + L2.SetGlobal("clo", clo) + errorIfScriptFail(t, L2, `clo()`) +} + +func TestRemove(t *testing.T) { + L := NewState() + defer L.Close() + L.Push(LString("a")) + L.Push(LString("b")) + L.Push(LString("c")) + + L.Remove(4) + errorIfNotEqual(t, LString("a"), L.Get(1)) + errorIfNotEqual(t, LString("b"), L.Get(2)) + errorIfNotEqual(t, LString("c"), L.Get(3)) + errorIfNotEqual(t, 3, L.GetTop()) + + L.Remove(3) + errorIfNotEqual(t, LString("a"), L.Get(1)) + errorIfNotEqual(t, LString("b"), L.Get(2)) + errorIfNotEqual(t, LNil, L.Get(3)) + errorIfNotEqual(t, 2, L.GetTop()) + L.Push(LString("c")) + + L.Remove(-10) + errorIfNotEqual(t, LString("a"), L.Get(1)) + errorIfNotEqual(t, LString("b"), L.Get(2)) + errorIfNotEqual(t, LString("c"), L.Get(3)) + errorIfNotEqual(t, 3, L.GetTop()) + + L.Remove(2) + errorIfNotEqual(t, LString("a"), L.Get(1)) + errorIfNotEqual(t, LString("c"), L.Get(2)) + errorIfNotEqual(t, LNil, L.Get(3)) + errorIfNotEqual(t, 2, L.GetTop()) +} + +func TestToInt(t *testing.T) { + L := NewState() + defer L.Close() + L.Push(LNumber(10)) + L.Push(LString("99.9")) + L.Push(L.NewTable()) + errorIfNotEqual(t, 10, L.ToInt(1)) + errorIfNotEqual(t, 99, L.ToInt(2)) + errorIfNotEqual(t, 0, L.ToInt(3)) +} + +func TestToInt64(t *testing.T) { + L := NewState() + defer L.Close() + L.Push(LNumber(10)) + L.Push(LString("99.9")) + L.Push(L.NewTable()) + errorIfNotEqual(t, int64(10), L.ToInt64(1)) + errorIfNotEqual(t, int64(99), L.ToInt64(2)) + errorIfNotEqual(t, int64(0), L.ToInt64(3)) +} + +func TestToNumber(t *testing.T) { + L := NewState() + defer L.Close() + L.Push(LNumber(10)) + L.Push(LString("99.9")) + L.Push(L.NewTable()) + errorIfNotEqual(t, LNumber(10), L.ToNumber(1)) + errorIfNotEqual(t, LNumber(99.9), L.ToNumber(2)) + errorIfNotEqual(t, LNumber(0), L.ToNumber(3)) +} + +func TestToString(t *testing.T) { + L := NewState() + defer L.Close() + L.Push(LNumber(10)) + L.Push(LString("99.9")) + L.Push(L.NewTable()) + errorIfNotEqual(t, "10", L.ToString(1)) + errorIfNotEqual(t, "99.9", L.ToString(2)) + errorIfNotEqual(t, "", L.ToString(3)) +} + +func TestToTable(t *testing.T) { + L := NewState() + defer L.Close() + L.Push(LNumber(10)) + L.Push(LString("99.9")) + L.Push(L.NewTable()) + errorIfFalse(t, L.ToTable(1) == nil, "index 1 must be nil") + errorIfFalse(t, L.ToTable(2) == nil, "index 2 must be nil") + errorIfNotEqual(t, L.Get(3), L.ToTable(3)) +} + +func TestToFunction(t *testing.T) { + L := NewState() + defer L.Close() + L.Push(LNumber(10)) + L.Push(LString("99.9")) + L.Push(L.NewFunction(func(L *LState) int { return 0 })) + errorIfFalse(t, L.ToFunction(1) == nil, "index 1 must be nil") + errorIfFalse(t, L.ToFunction(2) == nil, "index 2 must be nil") + errorIfNotEqual(t, L.Get(3), L.ToFunction(3)) +} + +func TestToUserData(t *testing.T) { + L := NewState() + defer L.Close() + L.Push(LNumber(10)) + L.Push(LString("99.9")) + L.Push(L.NewUserData()) + errorIfFalse(t, L.ToUserData(1) == nil, "index 1 must be nil") + errorIfFalse(t, L.ToUserData(2) == nil, "index 2 must be nil") + errorIfNotEqual(t, L.Get(3), L.ToUserData(3)) +} + +func TestToChannel(t *testing.T) { + L := NewState() + defer L.Close() + L.Push(LNumber(10)) + L.Push(LString("99.9")) + var ch chan LValue + L.Push(LChannel(ch)) + errorIfFalse(t, L.ToChannel(1) == nil, "index 1 must be nil") + errorIfFalse(t, L.ToChannel(2) == nil, "index 2 must be nil") + errorIfNotEqual(t, ch, L.ToChannel(3)) +} + +func TestObjLen(t *testing.T) { + L := NewState() + defer L.Close() + errorIfNotEqual(t, 3, L.ObjLen(LString("abc"))) + tbl := L.NewTable() + tbl.Append(LTrue) + tbl.Append(LTrue) + errorIfNotEqual(t, 2, L.ObjLen(tbl)) + mt := L.NewTable() + L.SetField(mt, "__len", L.NewFunction(func(L *LState) int { + tbl := L.CheckTable(1) + L.Push(LNumber(tbl.Len() + 1)) + return 1 + })) + L.SetMetatable(tbl, mt) + errorIfNotEqual(t, 3, L.ObjLen(tbl)) + errorIfNotEqual(t, 0, L.ObjLen(LNumber(10))) +} + +func TestConcat(t *testing.T) { + L := NewState() + defer L.Close() + errorIfNotEqual(t, "a1c", L.Concat(LString("a"), LNumber(1), LString("c"))) +} + +func TestPCall(t *testing.T) { + L := NewState() + defer L.Close() + L.Register("f1", func(L *LState) int { + panic("panic!") + return 0 + }) + errorIfScriptNotFail(t, L, `f1()`, "panic!") + L.Push(L.GetGlobal("f1")) + err := L.PCall(0, 0, L.NewFunction(func(L *LState) int { + L.Push(LString("by handler")) + return 1 + })) + errorIfFalse(t, strings.Contains(err.Error(), "by handler"), "") + + err = L.PCall(0, 0, L.NewFunction(func(L *LState) int { + L.RaiseError("error!") + return 1 + })) + errorIfFalse(t, strings.Contains(err.Error(), "error!"), "") + + err = L.PCall(0, 0, L.NewFunction(func(L *LState) int { + panic("panicc!") + return 1 + })) + errorIfFalse(t, strings.Contains(err.Error(), "panicc!"), "") +} + +func TestCoroutineApi1(t *testing.T) { + L := NewState() + defer L.Close() + co, _ := L.NewThread() + errorIfScriptFail(t, L, ` + function coro(v) + assert(v == 10) + local ret1, ret2 = coroutine.yield(1,2,3) + assert(ret1 == 11) + assert(ret2 == 12) + coroutine.yield(4) + return 5 + end + `) + fn := L.GetGlobal("coro").(*LFunction) + st, err, values := L.Resume(co, fn, LNumber(10)) + errorIfNotEqual(t, ResumeYield, st) + errorIfNotNil(t, err) + errorIfNotEqual(t, 3, len(values)) + errorIfNotEqual(t, LNumber(1), values[0].(LNumber)) + errorIfNotEqual(t, LNumber(2), values[1].(LNumber)) + errorIfNotEqual(t, LNumber(3), values[2].(LNumber)) + + st, err, values = L.Resume(co, fn, LNumber(11), LNumber(12)) + errorIfNotEqual(t, ResumeYield, st) + errorIfNotNil(t, err) + errorIfNotEqual(t, 1, len(values)) + errorIfNotEqual(t, LNumber(4), values[0].(LNumber)) + + st, err, values = L.Resume(co, fn) + errorIfNotEqual(t, ResumeOK, st) + errorIfNotNil(t, err) + errorIfNotEqual(t, 1, len(values)) + errorIfNotEqual(t, LNumber(5), values[0].(LNumber)) + + L.Register("myyield", func(L *LState) int { + return L.Yield(L.ToNumber(1)) + }) + errorIfScriptFail(t, L, ` + function coro_error() + coroutine.yield(1,2,3) + myyield(4) + assert(false, "--failed--") + end + `) + fn = L.GetGlobal("coro_error").(*LFunction) + co, _ = L.NewThread() + st, err, values = L.Resume(co, fn) + errorIfNotEqual(t, ResumeYield, st) + errorIfNotNil(t, err) + errorIfNotEqual(t, 3, len(values)) + errorIfNotEqual(t, LNumber(1), values[0].(LNumber)) + errorIfNotEqual(t, LNumber(2), values[1].(LNumber)) + errorIfNotEqual(t, LNumber(3), values[2].(LNumber)) + + st, err, values = L.Resume(co, fn) + errorIfNotEqual(t, ResumeYield, st) + errorIfNotNil(t, err) + errorIfNotEqual(t, 1, len(values)) + errorIfNotEqual(t, LNumber(4), values[0].(LNumber)) + + st, err, values = L.Resume(co, fn) + errorIfNotEqual(t, ResumeError, st) + errorIfNil(t, err) + errorIfFalse(t, strings.Contains(err.Error(), "--failed--"), "error message must be '--failed--'") + st, err, values = L.Resume(co, fn) + errorIfNotEqual(t, ResumeError, st) + errorIfNil(t, err) + errorIfFalse(t, strings.Contains(err.Error(), "can not resume a dead thread"), "can not resume a dead thread") + +} + +func TestContextTimeout(t *testing.T) { + L := NewState() + defer L.Close() + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + L.SetContext(ctx) + errorIfNotEqual(t, ctx, L.Context()) + err := L.DoString(` + local clock = os.clock + function sleep(n) -- seconds + local t0 = clock() + while clock() - t0 <= n do end + end + sleep(3) + `) + errorIfNil(t, err) + errorIfFalse(t, strings.Contains(err.Error(), "context deadline exceeded"), "execution must be canceled") + + oldctx := L.RemoveContext() + errorIfNotEqual(t, ctx, oldctx) + errorIfNotNil(t, L.ctx) +} + +func TestContextCancel(t *testing.T) { + L := NewState() + defer L.Close() + ctx, cancel := context.WithCancel(context.Background()) + errch := make(chan error, 1) + L.SetContext(ctx) + go func() { + errch <- L.DoString(` + local clock = os.clock + function sleep(n) -- seconds + local t0 = clock() + while clock() - t0 <= n do end + end + sleep(3) + `) + }() + time.Sleep(1 * time.Second) + cancel() + err := <-errch + errorIfNil(t, err) + errorIfFalse(t, strings.Contains(err.Error(), "context canceled"), "execution must be canceled") +} + +func TestContextWithCroutine(t *testing.T) { + L := NewState() + defer L.Close() + ctx, cancel := context.WithCancel(context.Background()) + L.SetContext(ctx) + defer cancel() + L.DoString(` + function coro() + local i = 0 + while true do + coroutine.yield(i) + i = i+1 + end + return i + end + `) + co, cocancel := L.NewThread() + defer cocancel() + fn := L.GetGlobal("coro").(*LFunction) + _, err, values := L.Resume(co, fn) + errorIfNotNil(t, err) + errorIfNotEqual(t, LNumber(0), values[0]) + // cancel the parent context + cancel() + _, err, values = L.Resume(co, fn) + errorIfNil(t, err) + errorIfFalse(t, strings.Contains(err.Error(), "context canceled"), "coroutine execution must be canceled when the parent context is canceled") + +} + +func TestPCallAfterFail(t *testing.T) { + L := NewState() + defer L.Close() + errFn := L.NewFunction(func(L *LState) int { + L.RaiseError("error!") + return 0 + }) + changeError := L.NewFunction(func(L *LState) int { + L.Push(errFn) + err := L.PCall(0, 0, nil) + if err != nil { + L.RaiseError("A New Error") + } + return 0 + }) + L.Push(changeError) + err := L.PCall(0, 0, nil) + errorIfFalse(t, strings.Contains(err.Error(), "A New Error"), "error not propogated correctly") +} diff --git a/vendor/github.com/yuin/gopher-lua/stringlib.go b/vendor/github.com/yuin/gopher-lua/stringlib.go new file mode 100644 index 0000000000000000000000000000000000000000..f484c2b33afad2dfc13433172a2c5d72dd8d8b94 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/stringlib.go @@ -0,0 +1,448 @@ +package lua + +import ( + "fmt" + "strings" + + "github.com/yuin/gopher-lua/pm" +) + +const emptyLString LString = LString("") + +func OpenString(L *LState) int { + var mod *LTable + //_, ok := L.G.builtinMts[int(LTString)] + //if !ok { + mod = L.RegisterModule(StringLibName, strFuncs).(*LTable) + gmatch := L.NewClosure(strGmatch, L.NewFunction(strGmatchIter)) + mod.RawSetString("gmatch", gmatch) + mod.RawSetString("gfind", gmatch) + mod.RawSetString("__index", mod) + L.G.builtinMts[int(LTString)] = mod + //} + L.Push(mod) + return 1 +} + +var strFuncs = map[string]LGFunction{ + "byte": strByte, + "char": strChar, + "dump": strDump, + "find": strFind, + "format": strFormat, + "gsub": strGsub, + "len": strLen, + "lower": strLower, + "match": strMatch, + "rep": strRep, + "reverse": strReverse, + "sub": strSub, + "upper": strUpper, +} + +func strByte(L *LState) int { + str := L.CheckString(1) + start := L.OptInt(2, 1) - 1 + end := L.OptInt(3, -1) + l := len(str) + if start < 0 { + start = l + start + 1 + } + if end < 0 { + end = l + end + 1 + } + + if L.GetTop() == 2 { + if start < 0 || start >= l { + return 0 + } + L.Push(LNumber(str[start])) + return 1 + } + + start = intMax(start, 0) + end = intMin(end, l) + if end < 0 || end <= start || start >= l { + return 0 + } + + for i := start; i < end; i++ { + L.Push(LNumber(str[i])) + } + return end - start +} + +func strChar(L *LState) int { + top := L.GetTop() + bytes := make([]byte, L.GetTop()) + for i := 1; i <= top; i++ { + bytes[i-1] = uint8(L.CheckInt(i)) + } + L.Push(LString(string(bytes))) + return 1 +} + +func strDump(L *LState) int { + L.RaiseError("GopherLua does not support the string.dump") + return 0 +} + +func strFind(L *LState) int { + str := L.CheckString(1) + pattern := L.CheckString(2) + if len(pattern) == 0 { + L.Push(LNumber(1)) + L.Push(LNumber(0)) + return 2 + } + init := luaIndex2StringIndex(str, L.OptInt(3, 1), true) + plain := false + if L.GetTop() == 4 { + plain = LVAsBool(L.Get(4)) + } + + if plain { + pos := strings.Index(str[init:], pattern) + if pos < 0 { + L.Push(LNil) + return 1 + } + L.Push(LNumber(init+pos) + 1) + L.Push(LNumber(init + pos + len(pattern))) + return 2 + } + + mds, err := pm.Find(pattern, unsafeFastStringToReadOnlyBytes(str), init, 1) + if err != nil { + L.RaiseError(err.Error()) + } + if len(mds) == 0 { + L.Push(LNil) + return 1 + } + md := mds[0] + L.Push(LNumber(md.Capture(0) + 1)) + L.Push(LNumber(md.Capture(1))) + for i := 2; i < md.CaptureLength(); i += 2 { + if md.IsPosCapture(i) { + L.Push(LNumber(md.Capture(i))) + } else { + L.Push(LString(str[md.Capture(i):md.Capture(i+1)])) + } + } + return md.CaptureLength()/2 + 1 +} + +func strFormat(L *LState) int { + str := L.CheckString(1) + args := make([]interface{}, L.GetTop()-1) + top := L.GetTop() + for i := 2; i <= top; i++ { + args[i-2] = L.Get(i) + } + npat := strings.Count(str, "%") - strings.Count(str, "%%") + L.Push(LString(fmt.Sprintf(str, args[:intMin(npat, len(args))]...))) + return 1 +} + +func strGsub(L *LState) int { + str := L.CheckString(1) + pat := L.CheckString(2) + L.CheckTypes(3, LTString, LTTable, LTFunction) + repl := L.CheckAny(3) + limit := L.OptInt(4, -1) + + mds, err := pm.Find(pat, unsafeFastStringToReadOnlyBytes(str), 0, limit) + if err != nil { + L.RaiseError(err.Error()) + } + if len(mds) == 0 { + L.SetTop(1) + L.Push(LNumber(0)) + return 2 + } + switch lv := repl.(type) { + case LString: + L.Push(LString(strGsubStr(L, str, string(lv), mds))) + case *LTable: + L.Push(LString(strGsubTable(L, str, lv, mds))) + case *LFunction: + L.Push(LString(strGsubFunc(L, str, lv, mds))) + } + L.Push(LNumber(len(mds))) + return 2 +} + +type replaceInfo struct { + Indicies []int + String string +} + +func checkCaptureIndex(L *LState, m *pm.MatchData, idx int) { + if idx <= 2 { + return + } + if idx >= m.CaptureLength() { + L.RaiseError("invalid capture index") + } +} + +func capturedString(L *LState, m *pm.MatchData, str string, idx int) string { + checkCaptureIndex(L, m, idx) + if idx >= m.CaptureLength() && idx == 2 { + idx = 0 + } + if m.IsPosCapture(idx) { + return fmt.Sprint(m.Capture(idx)) + } else { + return str[m.Capture(idx):m.Capture(idx+1)] + } + +} + +func strGsubDoReplace(str string, info []replaceInfo) string { + offset := 0 + buf := []byte(str) + for _, replace := range info { + oldlen := len(buf) + b1 := append([]byte(""), buf[0:offset+replace.Indicies[0]]...) + b2 := []byte("") + index2 := offset + replace.Indicies[1] + if index2 <= len(buf) { + b2 = append(b2, buf[index2:len(buf)]...) + } + buf = append(b1, replace.String...) + buf = append(buf, b2...) + offset += len(buf) - oldlen + } + return string(buf) +} + +func strGsubStr(L *LState, str string, repl string, matches []*pm.MatchData) string { + infoList := make([]replaceInfo, 0, len(matches)) + for _, match := range matches { + start, end := match.Capture(0), match.Capture(1) + sc := newFlagScanner('%', "", "", repl) + for c, eos := sc.Next(); !eos; c, eos = sc.Next() { + if !sc.ChangeFlag { + if sc.HasFlag { + if c >= '0' && c <= '9' { + sc.AppendString(capturedString(L, match, str, 2*(int(c)-48))) + } else { + sc.AppendChar('%') + sc.AppendChar(c) + } + sc.HasFlag = false + } else { + sc.AppendChar(c) + } + } + } + infoList = append(infoList, replaceInfo{[]int{start, end}, sc.String()}) + } + + return strGsubDoReplace(str, infoList) +} + +func strGsubTable(L *LState, str string, repl *LTable, matches []*pm.MatchData) string { + infoList := make([]replaceInfo, 0, len(matches)) + for _, match := range matches { + idx := 0 + if match.CaptureLength() > 2 { // has captures + idx = 2 + } + var value LValue + if match.IsPosCapture(idx) { + value = L.GetTable(repl, LNumber(match.Capture(idx))) + } else { + value = L.GetField(repl, str[match.Capture(idx):match.Capture(idx+1)]) + } + if !LVIsFalse(value) { + infoList = append(infoList, replaceInfo{[]int{match.Capture(0), match.Capture(1)}, LVAsString(value)}) + } + } + return strGsubDoReplace(str, infoList) +} + +func strGsubFunc(L *LState, str string, repl *LFunction, matches []*pm.MatchData) string { + infoList := make([]replaceInfo, 0, len(matches)) + for _, match := range matches { + start, end := match.Capture(0), match.Capture(1) + L.Push(repl) + nargs := 0 + if match.CaptureLength() > 2 { // has captures + for i := 2; i < match.CaptureLength(); i += 2 { + if match.IsPosCapture(i) { + L.Push(LNumber(match.Capture(i))) + } else { + L.Push(LString(capturedString(L, match, str, i))) + } + nargs++ + } + } else { + L.Push(LString(capturedString(L, match, str, 0))) + nargs++ + } + L.Call(nargs, 1) + ret := L.reg.Pop() + if !LVIsFalse(ret) { + infoList = append(infoList, replaceInfo{[]int{start, end}, LVAsString(ret)}) + } + } + return strGsubDoReplace(str, infoList) +} + +type strMatchData struct { + str string + pos int + matches []*pm.MatchData +} + +func strGmatchIter(L *LState) int { + md := L.CheckUserData(1).Value.(*strMatchData) + str := md.str + matches := md.matches + idx := md.pos + md.pos += 1 + if idx == len(matches) { + return 0 + } + L.Push(L.Get(1)) + match := matches[idx] + if match.CaptureLength() == 2 { + L.Push(LString(str[match.Capture(0):match.Capture(1)])) + return 1 + } + + for i := 2; i < match.CaptureLength(); i += 2 { + if match.IsPosCapture(i) { + L.Push(LNumber(match.Capture(i))) + } else { + L.Push(LString(str[match.Capture(i):match.Capture(i+1)])) + } + } + return match.CaptureLength()/2 - 1 +} + +func strGmatch(L *LState) int { + str := L.CheckString(1) + pattern := L.CheckString(2) + mds, err := pm.Find(pattern, []byte(str), 0, -1) + if err != nil { + L.RaiseError(err.Error()) + } + L.Push(L.Get(UpvalueIndex(1))) + ud := L.NewUserData() + ud.Value = &strMatchData{str, 0, mds} + L.Push(ud) + return 2 +} + +func strLen(L *LState) int { + str := L.CheckString(1) + L.Push(LNumber(len(str))) + return 1 +} + +func strLower(L *LState) int { + str := L.CheckString(1) + L.Push(LString(strings.ToLower(str))) + return 1 +} + +func strMatch(L *LState) int { + str := L.CheckString(1) + pattern := L.CheckString(2) + offset := L.OptInt(3, 1) + l := len(str) + if offset < 0 { + offset = l + offset + 1 + } + offset-- + if offset < 0 { + offset = 0 + } + + mds, err := pm.Find(pattern, unsafeFastStringToReadOnlyBytes(str), offset, 1) + if err != nil { + L.RaiseError(err.Error()) + } + if len(mds) == 0 { + L.Push(LNil) + return 0 + } + md := mds[0] + nsubs := md.CaptureLength() / 2 + switch nsubs { + case 1: + L.Push(LString(str[md.Capture(0):md.Capture(1)])) + return 1 + default: + for i := 2; i < md.CaptureLength(); i += 2 { + if md.IsPosCapture(i) { + L.Push(LNumber(md.Capture(i))) + } else { + L.Push(LString(str[md.Capture(i):md.Capture(i+1)])) + } + } + return nsubs - 1 + } +} + +func strRep(L *LState) int { + str := L.CheckString(1) + n := L.CheckInt(2) + if n < 0 { + L.Push(emptyLString) + } else { + L.Push(LString(strings.Repeat(str, n))) + } + return 1 +} + +func strReverse(L *LState) int { + str := L.CheckString(1) + bts := []byte(str) + out := make([]byte, len(bts)) + for i, j := 0, len(bts)-1; j >= 0; i, j = i+1, j-1 { + out[i] = bts[j] + } + L.Push(LString(string(out))) + return 1 +} + +func strSub(L *LState) int { + str := L.CheckString(1) + start := luaIndex2StringIndex(str, L.CheckInt(2), true) + end := luaIndex2StringIndex(str, L.OptInt(3, -1), false) + l := len(str) + if start >= l || end < start { + L.Push(emptyLString) + } else { + L.Push(LString(str[start:end])) + } + return 1 +} + +func strUpper(L *LState) int { + str := L.CheckString(1) + L.Push(LString(strings.ToUpper(str))) + return 1 +} + +func luaIndex2StringIndex(str string, i int, start bool) int { + if start && i != 0 { + i -= 1 + } + l := len(str) + if i < 0 { + i = l + i + 1 + } + i = intMax(0, i) + if !start && i > l { + i = l + } + return i +} + +// diff --git a/vendor/github.com/yuin/gopher-lua/table.go b/vendor/github.com/yuin/gopher-lua/table.go new file mode 100644 index 0000000000000000000000000000000000000000..863a5c69ce2fb7af6d0821058bfddadac22fcbcc --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/table.go @@ -0,0 +1,374 @@ +package lua + +const defaultArrayCap = 32 +const defaultHashCap = 32 + +type lValueArraySorter struct { + L *LState + Fn *LFunction + Values []LValue +} + +func (lv lValueArraySorter) Len() int { + return len(lv.Values) +} + +func (lv lValueArraySorter) Swap(i, j int) { + lv.Values[i], lv.Values[j] = lv.Values[j], lv.Values[i] +} + +func (lv lValueArraySorter) Less(i, j int) bool { + if lv.Fn != nil { + lv.L.Push(lv.Fn) + lv.L.Push(lv.Values[i]) + lv.L.Push(lv.Values[j]) + lv.L.Call(2, 1) + return LVAsBool(lv.L.reg.Pop()) + } + return lessThan(lv.L, lv.Values[i], lv.Values[j]) +} + +func newLTable(acap int, hcap int) *LTable { + if acap < 0 { + acap = 0 + } + if hcap < 0 { + hcap = 0 + } + tb := <able{} + tb.Metatable = LNil + if acap != 0 { + tb.array = make([]LValue, 0, acap) + } + if hcap != 0 { + tb.strdict = make(map[string]LValue, hcap) + } + return tb +} + +// Len returns length of this LTable. +func (tb *LTable) Len() int { + if tb.array == nil { + return 0 + } + var prev LValue = LNil + for i := len(tb.array) - 1; i >= 0; i-- { + v := tb.array[i] + if prev == LNil && v != LNil { + return i + 1 + } + prev = v + } + return 0 +} + +// Append appends a given LValue to this LTable. +func (tb *LTable) Append(value LValue) { + if value == LNil { + return + } + if tb.array == nil { + tb.array = make([]LValue, 0, defaultArrayCap) + } + tb.array = append(tb.array, value) +} + +// Insert inserts a given LValue at position `i` in this table. +func (tb *LTable) Insert(i int, value LValue) { + if tb.array == nil { + tb.array = make([]LValue, 0, defaultArrayCap) + } + if i > len(tb.array) { + tb.RawSetInt(i, value) + return + } + if i <= 0 { + tb.RawSet(LNumber(i), value) + return + } + i -= 1 + tb.array = append(tb.array, LNil) + copy(tb.array[i+1:], tb.array[i:]) + tb.array[i] = value +} + +// MaxN returns a maximum number key that nil value does not exist before it. +func (tb *LTable) MaxN() int { + if tb.array == nil { + return 0 + } + for i := len(tb.array) - 1; i >= 0; i-- { + if tb.array[i] != LNil { + return i + 1 + } + } + return 0 +} + +// Remove removes from this table the element at a given position. +func (tb *LTable) Remove(pos int) LValue { + if tb.array == nil { + return LNil + } + i := pos - 1 + larray := len(tb.array) + oldval := LNil + switch { + case i >= larray: + // nothing to do + case i == larray-1 || i < 0: + oldval = tb.array[larray-1] + tb.array = tb.array[:larray-1] + default: + oldval = tb.array[i] + copy(tb.array[i:], tb.array[i+1:]) + tb.array[larray-1] = nil + tb.array = tb.array[:larray-1] + } + return oldval +} + +// RawSet sets a given LValue to a given index without the __newindex metamethod. +// It is recommended to use `RawSetString` or `RawSetInt` for performance +// if you already know the given LValue is a string or number. +func (tb *LTable) RawSet(key LValue, value LValue) { + switch v := key.(type) { + case LNumber: + if isArrayKey(v) { + if tb.array == nil { + tb.array = make([]LValue, 0, defaultArrayCap) + } + index := int(v) - 1 + alen := len(tb.array) + switch { + case index == alen: + tb.array = append(tb.array, value) + case index > alen: + for i := 0; i < (index - alen); i++ { + tb.array = append(tb.array, LNil) + } + tb.array = append(tb.array, value) + case index < alen: + tb.array[index] = value + } + return + } + case LString: + tb.RawSetString(string(v), value) + return + } + + tb.RawSetH(key, value) +} + +// RawSetInt sets a given LValue at a position `key` without the __newindex metamethod. +func (tb *LTable) RawSetInt(key int, value LValue) { + if key < 1 || key >= MaxArrayIndex { + tb.RawSetH(LNumber(key), value) + return + } + if tb.array == nil { + tb.array = make([]LValue, 0, 32) + } + index := key - 1 + alen := len(tb.array) + switch { + case index == alen: + tb.array = append(tb.array, value) + case index > alen: + for i := 0; i < (index - alen); i++ { + tb.array = append(tb.array, LNil) + } + tb.array = append(tb.array, value) + case index < alen: + tb.array[index] = value + } +} + +// RawSetString sets a given LValue to a given string index without the __newindex metamethod. +func (tb *LTable) RawSetString(key string, value LValue) { + if tb.strdict == nil { + tb.strdict = make(map[string]LValue, defaultHashCap) + } + if tb.keys == nil { + tb.keys = []LValue{} + tb.k2i = map[LValue]int{} + } + + if value == LNil { + // TODO tb.keys and tb.k2i should also be removed + delete(tb.strdict, key) + } else { + tb.strdict[key] = value + lkey := LString(key) + if _, ok := tb.k2i[lkey]; !ok { + tb.k2i[lkey] = len(tb.keys) + tb.keys = append(tb.keys, lkey) + } + } +} + +// RawSetH sets a given LValue to a given index without the __newindex metamethod. +func (tb *LTable) RawSetH(key LValue, value LValue) { + if s, ok := key.(LString); ok { + tb.RawSetString(string(s), value) + return + } + if tb.dict == nil { + tb.dict = make(map[LValue]LValue, len(tb.strdict)) + } + if tb.keys == nil { + tb.keys = []LValue{} + tb.k2i = map[LValue]int{} + } + + if value == LNil { + // TODO tb.keys and tb.k2i should also be removed + delete(tb.dict, key) + } else { + tb.dict[key] = value + if _, ok := tb.k2i[key]; !ok { + tb.k2i[key] = len(tb.keys) + tb.keys = append(tb.keys, key) + } + } +} + +// RawGet returns an LValue associated with a given key without __index metamethod. +func (tb *LTable) RawGet(key LValue) LValue { + switch v := key.(type) { + case LNumber: + if isArrayKey(v) { + if tb.array == nil { + return LNil + } + index := int(v) - 1 + if index >= len(tb.array) { + return LNil + } + return tb.array[index] + } + case LString: + if tb.strdict == nil { + return LNil + } + if ret, ok := tb.strdict[string(v)]; ok { + return ret + } + return LNil + } + if tb.dict == nil { + return LNil + } + if v, ok := tb.dict[key]; ok { + return v + } + return LNil +} + +// RawGetInt returns an LValue at position `key` without __index metamethod. +func (tb *LTable) RawGetInt(key int) LValue { + if tb.array == nil { + return LNil + } + index := int(key) - 1 + if index >= len(tb.array) || index < 0 { + return LNil + } + return tb.array[index] +} + +// RawGet returns an LValue associated with a given key without __index metamethod. +func (tb *LTable) RawGetH(key LValue) LValue { + if s, sok := key.(LString); sok { + if tb.strdict == nil { + return LNil + } + if v, vok := tb.strdict[string(s)]; vok { + return v + } + return LNil + } + if tb.dict == nil { + return LNil + } + if v, ok := tb.dict[key]; ok { + return v + } + return LNil +} + +// RawGetString returns an LValue associated with a given key without __index metamethod. +func (tb *LTable) RawGetString(key string) LValue { + if tb.strdict == nil { + return LNil + } + if v, vok := tb.strdict[string(key)]; vok { + return v + } + return LNil +} + +// ForEach iterates over this table of elements, yielding each in turn to a given function. +func (tb *LTable) ForEach(cb func(LValue, LValue)) { + if tb.array != nil { + for i, v := range tb.array { + if v != LNil { + cb(LNumber(i+1), v) + } + } + } + if tb.strdict != nil { + for k, v := range tb.strdict { + if v != LNil { + cb(LString(k), v) + } + } + } + if tb.dict != nil { + for k, v := range tb.dict { + if v != LNil { + cb(k, v) + } + } + } +} + +// This function is equivalent to lua_next ( http://www.lua.org/manual/5.1/manual.html#lua_next ). +func (tb *LTable) Next(key LValue) (LValue, LValue) { + init := false + if key == LNil { + key = LNumber(0) + init = true + } + + if init || key != LNumber(0) { + if kv, ok := key.(LNumber); ok && isInteger(kv) && int(kv) >= 0 && kv < LNumber(MaxArrayIndex) { + index := int(kv) + if tb.array != nil { + for ; index < len(tb.array); index++ { + if v := tb.array[index]; v != LNil { + return LNumber(index + 1), v + } + } + } + if tb.array == nil || index == len(tb.array) { + if (tb.dict == nil || len(tb.dict) == 0) && (tb.strdict == nil || len(tb.strdict) == 0) { + return LNil, LNil + } + key = tb.keys[0] + if v := tb.RawGetH(key); v != LNil { + return key, v + } + } + } + } + + for i := tb.k2i[key] + 1; i < len(tb.keys); i++ { + key := tb.keys[i] + if v := tb.RawGetH(key); v != LNil { + return key, v + } + } + return LNil, LNil +} diff --git a/vendor/github.com/yuin/gopher-lua/table_test.go b/vendor/github.com/yuin/gopher-lua/table_test.go new file mode 100644 index 0000000000000000000000000000000000000000..6248296adf5004db523ed914296da94ea4efa28f --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/table_test.go @@ -0,0 +1,187 @@ +package lua + +import ( + "testing" +) + +func TestTableNewLTable(t *testing.T) { + tbl := newLTable(-1, -2) + errorIfNotEqual(t, 0, cap(tbl.array)) + + tbl = newLTable(10, 9) + errorIfNotEqual(t, 10, cap(tbl.array)) +} + +func TestTableLen(t *testing.T) { + tbl := newLTable(0, 0) + tbl.RawSetInt(10, LNil) + tbl.RawSetInt(9, LNumber(10)) + tbl.RawSetInt(8, LNil) + tbl.RawSetInt(7, LNumber(10)) + errorIfNotEqual(t, 9, tbl.Len()) + + tbl = newLTable(0, 0) + tbl.Append(LTrue) + tbl.Append(LTrue) + tbl.Append(LTrue) + errorIfNotEqual(t, 3, tbl.Len()) +} + +func TestTableInsert(t *testing.T) { + tbl := newLTable(0, 0) + tbl.Append(LTrue) + tbl.Append(LTrue) + tbl.Append(LTrue) + + tbl.Insert(5, LFalse) + errorIfNotEqual(t, LFalse, tbl.RawGetInt(5)) + errorIfNotEqual(t, 5, tbl.Len()) + + tbl.Insert(-10, LFalse) + errorIfNotEqual(t, LFalse, tbl.RawGet(LNumber(-10))) + errorIfNotEqual(t, 5, tbl.Len()) + + tbl = newLTable(0, 0) + tbl.Append(LNumber(1)) + tbl.Append(LNumber(2)) + tbl.Append(LNumber(3)) + tbl.Insert(1, LNumber(10)) + errorIfNotEqual(t, LNumber(10), tbl.RawGetInt(1)) + errorIfNotEqual(t, LNumber(1), tbl.RawGetInt(2)) + errorIfNotEqual(t, LNumber(2), tbl.RawGetInt(3)) + errorIfNotEqual(t, LNumber(3), tbl.RawGetInt(4)) + errorIfNotEqual(t, 4, tbl.Len()) + + tbl = newLTable(0, 0) + tbl.Insert(5, LNumber(10)) + errorIfNotEqual(t, LNumber(10), tbl.RawGetInt(5)) + +} + +func TestTableMaxN(t *testing.T) { + tbl := newLTable(0, 0) + tbl.Append(LTrue) + tbl.Append(LTrue) + tbl.Append(LTrue) + errorIfNotEqual(t, 3, tbl.MaxN()) + + tbl = newLTable(0, 0) + errorIfNotEqual(t, 0, tbl.MaxN()) + + tbl = newLTable(10, 0) + errorIfNotEqual(t, 0, tbl.MaxN()) +} + +func TestTableRemove(t *testing.T) { + tbl := newLTable(0, 0) + errorIfNotEqual(t, LNil, tbl.Remove(10)) + tbl.Append(LTrue) + errorIfNotEqual(t, LNil, tbl.Remove(10)) + + tbl.Append(LFalse) + tbl.Append(LTrue) + errorIfNotEqual(t, LFalse, tbl.Remove(2)) + errorIfNotEqual(t, 2, tbl.MaxN()) + tbl.Append(LFalse) + errorIfNotEqual(t, LFalse, tbl.Remove(-1)) + errorIfNotEqual(t, 2, tbl.MaxN()) + +} + +func TestTableRawSetInt(t *testing.T) { + tbl := newLTable(0, 0) + tbl.RawSetInt(MaxArrayIndex+1, LTrue) + errorIfNotEqual(t, 0, tbl.MaxN()) + errorIfNotEqual(t, LTrue, tbl.RawGet(LNumber(MaxArrayIndex+1))) + + tbl.RawSetInt(1, LTrue) + tbl.RawSetInt(3, LTrue) + errorIfNotEqual(t, 3, tbl.MaxN()) + errorIfNotEqual(t, LTrue, tbl.RawGetInt(1)) + errorIfNotEqual(t, LNil, tbl.RawGetInt(2)) + errorIfNotEqual(t, LTrue, tbl.RawGetInt(3)) + tbl.RawSetInt(2, LTrue) + errorIfNotEqual(t, LTrue, tbl.RawGetInt(1)) + errorIfNotEqual(t, LTrue, tbl.RawGetInt(2)) + errorIfNotEqual(t, LTrue, tbl.RawGetInt(3)) +} + +func TestTableRawSetH(t *testing.T) { + tbl := newLTable(0, 0) + tbl.RawSetH(LString("key"), LTrue) + tbl.RawSetH(LString("key"), LNil) + _, found := tbl.dict[LString("key")] + errorIfNotEqual(t, false, found) + + tbl.RawSetH(LTrue, LTrue) + tbl.RawSetH(LTrue, LNil) + _, foundb := tbl.dict[LTrue] + errorIfNotEqual(t, false, foundb) +} + +func TestTableRawGetH(t *testing.T) { + tbl := newLTable(0, 0) + errorIfNotEqual(t, LNil, tbl.RawGetH(LNumber(1))) + errorIfNotEqual(t, LNil, tbl.RawGetH(LString("key0"))) + tbl.RawSetH(LString("key0"), LTrue) + tbl.RawSetH(LString("key1"), LFalse) + tbl.RawSetH(LNumber(1), LTrue) + errorIfNotEqual(t, LTrue, tbl.RawGetH(LString("key0"))) + errorIfNotEqual(t, LTrue, tbl.RawGetH(LNumber(1))) + errorIfNotEqual(t, LNil, tbl.RawGetH(LString("notexist"))) + errorIfNotEqual(t, LNil, tbl.RawGetH(LTrue)) +} + +func TestTableForEach(t *testing.T) { + tbl := newLTable(0, 0) + tbl.Append(LNumber(1)) + tbl.Append(LNumber(2)) + tbl.Append(LNumber(3)) + tbl.Append(LNil) + tbl.Append(LNumber(5)) + + tbl.RawSetH(LString("a"), LString("a")) + tbl.RawSetH(LString("b"), LString("b")) + tbl.RawSetH(LString("c"), LString("c")) + + tbl.RawSetH(LTrue, LString("true")) + tbl.RawSetH(LFalse, LString("false")) + + tbl.ForEach(func(key, value LValue) { + switch k := key.(type) { + case LBool: + switch bool(k) { + case true: + errorIfNotEqual(t, LString("true"), value) + case false: + errorIfNotEqual(t, LString("false"), value) + default: + t.Fail() + } + case LNumber: + switch int(k) { + case 1: + errorIfNotEqual(t, LNumber(1), value) + case 2: + errorIfNotEqual(t, LNumber(2), value) + case 3: + errorIfNotEqual(t, LNumber(3), value) + case 4: + errorIfNotEqual(t, LNumber(5), value) + default: + t.Fail() + } + case LString: + switch string(k) { + case "a": + errorIfNotEqual(t, LString("a"), value) + case "b": + errorIfNotEqual(t, LString("b"), value) + case "c": + errorIfNotEqual(t, LString("c"), value) + default: + t.Fail() + } + } + }) +} diff --git a/vendor/github.com/yuin/gopher-lua/tablelib.go b/vendor/github.com/yuin/gopher-lua/tablelib.go new file mode 100644 index 0000000000000000000000000000000000000000..f3f460702f02e69a324abad22be8d52d3bed9b6a --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/tablelib.go @@ -0,0 +1,100 @@ +package lua + +import ( + "sort" +) + +func OpenTable(L *LState) int { + tabmod := L.RegisterModule(TabLibName, tableFuncs) + L.Push(tabmod) + return 1 +} + +var tableFuncs = map[string]LGFunction{ + "getn": tableGetN, + "concat": tableConcat, + "insert": tableInsert, + "maxn": tableMaxN, + "remove": tableRemove, + "sort": tableSort, +} + +func tableSort(L *LState) int { + tbl := L.CheckTable(1) + sorter := lValueArraySorter{L, nil, tbl.array} + if L.GetTop() != 1 { + sorter.Fn = L.CheckFunction(2) + } + sort.Sort(sorter) + return 0 +} + +func tableGetN(L *LState) int { + L.Push(LNumber(L.CheckTable(1).Len())) + return 1 +} + +func tableMaxN(L *LState) int { + L.Push(LNumber(L.CheckTable(1).MaxN())) + return 1 +} + +func tableRemove(L *LState) int { + tbl := L.CheckTable(1) + if L.GetTop() == 1 { + L.Push(tbl.Remove(-1)) + } else { + L.Push(tbl.Remove(L.CheckInt(2))) + } + return 1 +} + +func tableConcat(L *LState) int { + tbl := L.CheckTable(1) + sep := LString(L.OptString(2, "")) + i := L.OptInt(3, 1) + j := L.OptInt(4, tbl.Len()) + if L.GetTop() == 3 { + if i > tbl.Len() || i < 1 { + L.Push(emptyLString) + return 1 + } + } + i = intMax(intMin(i, tbl.Len()), 1) + j = intMin(intMin(j, tbl.Len()), tbl.Len()) + if i > j { + L.Push(emptyLString) + return 1 + } + //TODO should flushing? + retbottom := L.GetTop() + for ; i <= j; i++ { + v := tbl.RawGetInt(i) + if !LVCanConvToString(v) { + L.RaiseError("invalid value (%s) at index %d in table for concat", v.Type().String(), i) + } + L.Push(v) + if i != j { + L.Push(sep) + } + } + L.Push(stringConcat(L, L.GetTop()-retbottom, L.reg.Top()-1)) + return 1 +} + +func tableInsert(L *LState) int { + tbl := L.CheckTable(1) + nargs := L.GetTop() + if nargs == 1 { + L.RaiseError("wrong number of arguments") + } + + if L.GetTop() == 2 { + tbl.Append(L.Get(2)) + return 0 + } + tbl.Insert(int(L.CheckInt(2)), L.CheckAny(3)) + return 0 +} + +// diff --git a/vendor/github.com/yuin/gopher-lua/testutils_test.go b/vendor/github.com/yuin/gopher-lua/testutils_test.go new file mode 100644 index 0000000000000000000000000000000000000000..e8c8578b6f8d794c7419321fb1a64dfa46342aaa --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/testutils_test.go @@ -0,0 +1,78 @@ +package lua + +import ( + "fmt" + "path/filepath" + "regexp" + "runtime" + "testing" +) + +func positionString(level int) string { + _, file, line, _ := runtime.Caller(level + 1) + return fmt.Sprintf("%v:%v:", filepath.Base(file), line) +} + +func errorIfNotEqual(t *testing.T, v1, v2 interface{}) { + if v1 != v2 { + t.Errorf("%v '%v' expected, but got '%v'", positionString(1), v1, v2) + } +} + +func errorIfFalse(t *testing.T, cond bool, msg string, args ...interface{}) { + if !cond { + if len(args) > 0 { + t.Errorf("%v %v", positionString(1), fmt.Sprintf(msg, args...)) + } else { + t.Errorf("%v %v", positionString(1), msg) + } + } +} + +func errorIfNotNil(t *testing.T, v1 interface{}) { + if fmt.Sprint(v1) != "" { + t.Errorf("%v nil expected, but got '%v'", positionString(1), v1) + } +} + +func errorIfNil(t *testing.T, v1 interface{}) { + if fmt.Sprint(v1) == "" { + t.Errorf("%v non-nil value expected, but got nil", positionString(1)) + } +} + +func errorIfScriptFail(t *testing.T, L *LState, script string) { + if err := L.DoString(script); err != nil { + t.Errorf("%v %v", positionString(1), err.Error()) + } +} + +func errorIfGFuncFail(t *testing.T, L *LState, f LGFunction) { + if err := L.GPCall(f, LNil); err != nil { + t.Errorf("%v %v", positionString(1), err.Error()) + } +} + +func errorIfScriptNotFail(t *testing.T, L *LState, script string, pattern string) { + if err := L.DoString(script); err != nil { + reg := regexp.MustCompile(pattern) + if len(reg.FindStringIndex(err.Error())) == 0 { + t.Errorf("%v error message '%v' does not contains given pattern string '%v'.", positionString(1), err.Error(), pattern) + return + } + return + } + t.Errorf("%v script should fail", positionString(1)) +} + +func errorIfGFuncNotFail(t *testing.T, L *LState, f LGFunction, pattern string) { + if err := L.GPCall(f, LNil); err != nil { + reg := regexp.MustCompile(pattern) + if len(reg.FindStringIndex(err.Error())) == 0 { + t.Errorf("%v error message '%v' does not contains given pattern string '%v'.", positionString(1), err.Error(), pattern) + return + } + return + } + t.Errorf("%v LGFunction should fail", positionString(1)) +} diff --git a/vendor/github.com/yuin/gopher-lua/utils.go b/vendor/github.com/yuin/gopher-lua/utils.go new file mode 100644 index 0000000000000000000000000000000000000000..cb71bf53e87ac51a582128dc1f1852339030b681 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/utils.go @@ -0,0 +1,262 @@ +package lua + +import ( + "bufio" + "fmt" + "io" + "reflect" + "strconv" + "strings" + "time" + "unsafe" +) + +func intMin(a, b int) int { + if a < b { + return a + } else { + return b + } +} + +func intMax(a, b int) int { + if a > b { + return a + } else { + return b + } +} + +func defaultFormat(v interface{}, f fmt.State, c rune) { + buf := make([]string, 0, 10) + buf = append(buf, "%") + for i := 0; i < 128; i++ { + if f.Flag(i) { + buf = append(buf, string(i)) + } + } + + if w, ok := f.Width(); ok { + buf = append(buf, strconv.Itoa(w)) + } + if p, ok := f.Precision(); ok { + buf = append(buf, "."+strconv.Itoa(p)) + } + buf = append(buf, string(c)) + format := strings.Join(buf, "") + fmt.Fprintf(f, format, v) +} + +type flagScanner struct { + flag byte + start string + end string + buf []byte + str string + Length int + Pos int + HasFlag bool + ChangeFlag bool +} + +func newFlagScanner(flag byte, start, end, str string) *flagScanner { + return &flagScanner{flag, start, end, make([]byte, 0, len(str)), str, len(str), 0, false, false} +} + +func (fs *flagScanner) AppendString(str string) { fs.buf = append(fs.buf, str...) } + +func (fs *flagScanner) AppendChar(ch byte) { fs.buf = append(fs.buf, ch) } + +func (fs *flagScanner) String() string { return string(fs.buf) } + +func (fs *flagScanner) Next() (byte, bool) { + c := byte('\000') + fs.ChangeFlag = false + if fs.Pos == fs.Length { + if fs.HasFlag { + fs.AppendString(fs.end) + } + return c, true + } else { + c = fs.str[fs.Pos] + if c == fs.flag { + if fs.Pos < (fs.Length-1) && fs.str[fs.Pos+1] == fs.flag { + fs.HasFlag = false + fs.AppendChar(fs.flag) + fs.Pos += 2 + return fs.Next() + } else if fs.Pos != fs.Length-1 { + if fs.HasFlag { + fs.AppendString(fs.end) + } + fs.AppendString(fs.start) + fs.ChangeFlag = true + fs.HasFlag = true + } + } + } + fs.Pos++ + return c, false +} + +var cDateFlagToGo = map[byte]string{ + 'a': "mon", 'A': "Monday", 'b': "Jan", 'B': "January", 'c': "02 Jan 06 15:04 MST", 'd': "02", + 'F': "2006-01-02", 'H': "15", 'I': "03", 'm': "01", 'M': "04", 'p': "PM", 'P': "pm", 'S': "05", + 'x': "15/04/05", 'X': "15:04:05", 'y': "06", 'Y': "2006", 'z': "-0700", 'Z': "MST"} + +func strftime(t time.Time, cfmt string) string { + sc := newFlagScanner('%', "", "", cfmt) + for c, eos := sc.Next(); !eos; c, eos = sc.Next() { + if !sc.ChangeFlag { + if sc.HasFlag { + if v, ok := cDateFlagToGo[c]; ok { + sc.AppendString(t.Format(v)) + } else { + switch c { + case 'w': + sc.AppendString(fmt.Sprint(int(t.Weekday()))) + default: + sc.AppendChar('%') + sc.AppendChar(c) + } + } + sc.HasFlag = false + } else { + sc.AppendChar(c) + } + } + } + + return sc.String() +} + +func isInteger(v LNumber) bool { + return float64(v) == float64(int64(v)) + //_, frac := math.Modf(float64(v)) + //return frac == 0.0 +} + +func isArrayKey(v LNumber) bool { + return isInteger(v) && v < LNumber(int((^uint(0))>>1)) && v > LNumber(0) && v < LNumber(MaxArrayIndex) +} + +func parseNumber(number string) (LNumber, error) { + var value LNumber + number = strings.Trim(number, " \t\n") + if v, err := strconv.ParseInt(number, 0, LNumberBit); err != nil { + if v2, err2 := strconv.ParseFloat(number, LNumberBit); err2 != nil { + return LNumber(0), err2 + } else { + value = LNumber(v2) + } + } else { + value = LNumber(v) + } + return value, nil +} + +func popenArgs(arg string) (string, []string) { + cmd := "/bin/sh" + args := []string{"-c"} + if LuaOS == "windows" { + cmd = "C:\\Windows\\system32\\cmd.exe" + args = []string{"/c"} + } + args = append(args, arg) + return cmd, args +} + +func isGoroutineSafe(lv LValue) bool { + switch v := lv.(type) { + case *LFunction, *LUserData, *LState: + return false + case *LTable: + return v.Metatable == LNil + default: + return true + } +} + +func readBufioSize(reader *bufio.Reader, size int64) ([]byte, error, bool) { + result := []byte{} + read := int64(0) + var err error + var n int + for read != size { + buf := make([]byte, size-read) + n, err = reader.Read(buf) + if err != nil { + break + } + read += int64(n) + result = append(result, buf[:n]...) + } + e := err + if e != nil && e == io.EOF { + e = nil + } + + return result, e, len(result) == 0 && err == io.EOF +} + +func readBufioLine(reader *bufio.Reader) ([]byte, error, bool) { + result := []byte{} + var buf []byte + var err error + var isprefix bool = true + for isprefix { + buf, isprefix, err = reader.ReadLine() + if err != nil { + break + } + result = append(result, buf...) + } + e := err + if e != nil && e == io.EOF { + e = nil + } + + return result, e, len(result) == 0 && err == io.EOF +} + +func int2Fb(val int) int { + e := 0 + x := val + for x >= 16 { + x = (x + 1) >> 1 + e++ + } + if x < 8 { + return x + } + return ((e + 1) << 3) | (x - 8) +} + +func strCmp(s1, s2 string) int { + len1 := len(s1) + len2 := len(s2) + for i := 0; ; i++ { + c1 := -1 + if i < len1 { + c1 = int(s1[i]) + } + c2 := -1 + if i != len2 { + c2 = int(s2[i]) + } + switch { + case c1 < c2: + return -1 + case c1 > c2: + return +1 + case c1 < 0: + return 0 + } + } +} + +func unsafeFastStringToReadOnlyBytes(s string) []byte { + sh := (*reflect.StringHeader)(unsafe.Pointer(&s)) + bh := reflect.SliceHeader{sh.Data, sh.Len, sh.Len} + return *(*[]byte)(unsafe.Pointer(&bh)) +} diff --git a/vendor/github.com/yuin/gopher-lua/value.go b/vendor/github.com/yuin/gopher-lua/value.go new file mode 100644 index 0000000000000000000000000000000000000000..7bcf1f602df33772d4cf1ae4377416f1aef94a86 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/value.go @@ -0,0 +1,247 @@ +package lua + +import ( + "context" + "fmt" + "os" +) + +type LValueType int + +const ( + LTNil LValueType = iota + LTBool + LTNumber + LTString + LTFunction + LTUserData + LTThread + LTTable + LTChannel +) + +var lValueNames = [9]string{"nil", "boolean", "number", "string", "function", "userdata", "thread", "table", "channel"} + +func (vt LValueType) String() string { + return lValueNames[int(vt)] +} + +type LValue interface { + String() string + Type() LValueType + // to reduce `runtime.assertI2T2` costs, this method should be used instead of the type assertion in heavy paths(typically inside the VM). + assertFloat64() (float64, bool) + // to reduce `runtime.assertI2T2` costs, this method should be used instead of the type assertion in heavy paths(typically inside the VM). + assertString() (string, bool) + // to reduce `runtime.assertI2T2` costs, this method should be used instead of the type assertion in heavy paths(typically inside the VM). + assertFunction() (*LFunction, bool) +} + +// LVIsFalse returns true if a given LValue is a nil or false otherwise false. +func LVIsFalse(v LValue) bool { return v == LNil || v == LFalse } + +// LVIsFalse returns false if a given LValue is a nil or false otherwise true. +func LVAsBool(v LValue) bool { return v != LNil && v != LFalse } + +// LVAsString returns string representation of a given LValue +// if the LValue is a string or number, otherwise an empty string. +func LVAsString(v LValue) string { + switch sn := v.(type) { + case LString, LNumber: + return sn.String() + default: + return "" + } +} + +// LVCanConvToString returns true if a given LValue is a string or number +// otherwise false. +func LVCanConvToString(v LValue) bool { + switch v.(type) { + case LString, LNumber: + return true + default: + return false + } +} + +// LVAsNumber tries to convert a given LValue to a number. +func LVAsNumber(v LValue) LNumber { + switch lv := v.(type) { + case LNumber: + return lv + case LString: + if num, err := parseNumber(string(lv)); err == nil { + return num + } + } + return LNumber(0) +} + +type LNilType struct{} + +func (nl *LNilType) String() string { return "nil" } +func (nl *LNilType) Type() LValueType { return LTNil } +func (nl *LNilType) assertFloat64() (float64, bool) { return 0, false } +func (nl *LNilType) assertString() (string, bool) { return "", false } +func (nl *LNilType) assertFunction() (*LFunction, bool) { return nil, false } + +var LNil = LValue(&LNilType{}) + +type LBool bool + +func (bl LBool) String() string { + if bool(bl) { + return "true" + } + return "false" +} +func (bl LBool) Type() LValueType { return LTBool } +func (bl LBool) assertFloat64() (float64, bool) { return 0, false } +func (bl LBool) assertString() (string, bool) { return "", false } +func (bl LBool) assertFunction() (*LFunction, bool) { return nil, false } + +var LTrue = LBool(true) +var LFalse = LBool(false) + +type LString string + +func (st LString) String() string { return string(st) } +func (st LString) Type() LValueType { return LTString } +func (st LString) assertFloat64() (float64, bool) { return 0, false } +func (st LString) assertString() (string, bool) { return string(st), true } +func (st LString) assertFunction() (*LFunction, bool) { return nil, false } + +// fmt.Formatter interface +func (st LString) Format(f fmt.State, c rune) { + switch c { + case 'd', 'i': + if nm, err := parseNumber(string(st)); err != nil { + defaultFormat(nm, f, 'd') + } else { + defaultFormat(string(st), f, 's') + } + default: + defaultFormat(string(st), f, c) + } +} + +func (nm LNumber) String() string { + if isInteger(nm) { + return fmt.Sprint(int64(nm)) + } + return fmt.Sprint(float64(nm)) +} + +func (nm LNumber) Type() LValueType { return LTNumber } +func (nm LNumber) assertFloat64() (float64, bool) { return float64(nm), true } +func (nm LNumber) assertString() (string, bool) { return "", false } +func (nm LNumber) assertFunction() (*LFunction, bool) { return nil, false } + +// fmt.Formatter interface +func (nm LNumber) Format(f fmt.State, c rune) { + switch c { + case 'q', 's': + defaultFormat(nm.String(), f, c) + case 'b', 'c', 'd', 'o', 'x', 'X', 'U': + defaultFormat(int64(nm), f, c) + case 'e', 'E', 'f', 'F', 'g', 'G': + defaultFormat(float64(nm), f, c) + case 'i': + defaultFormat(int64(nm), f, 'd') + default: + if isInteger(nm) { + defaultFormat(int64(nm), f, c) + } else { + defaultFormat(float64(nm), f, c) + } + } +} + +type LTable struct { + Metatable LValue + + array []LValue + dict map[LValue]LValue + strdict map[string]LValue + keys []LValue + k2i map[LValue]int +} + +func (tb *LTable) String() string { return fmt.Sprintf("table: %p", tb) } +func (tb *LTable) Type() LValueType { return LTTable } +func (tb *LTable) assertFloat64() (float64, bool) { return 0, false } +func (tb *LTable) assertString() (string, bool) { return "", false } +func (tb *LTable) assertFunction() (*LFunction, bool) { return nil, false } + +type LFunction struct { + IsG bool + Env *LTable + Proto *FunctionProto + GFunction LGFunction + Upvalues []*Upvalue +} +type LGFunction func(*LState) int + +func (fn *LFunction) String() string { return fmt.Sprintf("function: %p", fn) } +func (fn *LFunction) Type() LValueType { return LTFunction } +func (fn *LFunction) assertFloat64() (float64, bool) { return 0, false } +func (fn *LFunction) assertString() (string, bool) { return "", false } +func (fn *LFunction) assertFunction() (*LFunction, bool) { return fn, true } + +type Global struct { + MainThread *LState + CurrentThread *LState + Registry *LTable + Global *LTable + + builtinMts map[int]LValue + tempFiles []*os.File + gccount int32 +} + +type LState struct { + G *Global + Parent *LState + Env *LTable + Panic func(*LState) + Dead bool + Options Options + + stop int32 + reg *registry + stack *callFrameStack + alloc *allocator + currentFrame *callFrame + wrapped bool + uvcache *Upvalue + hasErrorFunc bool + mainLoop func(*LState, *callFrame) + ctx context.Context +} + +func (ls *LState) String() string { return fmt.Sprintf("thread: %p", ls) } +func (ls *LState) Type() LValueType { return LTThread } +func (ls *LState) assertFloat64() (float64, bool) { return 0, false } +func (ls *LState) assertString() (string, bool) { return "", false } +func (ls *LState) assertFunction() (*LFunction, bool) { return nil, false } + +type LUserData struct { + Value interface{} + Env *LTable + Metatable LValue +} + +func (ud *LUserData) String() string { return fmt.Sprintf("userdata: %p", ud) } +func (ud *LUserData) Type() LValueType { return LTUserData } +func (ud *LUserData) assertFloat64() (float64, bool) { return 0, false } +func (ud *LUserData) assertString() (string, bool) { return "", false } +func (ud *LUserData) assertFunction() (*LFunction, bool) { return nil, false } + +type LChannel chan LValue + +func (ch LChannel) String() string { return fmt.Sprintf("channel: %p", ch) } +func (ch LChannel) Type() LValueType { return LTChannel } +func (ch LChannel) assertFloat64() (float64, bool) { return 0, false } +func (ch LChannel) assertString() (string, bool) { return "", false } +func (ch LChannel) assertFunction() (*LFunction, bool) { return nil, false } diff --git a/vendor/github.com/yuin/gopher-lua/vm.go b/vendor/github.com/yuin/gopher-lua/vm.go new file mode 100644 index 0000000000000000000000000000000000000000..c18399ab9b7296f39a321f335315f2fb9f90ef7d --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/vm.go @@ -0,0 +1,1395 @@ +package lua + +//////////////////////////////////////////////////////// +// This file was generated by go-inline. DO NOT EDIT. // +//////////////////////////////////////////////////////// + +import ( + "fmt" + "math" + "strings" +) + +func mainLoop(L *LState, baseframe *callFrame) { + var inst uint32 + var cf *callFrame + + if L.stack.IsEmpty() { + return + } + + L.currentFrame = L.stack.Last() + if L.currentFrame.Fn.IsG { + callGFunction(L, false) + return + } + + for { + cf = L.currentFrame + inst = cf.Fn.Proto.Code[cf.Pc] + cf.Pc++ + if jumpTable[int(inst>>26)](L, inst, baseframe) == 1 { + return + } + } +} + +func mainLoopWithContext(L *LState, baseframe *callFrame) { + var inst uint32 + var cf *callFrame + + if L.stack.IsEmpty() { + return + } + + L.currentFrame = L.stack.Last() + if L.currentFrame.Fn.IsG { + callGFunction(L, false) + return + } + + for { + cf = L.currentFrame + inst = cf.Fn.Proto.Code[cf.Pc] + cf.Pc++ + select { + case <-L.ctx.Done(): + L.RaiseError(L.ctx.Err().Error()) + return + default: + if jumpTable[int(inst>>26)](L, inst, baseframe) == 1 { + return + } + } + } +} + +func copyReturnValues(L *LState, regv, start, n, b int) { // +inline-start + if b == 1 { + // this section is inlined by go-inline + // source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go' + { + rg := L.reg + regm := regv + for i := 0; i < n; i++ { + rg.array[regm+i] = LNil + } + rg.top = regm + n + } + } else { + // this section is inlined by go-inline + // source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go' + { + rg := L.reg + limit := -1 + for i := 0; i < n; i++ { + if tidx := start + i; tidx >= rg.top || limit > -1 && tidx >= limit || tidx < 0 { + rg.array[regv+i] = LNil + } else { + rg.array[regv+i] = rg.array[tidx] + } + } + rg.top = regv + n + } + } +} // +inline-end + +func switchToParentThread(L *LState, nargs int, haserror bool, kill bool) { + parent := L.Parent + if parent == nil { + L.RaiseError("can not yield from outside of a coroutine") + } + L.G.CurrentThread = parent + L.Parent = nil + if !L.wrapped { + if haserror { + parent.Push(LFalse) + } else { + parent.Push(LTrue) + } + } + L.XMoveTo(parent, nargs) + L.stack.Pop() + offset := L.currentFrame.LocalBase - L.currentFrame.ReturnBase + L.currentFrame = L.stack.Last() + L.reg.SetTop(L.reg.Top() - offset) // remove 'yield' function(including tailcalled functions) + if kill { + L.kill() + } +} + +func callGFunction(L *LState, tailcall bool) bool { + frame := L.currentFrame + gfnret := frame.Fn.GFunction(L) + if tailcall { + L.stack.Remove(L.stack.Sp() - 2) // remove caller lua function frame + L.currentFrame = L.stack.Last() + } + + if gfnret < 0 { + switchToParentThread(L, L.GetTop(), false, false) + return true + } + + wantret := frame.NRet + if wantret == MultRet { + wantret = gfnret + } + + if tailcall && L.Parent != nil && L.stack.Sp() == 1 { + switchToParentThread(L, wantret, false, true) + return true + } + + // this section is inlined by go-inline + // source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go' + { + rg := L.reg + regv := frame.ReturnBase + start := L.reg.Top() - gfnret + limit := -1 + n := wantret + for i := 0; i < n; i++ { + if tidx := start + i; tidx >= rg.top || limit > -1 && tidx >= limit || tidx < 0 { + rg.array[regv+i] = LNil + } else { + rg.array[regv+i] = rg.array[tidx] + } + } + rg.top = regv + n + } + L.stack.Pop() + L.currentFrame = L.stack.Last() + return false +} + +func threadRun(L *LState) { + if L.stack.IsEmpty() { + return + } + + defer func() { + if rcv := recover(); rcv != nil { + var lv LValue + if v, ok := rcv.(*ApiError); ok { + lv = v.Object + } else { + lv = LString(fmt.Sprint(rcv)) + } + if parent := L.Parent; parent != nil { + if L.wrapped { + L.Push(lv) + parent.Panic(L) + } else { + L.SetTop(0) + L.Push(lv) + switchToParentThread(L, 1, true, true) + } + } else { + panic(rcv) + } + } + }() + L.mainLoop(L, nil) +} + +type instFunc func(*LState, uint32, *callFrame) int + +var jumpTable [opCodeMax + 1]instFunc + +func init() { + jumpTable = [opCodeMax + 1]instFunc{ + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_MOVE + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + reg.Set(RA, reg.Get(lbase+B)) + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_MOVEN + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + B := int(inst & 0x1ff) //GETB + C := int(inst>>9) & 0x1ff //GETC + reg.Set(lbase+A, reg.Get(lbase+B)) + code := cf.Fn.Proto.Code + pc := cf.Pc + for i := 0; i < C; i++ { + inst = code[pc] + pc++ + A = int(inst>>18) & 0xff //GETA + B = int(inst & 0x1ff) //GETB + reg.Set(lbase+A, reg.Get(lbase+B)) + } + cf.Pc = pc + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LOADK + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + Bx := int(inst & 0x3ffff) //GETBX + reg.Set(RA, cf.Fn.Proto.Constants[Bx]) + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LOADBOOL + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + C := int(inst>>9) & 0x1ff //GETC + if B != 0 { + reg.Set(RA, LTrue) + } else { + reg.Set(RA, LFalse) + } + if C != 0 { + cf.Pc++ + } + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LOADNIL + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + for i := RA; i <= lbase+B; i++ { + reg.Set(i, LNil) + } + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETUPVAL + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + reg.Set(RA, cf.Fn.Upvalues[B].Value()) + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETGLOBAL + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + Bx := int(inst & 0x3ffff) //GETBX + //reg.Set(RA, L.getField(cf.Fn.Env, cf.Fn.Proto.Constants[Bx])) + reg.Set(RA, L.getFieldString(cf.Fn.Env, cf.Fn.Proto.stringConstants[Bx])) + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETTABLE + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + C := int(inst>>9) & 0x1ff //GETC + reg.Set(RA, L.getField(reg.Get(lbase+B), L.rkValue(C))) + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETTABLEKS + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + C := int(inst>>9) & 0x1ff //GETC + reg.Set(RA, L.getFieldString(reg.Get(lbase+B), L.rkString(C))) + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETGLOBAL + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + Bx := int(inst & 0x3ffff) //GETBX + //L.setField(cf.Fn.Env, cf.Fn.Proto.Constants[Bx], reg.Get(RA)) + L.setFieldString(cf.Fn.Env, cf.Fn.Proto.stringConstants[Bx], reg.Get(RA)) + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETUPVAL + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + cf.Fn.Upvalues[B].SetValue(reg.Get(RA)) + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETTABLE + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + C := int(inst>>9) & 0x1ff //GETC + L.setField(reg.Get(RA), L.rkValue(B), L.rkValue(C)) + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETTABLEKS + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + C := int(inst>>9) & 0x1ff //GETC + L.setFieldString(reg.Get(RA), L.rkString(B), L.rkValue(C)) + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_NEWTABLE + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + C := int(inst>>9) & 0x1ff //GETC + reg.Set(RA, newLTable(B, C)) + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SELF + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + C := int(inst>>9) & 0x1ff //GETC + selfobj := reg.Get(lbase + B) + reg.Set(RA, L.getFieldString(selfobj, L.rkString(C))) + reg.Set(RA+1, selfobj) + return 0 + }, + opArith, // OP_ADD + opArith, // OP_SUB + opArith, // OP_MUL + opArith, // OP_DIV + opArith, // OP_MOD + opArith, // OP_POW + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_UNM + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + unaryv := L.rkValue(B) + if nm, ok := unaryv.(LNumber); ok { + reg.SetNumber(RA, -nm) + } else { + op := L.metaOp1(unaryv, "__unm") + if op.Type() == LTFunction { + reg.Push(op) + reg.Push(unaryv) + L.Call(1, 1) + reg.Set(RA, reg.Pop()) + } else if str, ok1 := unaryv.(LString); ok1 { + if num, err := parseNumber(string(str)); err == nil { + reg.Set(RA, -num) + } else { + L.RaiseError("__unm undefined") + } + } else { + L.RaiseError("__unm undefined") + } + } + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_NOT + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + if LVIsFalse(reg.Get(lbase + B)) { + reg.Set(RA, LTrue) + } else { + reg.Set(RA, LFalse) + } + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LEN + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + switch lv := L.rkValue(B).(type) { + case LString: + reg.SetNumber(RA, LNumber(len(lv))) + default: + op := L.metaOp1(lv, "__len") + if op.Type() == LTFunction { + reg.Push(op) + reg.Push(lv) + L.Call(1, 1) + ret := reg.Pop() + if ret.Type() == LTNumber { + reg.SetNumber(RA, ret.(LNumber)) + } else { + reg.SetNumber(RA, LNumber(0)) + } + } else if lv.Type() == LTTable { + reg.SetNumber(RA, LNumber(lv.(*LTable).Len())) + } else { + L.RaiseError("__len undefined") + } + } + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CONCAT + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + C := int(inst>>9) & 0x1ff //GETC + RC := lbase + C + RB := lbase + B + reg.Set(RA, stringConcat(L, RC-RB+1, RC)) + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_JMP + cf := L.currentFrame + Sbx := int(inst&0x3ffff) - opMaxArgSbx //GETSBX + cf.Pc += Sbx + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_EQ + cf := L.currentFrame + A := int(inst>>18) & 0xff //GETA + B := int(inst & 0x1ff) //GETB + C := int(inst>>9) & 0x1ff //GETC + ret := equals(L, L.rkValue(B), L.rkValue(C), false) + v := 1 + if ret { + v = 0 + } + if v == A { + cf.Pc++ + } + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LT + cf := L.currentFrame + A := int(inst>>18) & 0xff //GETA + B := int(inst & 0x1ff) //GETB + C := int(inst>>9) & 0x1ff //GETC + ret := lessThan(L, L.rkValue(B), L.rkValue(C)) + v := 1 + if ret { + v = 0 + } + if v == A { + cf.Pc++ + } + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LE + cf := L.currentFrame + A := int(inst>>18) & 0xff //GETA + B := int(inst & 0x1ff) //GETB + C := int(inst>>9) & 0x1ff //GETC + lhs := L.rkValue(B) + rhs := L.rkValue(C) + ret := false + + if v1, ok1 := lhs.assertFloat64(); ok1 { + if v2, ok2 := rhs.assertFloat64(); ok2 { + ret = v1 <= v2 + } else { + L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String()) + } + } else { + if lhs.Type() != rhs.Type() { + L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String()) + } + switch lhs.Type() { + case LTString: + ret = strCmp(string(lhs.(LString)), string(rhs.(LString))) <= 0 + default: + switch objectRational(L, lhs, rhs, "__le") { + case 1: + ret = true + case 0: + ret = false + default: + ret = !objectRationalWithError(L, rhs, lhs, "__lt") + } + } + } + + v := 1 + if ret { + v = 0 + } + if v == A { + cf.Pc++ + } + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TEST + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + C := int(inst>>9) & 0x1ff //GETC + if LVAsBool(reg.Get(RA)) == (C == 0) { + cf.Pc++ + } + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TESTSET + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + C := int(inst>>9) & 0x1ff //GETC + if value := reg.Get(lbase + B); LVAsBool(value) != (C == 0) { + reg.Set(RA, value) + } else { + cf.Pc++ + } + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CALL + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + C := int(inst>>9) & 0x1ff //GETC + nargs := B - 1 + if B == 0 { + nargs = reg.Top() - (RA + 1) + } + lv := reg.Get(RA) + nret := C - 1 + var callable *LFunction + var meta bool + if fn, ok := lv.assertFunction(); ok { + callable = fn + meta = false + } else { + callable, meta = L.metaCall(lv) + } + // this section is inlined by go-inline + // source function is 'func (ls *LState) pushCallFrame(cf callFrame, fn LValue, meta bool) ' in '_state.go' + { + ls := L + cf := callFrame{Fn: callable, Pc: 0, Base: RA, LocalBase: RA + 1, ReturnBase: RA, NArgs: nargs, NRet: nret, Parent: cf, TailCall: 0} + fn := lv + if meta { + cf.NArgs++ + ls.reg.Insert(fn, cf.LocalBase) + } + if cf.Fn == nil { + ls.RaiseError("attempt to call a non-function object") + } + if ls.stack.sp == ls.Options.CallStackSize { + ls.RaiseError("stack overflow") + } + // this section is inlined by go-inline + // source function is 'func (cs *callFrameStack) Push(v callFrame) ' in '_state.go' + { + cs := ls.stack + v := cf + cs.array[cs.sp] = v + cs.array[cs.sp].Idx = cs.sp + cs.sp++ + } + newcf := ls.stack.Last() + // this section is inlined by go-inline + // source function is 'func (ls *LState) initCallFrame(cf *callFrame) ' in '_state.go' + { + cf := newcf + if cf.Fn.IsG { + ls.reg.SetTop(cf.LocalBase + cf.NArgs) + } else { + proto := cf.Fn.Proto + nargs := cf.NArgs + np := int(proto.NumParameters) + for i := nargs; i < np; i++ { + ls.reg.array[cf.LocalBase+i] = LNil + nargs = np + } + + if (proto.IsVarArg & VarArgIsVarArg) == 0 { + if nargs < int(proto.NumUsedRegisters) { + nargs = int(proto.NumUsedRegisters) + } + for i := np; i < nargs; i++ { + ls.reg.array[cf.LocalBase+i] = LNil + } + ls.reg.top = cf.LocalBase + int(proto.NumUsedRegisters) + } else { + /* swap vararg positions: + closure + namedparam1 <- lbase + namedparam2 + vararg1 + vararg2 + + TO + + closure + nil + nil + vararg1 + vararg2 + namedparam1 <- lbase + namedparam2 + */ + nvarargs := nargs - np + if nvarargs < 0 { + nvarargs = 0 + } + + ls.reg.SetTop(cf.LocalBase + nargs + np) + for i := 0; i < np; i++ { + //ls.reg.Set(cf.LocalBase+nargs+i, ls.reg.Get(cf.LocalBase+i)) + ls.reg.array[cf.LocalBase+nargs+i] = ls.reg.array[cf.LocalBase+i] + //ls.reg.Set(cf.LocalBase+i, LNil) + ls.reg.array[cf.LocalBase+i] = LNil + } + + if CompatVarArg { + ls.reg.SetTop(cf.LocalBase + nargs + np + 1) + if (proto.IsVarArg & VarArgNeedsArg) != 0 { + argtb := newLTable(nvarargs, 0) + for i := 0; i < nvarargs; i++ { + argtb.RawSetInt(i+1, ls.reg.Get(cf.LocalBase+np+i)) + } + argtb.RawSetString("n", LNumber(nvarargs)) + //ls.reg.Set(cf.LocalBase+nargs+np, argtb) + ls.reg.array[cf.LocalBase+nargs+np] = argtb + } else { + ls.reg.array[cf.LocalBase+nargs+np] = LNil + } + } + cf.LocalBase += nargs + maxreg := cf.LocalBase + int(proto.NumUsedRegisters) + ls.reg.SetTop(maxreg) + } + } + } + ls.currentFrame = newcf + } + if callable.IsG && callGFunction(L, false) { + return 1 + } + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TAILCALL + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + nargs := B - 1 + if B == 0 { + nargs = reg.Top() - (RA + 1) + } + lv := reg.Get(RA) + var callable *LFunction + var meta bool + if fn, ok := lv.assertFunction(); ok { + callable = fn + meta = false + } else { + callable, meta = L.metaCall(lv) + } + if callable == nil { + L.RaiseError("attempt to call a non-function object") + } + // this section is inlined by go-inline + // source function is 'func (ls *LState) closeUpvalues(idx int) ' in '_state.go' + { + ls := L + idx := lbase + if ls.uvcache != nil { + var prev *Upvalue + for uv := ls.uvcache; uv != nil; uv = uv.next { + if uv.index >= idx { + if prev != nil { + prev.next = nil + } else { + ls.uvcache = nil + } + uv.Close() + } + prev = uv + } + } + } + if callable.IsG { + luaframe := cf + L.pushCallFrame(callFrame{ + Fn: callable, + Pc: 0, + Base: RA, + LocalBase: RA + 1, + ReturnBase: cf.ReturnBase, + NArgs: nargs, + NRet: cf.NRet, + Parent: cf, + TailCall: 0, + }, lv, meta) + if callGFunction(L, true) { + return 1 + } + if L.currentFrame == nil || L.currentFrame.Fn.IsG || luaframe == baseframe { + return 1 + } + } else { + base := cf.Base + cf.Fn = callable + cf.Pc = 0 + cf.Base = RA + cf.LocalBase = RA + 1 + cf.ReturnBase = cf.ReturnBase + cf.NArgs = nargs + cf.NRet = cf.NRet + cf.TailCall++ + lbase := cf.LocalBase + if meta { + cf.NArgs++ + L.reg.Insert(lv, cf.LocalBase) + } + // this section is inlined by go-inline + // source function is 'func (ls *LState) initCallFrame(cf *callFrame) ' in '_state.go' + { + ls := L + if cf.Fn.IsG { + ls.reg.SetTop(cf.LocalBase + cf.NArgs) + } else { + proto := cf.Fn.Proto + nargs := cf.NArgs + np := int(proto.NumParameters) + for i := nargs; i < np; i++ { + ls.reg.array[cf.LocalBase+i] = LNil + nargs = np + } + + if (proto.IsVarArg & VarArgIsVarArg) == 0 { + if nargs < int(proto.NumUsedRegisters) { + nargs = int(proto.NumUsedRegisters) + } + for i := np; i < nargs; i++ { + ls.reg.array[cf.LocalBase+i] = LNil + } + ls.reg.top = cf.LocalBase + int(proto.NumUsedRegisters) + } else { + /* swap vararg positions: + closure + namedparam1 <- lbase + namedparam2 + vararg1 + vararg2 + + TO + + closure + nil + nil + vararg1 + vararg2 + namedparam1 <- lbase + namedparam2 + */ + nvarargs := nargs - np + if nvarargs < 0 { + nvarargs = 0 + } + + ls.reg.SetTop(cf.LocalBase + nargs + np) + for i := 0; i < np; i++ { + //ls.reg.Set(cf.LocalBase+nargs+i, ls.reg.Get(cf.LocalBase+i)) + ls.reg.array[cf.LocalBase+nargs+i] = ls.reg.array[cf.LocalBase+i] + //ls.reg.Set(cf.LocalBase+i, LNil) + ls.reg.array[cf.LocalBase+i] = LNil + } + + if CompatVarArg { + ls.reg.SetTop(cf.LocalBase + nargs + np + 1) + if (proto.IsVarArg & VarArgNeedsArg) != 0 { + argtb := newLTable(nvarargs, 0) + for i := 0; i < nvarargs; i++ { + argtb.RawSetInt(i+1, ls.reg.Get(cf.LocalBase+np+i)) + } + argtb.RawSetString("n", LNumber(nvarargs)) + //ls.reg.Set(cf.LocalBase+nargs+np, argtb) + ls.reg.array[cf.LocalBase+nargs+np] = argtb + } else { + ls.reg.array[cf.LocalBase+nargs+np] = LNil + } + } + cf.LocalBase += nargs + maxreg := cf.LocalBase + int(proto.NumUsedRegisters) + ls.reg.SetTop(maxreg) + } + } + } + // this section is inlined by go-inline + // source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go' + { + rg := L.reg + regv := base + start := RA + limit := -1 + n := reg.Top() - RA - 1 + for i := 0; i < n; i++ { + if tidx := start + i; tidx >= rg.top || limit > -1 && tidx >= limit || tidx < 0 { + rg.array[regv+i] = LNil + } else { + rg.array[regv+i] = rg.array[tidx] + } + } + rg.top = regv + n + } + cf.Base = base + cf.LocalBase = base + (cf.LocalBase - lbase + 1) + } + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_RETURN + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + // this section is inlined by go-inline + // source function is 'func (ls *LState) closeUpvalues(idx int) ' in '_state.go' + { + ls := L + idx := lbase + if ls.uvcache != nil { + var prev *Upvalue + for uv := ls.uvcache; uv != nil; uv = uv.next { + if uv.index >= idx { + if prev != nil { + prev.next = nil + } else { + ls.uvcache = nil + } + uv.Close() + } + prev = uv + } + } + } + nret := B - 1 + if B == 0 { + nret = reg.Top() - RA + } + n := cf.NRet + if cf.NRet == MultRet { + n = nret + } + + if L.Parent != nil && L.stack.Sp() == 1 { + // this section is inlined by go-inline + // source function is 'func copyReturnValues(L *LState, regv, start, n, b int) ' in '_vm.go' + { + regv := reg.Top() + start := RA + b := B + if b == 1 { + // this section is inlined by go-inline + // source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go' + { + rg := L.reg + regm := regv + for i := 0; i < n; i++ { + rg.array[regm+i] = LNil + } + rg.top = regm + n + } + } else { + // this section is inlined by go-inline + // source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go' + { + rg := L.reg + limit := -1 + for i := 0; i < n; i++ { + if tidx := start + i; tidx >= rg.top || limit > -1 && tidx >= limit || tidx < 0 { + rg.array[regv+i] = LNil + } else { + rg.array[regv+i] = rg.array[tidx] + } + } + rg.top = regv + n + } + } + } + switchToParentThread(L, n, false, true) + return 1 + } + islast := baseframe == L.stack.Pop() || L.stack.IsEmpty() + // this section is inlined by go-inline + // source function is 'func copyReturnValues(L *LState, regv, start, n, b int) ' in '_vm.go' + { + regv := cf.ReturnBase + start := RA + b := B + if b == 1 { + // this section is inlined by go-inline + // source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go' + { + rg := L.reg + regm := regv + for i := 0; i < n; i++ { + rg.array[regm+i] = LNil + } + rg.top = regm + n + } + } else { + // this section is inlined by go-inline + // source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go' + { + rg := L.reg + limit := -1 + for i := 0; i < n; i++ { + if tidx := start + i; tidx >= rg.top || limit > -1 && tidx >= limit || tidx < 0 { + rg.array[regv+i] = LNil + } else { + rg.array[regv+i] = rg.array[tidx] + } + } + rg.top = regv + n + } + } + } + L.currentFrame = L.stack.Last() + if islast || L.currentFrame == nil || L.currentFrame.Fn.IsG { + return 1 + } + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_FORLOOP + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + if init, ok1 := reg.Get(RA).assertFloat64(); ok1 { + if limit, ok2 := reg.Get(RA + 1).assertFloat64(); ok2 { + if step, ok3 := reg.Get(RA + 2).assertFloat64(); ok3 { + init += step + reg.SetNumber(RA, LNumber(init)) + if (step > 0 && init <= limit) || (step <= 0 && init >= limit) { + Sbx := int(inst&0x3ffff) - opMaxArgSbx //GETSBX + cf.Pc += Sbx + reg.SetNumber(RA+3, LNumber(init)) + } else { + reg.SetTop(RA + 1) + } + } else { + L.RaiseError("for statement step must be a number") + } + } else { + L.RaiseError("for statement limit must be a number") + } + } else { + L.RaiseError("for statement init must be a number") + } + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_FORPREP + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + Sbx := int(inst&0x3ffff) - opMaxArgSbx //GETSBX + if init, ok1 := reg.Get(RA).assertFloat64(); ok1 { + if step, ok2 := reg.Get(RA + 2).assertFloat64(); ok2 { + reg.SetNumber(RA, LNumber(init-step)) + } else { + L.RaiseError("for statement step must be a number") + } + } else { + L.RaiseError("for statement init must be a number") + } + cf.Pc += Sbx + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TFORLOOP + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + C := int(inst>>9) & 0x1ff //GETC + nret := C + reg.SetTop(RA + 3 + 2) + reg.Set(RA+3+2, reg.Get(RA+2)) + reg.Set(RA+3+1, reg.Get(RA+1)) + reg.Set(RA+3, reg.Get(RA)) + L.callR(2, nret, RA+3) + if value := reg.Get(RA + 3); value != LNil { + reg.Set(RA+2, value) + pc := cf.Fn.Proto.Code[cf.Pc] + cf.Pc += int(pc&0x3ffff) - opMaxArgSbx + } + cf.Pc++ + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETLIST + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + C := int(inst>>9) & 0x1ff //GETC + if C == 0 { + C = int(cf.Fn.Proto.Code[cf.Pc]) + cf.Pc++ + } + offset := (C - 1) * FieldsPerFlush + table := reg.Get(RA).(*LTable) + nelem := B + if B == 0 { + nelem = reg.Top() - RA - 1 + } + for i := 1; i <= nelem; i++ { + table.RawSetInt(offset+i, reg.Get(RA+i)) + } + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CLOSE + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + // this section is inlined by go-inline + // source function is 'func (ls *LState) closeUpvalues(idx int) ' in '_state.go' + { + ls := L + idx := RA + if ls.uvcache != nil { + var prev *Upvalue + for uv := ls.uvcache; uv != nil; uv = uv.next { + if uv.index >= idx { + if prev != nil { + prev.next = nil + } else { + ls.uvcache = nil + } + uv.Close() + } + prev = uv + } + } + } + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CLOSURE + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + Bx := int(inst & 0x3ffff) //GETBX + proto := cf.Fn.Proto.FunctionPrototypes[Bx] + closure := newLFunctionL(proto, cf.Fn.Env, int(proto.NumUpvalues)) + reg.Set(RA, closure) + for i := 0; i < int(proto.NumUpvalues); i++ { + inst = cf.Fn.Proto.Code[cf.Pc] + cf.Pc++ + B := opGetArgB(inst) + switch opGetOpCode(inst) { + case OP_MOVE: + closure.Upvalues[i] = L.findUpvalue(lbase + B) + case OP_GETUPVAL: + closure.Upvalues[i] = cf.Fn.Upvalues[B] + } + } + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_VARARG + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + nparams := int(cf.Fn.Proto.NumParameters) + nvarargs := cf.NArgs - nparams + if nvarargs < 0 { + nvarargs = 0 + } + nwant := B - 1 + if B == 0 { + nwant = nvarargs + } + // this section is inlined by go-inline + // source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go' + { + rg := reg + regv := RA + start := cf.Base + nparams + 1 + limit := cf.LocalBase + n := nwant + for i := 0; i < n; i++ { + if tidx := start + i; tidx >= rg.top || limit > -1 && tidx >= limit || tidx < 0 { + rg.array[regv+i] = LNil + } else { + rg.array[regv+i] = rg.array[tidx] + } + } + rg.top = regv + n + } + return 0 + }, + func(L *LState, inst uint32, baseframe *callFrame) int { //OP_NOP + return 0 + }, + } +} + +func opArith(L *LState, inst uint32, baseframe *callFrame) int { //OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_MOD, OP_POW + reg := L.reg + cf := L.currentFrame + lbase := cf.LocalBase + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + opcode := int(inst >> 26) //GETOPCODE + B := int(inst & 0x1ff) //GETB + C := int(inst>>9) & 0x1ff //GETC + lhs := L.rkValue(B) + rhs := L.rkValue(C) + v1, ok1 := lhs.assertFloat64() + v2, ok2 := rhs.assertFloat64() + if ok1 && ok2 { + reg.SetNumber(RA, numberArith(L, opcode, LNumber(v1), LNumber(v2))) + } else { + reg.Set(RA, objectArith(L, opcode, lhs, rhs)) + } + return 0 +} + +func luaModulo(lhs, rhs LNumber) LNumber { + flhs := float64(lhs) + frhs := float64(rhs) + v := math.Mod(flhs, frhs) + if flhs < 0 || frhs < 0 && !(flhs < 0 && frhs < 0) { + v += frhs + } + return LNumber(v) +} + +func numberArith(L *LState, opcode int, lhs, rhs LNumber) LNumber { + switch opcode { + case OP_ADD: + return lhs + rhs + case OP_SUB: + return lhs - rhs + case OP_MUL: + return lhs * rhs + case OP_DIV: + return lhs / rhs + case OP_MOD: + return luaModulo(lhs, rhs) + case OP_POW: + flhs := float64(lhs) + frhs := float64(rhs) + return LNumber(math.Pow(flhs, frhs)) + } + panic("should not reach here") + return LNumber(0) +} + +func objectArith(L *LState, opcode int, lhs, rhs LValue) LValue { + event := "" + switch opcode { + case OP_ADD: + event = "__add" + case OP_SUB: + event = "__sub" + case OP_MUL: + event = "__mul" + case OP_DIV: + event = "__div" + case OP_MOD: + event = "__mod" + case OP_POW: + event = "__pow" + } + op := L.metaOp2(lhs, rhs, event) + if op.Type() == LTFunction { + L.reg.Push(op) + L.reg.Push(lhs) + L.reg.Push(rhs) + L.Call(2, 1) + return L.reg.Pop() + } + if str, ok := lhs.(LString); ok { + if lnum, err := parseNumber(string(str)); err == nil { + lhs = lnum + } + } + if str, ok := rhs.(LString); ok { + if rnum, err := parseNumber(string(str)); err == nil { + rhs = rnum + } + } + if v1, ok1 := lhs.assertFloat64(); ok1 { + if v2, ok2 := rhs.assertFloat64(); ok2 { + return numberArith(L, opcode, LNumber(v1), LNumber(v2)) + } + } + L.RaiseError(fmt.Sprintf("cannot perform %v operation between %v and %v", + strings.TrimLeft(event, "_"), lhs.Type().String(), rhs.Type().String())) + + return LNil +} + +func stringConcat(L *LState, total, last int) LValue { + rhs := L.reg.Get(last) + total-- + for i := last - 1; total > 0; { + lhs := L.reg.Get(i) + if !(LVCanConvToString(lhs) && LVCanConvToString(rhs)) { + op := L.metaOp2(lhs, rhs, "__concat") + if op.Type() == LTFunction { + L.reg.Push(op) + L.reg.Push(lhs) + L.reg.Push(rhs) + L.Call(2, 1) + rhs = L.reg.Pop() + total-- + i-- + } else { + L.RaiseError("cannot perform concat operation between %v and %v", lhs.Type().String(), rhs.Type().String()) + return LNil + } + } else { + buf := make([]string, total+1) + buf[total] = LVAsString(rhs) + for total > 0 { + lhs = L.reg.Get(i) + if !LVCanConvToString(lhs) { + break + } + buf[total-1] = LVAsString(lhs) + i-- + total-- + } + rhs = LString(strings.Join(buf, "")) + } + } + return rhs +} + +func lessThan(L *LState, lhs, rhs LValue) bool { + // optimization for numbers + if v1, ok1 := lhs.assertFloat64(); ok1 { + if v2, ok2 := rhs.assertFloat64(); ok2 { + return v1 < v2 + } + L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String()) + } + if lhs.Type() != rhs.Type() { + L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String()) + return false + } + ret := false + switch lhs.Type() { + case LTString: + ret = strCmp(string(lhs.(LString)), string(rhs.(LString))) < 0 + default: + ret = objectRationalWithError(L, lhs, rhs, "__lt") + } + return ret +} + +func equals(L *LState, lhs, rhs LValue, raw bool) bool { + if lhs.Type() != rhs.Type() { + return false + } + + ret := false + switch lhs.Type() { + case LTNil: + ret = true + case LTNumber: + v1, _ := lhs.assertFloat64() + v2, _ := rhs.assertFloat64() + ret = v1 == v2 + case LTBool: + ret = bool(lhs.(LBool)) == bool(rhs.(LBool)) + case LTString: + ret = string(lhs.(LString)) == string(rhs.(LString)) + case LTUserData, LTTable: + if lhs == rhs { + ret = true + } else if !raw { + switch objectRational(L, lhs, rhs, "__eq") { + case 1: + ret = true + default: + ret = false + } + } + default: + ret = lhs == rhs + } + return ret +} + +func objectRationalWithError(L *LState, lhs, rhs LValue, event string) bool { + switch objectRational(L, lhs, rhs, event) { + case 1: + return true + case 0: + return false + } + L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String()) + return false +} + +func objectRational(L *LState, lhs, rhs LValue, event string) int { + m1 := L.metaOp1(lhs, event) + m2 := L.metaOp1(rhs, event) + if m1.Type() == LTFunction && m1 == m2 { + L.reg.Push(m1) + L.reg.Push(lhs) + L.reg.Push(rhs) + L.Call(2, 1) + if LVAsBool(L.reg.Pop()) { + return 1 + } + return 0 + } + return -1 +} diff --git a/vendor/go.uber.org/zap/BUILD.bazel b/vendor/go.uber.org/zap/BUILD.bazel deleted file mode 100644 index 55ecf3c1229a2e2147da645d4834240fa45673d7..0000000000000000000000000000000000000000 --- a/vendor/go.uber.org/zap/BUILD.bazel +++ /dev/null @@ -1,78 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") - -go_library( - name = "go_default_library", - srcs = [ - "array.go", - "config.go", - "doc.go", - "encoder.go", - "error.go", - "field.go", - "flag.go", - "global.go", - "http_handler.go", - "level.go", - "logger.go", - "options.go", - "stacktrace.go", - "sugar.go", - "time.go", - "writer.go", - ], - importpath = "go.uber.org/zap", - visibility = ["//visibility:public"], - deps = [ - "//vendor/go.uber.org/atomic:go_default_library", - "//vendor/go.uber.org/multierr:go_default_library", - "//vendor/go.uber.org/zap/internal/bufferpool:go_default_library", - "//vendor/go.uber.org/zap/zapcore:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = [ - "array_test.go", - "common_test.go", - "config_test.go", - "encoder_test.go", - "error_test.go", - "field_test.go", - "flag_test.go", - "global_test.go", - "level_test.go", - "logger_bench_test.go", - "logger_test.go", - "stacktrace_test.go", - "sugar_test.go", - "time_test.go", - "writer_test.go", - ], - embed = [":go_default_library"], - deps = [ - "//vendor/go.uber.org/atomic:go_default_library", - "//vendor/go.uber.org/zap/internal/exit:go_default_library", - "//vendor/go.uber.org/zap/zapcore:go_default_library", - "//vendor/go.uber.org/zap/zaptest:go_default_library", - "//vendor/go.uber.org/zap/zaptest/observer:go_default_library", - "@com_github_pkg_errors//:go_default_library", - "@com_github_stretchr_testify//assert:go_default_library", - "@com_github_stretchr_testify//require:go_default_library", - ], -) - -go_test( - name = "go_default_xtest", - srcs = [ - "example_test.go", - "http_handler_test.go", - "stacktrace_ext_test.go", - ], - deps = [ - ":go_default_library", - "//vendor/go.uber.org/zap/zapcore:go_default_library", - "@com_github_stretchr_testify//assert:go_default_library", - "@com_github_stretchr_testify//require:go_default_library", - ], -) diff --git a/vendor/golang.org/x/crypto/.gitattributes b/vendor/golang.org/x/crypto/.gitattributes new file mode 100644 index 0000000000000000000000000000000000000000..d2f212e5da80c5c7445cf4f272517b33c564e734 --- /dev/null +++ b/vendor/golang.org/x/crypto/.gitattributes @@ -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 diff --git a/vendor/golang.org/x/crypto/.gitignore b/vendor/golang.org/x/crypto/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..8339fd61d3f419870728bc269fe5e71927892cde --- /dev/null +++ b/vendor/golang.org/x/crypto/.gitignore @@ -0,0 +1,2 @@ +# Add no patterns to .hgignore except for files generated by the build. +last-change diff --git a/vendor/golang.org/x/crypto/AUTHORS b/vendor/golang.org/x/crypto/AUTHORS new file mode 100644 index 0000000000000000000000000000000000000000..2b00ddba0dfee1022198444c16670d443840ef86 --- /dev/null +++ b/vendor/golang.org/x/crypto/AUTHORS @@ -0,0 +1,3 @@ +# This source code refers to The Go Authors for copyright purposes. +# The master list of authors is in the main Go distribution, +# visible at https://tip.golang.org/AUTHORS. diff --git a/vendor/golang.org/x/crypto/CONTRIBUTING.md b/vendor/golang.org/x/crypto/CONTRIBUTING.md new file mode 100644 index 0000000000000000000000000000000000000000..88dff59bc7d200392543337d37013f2d89dde6df --- /dev/null +++ b/vendor/golang.org/x/crypto/CONTRIBUTING.md @@ -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. + diff --git a/vendor/golang.org/x/crypto/CONTRIBUTORS b/vendor/golang.org/x/crypto/CONTRIBUTORS new file mode 100644 index 0000000000000000000000000000000000000000..1fbd3e976faf5af5bbd1d8268a70399234969ae4 --- /dev/null +++ b/vendor/golang.org/x/crypto/CONTRIBUTORS @@ -0,0 +1,3 @@ +# This source code was written by the Go contributors. +# The master list of contributors is in the main Go distribution, +# visible at https://tip.golang.org/CONTRIBUTORS. diff --git a/vendor/golang.org/x/crypto/LICENSE b/vendor/golang.org/x/crypto/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..6a66aea5eafe0ca6a688840c47219556c552488e --- /dev/null +++ b/vendor/golang.org/x/crypto/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/golang.org/x/crypto/PATENTS b/vendor/golang.org/x/crypto/PATENTS new file mode 100644 index 0000000000000000000000000000000000000000..733099041f84fa1e58611ab2e11af51c1f26d1d2 --- /dev/null +++ b/vendor/golang.org/x/crypto/PATENTS @@ -0,0 +1,22 @@ +Additional IP Rights Grant (Patents) + +"This implementation" means the copyrightable works distributed by +Google as part of the Go project. + +Google hereby grants to You a perpetual, worldwide, non-exclusive, +no-charge, royalty-free, irrevocable (except as stated in this section) +patent license to make, have made, use, offer to sell, sell, import, +transfer and otherwise run, modify and propagate the contents of this +implementation of Go, where such license applies only to those patent +claims, both currently owned or controlled by Google and acquired in +the future, licensable by Google that are necessarily infringed by this +implementation of Go. This grant does not include claims that would be +infringed only as a consequence of further modification of this +implementation. If you or your agent or exclusive licensee institute or +order or agree to the institution of patent litigation against any +entity (including a cross-claim or counterclaim in a lawsuit) alleging +that this implementation of Go or any code incorporated within this +implementation of Go constitutes direct or contributory patent +infringement, or inducement of patent infringement, then any patent +rights granted to you under this License for this implementation of Go +shall terminate as of the date such litigation is filed. diff --git a/vendor/golang.org/x/crypto/README.md b/vendor/golang.org/x/crypto/README.md new file mode 100644 index 0000000000000000000000000000000000000000..c9d6fecd1e5f380aa56d319a93297ca050939c18 --- /dev/null +++ b/vendor/golang.org/x/crypto/README.md @@ -0,0 +1,21 @@ +# Go Cryptography + +This repository holds supplementary Go cryptography libraries. + +## Download/Install + +The easiest way to install is to run `go get -u golang.org/x/crypto/...`. You +can also manually git clone the repository to `$GOPATH/src/golang.org/x/crypto`. + +## Report Issues / Send Patches + +This repository uses Gerrit for code changes. To learn how to submit changes to +this repository, see https://golang.org/doc/contribute.html. + +The main issue tracker for the crypto repository is located at +https://github.com/golang/go/issues. Prefix your issue with "x/crypto:" in the +subject line, so it is easy to find. + +Note that contributions to the cryptography package receive additional scrutiny +due to their sensitive nature. Patches may take longer than normal to receive +feedback. diff --git a/vendor/golang.org/x/crypto/acme/acme.go b/vendor/golang.org/x/crypto/acme/acme.go new file mode 100644 index 0000000000000000000000000000000000000000..fa9c4b39e2e53022c058786620f3c7de428e1ecb --- /dev/null +++ b/vendor/golang.org/x/crypto/acme/acme.go @@ -0,0 +1,1058 @@ +// Copyright 2015 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 acme provides an implementation of the +// Automatic Certificate Management Environment (ACME) spec. +// See https://tools.ietf.org/html/draft-ietf-acme-acme-02 for details. +// +// Most common scenarios will want to use autocert subdirectory instead, +// which provides automatic access to certificates from Let's Encrypt +// and any other ACME-based CA. +// +// This package is a work in progress and makes no API stability promises. +package acme + +import ( + "bytes" + "context" + "crypto" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/sha256" + "crypto/tls" + "crypto/x509" + "encoding/base64" + "encoding/hex" + "encoding/json" + "encoding/pem" + "errors" + "fmt" + "io" + "io/ioutil" + "math/big" + "net/http" + "strconv" + "strings" + "sync" + "time" +) + +// LetsEncryptURL is the Directory endpoint of Let's Encrypt CA. +const LetsEncryptURL = "https://acme-v01.api.letsencrypt.org/directory" + +const ( + maxChainLen = 5 // max depth and breadth of a certificate chain + maxCertSize = 1 << 20 // max size of a certificate, in bytes + + // Max number of collected nonces kept in memory. + // Expect usual peak of 1 or 2. + maxNonces = 100 +) + +// Client is an ACME client. +// The only required field is Key. An example of creating a client with a new key +// is as follows: +// +// key, err := rsa.GenerateKey(rand.Reader, 2048) +// if err != nil { +// log.Fatal(err) +// } +// client := &Client{Key: key} +// +type Client struct { + // Key is the account key used to register with a CA and sign requests. + // Key.Public() must return a *rsa.PublicKey or *ecdsa.PublicKey. + Key crypto.Signer + + // HTTPClient optionally specifies an HTTP client to use + // instead of http.DefaultClient. + HTTPClient *http.Client + + // DirectoryURL points to the CA directory endpoint. + // If empty, LetsEncryptURL is used. + // Mutating this value after a successful call of Client's Discover method + // will have no effect. + DirectoryURL string + + dirMu sync.Mutex // guards writes to dir + dir *Directory // cached result of Client's Discover method + + noncesMu sync.Mutex + nonces map[string]struct{} // nonces collected from previous responses +} + +// Discover performs ACME server discovery using c.DirectoryURL. +// +// It caches successful result. So, subsequent calls will not result in +// a network round-trip. This also means mutating c.DirectoryURL after successful call +// of this method will have no effect. +func (c *Client) Discover(ctx context.Context) (Directory, error) { + c.dirMu.Lock() + defer c.dirMu.Unlock() + if c.dir != nil { + return *c.dir, nil + } + + dirURL := c.DirectoryURL + if dirURL == "" { + dirURL = LetsEncryptURL + } + res, err := c.get(ctx, dirURL) + if err != nil { + return Directory{}, err + } + defer res.Body.Close() + c.addNonce(res.Header) + if res.StatusCode != http.StatusOK { + return Directory{}, responseError(res) + } + + var v struct { + Reg string `json:"new-reg"` + Authz string `json:"new-authz"` + Cert string `json:"new-cert"` + Revoke string `json:"revoke-cert"` + Meta struct { + Terms string `json:"terms-of-service"` + Website string `json:"website"` + CAA []string `json:"caa-identities"` + } + } + if err := json.NewDecoder(res.Body).Decode(&v); err != nil { + return Directory{}, err + } + c.dir = &Directory{ + RegURL: v.Reg, + AuthzURL: v.Authz, + CertURL: v.Cert, + RevokeURL: v.Revoke, + Terms: v.Meta.Terms, + Website: v.Meta.Website, + CAA: v.Meta.CAA, + } + return *c.dir, nil +} + +// CreateCert requests a new certificate using the Certificate Signing Request csr encoded in DER format. +// The exp argument indicates the desired certificate validity duration. CA may issue a certificate +// with a different duration. +// If the bundle argument is true, the returned value will also contain the CA (issuer) certificate chain. +// +// In the case where CA server does not provide the issued certificate in the response, +// CreateCert will poll certURL using c.FetchCert, which will result in additional round-trips. +// In such a scenario, the caller can cancel the polling with ctx. +// +// CreateCert returns an error if the CA's response or chain was unreasonably large. +// Callers are encouraged to parse the returned value to ensure the certificate is valid and has the expected features. +func (c *Client) CreateCert(ctx context.Context, csr []byte, exp time.Duration, bundle bool) (der [][]byte, certURL string, err error) { + if _, err := c.Discover(ctx); err != nil { + return nil, "", err + } + + req := struct { + Resource string `json:"resource"` + CSR string `json:"csr"` + NotBefore string `json:"notBefore,omitempty"` + NotAfter string `json:"notAfter,omitempty"` + }{ + Resource: "new-cert", + CSR: base64.RawURLEncoding.EncodeToString(csr), + } + now := timeNow() + req.NotBefore = now.Format(time.RFC3339) + if exp > 0 { + req.NotAfter = now.Add(exp).Format(time.RFC3339) + } + + res, err := c.retryPostJWS(ctx, c.Key, c.dir.CertURL, req) + if err != nil { + return nil, "", err + } + defer res.Body.Close() + if res.StatusCode != http.StatusCreated { + return nil, "", responseError(res) + } + + curl := res.Header.Get("Location") // cert permanent URL + if res.ContentLength == 0 { + // no cert in the body; poll until we get it + cert, err := c.FetchCert(ctx, curl, bundle) + return cert, curl, err + } + // slurp issued cert and CA chain, if requested + cert, err := c.responseCert(ctx, res, bundle) + return cert, curl, err +} + +// FetchCert retrieves already issued certificate from the given url, in DER format. +// It retries the request until the certificate is successfully retrieved, +// context is cancelled by the caller or an error response is received. +// +// The returned value will also contain the CA (issuer) certificate if the bundle argument is true. +// +// FetchCert returns an error if the CA's response or chain was unreasonably large. +// Callers are encouraged to parse the returned value to ensure the certificate is valid +// and has expected features. +func (c *Client) FetchCert(ctx context.Context, url string, bundle bool) ([][]byte, error) { + for { + res, err := c.get(ctx, url) + if err != nil { + return nil, err + } + defer res.Body.Close() + if res.StatusCode == http.StatusOK { + return c.responseCert(ctx, res, bundle) + } + if res.StatusCode > 299 { + return nil, responseError(res) + } + d := retryAfter(res.Header.Get("Retry-After"), 3*time.Second) + select { + case <-time.After(d): + // retry + case <-ctx.Done(): + return nil, ctx.Err() + } + } +} + +// RevokeCert revokes a previously issued certificate cert, provided in DER format. +// +// The key argument, used to sign the request, must be authorized +// to revoke the certificate. It's up to the CA to decide which keys are authorized. +// For instance, the key pair of the certificate may be authorized. +// If the key is nil, c.Key is used instead. +func (c *Client) RevokeCert(ctx context.Context, key crypto.Signer, cert []byte, reason CRLReasonCode) error { + if _, err := c.Discover(ctx); err != nil { + return err + } + + body := &struct { + Resource string `json:"resource"` + Cert string `json:"certificate"` + Reason int `json:"reason"` + }{ + Resource: "revoke-cert", + Cert: base64.RawURLEncoding.EncodeToString(cert), + Reason: int(reason), + } + if key == nil { + key = c.Key + } + res, err := c.retryPostJWS(ctx, key, c.dir.RevokeURL, body) + if err != nil { + return err + } + defer res.Body.Close() + if res.StatusCode != http.StatusOK { + return responseError(res) + } + return nil +} + +// AcceptTOS always returns true to indicate the acceptance of a CA's Terms of Service +// during account registration. See Register method of Client for more details. +func AcceptTOS(tosURL string) bool { return true } + +// Register creates a new account registration by following the "new-reg" flow. +// It returns the registered account. The account is not modified. +// +// The registration may require the caller to agree to the CA's Terms of Service (TOS). +// If so, and the account has not indicated the acceptance of the terms (see Account for details), +// Register calls prompt with a TOS URL provided by the CA. Prompt should report +// whether the caller agrees to the terms. To always accept the terms, the caller can use AcceptTOS. +func (c *Client) Register(ctx context.Context, a *Account, prompt func(tosURL string) bool) (*Account, error) { + if _, err := c.Discover(ctx); err != nil { + return nil, err + } + + var err error + if a, err = c.doReg(ctx, c.dir.RegURL, "new-reg", a); err != nil { + return nil, err + } + var accept bool + if a.CurrentTerms != "" && a.CurrentTerms != a.AgreedTerms { + accept = prompt(a.CurrentTerms) + } + if accept { + a.AgreedTerms = a.CurrentTerms + a, err = c.UpdateReg(ctx, a) + } + return a, err +} + +// GetReg retrieves an existing registration. +// The url argument is an Account URI. +func (c *Client) GetReg(ctx context.Context, url string) (*Account, error) { + a, err := c.doReg(ctx, url, "reg", nil) + if err != nil { + return nil, err + } + a.URI = url + return a, nil +} + +// UpdateReg updates an existing registration. +// It returns an updated account copy. The provided account is not modified. +func (c *Client) UpdateReg(ctx context.Context, a *Account) (*Account, error) { + uri := a.URI + a, err := c.doReg(ctx, uri, "reg", a) + if err != nil { + return nil, err + } + a.URI = uri + return a, nil +} + +// Authorize performs the initial step in an authorization flow. +// The caller will then need to choose from and perform a set of returned +// challenges using c.Accept in order to successfully complete authorization. +// +// If an authorization has been previously granted, the CA may return +// a valid authorization (Authorization.Status is StatusValid). If so, the caller +// need not fulfill any challenge and can proceed to requesting a certificate. +func (c *Client) Authorize(ctx context.Context, domain string) (*Authorization, error) { + if _, err := c.Discover(ctx); err != nil { + return nil, err + } + + type authzID struct { + Type string `json:"type"` + Value string `json:"value"` + } + req := struct { + Resource string `json:"resource"` + Identifier authzID `json:"identifier"` + }{ + Resource: "new-authz", + Identifier: authzID{Type: "dns", Value: domain}, + } + res, err := c.retryPostJWS(ctx, c.Key, c.dir.AuthzURL, req) + if err != nil { + return nil, err + } + defer res.Body.Close() + if res.StatusCode != http.StatusCreated { + return nil, responseError(res) + } + + var v wireAuthz + if err := json.NewDecoder(res.Body).Decode(&v); err != nil { + return nil, fmt.Errorf("acme: invalid response: %v", err) + } + if v.Status != StatusPending && v.Status != StatusValid { + return nil, fmt.Errorf("acme: unexpected status: %s", v.Status) + } + return v.authorization(res.Header.Get("Location")), nil +} + +// GetAuthorization retrieves an authorization identified by the given URL. +// +// If a caller needs to poll an authorization until its status is final, +// see the WaitAuthorization method. +func (c *Client) GetAuthorization(ctx context.Context, url string) (*Authorization, error) { + res, err := c.get(ctx, url) + if err != nil { + return nil, err + } + defer res.Body.Close() + if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted { + return nil, responseError(res) + } + var v wireAuthz + if err := json.NewDecoder(res.Body).Decode(&v); err != nil { + return nil, fmt.Errorf("acme: invalid response: %v", err) + } + return v.authorization(url), nil +} + +// RevokeAuthorization relinquishes an existing authorization identified +// by the given URL. +// The url argument is an Authorization.URI value. +// +// If successful, the caller will be required to obtain a new authorization +// using the Authorize method before being able to request a new certificate +// for the domain associated with the authorization. +// +// It does not revoke existing certificates. +func (c *Client) RevokeAuthorization(ctx context.Context, url string) error { + req := struct { + Resource string `json:"resource"` + Status string `json:"status"` + Delete bool `json:"delete"` + }{ + Resource: "authz", + Status: "deactivated", + Delete: true, + } + res, err := c.retryPostJWS(ctx, c.Key, url, req) + if err != nil { + return err + } + defer res.Body.Close() + if res.StatusCode != http.StatusOK { + return responseError(res) + } + return nil +} + +// WaitAuthorization polls an authorization at the given URL +// until it is in one of the final states, StatusValid or StatusInvalid, +// or the context is done. +// +// It returns a non-nil Authorization only if its Status is StatusValid. +// In all other cases WaitAuthorization returns an error. +// If the Status is StatusInvalid, the returned error is of type *AuthorizationError. +func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorization, error) { + sleep := sleeper(ctx) + for { + res, err := c.get(ctx, url) + if err != nil { + return nil, err + } + retry := res.Header.Get("Retry-After") + if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted { + res.Body.Close() + if err := sleep(retry, 1); err != nil { + return nil, err + } + continue + } + var raw wireAuthz + err = json.NewDecoder(res.Body).Decode(&raw) + res.Body.Close() + if err != nil { + if err := sleep(retry, 0); err != nil { + return nil, err + } + continue + } + if raw.Status == StatusValid { + return raw.authorization(url), nil + } + if raw.Status == StatusInvalid { + return nil, raw.error(url) + } + if err := sleep(retry, 0); err != nil { + return nil, err + } + } +} + +// GetChallenge retrieves the current status of an challenge. +// +// A client typically polls a challenge status using this method. +func (c *Client) GetChallenge(ctx context.Context, url string) (*Challenge, error) { + res, err := c.get(ctx, url) + if err != nil { + return nil, err + } + defer res.Body.Close() + if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted { + return nil, responseError(res) + } + v := wireChallenge{URI: url} + if err := json.NewDecoder(res.Body).Decode(&v); err != nil { + return nil, fmt.Errorf("acme: invalid response: %v", err) + } + return v.challenge(), nil +} + +// Accept informs the server that the client accepts one of its challenges +// previously obtained with c.Authorize. +// +// The server will then perform the validation asynchronously. +func (c *Client) Accept(ctx context.Context, chal *Challenge) (*Challenge, error) { + auth, err := keyAuth(c.Key.Public(), chal.Token) + if err != nil { + return nil, err + } + + req := struct { + Resource string `json:"resource"` + Type string `json:"type"` + Auth string `json:"keyAuthorization"` + }{ + Resource: "challenge", + Type: chal.Type, + Auth: auth, + } + res, err := c.retryPostJWS(ctx, c.Key, chal.URI, req) + if err != nil { + return nil, err + } + defer res.Body.Close() + // Note: the protocol specifies 200 as the expected response code, but + // letsencrypt seems to be returning 202. + if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted { + return nil, responseError(res) + } + + var v wireChallenge + if err := json.NewDecoder(res.Body).Decode(&v); err != nil { + return nil, fmt.Errorf("acme: invalid response: %v", err) + } + return v.challenge(), nil +} + +// DNS01ChallengeRecord returns a DNS record value for a dns-01 challenge response. +// A TXT record containing the returned value must be provisioned under +// "_acme-challenge" name of the domain being validated. +// +// The token argument is a Challenge.Token value. +func (c *Client) DNS01ChallengeRecord(token string) (string, error) { + ka, err := keyAuth(c.Key.Public(), token) + if err != nil { + return "", err + } + b := sha256.Sum256([]byte(ka)) + return base64.RawURLEncoding.EncodeToString(b[:]), nil +} + +// HTTP01ChallengeResponse returns the response for an http-01 challenge. +// Servers should respond with the value to HTTP requests at the URL path +// provided by HTTP01ChallengePath to validate the challenge and prove control +// over a domain name. +// +// The token argument is a Challenge.Token value. +func (c *Client) HTTP01ChallengeResponse(token string) (string, error) { + return keyAuth(c.Key.Public(), token) +} + +// HTTP01ChallengePath returns the URL path at which the response for an http-01 challenge +// should be provided by the servers. +// The response value can be obtained with HTTP01ChallengeResponse. +// +// The token argument is a Challenge.Token value. +func (c *Client) HTTP01ChallengePath(token string) string { + return "/.well-known/acme-challenge/" + token +} + +// TLSSNI01ChallengeCert creates a certificate for TLS-SNI-01 challenge response. +// Servers can present the certificate to validate the challenge and prove control +// over a domain name. +// +// The implementation is incomplete in that the returned value is a single certificate, +// computed only for Z0 of the key authorization. ACME CAs are expected to update +// their implementations to use the newer version, TLS-SNI-02. +// For more details on TLS-SNI-01 see https://tools.ietf.org/html/draft-ietf-acme-acme-01#section-7.3. +// +// The token argument is a Challenge.Token value. +// If a WithKey option is provided, its private part signs the returned cert, +// and the public part is used to specify the signee. +// If no WithKey option is provided, a new ECDSA key is generated using P-256 curve. +// +// The returned certificate is valid for the next 24 hours and must be presented only when +// the server name of the client hello matches exactly the returned name value. +func (c *Client) TLSSNI01ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error) { + ka, err := keyAuth(c.Key.Public(), token) + if err != nil { + return tls.Certificate{}, "", err + } + b := sha256.Sum256([]byte(ka)) + h := hex.EncodeToString(b[:]) + name = fmt.Sprintf("%s.%s.acme.invalid", h[:32], h[32:]) + cert, err = tlsChallengeCert([]string{name}, opt) + if err != nil { + return tls.Certificate{}, "", err + } + return cert, name, nil +} + +// TLSSNI02ChallengeCert creates a certificate for TLS-SNI-02 challenge response. +// Servers can present the certificate to validate the challenge and prove control +// over a domain name. For more details on TLS-SNI-02 see +// https://tools.ietf.org/html/draft-ietf-acme-acme-03#section-7.3. +// +// The token argument is a Challenge.Token value. +// If a WithKey option is provided, its private part signs the returned cert, +// and the public part is used to specify the signee. +// If no WithKey option is provided, a new ECDSA key is generated using P-256 curve. +// +// The returned certificate is valid for the next 24 hours and must be presented only when +// the server name in the client hello matches exactly the returned name value. +func (c *Client) TLSSNI02ChallengeCert(token string, opt ...CertOption) (cert tls.Certificate, name string, err error) { + b := sha256.Sum256([]byte(token)) + h := hex.EncodeToString(b[:]) + sanA := fmt.Sprintf("%s.%s.token.acme.invalid", h[:32], h[32:]) + + ka, err := keyAuth(c.Key.Public(), token) + if err != nil { + return tls.Certificate{}, "", err + } + b = sha256.Sum256([]byte(ka)) + h = hex.EncodeToString(b[:]) + sanB := fmt.Sprintf("%s.%s.ka.acme.invalid", h[:32], h[32:]) + + cert, err = tlsChallengeCert([]string{sanA, sanB}, opt) + if err != nil { + return tls.Certificate{}, "", err + } + return cert, sanA, nil +} + +// doReg sends all types of registration requests. +// The type of request is identified by typ argument, which is a "resource" +// in the ACME spec terms. +// +// A non-nil acct argument indicates whether the intention is to mutate data +// of the Account. Only Contact and Agreement of its fields are used +// in such cases. +func (c *Client) doReg(ctx context.Context, url string, typ string, acct *Account) (*Account, error) { + req := struct { + Resource string `json:"resource"` + Contact []string `json:"contact,omitempty"` + Agreement string `json:"agreement,omitempty"` + }{ + Resource: typ, + } + if acct != nil { + req.Contact = acct.Contact + req.Agreement = acct.AgreedTerms + } + res, err := c.retryPostJWS(ctx, c.Key, url, req) + if err != nil { + return nil, err + } + defer res.Body.Close() + if res.StatusCode < 200 || res.StatusCode > 299 { + return nil, responseError(res) + } + + var v struct { + Contact []string + Agreement string + Authorizations string + Certificates string + } + if err := json.NewDecoder(res.Body).Decode(&v); err != nil { + return nil, fmt.Errorf("acme: invalid response: %v", err) + } + var tos string + if v := linkHeader(res.Header, "terms-of-service"); len(v) > 0 { + tos = v[0] + } + var authz string + if v := linkHeader(res.Header, "next"); len(v) > 0 { + authz = v[0] + } + return &Account{ + URI: res.Header.Get("Location"), + Contact: v.Contact, + AgreedTerms: v.Agreement, + CurrentTerms: tos, + Authz: authz, + Authorizations: v.Authorizations, + Certificates: v.Certificates, + }, nil +} + +// retryPostJWS will retry calls to postJWS if there is a badNonce error, +// clearing the stored nonces after each error. +// If the response was 4XX-5XX, then responseError is called on the body, +// the body is closed, and the error returned. +func (c *Client) retryPostJWS(ctx context.Context, key crypto.Signer, url string, body interface{}) (*http.Response, error) { + sleep := sleeper(ctx) + for { + res, err := c.postJWS(ctx, key, url, body) + if err != nil { + return nil, err + } + // handle errors 4XX-5XX with responseError + if res.StatusCode >= 400 && res.StatusCode <= 599 { + err := responseError(res) + res.Body.Close() + // according to spec badNonce is urn:ietf:params:acme:error:badNonce + // however, acme servers in the wild return their version of the error + // https://tools.ietf.org/html/draft-ietf-acme-acme-02#section-5.4 + if ae, ok := err.(*Error); ok && strings.HasSuffix(strings.ToLower(ae.ProblemType), ":badnonce") { + // clear any nonces that we might've stored that might now be + // considered bad + c.clearNonces() + retry := res.Header.Get("Retry-After") + if err := sleep(retry, 1); err != nil { + return nil, err + } + continue + } + return nil, err + } + return res, nil + } +} + +// postJWS signs the body with the given key and POSTs it to the provided url. +// The body argument must be JSON-serializable. +func (c *Client) postJWS(ctx context.Context, key crypto.Signer, url string, body interface{}) (*http.Response, error) { + nonce, err := c.popNonce(ctx, url) + if err != nil { + return nil, err + } + b, err := jwsEncodeJSON(body, key, nonce) + if err != nil { + return nil, err + } + res, err := c.post(ctx, url, "application/jose+json", bytes.NewReader(b)) + if err != nil { + return nil, err + } + c.addNonce(res.Header) + return res, nil +} + +// popNonce returns a nonce value previously stored with c.addNonce +// or fetches a fresh one from the given URL. +func (c *Client) popNonce(ctx context.Context, url string) (string, error) { + c.noncesMu.Lock() + defer c.noncesMu.Unlock() + if len(c.nonces) == 0 { + return c.fetchNonce(ctx, url) + } + var nonce string + for nonce = range c.nonces { + delete(c.nonces, nonce) + break + } + return nonce, nil +} + +// clearNonces clears any stored nonces +func (c *Client) clearNonces() { + c.noncesMu.Lock() + defer c.noncesMu.Unlock() + c.nonces = make(map[string]struct{}) +} + +// addNonce stores a nonce value found in h (if any) for future use. +func (c *Client) addNonce(h http.Header) { + v := nonceFromHeader(h) + if v == "" { + return + } + c.noncesMu.Lock() + defer c.noncesMu.Unlock() + if len(c.nonces) >= maxNonces { + return + } + if c.nonces == nil { + c.nonces = make(map[string]struct{}) + } + c.nonces[v] = struct{}{} +} + +func (c *Client) httpClient() *http.Client { + if c.HTTPClient != nil { + return c.HTTPClient + } + return http.DefaultClient +} + +func (c *Client) get(ctx context.Context, urlStr string) (*http.Response, error) { + req, err := http.NewRequest("GET", urlStr, nil) + if err != nil { + return nil, err + } + return c.do(ctx, req) +} + +func (c *Client) head(ctx context.Context, urlStr string) (*http.Response, error) { + req, err := http.NewRequest("HEAD", urlStr, nil) + if err != nil { + return nil, err + } + return c.do(ctx, req) +} + +func (c *Client) post(ctx context.Context, urlStr, contentType string, body io.Reader) (*http.Response, error) { + req, err := http.NewRequest("POST", urlStr, body) + if err != nil { + return nil, err + } + req.Header.Set("Content-Type", contentType) + return c.do(ctx, req) +} + +func (c *Client) do(ctx context.Context, req *http.Request) (*http.Response, error) { + res, err := c.httpClient().Do(req.WithContext(ctx)) + if err != nil { + select { + case <-ctx.Done(): + // Prefer the unadorned context error. + // (The acme package had tests assuming this, previously from ctxhttp's + // behavior, predating net/http supporting contexts natively) + // TODO(bradfitz): reconsider this in the future. But for now this + // requires no test updates. + return nil, ctx.Err() + default: + return nil, err + } + } + return res, nil +} + +func (c *Client) fetchNonce(ctx context.Context, url string) (string, error) { + resp, err := c.head(ctx, url) + if err != nil { + return "", err + } + defer resp.Body.Close() + nonce := nonceFromHeader(resp.Header) + if nonce == "" { + if resp.StatusCode > 299 { + return "", responseError(resp) + } + return "", errors.New("acme: nonce not found") + } + return nonce, nil +} + +func nonceFromHeader(h http.Header) string { + return h.Get("Replay-Nonce") +} + +func (c *Client) responseCert(ctx context.Context, res *http.Response, bundle bool) ([][]byte, error) { + b, err := ioutil.ReadAll(io.LimitReader(res.Body, maxCertSize+1)) + if err != nil { + return nil, fmt.Errorf("acme: response stream: %v", err) + } + if len(b) > maxCertSize { + return nil, errors.New("acme: certificate is too big") + } + cert := [][]byte{b} + if !bundle { + return cert, nil + } + + // Append CA chain cert(s). + // At least one is required according to the spec: + // https://tools.ietf.org/html/draft-ietf-acme-acme-03#section-6.3.1 + up := linkHeader(res.Header, "up") + if len(up) == 0 { + return nil, errors.New("acme: rel=up link not found") + } + if len(up) > maxChainLen { + return nil, errors.New("acme: rel=up link is too large") + } + for _, url := range up { + cc, err := c.chainCert(ctx, url, 0) + if err != nil { + return nil, err + } + cert = append(cert, cc...) + } + return cert, nil +} + +// responseError creates an error of Error type from resp. +func responseError(resp *http.Response) error { + // don't care if ReadAll returns an error: + // json.Unmarshal will fail in that case anyway + b, _ := ioutil.ReadAll(resp.Body) + e := &wireError{Status: resp.StatusCode} + if err := json.Unmarshal(b, e); err != nil { + // this is not a regular error response: + // populate detail with anything we received, + // e.Status will already contain HTTP response code value + e.Detail = string(b) + if e.Detail == "" { + e.Detail = resp.Status + } + } + return e.error(resp.Header) +} + +// chainCert fetches CA certificate chain recursively by following "up" links. +// Each recursive call increments the depth by 1, resulting in an error +// if the recursion level reaches maxChainLen. +// +// First chainCert call starts with depth of 0. +func (c *Client) chainCert(ctx context.Context, url string, depth int) ([][]byte, error) { + if depth >= maxChainLen { + return nil, errors.New("acme: certificate chain is too deep") + } + + res, err := c.get(ctx, url) + if err != nil { + return nil, err + } + defer res.Body.Close() + if res.StatusCode != http.StatusOK { + return nil, responseError(res) + } + b, err := ioutil.ReadAll(io.LimitReader(res.Body, maxCertSize+1)) + if err != nil { + return nil, err + } + if len(b) > maxCertSize { + return nil, errors.New("acme: certificate is too big") + } + chain := [][]byte{b} + + uplink := linkHeader(res.Header, "up") + if len(uplink) > maxChainLen { + return nil, errors.New("acme: certificate chain is too large") + } + for _, up := range uplink { + cc, err := c.chainCert(ctx, up, depth+1) + if err != nil { + return nil, err + } + chain = append(chain, cc...) + } + + return chain, nil +} + +// linkHeader returns URI-Reference values of all Link headers +// with relation-type rel. +// See https://tools.ietf.org/html/rfc5988#section-5 for details. +func linkHeader(h http.Header, rel string) []string { + var links []string + for _, v := range h["Link"] { + parts := strings.Split(v, ";") + for _, p := range parts { + p = strings.TrimSpace(p) + if !strings.HasPrefix(p, "rel=") { + continue + } + if v := strings.Trim(p[4:], `"`); v == rel { + links = append(links, strings.Trim(parts[0], "<>")) + } + } + } + return links +} + +// sleeper returns a function that accepts the Retry-After HTTP header value +// and an increment that's used with backoff to increasingly sleep on +// consecutive calls until the context is done. If the Retry-After header +// cannot be parsed, then backoff is used with a maximum sleep time of 10 +// seconds. +func sleeper(ctx context.Context) func(ra string, inc int) error { + var count int + return func(ra string, inc int) error { + count += inc + d := backoff(count, 10*time.Second) + d = retryAfter(ra, d) + wakeup := time.NewTimer(d) + defer wakeup.Stop() + select { + case <-ctx.Done(): + return ctx.Err() + case <-wakeup.C: + return nil + } + } +} + +// retryAfter parses a Retry-After HTTP header value, +// trying to convert v into an int (seconds) or use http.ParseTime otherwise. +// It returns d if v cannot be parsed. +func retryAfter(v string, d time.Duration) time.Duration { + if i, err := strconv.Atoi(v); err == nil { + return time.Duration(i) * time.Second + } + t, err := http.ParseTime(v) + if err != nil { + return d + } + return t.Sub(timeNow()) +} + +// backoff computes a duration after which an n+1 retry iteration should occur +// using truncated exponential backoff algorithm. +// +// The n argument is always bounded between 0 and 30. +// The max argument defines upper bound for the returned value. +func backoff(n int, max time.Duration) time.Duration { + if n < 0 { + n = 0 + } + if n > 30 { + n = 30 + } + var d time.Duration + if x, err := rand.Int(rand.Reader, big.NewInt(1000)); err == nil { + d = time.Duration(x.Int64()) * time.Millisecond + } + d += time.Duration(1< max { + return max + } + return d +} + +// keyAuth generates a key authorization string for a given token. +func keyAuth(pub crypto.PublicKey, token string) (string, error) { + th, err := JWKThumbprint(pub) + if err != nil { + return "", err + } + return fmt.Sprintf("%s.%s", token, th), nil +} + +// tlsChallengeCert creates a temporary certificate for TLS-SNI challenges +// with the given SANs and auto-generated public/private key pair. +// The Subject Common Name is set to the first SAN to aid debugging. +// To create a cert with a custom key pair, specify WithKey option. +func tlsChallengeCert(san []string, opt []CertOption) (tls.Certificate, error) { + var ( + key crypto.Signer + tmpl *x509.Certificate + ) + for _, o := range opt { + switch o := o.(type) { + case *certOptKey: + if key != nil { + return tls.Certificate{}, errors.New("acme: duplicate key option") + } + key = o.key + case *certOptTemplate: + var t = *(*x509.Certificate)(o) // shallow copy is ok + tmpl = &t + default: + // package's fault, if we let this happen: + panic(fmt.Sprintf("unsupported option type %T", o)) + } + } + if key == nil { + var err error + if key, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader); err != nil { + return tls.Certificate{}, err + } + } + if tmpl == nil { + tmpl = &x509.Certificate{ + SerialNumber: big.NewInt(1), + NotBefore: time.Now(), + NotAfter: time.Now().Add(24 * time.Hour), + BasicConstraintsValid: true, + KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + } + } + tmpl.DNSNames = san + if len(san) > 0 { + tmpl.Subject.CommonName = san[0] + } + + der, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, key.Public(), key) + if err != nil { + return tls.Certificate{}, err + } + return tls.Certificate{ + Certificate: [][]byte{der}, + PrivateKey: key, + }, nil +} + +// encodePEM returns b encoded as PEM with block of type typ. +func encodePEM(typ string, b []byte) []byte { + pb := &pem.Block{Type: typ, Bytes: b} + return pem.EncodeToMemory(pb) +} + +// timeNow is useful for testing for fixed current time. +var timeNow = time.Now diff --git a/vendor/golang.org/x/crypto/acme/acme_test.go b/vendor/golang.org/x/crypto/acme/acme_test.go new file mode 100644 index 0000000000000000000000000000000000000000..89f2efaa5e5c526c1a1a70aca88b2fa89d3f1857 --- /dev/null +++ b/vendor/golang.org/x/crypto/acme/acme_test.go @@ -0,0 +1,1352 @@ +// Copyright 2015 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 acme + +import ( + "bytes" + "context" + "crypto/rand" + "crypto/rsa" + "crypto/tls" + "crypto/x509" + "crypto/x509/pkix" + "encoding/base64" + "encoding/json" + "fmt" + "io/ioutil" + "math/big" + "net/http" + "net/http/httptest" + "reflect" + "sort" + "strings" + "testing" + "time" +) + +// Decodes a JWS-encoded request and unmarshals the decoded JSON into a provided +// interface. +func decodeJWSRequest(t *testing.T, v interface{}, r *http.Request) { + // Decode request + var req struct{ Payload string } + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + t.Fatal(err) + } + payload, err := base64.RawURLEncoding.DecodeString(req.Payload) + if err != nil { + t.Fatal(err) + } + err = json.Unmarshal(payload, v) + if err != nil { + t.Fatal(err) + } +} + +type jwsHead struct { + Alg string + Nonce string + JWK map[string]string `json:"jwk"` +} + +func decodeJWSHead(r *http.Request) (*jwsHead, error) { + var req struct{ Protected string } + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + return nil, err + } + b, err := base64.RawURLEncoding.DecodeString(req.Protected) + if err != nil { + return nil, err + } + var head jwsHead + if err := json.Unmarshal(b, &head); err != nil { + return nil, err + } + return &head, nil +} + +func TestDiscover(t *testing.T) { + const ( + reg = "https://example.com/acme/new-reg" + authz = "https://example.com/acme/new-authz" + cert = "https://example.com/acme/new-cert" + revoke = "https://example.com/acme/revoke-cert" + ) + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + fmt.Fprintf(w, `{ + "new-reg": %q, + "new-authz": %q, + "new-cert": %q, + "revoke-cert": %q + }`, reg, authz, cert, revoke) + })) + defer ts.Close() + c := Client{DirectoryURL: ts.URL} + dir, err := c.Discover(context.Background()) + if err != nil { + t.Fatal(err) + } + if dir.RegURL != reg { + t.Errorf("dir.RegURL = %q; want %q", dir.RegURL, reg) + } + if dir.AuthzURL != authz { + t.Errorf("dir.AuthzURL = %q; want %q", dir.AuthzURL, authz) + } + if dir.CertURL != cert { + t.Errorf("dir.CertURL = %q; want %q", dir.CertURL, cert) + } + if dir.RevokeURL != revoke { + t.Errorf("dir.RevokeURL = %q; want %q", dir.RevokeURL, revoke) + } +} + +func TestRegister(t *testing.T) { + contacts := []string{"mailto:admin@example.com"} + + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method == "HEAD" { + w.Header().Set("Replay-Nonce", "test-nonce") + return + } + if r.Method != "POST" { + t.Errorf("r.Method = %q; want POST", r.Method) + } + + var j struct { + Resource string + Contact []string + Agreement string + } + decodeJWSRequest(t, &j, r) + + // Test request + if j.Resource != "new-reg" { + t.Errorf("j.Resource = %q; want new-reg", j.Resource) + } + if !reflect.DeepEqual(j.Contact, contacts) { + t.Errorf("j.Contact = %v; want %v", j.Contact, contacts) + } + + w.Header().Set("Location", "https://ca.tld/acme/reg/1") + w.Header().Set("Link", `;rel="next"`) + w.Header().Add("Link", `;rel="recover"`) + w.Header().Add("Link", `;rel="terms-of-service"`) + w.WriteHeader(http.StatusCreated) + b, _ := json.Marshal(contacts) + fmt.Fprintf(w, `{"contact": %s}`, b) + })) + defer ts.Close() + + prompt := func(url string) bool { + const terms = "https://ca.tld/acme/terms" + if url != terms { + t.Errorf("prompt url = %q; want %q", url, terms) + } + return false + } + + c := Client{Key: testKeyEC, dir: &Directory{RegURL: ts.URL}} + a := &Account{Contact: contacts} + var err error + if a, err = c.Register(context.Background(), a, prompt); err != nil { + t.Fatal(err) + } + if a.URI != "https://ca.tld/acme/reg/1" { + t.Errorf("a.URI = %q; want https://ca.tld/acme/reg/1", a.URI) + } + if a.Authz != "https://ca.tld/acme/new-authz" { + t.Errorf("a.Authz = %q; want https://ca.tld/acme/new-authz", a.Authz) + } + if a.CurrentTerms != "https://ca.tld/acme/terms" { + t.Errorf("a.CurrentTerms = %q; want https://ca.tld/acme/terms", a.CurrentTerms) + } + if !reflect.DeepEqual(a.Contact, contacts) { + t.Errorf("a.Contact = %v; want %v", a.Contact, contacts) + } +} + +func TestUpdateReg(t *testing.T) { + const terms = "https://ca.tld/acme/terms" + contacts := []string{"mailto:admin@example.com"} + + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method == "HEAD" { + w.Header().Set("Replay-Nonce", "test-nonce") + return + } + if r.Method != "POST" { + t.Errorf("r.Method = %q; want POST", r.Method) + } + + var j struct { + Resource string + Contact []string + Agreement string + } + decodeJWSRequest(t, &j, r) + + // Test request + if j.Resource != "reg" { + t.Errorf("j.Resource = %q; want reg", j.Resource) + } + if j.Agreement != terms { + t.Errorf("j.Agreement = %q; want %q", j.Agreement, terms) + } + if !reflect.DeepEqual(j.Contact, contacts) { + t.Errorf("j.Contact = %v; want %v", j.Contact, contacts) + } + + w.Header().Set("Link", `;rel="next"`) + w.Header().Add("Link", `;rel="recover"`) + w.Header().Add("Link", fmt.Sprintf(`<%s>;rel="terms-of-service"`, terms)) + w.WriteHeader(http.StatusOK) + b, _ := json.Marshal(contacts) + fmt.Fprintf(w, `{"contact":%s, "agreement":%q}`, b, terms) + })) + defer ts.Close() + + c := Client{Key: testKeyEC} + a := &Account{URI: ts.URL, Contact: contacts, AgreedTerms: terms} + var err error + if a, err = c.UpdateReg(context.Background(), a); err != nil { + t.Fatal(err) + } + if a.Authz != "https://ca.tld/acme/new-authz" { + t.Errorf("a.Authz = %q; want https://ca.tld/acme/new-authz", a.Authz) + } + if a.AgreedTerms != terms { + t.Errorf("a.AgreedTerms = %q; want %q", a.AgreedTerms, terms) + } + if a.CurrentTerms != terms { + t.Errorf("a.CurrentTerms = %q; want %q", a.CurrentTerms, terms) + } + if a.URI != ts.URL { + t.Errorf("a.URI = %q; want %q", a.URI, ts.URL) + } +} + +func TestGetReg(t *testing.T) { + const terms = "https://ca.tld/acme/terms" + const newTerms = "https://ca.tld/acme/new-terms" + contacts := []string{"mailto:admin@example.com"} + + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method == "HEAD" { + w.Header().Set("Replay-Nonce", "test-nonce") + return + } + if r.Method != "POST" { + t.Errorf("r.Method = %q; want POST", r.Method) + } + + var j struct { + Resource string + Contact []string + Agreement string + } + decodeJWSRequest(t, &j, r) + + // Test request + if j.Resource != "reg" { + t.Errorf("j.Resource = %q; want reg", j.Resource) + } + if len(j.Contact) != 0 { + t.Errorf("j.Contact = %v", j.Contact) + } + if j.Agreement != "" { + t.Errorf("j.Agreement = %q", j.Agreement) + } + + w.Header().Set("Link", `;rel="next"`) + w.Header().Add("Link", `;rel="recover"`) + w.Header().Add("Link", fmt.Sprintf(`<%s>;rel="terms-of-service"`, newTerms)) + w.WriteHeader(http.StatusOK) + b, _ := json.Marshal(contacts) + fmt.Fprintf(w, `{"contact":%s, "agreement":%q}`, b, terms) + })) + defer ts.Close() + + c := Client{Key: testKeyEC} + a, err := c.GetReg(context.Background(), ts.URL) + if err != nil { + t.Fatal(err) + } + if a.Authz != "https://ca.tld/acme/new-authz" { + t.Errorf("a.AuthzURL = %q; want https://ca.tld/acme/new-authz", a.Authz) + } + if a.AgreedTerms != terms { + t.Errorf("a.AgreedTerms = %q; want %q", a.AgreedTerms, terms) + } + if a.CurrentTerms != newTerms { + t.Errorf("a.CurrentTerms = %q; want %q", a.CurrentTerms, newTerms) + } + if a.URI != ts.URL { + t.Errorf("a.URI = %q; want %q", a.URI, ts.URL) + } +} + +func TestAuthorize(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method == "HEAD" { + w.Header().Set("Replay-Nonce", "test-nonce") + return + } + if r.Method != "POST" { + t.Errorf("r.Method = %q; want POST", r.Method) + } + + var j struct { + Resource string + Identifier struct { + Type string + Value string + } + } + decodeJWSRequest(t, &j, r) + + // Test request + if j.Resource != "new-authz" { + t.Errorf("j.Resource = %q; want new-authz", j.Resource) + } + if j.Identifier.Type != "dns" { + t.Errorf("j.Identifier.Type = %q; want dns", j.Identifier.Type) + } + if j.Identifier.Value != "example.com" { + t.Errorf("j.Identifier.Value = %q; want example.com", j.Identifier.Value) + } + + w.Header().Set("Location", "https://ca.tld/acme/auth/1") + w.WriteHeader(http.StatusCreated) + fmt.Fprintf(w, `{ + "identifier": {"type":"dns","value":"example.com"}, + "status":"pending", + "challenges":[ + { + "type":"http-01", + "status":"pending", + "uri":"https://ca.tld/acme/challenge/publickey/id1", + "token":"token1" + }, + { + "type":"tls-sni-01", + "status":"pending", + "uri":"https://ca.tld/acme/challenge/publickey/id2", + "token":"token2" + } + ], + "combinations":[[0],[1]]}`) + })) + defer ts.Close() + + cl := Client{Key: testKeyEC, dir: &Directory{AuthzURL: ts.URL}} + auth, err := cl.Authorize(context.Background(), "example.com") + if err != nil { + t.Fatal(err) + } + + if auth.URI != "https://ca.tld/acme/auth/1" { + t.Errorf("URI = %q; want https://ca.tld/acme/auth/1", auth.URI) + } + if auth.Status != "pending" { + t.Errorf("Status = %q; want pending", auth.Status) + } + if auth.Identifier.Type != "dns" { + t.Errorf("Identifier.Type = %q; want dns", auth.Identifier.Type) + } + if auth.Identifier.Value != "example.com" { + t.Errorf("Identifier.Value = %q; want example.com", auth.Identifier.Value) + } + + if n := len(auth.Challenges); n != 2 { + t.Fatalf("len(auth.Challenges) = %d; want 2", n) + } + + c := auth.Challenges[0] + if c.Type != "http-01" { + t.Errorf("c.Type = %q; want http-01", c.Type) + } + if c.URI != "https://ca.tld/acme/challenge/publickey/id1" { + t.Errorf("c.URI = %q; want https://ca.tld/acme/challenge/publickey/id1", c.URI) + } + if c.Token != "token1" { + t.Errorf("c.Token = %q; want token1", c.Token) + } + + c = auth.Challenges[1] + if c.Type != "tls-sni-01" { + t.Errorf("c.Type = %q; want tls-sni-01", c.Type) + } + if c.URI != "https://ca.tld/acme/challenge/publickey/id2" { + t.Errorf("c.URI = %q; want https://ca.tld/acme/challenge/publickey/id2", c.URI) + } + if c.Token != "token2" { + t.Errorf("c.Token = %q; want token2", c.Token) + } + + combs := [][]int{{0}, {1}} + if !reflect.DeepEqual(auth.Combinations, combs) { + t.Errorf("auth.Combinations: %+v\nwant: %+v\n", auth.Combinations, combs) + } +} + +func TestAuthorizeValid(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method == "HEAD" { + w.Header().Set("Replay-Nonce", "nonce") + return + } + w.WriteHeader(http.StatusCreated) + w.Write([]byte(`{"status":"valid"}`)) + })) + defer ts.Close() + client := Client{Key: testKey, dir: &Directory{AuthzURL: ts.URL}} + _, err := client.Authorize(context.Background(), "example.com") + if err != nil { + t.Errorf("err = %v", err) + } +} + +func TestGetAuthorization(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method != "GET" { + t.Errorf("r.Method = %q; want GET", r.Method) + } + + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, `{ + "identifier": {"type":"dns","value":"example.com"}, + "status":"pending", + "challenges":[ + { + "type":"http-01", + "status":"pending", + "uri":"https://ca.tld/acme/challenge/publickey/id1", + "token":"token1" + }, + { + "type":"tls-sni-01", + "status":"pending", + "uri":"https://ca.tld/acme/challenge/publickey/id2", + "token":"token2" + } + ], + "combinations":[[0],[1]]}`) + })) + defer ts.Close() + + cl := Client{Key: testKeyEC} + auth, err := cl.GetAuthorization(context.Background(), ts.URL) + if err != nil { + t.Fatal(err) + } + + if auth.Status != "pending" { + t.Errorf("Status = %q; want pending", auth.Status) + } + if auth.Identifier.Type != "dns" { + t.Errorf("Identifier.Type = %q; want dns", auth.Identifier.Type) + } + if auth.Identifier.Value != "example.com" { + t.Errorf("Identifier.Value = %q; want example.com", auth.Identifier.Value) + } + + if n := len(auth.Challenges); n != 2 { + t.Fatalf("len(set.Challenges) = %d; want 2", n) + } + + c := auth.Challenges[0] + if c.Type != "http-01" { + t.Errorf("c.Type = %q; want http-01", c.Type) + } + if c.URI != "https://ca.tld/acme/challenge/publickey/id1" { + t.Errorf("c.URI = %q; want https://ca.tld/acme/challenge/publickey/id1", c.URI) + } + if c.Token != "token1" { + t.Errorf("c.Token = %q; want token1", c.Token) + } + + c = auth.Challenges[1] + if c.Type != "tls-sni-01" { + t.Errorf("c.Type = %q; want tls-sni-01", c.Type) + } + if c.URI != "https://ca.tld/acme/challenge/publickey/id2" { + t.Errorf("c.URI = %q; want https://ca.tld/acme/challenge/publickey/id2", c.URI) + } + if c.Token != "token2" { + t.Errorf("c.Token = %q; want token2", c.Token) + } + + combs := [][]int{{0}, {1}} + if !reflect.DeepEqual(auth.Combinations, combs) { + t.Errorf("auth.Combinations: %+v\nwant: %+v\n", auth.Combinations, combs) + } +} + +func TestWaitAuthorization(t *testing.T) { + var count int + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + count++ + w.Header().Set("Retry-After", "0") + if count > 1 { + fmt.Fprintf(w, `{"status":"valid"}`) + return + } + fmt.Fprintf(w, `{"status":"pending"}`) + })) + defer ts.Close() + + type res struct { + authz *Authorization + err error + } + done := make(chan res) + defer close(done) + go func() { + var client Client + a, err := client.WaitAuthorization(context.Background(), ts.URL) + done <- res{a, err} + }() + + select { + case <-time.After(5 * time.Second): + t.Fatal("WaitAuthz took too long to return") + case res := <-done: + if res.err != nil { + t.Fatalf("res.err = %v", res.err) + } + if res.authz == nil { + t.Fatal("res.authz is nil") + } + } +} + +func TestWaitAuthorizationInvalid(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fmt.Fprintf(w, `{"status":"invalid"}`) + })) + defer ts.Close() + + res := make(chan error) + defer close(res) + go func() { + var client Client + _, err := client.WaitAuthorization(context.Background(), ts.URL) + res <- err + }() + + select { + case <-time.After(3 * time.Second): + t.Fatal("WaitAuthz took too long to return") + case err := <-res: + if err == nil { + t.Error("err is nil") + } + if _, ok := err.(*AuthorizationError); !ok { + t.Errorf("err is %T; want *AuthorizationError", err) + } + } +} + +func TestWaitAuthorizationCancel(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Retry-After", "60") + fmt.Fprintf(w, `{"status":"pending"}`) + })) + defer ts.Close() + + res := make(chan error) + defer close(res) + go func() { + var client Client + ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond) + defer cancel() + _, err := client.WaitAuthorization(ctx, ts.URL) + res <- err + }() + + select { + case <-time.After(time.Second): + t.Fatal("WaitAuthz took too long to return") + case err := <-res: + if err == nil { + t.Error("err is nil") + } + } +} + +func TestRevokeAuthorization(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method == "HEAD" { + w.Header().Set("Replay-Nonce", "nonce") + return + } + switch r.URL.Path { + case "/1": + var req struct { + Resource string + Status string + Delete bool + } + decodeJWSRequest(t, &req, r) + if req.Resource != "authz" { + t.Errorf("req.Resource = %q; want authz", req.Resource) + } + if req.Status != "deactivated" { + t.Errorf("req.Status = %q; want deactivated", req.Status) + } + if !req.Delete { + t.Errorf("req.Delete is false") + } + case "/2": + w.WriteHeader(http.StatusInternalServerError) + } + })) + defer ts.Close() + client := &Client{Key: testKey} + ctx := context.Background() + if err := client.RevokeAuthorization(ctx, ts.URL+"/1"); err != nil { + t.Errorf("err = %v", err) + } + if client.RevokeAuthorization(ctx, ts.URL+"/2") == nil { + t.Error("nil error") + } +} + +func TestPollChallenge(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method != "GET" { + t.Errorf("r.Method = %q; want GET", r.Method) + } + + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, `{ + "type":"http-01", + "status":"pending", + "uri":"https://ca.tld/acme/challenge/publickey/id1", + "token":"token1"}`) + })) + defer ts.Close() + + cl := Client{Key: testKeyEC} + chall, err := cl.GetChallenge(context.Background(), ts.URL) + if err != nil { + t.Fatal(err) + } + + if chall.Status != "pending" { + t.Errorf("Status = %q; want pending", chall.Status) + } + if chall.Type != "http-01" { + t.Errorf("c.Type = %q; want http-01", chall.Type) + } + if chall.URI != "https://ca.tld/acme/challenge/publickey/id1" { + t.Errorf("c.URI = %q; want https://ca.tld/acme/challenge/publickey/id1", chall.URI) + } + if chall.Token != "token1" { + t.Errorf("c.Token = %q; want token1", chall.Token) + } +} + +func TestAcceptChallenge(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method == "HEAD" { + w.Header().Set("Replay-Nonce", "test-nonce") + return + } + if r.Method != "POST" { + t.Errorf("r.Method = %q; want POST", r.Method) + } + + var j struct { + Resource string + Type string + Auth string `json:"keyAuthorization"` + } + decodeJWSRequest(t, &j, r) + + // Test request + if j.Resource != "challenge" { + t.Errorf(`resource = %q; want "challenge"`, j.Resource) + } + if j.Type != "http-01" { + t.Errorf(`type = %q; want "http-01"`, j.Type) + } + keyAuth := "token1." + testKeyECThumbprint + if j.Auth != keyAuth { + t.Errorf(`keyAuthorization = %q; want %q`, j.Auth, keyAuth) + } + + // Respond to request + w.WriteHeader(http.StatusAccepted) + fmt.Fprintf(w, `{ + "type":"http-01", + "status":"pending", + "uri":"https://ca.tld/acme/challenge/publickey/id1", + "token":"token1", + "keyAuthorization":%q + }`, keyAuth) + })) + defer ts.Close() + + cl := Client{Key: testKeyEC} + c, err := cl.Accept(context.Background(), &Challenge{ + URI: ts.URL, + Token: "token1", + Type: "http-01", + }) + if err != nil { + t.Fatal(err) + } + + if c.Type != "http-01" { + t.Errorf("c.Type = %q; want http-01", c.Type) + } + if c.URI != "https://ca.tld/acme/challenge/publickey/id1" { + t.Errorf("c.URI = %q; want https://ca.tld/acme/challenge/publickey/id1", c.URI) + } + if c.Token != "token1" { + t.Errorf("c.Token = %q; want token1", c.Token) + } +} + +func TestNewCert(t *testing.T) { + notBefore := time.Now() + notAfter := notBefore.AddDate(0, 2, 0) + timeNow = func() time.Time { return notBefore } + + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method == "HEAD" { + w.Header().Set("Replay-Nonce", "test-nonce") + return + } + if r.Method != "POST" { + t.Errorf("r.Method = %q; want POST", r.Method) + } + + var j struct { + Resource string `json:"resource"` + CSR string `json:"csr"` + NotBefore string `json:"notBefore,omitempty"` + NotAfter string `json:"notAfter,omitempty"` + } + decodeJWSRequest(t, &j, r) + + // Test request + if j.Resource != "new-cert" { + t.Errorf(`resource = %q; want "new-cert"`, j.Resource) + } + if j.NotBefore != notBefore.Format(time.RFC3339) { + t.Errorf(`notBefore = %q; wanted %q`, j.NotBefore, notBefore.Format(time.RFC3339)) + } + if j.NotAfter != notAfter.Format(time.RFC3339) { + t.Errorf(`notAfter = %q; wanted %q`, j.NotAfter, notAfter.Format(time.RFC3339)) + } + + // Respond to request + template := x509.Certificate{ + SerialNumber: big.NewInt(int64(1)), + Subject: pkix.Name{ + Organization: []string{"goacme"}, + }, + NotBefore: notBefore, + NotAfter: notAfter, + + KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + BasicConstraintsValid: true, + } + + sampleCert, err := x509.CreateCertificate(rand.Reader, &template, &template, &testKeyEC.PublicKey, testKeyEC) + if err != nil { + t.Fatalf("Error creating certificate: %v", err) + } + + w.Header().Set("Location", "https://ca.tld/acme/cert/1") + w.WriteHeader(http.StatusCreated) + w.Write(sampleCert) + })) + defer ts.Close() + + csr := x509.CertificateRequest{ + Version: 0, + Subject: pkix.Name{ + CommonName: "example.com", + Organization: []string{"goacme"}, + }, + } + csrb, err := x509.CreateCertificateRequest(rand.Reader, &csr, testKeyEC) + if err != nil { + t.Fatal(err) + } + + c := Client{Key: testKeyEC, dir: &Directory{CertURL: ts.URL}} + cert, certURL, err := c.CreateCert(context.Background(), csrb, notAfter.Sub(notBefore), false) + if err != nil { + t.Fatal(err) + } + if cert == nil { + t.Errorf("cert is nil") + } + if certURL != "https://ca.tld/acme/cert/1" { + t.Errorf("certURL = %q; want https://ca.tld/acme/cert/1", certURL) + } +} + +func TestFetchCert(t *testing.T) { + var count byte + var ts *httptest.Server + ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + count++ + if count < 3 { + up := fmt.Sprintf("<%s>;rel=up", ts.URL) + w.Header().Set("Link", up) + } + w.Write([]byte{count}) + })) + defer ts.Close() + res, err := (&Client{}).FetchCert(context.Background(), ts.URL, true) + if err != nil { + t.Fatalf("FetchCert: %v", err) + } + cert := [][]byte{{1}, {2}, {3}} + if !reflect.DeepEqual(res, cert) { + t.Errorf("res = %v; want %v", res, cert) + } +} + +func TestFetchCertRetry(t *testing.T) { + var count int + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if count < 1 { + w.Header().Set("Retry-After", "0") + w.WriteHeader(http.StatusAccepted) + count++ + return + } + w.Write([]byte{1}) + })) + defer ts.Close() + res, err := (&Client{}).FetchCert(context.Background(), ts.URL, false) + if err != nil { + t.Fatalf("FetchCert: %v", err) + } + cert := [][]byte{{1}} + if !reflect.DeepEqual(res, cert) { + t.Errorf("res = %v; want %v", res, cert) + } +} + +func TestFetchCertCancel(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Retry-After", "0") + w.WriteHeader(http.StatusAccepted) + })) + defer ts.Close() + ctx, cancel := context.WithCancel(context.Background()) + done := make(chan struct{}) + var err error + go func() { + _, err = (&Client{}).FetchCert(ctx, ts.URL, false) + close(done) + }() + cancel() + <-done + if err != context.Canceled { + t.Errorf("err = %v; want %v", err, context.Canceled) + } +} + +func TestFetchCertDepth(t *testing.T) { + var count byte + var ts *httptest.Server + ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + count++ + if count > maxChainLen+1 { + t.Errorf("count = %d; want at most %d", count, maxChainLen+1) + w.WriteHeader(http.StatusInternalServerError) + } + w.Header().Set("Link", fmt.Sprintf("<%s>;rel=up", ts.URL)) + w.Write([]byte{count}) + })) + defer ts.Close() + _, err := (&Client{}).FetchCert(context.Background(), ts.URL, true) + if err == nil { + t.Errorf("err is nil") + } +} + +func TestFetchCertBreadth(t *testing.T) { + var ts *httptest.Server + ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + for i := 0; i < maxChainLen+1; i++ { + w.Header().Add("Link", fmt.Sprintf("<%s>;rel=up", ts.URL)) + } + w.Write([]byte{1}) + })) + defer ts.Close() + _, err := (&Client{}).FetchCert(context.Background(), ts.URL, true) + if err == nil { + t.Errorf("err is nil") + } +} + +func TestFetchCertSize(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + b := bytes.Repeat([]byte{1}, maxCertSize+1) + w.Write(b) + })) + defer ts.Close() + _, err := (&Client{}).FetchCert(context.Background(), ts.URL, false) + if err == nil { + t.Errorf("err is nil") + } +} + +func TestRevokeCert(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method == "HEAD" { + w.Header().Set("Replay-Nonce", "nonce") + return + } + + var req struct { + Resource string + Certificate string + Reason int + } + decodeJWSRequest(t, &req, r) + if req.Resource != "revoke-cert" { + t.Errorf("req.Resource = %q; want revoke-cert", req.Resource) + } + if req.Reason != 1 { + t.Errorf("req.Reason = %d; want 1", req.Reason) + } + // echo -n cert | base64 | tr -d '=' | tr '/+' '_-' + cert := "Y2VydA" + if req.Certificate != cert { + t.Errorf("req.Certificate = %q; want %q", req.Certificate, cert) + } + })) + defer ts.Close() + client := &Client{ + Key: testKeyEC, + dir: &Directory{RevokeURL: ts.URL}, + } + ctx := context.Background() + if err := client.RevokeCert(ctx, nil, []byte("cert"), CRLReasonKeyCompromise); err != nil { + t.Fatal(err) + } +} + +func TestNonce_add(t *testing.T) { + var c Client + c.addNonce(http.Header{"Replay-Nonce": {"nonce"}}) + c.addNonce(http.Header{"Replay-Nonce": {}}) + c.addNonce(http.Header{"Replay-Nonce": {"nonce"}}) + + nonces := map[string]struct{}{"nonce": {}} + if !reflect.DeepEqual(c.nonces, nonces) { + t.Errorf("c.nonces = %q; want %q", c.nonces, nonces) + } +} + +func TestNonce_addMax(t *testing.T) { + c := &Client{nonces: make(map[string]struct{})} + for i := 0; i < maxNonces; i++ { + c.nonces[fmt.Sprintf("%d", i)] = struct{}{} + } + c.addNonce(http.Header{"Replay-Nonce": {"nonce"}}) + if n := len(c.nonces); n != maxNonces { + t.Errorf("len(c.nonces) = %d; want %d", n, maxNonces) + } +} + +func TestNonce_fetch(t *testing.T) { + tests := []struct { + code int + nonce string + }{ + {http.StatusOK, "nonce1"}, + {http.StatusBadRequest, "nonce2"}, + {http.StatusOK, ""}, + } + var i int + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method != "HEAD" { + t.Errorf("%d: r.Method = %q; want HEAD", i, r.Method) + } + w.Header().Set("Replay-Nonce", tests[i].nonce) + w.WriteHeader(tests[i].code) + })) + defer ts.Close() + for ; i < len(tests); i++ { + test := tests[i] + c := &Client{} + n, err := c.fetchNonce(context.Background(), ts.URL) + if n != test.nonce { + t.Errorf("%d: n=%q; want %q", i, n, test.nonce) + } + switch { + case err == nil && test.nonce == "": + t.Errorf("%d: n=%q, err=%v; want non-nil error", i, n, err) + case err != nil && test.nonce != "": + t.Errorf("%d: n=%q, err=%v; want %q", i, n, err, test.nonce) + } + } +} + +func TestNonce_fetchError(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusTooManyRequests) + })) + defer ts.Close() + c := &Client{} + _, err := c.fetchNonce(context.Background(), ts.URL) + e, ok := err.(*Error) + if !ok { + t.Fatalf("err is %T; want *Error", err) + } + if e.StatusCode != http.StatusTooManyRequests { + t.Errorf("e.StatusCode = %d; want %d", e.StatusCode, http.StatusTooManyRequests) + } +} + +func TestNonce_postJWS(t *testing.T) { + var count int + seen := make(map[string]bool) + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + count++ + w.Header().Set("Replay-Nonce", fmt.Sprintf("nonce%d", count)) + if r.Method == "HEAD" { + // We expect the client do a HEAD request + // but only to fetch the first nonce. + return + } + // Make client.Authorize happy; we're not testing its result. + defer func() { + w.WriteHeader(http.StatusCreated) + w.Write([]byte(`{"status":"valid"}`)) + }() + + head, err := decodeJWSHead(r) + if err != nil { + t.Errorf("decodeJWSHead: %v", err) + return + } + if head.Nonce == "" { + t.Error("head.Nonce is empty") + return + } + if seen[head.Nonce] { + t.Errorf("nonce is already used: %q", head.Nonce) + } + seen[head.Nonce] = true + })) + defer ts.Close() + + client := Client{Key: testKey, dir: &Directory{AuthzURL: ts.URL}} + if _, err := client.Authorize(context.Background(), "example.com"); err != nil { + t.Errorf("client.Authorize 1: %v", err) + } + // The second call should not generate another extra HEAD request. + if _, err := client.Authorize(context.Background(), "example.com"); err != nil { + t.Errorf("client.Authorize 2: %v", err) + } + + if count != 3 { + t.Errorf("total requests count: %d; want 3", count) + } + if n := len(client.nonces); n != 1 { + t.Errorf("len(client.nonces) = %d; want 1", n) + } + for k := range seen { + if _, exist := client.nonces[k]; exist { + t.Errorf("used nonce %q in client.nonces", k) + } + } +} + +func TestRetryPostJWS(t *testing.T) { + var count int + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + count++ + w.Header().Set("Replay-Nonce", fmt.Sprintf("nonce%d", count)) + if r.Method == "HEAD" { + // We expect the client to do 2 head requests to fetch + // nonces, one to start and another after getting badNonce + return + } + + head, err := decodeJWSHead(r) + if err != nil { + t.Errorf("decodeJWSHead: %v", err) + } else if head.Nonce == "" { + t.Error("head.Nonce is empty") + } else if head.Nonce == "nonce1" { + // return a badNonce error to force the call to retry + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(`{"type":"urn:ietf:params:acme:error:badNonce"}`)) + return + } + // Make client.Authorize happy; we're not testing its result. + w.WriteHeader(http.StatusCreated) + w.Write([]byte(`{"status":"valid"}`)) + })) + defer ts.Close() + + client := Client{Key: testKey, dir: &Directory{AuthzURL: ts.URL}} + // This call will fail with badNonce, causing a retry + if _, err := client.Authorize(context.Background(), "example.com"); err != nil { + t.Errorf("client.Authorize 1: %v", err) + } + if count != 4 { + t.Errorf("total requests count: %d; want 4", count) + } +} + +func TestLinkHeader(t *testing.T) { + h := http.Header{"Link": { + `;rel="next"`, + `; rel=recover`, + `; foo=bar; rel="terms-of-service"`, + `;rel="next"`, + }} + tests := []struct { + rel string + out []string + }{ + {"next", []string{"https://example.com/acme/new-authz", "dup"}}, + {"recover", []string{"https://example.com/acme/recover-reg"}}, + {"terms-of-service", []string{"https://example.com/acme/terms"}}, + {"empty", nil}, + } + for i, test := range tests { + if v := linkHeader(h, test.rel); !reflect.DeepEqual(v, test.out) { + t.Errorf("%d: linkHeader(%q): %v; want %v", i, test.rel, v, test.out) + } + } +} + +func TestErrorResponse(t *testing.T) { + s := `{ + "status": 400, + "type": "urn:acme:error:xxx", + "detail": "text" + }` + res := &http.Response{ + StatusCode: 400, + Status: "400 Bad Request", + Body: ioutil.NopCloser(strings.NewReader(s)), + Header: http.Header{"X-Foo": {"bar"}}, + } + err := responseError(res) + v, ok := err.(*Error) + if !ok { + t.Fatalf("err = %+v (%T); want *Error type", err, err) + } + if v.StatusCode != 400 { + t.Errorf("v.StatusCode = %v; want 400", v.StatusCode) + } + if v.ProblemType != "urn:acme:error:xxx" { + t.Errorf("v.ProblemType = %q; want urn:acme:error:xxx", v.ProblemType) + } + if v.Detail != "text" { + t.Errorf("v.Detail = %q; want text", v.Detail) + } + if !reflect.DeepEqual(v.Header, res.Header) { + t.Errorf("v.Header = %+v; want %+v", v.Header, res.Header) + } +} + +func TestTLSSNI01ChallengeCert(t *testing.T) { + const ( + token = "evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA" + // echo -n | shasum -a 256 + san = "dbbd5eefe7b4d06eb9d1d9f5acb4c7cd.a27d320e4b30332f0b6cb441734ad7b0.acme.invalid" + ) + + client := &Client{Key: testKeyEC} + tlscert, name, err := client.TLSSNI01ChallengeCert(token) + if err != nil { + t.Fatal(err) + } + + if n := len(tlscert.Certificate); n != 1 { + t.Fatalf("len(tlscert.Certificate) = %d; want 1", n) + } + cert, err := x509.ParseCertificate(tlscert.Certificate[0]) + if err != nil { + t.Fatal(err) + } + if len(cert.DNSNames) != 1 || cert.DNSNames[0] != san { + t.Fatalf("cert.DNSNames = %v; want %q", cert.DNSNames, san) + } + if cert.DNSNames[0] != name { + t.Errorf("cert.DNSNames[0] != name: %q vs %q", cert.DNSNames[0], name) + } + if cn := cert.Subject.CommonName; cn != san { + t.Errorf("cert.Subject.CommonName = %q; want %q", cn, san) + } +} + +func TestTLSSNI02ChallengeCert(t *testing.T) { + const ( + token = "evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA" + // echo -n evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA | shasum -a 256 + sanA = "7ea0aaa69214e71e02cebb18bb867736.09b730209baabf60e43d4999979ff139.token.acme.invalid" + // echo -n | shasum -a 256 + sanB = "dbbd5eefe7b4d06eb9d1d9f5acb4c7cd.a27d320e4b30332f0b6cb441734ad7b0.ka.acme.invalid" + ) + + client := &Client{Key: testKeyEC} + tlscert, name, err := client.TLSSNI02ChallengeCert(token) + if err != nil { + t.Fatal(err) + } + + if n := len(tlscert.Certificate); n != 1 { + t.Fatalf("len(tlscert.Certificate) = %d; want 1", n) + } + cert, err := x509.ParseCertificate(tlscert.Certificate[0]) + if err != nil { + t.Fatal(err) + } + names := []string{sanA, sanB} + if !reflect.DeepEqual(cert.DNSNames, names) { + t.Fatalf("cert.DNSNames = %v;\nwant %v", cert.DNSNames, names) + } + sort.Strings(cert.DNSNames) + i := sort.SearchStrings(cert.DNSNames, name) + if i >= len(cert.DNSNames) || cert.DNSNames[i] != name { + t.Errorf("%v doesn't have %q", cert.DNSNames, name) + } + if cn := cert.Subject.CommonName; cn != sanA { + t.Errorf("CommonName = %q; want %q", cn, sanA) + } +} + +func TestTLSChallengeCertOpt(t *testing.T) { + key, err := rsa.GenerateKey(rand.Reader, 512) + if err != nil { + t.Fatal(err) + } + tmpl := &x509.Certificate{ + SerialNumber: big.NewInt(2), + Subject: pkix.Name{Organization: []string{"Test"}}, + DNSNames: []string{"should-be-overwritten"}, + } + opts := []CertOption{WithKey(key), WithTemplate(tmpl)} + + client := &Client{Key: testKeyEC} + cert1, _, err := client.TLSSNI01ChallengeCert("token", opts...) + if err != nil { + t.Fatal(err) + } + cert2, _, err := client.TLSSNI02ChallengeCert("token", opts...) + if err != nil { + t.Fatal(err) + } + + for i, tlscert := range []tls.Certificate{cert1, cert2} { + // verify generated cert private key + tlskey, ok := tlscert.PrivateKey.(*rsa.PrivateKey) + if !ok { + t.Errorf("%d: tlscert.PrivateKey is %T; want *rsa.PrivateKey", i, tlscert.PrivateKey) + continue + } + if tlskey.D.Cmp(key.D) != 0 { + t.Errorf("%d: tlskey.D = %v; want %v", i, tlskey.D, key.D) + } + // verify generated cert public key + x509Cert, err := x509.ParseCertificate(tlscert.Certificate[0]) + if err != nil { + t.Errorf("%d: %v", i, err) + continue + } + tlspub, ok := x509Cert.PublicKey.(*rsa.PublicKey) + if !ok { + t.Errorf("%d: x509Cert.PublicKey is %T; want *rsa.PublicKey", i, x509Cert.PublicKey) + continue + } + if tlspub.N.Cmp(key.N) != 0 { + t.Errorf("%d: tlspub.N = %v; want %v", i, tlspub.N, key.N) + } + // verify template option + sn := big.NewInt(2) + if x509Cert.SerialNumber.Cmp(sn) != 0 { + t.Errorf("%d: SerialNumber = %v; want %v", i, x509Cert.SerialNumber, sn) + } + org := []string{"Test"} + if !reflect.DeepEqual(x509Cert.Subject.Organization, org) { + t.Errorf("%d: Subject.Organization = %+v; want %+v", i, x509Cert.Subject.Organization, org) + } + for _, v := range x509Cert.DNSNames { + if !strings.HasSuffix(v, ".acme.invalid") { + t.Errorf("%d: invalid DNSNames element: %q", i, v) + } + } + } +} + +func TestHTTP01Challenge(t *testing.T) { + const ( + token = "xxx" + // thumbprint is precomputed for testKeyEC in jws_test.go + value = token + "." + testKeyECThumbprint + urlpath = "/.well-known/acme-challenge/" + token + ) + client := &Client{Key: testKeyEC} + val, err := client.HTTP01ChallengeResponse(token) + if err != nil { + t.Fatal(err) + } + if val != value { + t.Errorf("val = %q; want %q", val, value) + } + if path := client.HTTP01ChallengePath(token); path != urlpath { + t.Errorf("path = %q; want %q", path, urlpath) + } +} + +func TestDNS01ChallengeRecord(t *testing.T) { + // echo -n xxx. | \ + // openssl dgst -binary -sha256 | \ + // base64 | tr -d '=' | tr '/+' '_-' + const value = "8DERMexQ5VcdJ_prpPiA0mVdp7imgbCgjsG4SqqNMIo" + + client := &Client{Key: testKeyEC} + val, err := client.DNS01ChallengeRecord("xxx") + if err != nil { + t.Fatal(err) + } + if val != value { + t.Errorf("val = %q; want %q", val, value) + } +} + +func TestBackoff(t *testing.T) { + tt := []struct{ min, max time.Duration }{ + {time.Second, 2 * time.Second}, + {2 * time.Second, 3 * time.Second}, + {4 * time.Second, 5 * time.Second}, + {8 * time.Second, 9 * time.Second}, + } + for i, test := range tt { + d := backoff(i, time.Minute) + if d < test.min || test.max < d { + t.Errorf("%d: d = %v; want between %v and %v", i, d, test.min, test.max) + } + } + + min, max := time.Second, 2*time.Second + if d := backoff(-1, time.Minute); d < min || max < d { + t.Errorf("d = %v; want between %v and %v", d, min, max) + } + + bound := 10 * time.Second + if d := backoff(100, bound); d != bound { + t.Errorf("d = %v; want %v", d, bound) + } +} diff --git a/vendor/golang.org/x/crypto/acme/autocert/autocert.go b/vendor/golang.org/x/crypto/acme/autocert/autocert.go new file mode 100644 index 0000000000000000000000000000000000000000..453e72291faa72f1ef38440645fc5bef4768e5a6 --- /dev/null +++ b/vendor/golang.org/x/crypto/acme/autocert/autocert.go @@ -0,0 +1,973 @@ +// Copyright 2016 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 autocert provides automatic access to certificates from Let's Encrypt +// and any other ACME-based CA. +// +// This package is a work in progress and makes no API stability promises. +package autocert + +import ( + "bytes" + "context" + "crypto" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/rsa" + "crypto/tls" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "errors" + "fmt" + "io" + mathrand "math/rand" + "net" + "net/http" + "path" + "strconv" + "strings" + "sync" + "time" + + "golang.org/x/crypto/acme" +) + +// createCertRetryAfter is how much time to wait before removing a failed state +// entry due to an unsuccessful createCert call. +// This is a variable instead of a const for testing. +// TODO: Consider making it configurable or an exp backoff? +var createCertRetryAfter = time.Minute + +// pseudoRand is safe for concurrent use. +var pseudoRand *lockedMathRand + +func init() { + src := mathrand.NewSource(timeNow().UnixNano()) + pseudoRand = &lockedMathRand{rnd: mathrand.New(src)} +} + +// AcceptTOS is a Manager.Prompt function that always returns true to +// indicate acceptance of the CA's Terms of Service during account +// registration. +func AcceptTOS(tosURL string) bool { return true } + +// HostPolicy specifies which host names the Manager is allowed to respond to. +// It returns a non-nil error if the host should be rejected. +// The returned error is accessible via tls.Conn.Handshake and its callers. +// See Manager's HostPolicy field and GetCertificate method docs for more details. +type HostPolicy func(ctx context.Context, host string) error + +// HostWhitelist returns a policy where only the specified host names are allowed. +// Only exact matches are currently supported. Subdomains, regexp or wildcard +// will not match. +func HostWhitelist(hosts ...string) HostPolicy { + whitelist := make(map[string]bool, len(hosts)) + for _, h := range hosts { + whitelist[h] = true + } + return func(_ context.Context, host string) error { + if !whitelist[host] { + return errors.New("acme/autocert: host not configured") + } + return nil + } +} + +// defaultHostPolicy is used when Manager.HostPolicy is not set. +func defaultHostPolicy(context.Context, string) error { + return nil +} + +// Manager is a stateful certificate manager built on top of acme.Client. +// It obtains and refreshes certificates automatically using "tls-sni-01", +// "tls-sni-02" and "http-01" challenge types, as well as providing them +// to a TLS server via tls.Config. +// +// You must specify a cache implementation, such as DirCache, +// to reuse obtained certificates across program restarts. +// Otherwise your server is very likely to exceed the certificate +// issuer's request rate limits. +type Manager struct { + // Prompt specifies a callback function to conditionally accept a CA's Terms of Service (TOS). + // The registration may require the caller to agree to the CA's TOS. + // If so, Manager calls Prompt with a TOS URL provided by the CA. Prompt should report + // whether the caller agrees to the terms. + // + // To always accept the terms, the callers can use AcceptTOS. + Prompt func(tosURL string) bool + + // Cache optionally stores and retrieves previously-obtained certificates. + // If nil, certs will only be cached for the lifetime of the Manager. + // + // Manager passes the Cache certificates data encoded in PEM, with private/public + // parts combined in a single Cache.Put call, private key first. + Cache Cache + + // HostPolicy controls which domains the Manager will attempt + // to retrieve new certificates for. It does not affect cached certs. + // + // If non-nil, HostPolicy is called before requesting a new cert. + // If nil, all hosts are currently allowed. This is not recommended, + // as it opens a potential attack where clients connect to a server + // by IP address and pretend to be asking for an incorrect host name. + // Manager will attempt to obtain a certificate for that host, incorrectly, + // eventually reaching the CA's rate limit for certificate requests + // and making it impossible to obtain actual certificates. + // + // See GetCertificate for more details. + HostPolicy HostPolicy + + // RenewBefore optionally specifies how early certificates should + // be renewed before they expire. + // + // If zero, they're renewed 30 days before expiration. + RenewBefore time.Duration + + // Client is used to perform low-level operations, such as account registration + // and requesting new certificates. + // If Client is nil, a zero-value acme.Client is used with acme.LetsEncryptURL + // directory endpoint and a newly-generated ECDSA P-256 key. + // + // Mutating the field after the first call of GetCertificate method will have no effect. + Client *acme.Client + + // Email optionally specifies a contact email address. + // This is used by CAs, such as Let's Encrypt, to notify about problems + // with issued certificates. + // + // If the Client's account key is already registered, Email is not used. + Email string + + // ForceRSA makes the Manager generate certificates with 2048-bit RSA keys. + // + // If false, a default is used. Currently the default + // is EC-based keys using the P-256 curve. + ForceRSA bool + + clientMu sync.Mutex + client *acme.Client // initialized by acmeClient method + + stateMu sync.Mutex + state map[string]*certState // keyed by domain name + + // renewal tracks the set of domains currently running renewal timers. + // It is keyed by domain name. + renewalMu sync.Mutex + renewal map[string]*domainRenewal + + // tokensMu guards the rest of the fields: tryHTTP01, certTokens and httpTokens. + tokensMu sync.RWMutex + // tryHTTP01 indicates whether the Manager should try "http-01" challenge type + // during the authorization flow. + tryHTTP01 bool + // httpTokens contains response body values for http-01 challenges + // and is keyed by the URL path at which a challenge response is expected + // to be provisioned. + // The entries are stored for the duration of the authorization flow. + httpTokens map[string][]byte + // certTokens contains temporary certificates for tls-sni challenges + // and is keyed by token domain name, which matches server name of ClientHello. + // Keys always have ".acme.invalid" suffix. + // The entries are stored for the duration of the authorization flow. + certTokens map[string]*tls.Certificate +} + +// GetCertificate implements the tls.Config.GetCertificate hook. +// It provides a TLS certificate for hello.ServerName host, including answering +// *.acme.invalid (TLS-SNI) challenges. All other fields of hello are ignored. +// +// If m.HostPolicy is non-nil, GetCertificate calls the policy before requesting +// a new cert. A non-nil error returned from m.HostPolicy halts TLS negotiation. +// The error is propagated back to the caller of GetCertificate and is user-visible. +// This does not affect cached certs. See HostPolicy field description for more details. +func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, error) { + if m.Prompt == nil { + return nil, errors.New("acme/autocert: Manager.Prompt not set") + } + + name := hello.ServerName + if name == "" { + return nil, errors.New("acme/autocert: missing server name") + } + if !strings.Contains(strings.Trim(name, "."), ".") { + return nil, errors.New("acme/autocert: server name component count invalid") + } + if strings.ContainsAny(name, `/\`) { + return nil, errors.New("acme/autocert: server name contains invalid character") + } + + // In the worst-case scenario, the timeout needs to account for caching, host policy, + // domain ownership verification and certificate issuance. + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) + defer cancel() + + // check whether this is a token cert requested for TLS-SNI challenge + if strings.HasSuffix(name, ".acme.invalid") { + m.tokensMu.RLock() + defer m.tokensMu.RUnlock() + if cert := m.certTokens[name]; cert != nil { + return cert, nil + } + if cert, err := m.cacheGet(ctx, name); err == nil { + return cert, nil + } + // TODO: cache error results? + return nil, fmt.Errorf("acme/autocert: no token cert for %q", name) + } + + // regular domain + name = strings.TrimSuffix(name, ".") // golang.org/issue/18114 + cert, err := m.cert(ctx, name) + if err == nil { + return cert, nil + } + if err != ErrCacheMiss { + return nil, err + } + + // first-time + if err := m.hostPolicy()(ctx, name); err != nil { + return nil, err + } + cert, err = m.createCert(ctx, name) + if err != nil { + return nil, err + } + m.cachePut(ctx, name, cert) + return cert, nil +} + +// HTTPHandler configures the Manager to provision ACME "http-01" challenge responses. +// It returns an http.Handler that responds to the challenges and must be +// running on port 80. If it receives a request that is not an ACME challenge, +// it delegates the request to the optional fallback handler. +// +// If fallback is nil, the returned handler redirects all GET and HEAD requests +// to the default TLS port 443 with 302 Found status code, preserving the original +// request path and query. It responds with 400 Bad Request to all other HTTP methods. +// The fallback is not protected by the optional HostPolicy. +// +// Because the fallback handler is run with unencrypted port 80 requests, +// the fallback should not serve TLS-only requests. +// +// If HTTPHandler is never called, the Manager will only use TLS SNI +// challenges for domain verification. +func (m *Manager) HTTPHandler(fallback http.Handler) http.Handler { + m.tokensMu.Lock() + defer m.tokensMu.Unlock() + m.tryHTTP01 = true + + if fallback == nil { + fallback = http.HandlerFunc(handleHTTPRedirect) + } + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if !strings.HasPrefix(r.URL.Path, "/.well-known/acme-challenge/") { + fallback.ServeHTTP(w, r) + return + } + // A reasonable context timeout for cache and host policy only, + // because we don't wait for a new certificate issuance here. + ctx, cancel := context.WithTimeout(r.Context(), time.Minute) + defer cancel() + if err := m.hostPolicy()(ctx, r.Host); err != nil { + http.Error(w, err.Error(), http.StatusForbidden) + return + } + data, err := m.httpToken(ctx, r.URL.Path) + if err != nil { + http.Error(w, err.Error(), http.StatusNotFound) + return + } + w.Write(data) + }) +} + +func handleHTTPRedirect(w http.ResponseWriter, r *http.Request) { + if r.Method != "GET" && r.Method != "HEAD" { + http.Error(w, "Use HTTPS", http.StatusBadRequest) + return + } + target := "https://" + stripPort(r.Host) + r.URL.RequestURI() + http.Redirect(w, r, target, http.StatusFound) +} + +func stripPort(hostport string) string { + host, _, err := net.SplitHostPort(hostport) + if err != nil { + return hostport + } + return net.JoinHostPort(host, "443") +} + +// cert returns an existing certificate either from m.state or cache. +// If a certificate is found in cache but not in m.state, the latter will be filled +// with the cached value. +func (m *Manager) cert(ctx context.Context, name string) (*tls.Certificate, error) { + m.stateMu.Lock() + if s, ok := m.state[name]; ok { + m.stateMu.Unlock() + s.RLock() + defer s.RUnlock() + return s.tlscert() + } + defer m.stateMu.Unlock() + cert, err := m.cacheGet(ctx, name) + if err != nil { + return nil, err + } + signer, ok := cert.PrivateKey.(crypto.Signer) + if !ok { + return nil, errors.New("acme/autocert: private key cannot sign") + } + if m.state == nil { + m.state = make(map[string]*certState) + } + s := &certState{ + key: signer, + cert: cert.Certificate, + leaf: cert.Leaf, + } + m.state[name] = s + go m.renew(name, s.key, s.leaf.NotAfter) + return cert, nil +} + +// cacheGet always returns a valid certificate, or an error otherwise. +// If a cached certficate exists but is not valid, ErrCacheMiss is returned. +func (m *Manager) cacheGet(ctx context.Context, domain string) (*tls.Certificate, error) { + if m.Cache == nil { + return nil, ErrCacheMiss + } + data, err := m.Cache.Get(ctx, domain) + if err != nil { + return nil, err + } + + // private + priv, pub := pem.Decode(data) + if priv == nil || !strings.Contains(priv.Type, "PRIVATE") { + return nil, ErrCacheMiss + } + privKey, err := parsePrivateKey(priv.Bytes) + if err != nil { + return nil, err + } + + // public + var pubDER [][]byte + for len(pub) > 0 { + var b *pem.Block + b, pub = pem.Decode(pub) + if b == nil { + break + } + pubDER = append(pubDER, b.Bytes) + } + if len(pub) > 0 { + // Leftover content not consumed by pem.Decode. Corrupt. Ignore. + return nil, ErrCacheMiss + } + + // verify and create TLS cert + leaf, err := validCert(domain, pubDER, privKey) + if err != nil { + return nil, ErrCacheMiss + } + tlscert := &tls.Certificate{ + Certificate: pubDER, + PrivateKey: privKey, + Leaf: leaf, + } + return tlscert, nil +} + +func (m *Manager) cachePut(ctx context.Context, domain string, tlscert *tls.Certificate) error { + if m.Cache == nil { + return nil + } + + // contains PEM-encoded data + var buf bytes.Buffer + + // private + switch key := tlscert.PrivateKey.(type) { + case *ecdsa.PrivateKey: + if err := encodeECDSAKey(&buf, key); err != nil { + return err + } + case *rsa.PrivateKey: + b := x509.MarshalPKCS1PrivateKey(key) + pb := &pem.Block{Type: "RSA PRIVATE KEY", Bytes: b} + if err := pem.Encode(&buf, pb); err != nil { + return err + } + default: + return errors.New("acme/autocert: unknown private key type") + } + + // public + for _, b := range tlscert.Certificate { + pb := &pem.Block{Type: "CERTIFICATE", Bytes: b} + if err := pem.Encode(&buf, pb); err != nil { + return err + } + } + + return m.Cache.Put(ctx, domain, buf.Bytes()) +} + +func encodeECDSAKey(w io.Writer, key *ecdsa.PrivateKey) error { + b, err := x509.MarshalECPrivateKey(key) + if err != nil { + return err + } + pb := &pem.Block{Type: "EC PRIVATE KEY", Bytes: b} + return pem.Encode(w, pb) +} + +// createCert starts the domain ownership verification and returns a certificate +// for that domain upon success. +// +// If the domain is already being verified, it waits for the existing verification to complete. +// Either way, createCert blocks for the duration of the whole process. +func (m *Manager) createCert(ctx context.Context, domain string) (*tls.Certificate, error) { + // TODO: maybe rewrite this whole piece using sync.Once + state, err := m.certState(domain) + if err != nil { + return nil, err + } + // state may exist if another goroutine is already working on it + // in which case just wait for it to finish + if !state.locked { + state.RLock() + defer state.RUnlock() + return state.tlscert() + } + + // We are the first; state is locked. + // Unblock the readers when domain ownership is verified + // and we got the cert or the process failed. + defer state.Unlock() + state.locked = false + + der, leaf, err := m.authorizedCert(ctx, state.key, domain) + if err != nil { + // Remove the failed state after some time, + // making the manager call createCert again on the following TLS hello. + time.AfterFunc(createCertRetryAfter, func() { + defer testDidRemoveState(domain) + m.stateMu.Lock() + defer m.stateMu.Unlock() + // Verify the state hasn't changed and it's still invalid + // before deleting. + s, ok := m.state[domain] + if !ok { + return + } + if _, err := validCert(domain, s.cert, s.key); err == nil { + return + } + delete(m.state, domain) + }) + return nil, err + } + state.cert = der + state.leaf = leaf + go m.renew(domain, state.key, state.leaf.NotAfter) + return state.tlscert() +} + +// certState returns a new or existing certState. +// If a new certState is returned, state.exist is false and the state is locked. +// The returned error is non-nil only in the case where a new state could not be created. +func (m *Manager) certState(domain string) (*certState, error) { + m.stateMu.Lock() + defer m.stateMu.Unlock() + if m.state == nil { + m.state = make(map[string]*certState) + } + // existing state + if state, ok := m.state[domain]; ok { + return state, nil + } + + // new locked state + var ( + err error + key crypto.Signer + ) + if m.ForceRSA { + key, err = rsa.GenerateKey(rand.Reader, 2048) + } else { + key, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + } + if err != nil { + return nil, err + } + + state := &certState{ + key: key, + locked: true, + } + state.Lock() // will be unlocked by m.certState caller + m.state[domain] = state + return state, nil +} + +// authorizedCert starts the domain ownership verification process and requests a new cert upon success. +// The key argument is the certificate private key. +func (m *Manager) authorizedCert(ctx context.Context, key crypto.Signer, domain string) (der [][]byte, leaf *x509.Certificate, err error) { + client, err := m.acmeClient(ctx) + if err != nil { + return nil, nil, err + } + + if err := m.verify(ctx, client, domain); err != nil { + return nil, nil, err + } + csr, err := certRequest(key, domain) + if err != nil { + return nil, nil, err + } + der, _, err = client.CreateCert(ctx, csr, 0, true) + if err != nil { + return nil, nil, err + } + leaf, err = validCert(domain, der, key) + if err != nil { + return nil, nil, err + } + return der, leaf, nil +} + +// verify runs the identifier (domain) authorization flow +// using each applicable ACME challenge type. +func (m *Manager) verify(ctx context.Context, client *acme.Client, domain string) error { + // The list of challenge types we'll try to fulfill + // in this specific order. + challengeTypes := []string{"tls-sni-02", "tls-sni-01"} + m.tokensMu.RLock() + if m.tryHTTP01 { + challengeTypes = append(challengeTypes, "http-01") + } + m.tokensMu.RUnlock() + + var nextTyp int // challengeType index of the next challenge type to try + for { + // Start domain authorization and get the challenge. + authz, err := client.Authorize(ctx, domain) + if err != nil { + return err + } + // No point in accepting challenges if the authorization status + // is in a final state. + switch authz.Status { + case acme.StatusValid: + return nil // already authorized + case acme.StatusInvalid: + return fmt.Errorf("acme/autocert: invalid authorization %q", authz.URI) + } + + // Pick the next preferred challenge. + var chal *acme.Challenge + for chal == nil && nextTyp < len(challengeTypes) { + chal = pickChallenge(challengeTypes[nextTyp], authz.Challenges) + nextTyp++ + } + if chal == nil { + return fmt.Errorf("acme/autocert: unable to authorize %q; tried %q", domain, challengeTypes) + } + cleanup, err := m.fulfill(ctx, client, chal) + if err != nil { + continue + } + defer cleanup() + if _, err := client.Accept(ctx, chal); err != nil { + continue + } + + // A challenge is fulfilled and accepted: wait for the CA to validate. + if _, err := client.WaitAuthorization(ctx, authz.URI); err == nil { + return nil + } + } +} + +// fulfill provisions a response to the challenge chal. +// The cleanup is non-nil only if provisioning succeeded. +func (m *Manager) fulfill(ctx context.Context, client *acme.Client, chal *acme.Challenge) (cleanup func(), err error) { + switch chal.Type { + case "tls-sni-01": + cert, name, err := client.TLSSNI01ChallengeCert(chal.Token) + if err != nil { + return nil, err + } + m.putCertToken(ctx, name, &cert) + return func() { go m.deleteCertToken(name) }, nil + case "tls-sni-02": + cert, name, err := client.TLSSNI02ChallengeCert(chal.Token) + if err != nil { + return nil, err + } + m.putCertToken(ctx, name, &cert) + return func() { go m.deleteCertToken(name) }, nil + case "http-01": + resp, err := client.HTTP01ChallengeResponse(chal.Token) + if err != nil { + return nil, err + } + p := client.HTTP01ChallengePath(chal.Token) + m.putHTTPToken(ctx, p, resp) + return func() { go m.deleteHTTPToken(p) }, nil + } + return nil, fmt.Errorf("acme/autocert: unknown challenge type %q", chal.Type) +} + +func pickChallenge(typ string, chal []*acme.Challenge) *acme.Challenge { + for _, c := range chal { + if c.Type == typ { + return c + } + } + return nil +} + +// putCertToken stores the cert under the named key in both m.certTokens map +// and m.Cache. +func (m *Manager) putCertToken(ctx context.Context, name string, cert *tls.Certificate) { + m.tokensMu.Lock() + defer m.tokensMu.Unlock() + if m.certTokens == nil { + m.certTokens = make(map[string]*tls.Certificate) + } + m.certTokens[name] = cert + m.cachePut(ctx, name, cert) +} + +// deleteCertToken removes the token certificate for the specified domain name +// from both m.certTokens map and m.Cache. +func (m *Manager) deleteCertToken(name string) { + m.tokensMu.Lock() + defer m.tokensMu.Unlock() + delete(m.certTokens, name) + if m.Cache != nil { + m.Cache.Delete(context.Background(), name) + } +} + +// httpToken retrieves an existing http-01 token value from an in-memory map +// or the optional cache. +func (m *Manager) httpToken(ctx context.Context, tokenPath string) ([]byte, error) { + m.tokensMu.RLock() + defer m.tokensMu.RUnlock() + if v, ok := m.httpTokens[tokenPath]; ok { + return v, nil + } + if m.Cache == nil { + return nil, fmt.Errorf("acme/autocert: no token at %q", tokenPath) + } + return m.Cache.Get(ctx, httpTokenCacheKey(tokenPath)) +} + +// putHTTPToken stores an http-01 token value using tokenPath as key +// in both in-memory map and the optional Cache. +// +// It ignores any error returned from Cache.Put. +func (m *Manager) putHTTPToken(ctx context.Context, tokenPath, val string) { + m.tokensMu.Lock() + defer m.tokensMu.Unlock() + if m.httpTokens == nil { + m.httpTokens = make(map[string][]byte) + } + b := []byte(val) + m.httpTokens[tokenPath] = b + if m.Cache != nil { + m.Cache.Put(ctx, httpTokenCacheKey(tokenPath), b) + } +} + +// deleteHTTPToken removes an http-01 token value from both in-memory map +// and the optional Cache, ignoring any error returned from the latter. +// +// If m.Cache is non-nil, it blocks until Cache.Delete returns without a timeout. +func (m *Manager) deleteHTTPToken(tokenPath string) { + m.tokensMu.Lock() + defer m.tokensMu.Unlock() + delete(m.httpTokens, tokenPath) + if m.Cache != nil { + m.Cache.Delete(context.Background(), httpTokenCacheKey(tokenPath)) + } +} + +// httpTokenCacheKey returns a key at which an http-01 token value may be stored +// in the Manager's optional Cache. +func httpTokenCacheKey(tokenPath string) string { + return "http-01-" + path.Base(tokenPath) +} + +// renew starts a cert renewal timer loop, one per domain. +// +// The loop is scheduled in two cases: +// - a cert was fetched from cache for the first time (wasn't in m.state) +// - a new cert was created by m.createCert +// +// The key argument is a certificate private key. +// The exp argument is the cert expiration time (NotAfter). +func (m *Manager) renew(domain string, key crypto.Signer, exp time.Time) { + m.renewalMu.Lock() + defer m.renewalMu.Unlock() + if m.renewal[domain] != nil { + // another goroutine is already on it + return + } + if m.renewal == nil { + m.renewal = make(map[string]*domainRenewal) + } + dr := &domainRenewal{m: m, domain: domain, key: key} + m.renewal[domain] = dr + dr.start(exp) +} + +// stopRenew stops all currently running cert renewal timers. +// The timers are not restarted during the lifetime of the Manager. +func (m *Manager) stopRenew() { + m.renewalMu.Lock() + defer m.renewalMu.Unlock() + for name, dr := range m.renewal { + delete(m.renewal, name) + dr.stop() + } +} + +func (m *Manager) accountKey(ctx context.Context) (crypto.Signer, error) { + const keyName = "acme_account.key" + + genKey := func() (*ecdsa.PrivateKey, error) { + return ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + } + + if m.Cache == nil { + return genKey() + } + + data, err := m.Cache.Get(ctx, keyName) + if err == ErrCacheMiss { + key, err := genKey() + if err != nil { + return nil, err + } + var buf bytes.Buffer + if err := encodeECDSAKey(&buf, key); err != nil { + return nil, err + } + if err := m.Cache.Put(ctx, keyName, buf.Bytes()); err != nil { + return nil, err + } + return key, nil + } + if err != nil { + return nil, err + } + + priv, _ := pem.Decode(data) + if priv == nil || !strings.Contains(priv.Type, "PRIVATE") { + return nil, errors.New("acme/autocert: invalid account key found in cache") + } + return parsePrivateKey(priv.Bytes) +} + +func (m *Manager) acmeClient(ctx context.Context) (*acme.Client, error) { + m.clientMu.Lock() + defer m.clientMu.Unlock() + if m.client != nil { + return m.client, nil + } + + client := m.Client + if client == nil { + client = &acme.Client{DirectoryURL: acme.LetsEncryptURL} + } + if client.Key == nil { + var err error + client.Key, err = m.accountKey(ctx) + if err != nil { + return nil, err + } + } + var contact []string + if m.Email != "" { + contact = []string{"mailto:" + m.Email} + } + a := &acme.Account{Contact: contact} + _, err := client.Register(ctx, a, m.Prompt) + if ae, ok := err.(*acme.Error); err == nil || ok && ae.StatusCode == http.StatusConflict { + // conflict indicates the key is already registered + m.client = client + err = nil + } + return m.client, err +} + +func (m *Manager) hostPolicy() HostPolicy { + if m.HostPolicy != nil { + return m.HostPolicy + } + return defaultHostPolicy +} + +func (m *Manager) renewBefore() time.Duration { + if m.RenewBefore > renewJitter { + return m.RenewBefore + } + return 720 * time.Hour // 30 days +} + +// certState is ready when its mutex is unlocked for reading. +type certState struct { + sync.RWMutex + locked bool // locked for read/write + key crypto.Signer // private key for cert + cert [][]byte // DER encoding + leaf *x509.Certificate // parsed cert[0]; always non-nil if cert != nil +} + +// tlscert creates a tls.Certificate from s.key and s.cert. +// Callers should wrap it in s.RLock() and s.RUnlock(). +func (s *certState) tlscert() (*tls.Certificate, error) { + if s.key == nil { + return nil, errors.New("acme/autocert: missing signer") + } + if len(s.cert) == 0 { + return nil, errors.New("acme/autocert: missing certificate") + } + return &tls.Certificate{ + PrivateKey: s.key, + Certificate: s.cert, + Leaf: s.leaf, + }, nil +} + +// certRequest creates a certificate request for the given common name cn +// and optional SANs. +func certRequest(key crypto.Signer, cn string, san ...string) ([]byte, error) { + req := &x509.CertificateRequest{ + Subject: pkix.Name{CommonName: cn}, + DNSNames: san, + } + return x509.CreateCertificateRequest(rand.Reader, req, key) +} + +// Attempt to parse the given private key DER block. OpenSSL 0.9.8 generates +// PKCS#1 private keys by default, while OpenSSL 1.0.0 generates PKCS#8 keys. +// OpenSSL ecparam generates SEC1 EC private keys for ECDSA. We try all three. +// +// Inspired by parsePrivateKey in crypto/tls/tls.go. +func parsePrivateKey(der []byte) (crypto.Signer, error) { + if key, err := x509.ParsePKCS1PrivateKey(der); err == nil { + return key, nil + } + if key, err := x509.ParsePKCS8PrivateKey(der); err == nil { + switch key := key.(type) { + case *rsa.PrivateKey: + return key, nil + case *ecdsa.PrivateKey: + return key, nil + default: + return nil, errors.New("acme/autocert: unknown private key type in PKCS#8 wrapping") + } + } + if key, err := x509.ParseECPrivateKey(der); err == nil { + return key, nil + } + + return nil, errors.New("acme/autocert: failed to parse private key") +} + +// validCert parses a cert chain provided as der argument and verifies the leaf, der[0], +// corresponds to the private key, as well as the domain match and expiration dates. +// It doesn't do any revocation checking. +// +// The returned value is the verified leaf cert. +func validCert(domain string, der [][]byte, key crypto.Signer) (leaf *x509.Certificate, err error) { + // parse public part(s) + var n int + for _, b := range der { + n += len(b) + } + pub := make([]byte, n) + n = 0 + for _, b := range der { + n += copy(pub[n:], b) + } + x509Cert, err := x509.ParseCertificates(pub) + if len(x509Cert) == 0 { + return nil, errors.New("acme/autocert: no public key found") + } + // verify the leaf is not expired and matches the domain name + leaf = x509Cert[0] + now := timeNow() + if now.Before(leaf.NotBefore) { + return nil, errors.New("acme/autocert: certificate is not valid yet") + } + if now.After(leaf.NotAfter) { + return nil, errors.New("acme/autocert: expired certificate") + } + if err := leaf.VerifyHostname(domain); err != nil { + return nil, err + } + // ensure the leaf corresponds to the private key + switch pub := leaf.PublicKey.(type) { + case *rsa.PublicKey: + prv, ok := key.(*rsa.PrivateKey) + if !ok { + return nil, errors.New("acme/autocert: private key type does not match public key type") + } + if pub.N.Cmp(prv.N) != 0 { + return nil, errors.New("acme/autocert: private key does not match public key") + } + case *ecdsa.PublicKey: + prv, ok := key.(*ecdsa.PrivateKey) + if !ok { + return nil, errors.New("acme/autocert: private key type does not match public key type") + } + if pub.X.Cmp(prv.X) != 0 || pub.Y.Cmp(prv.Y) != 0 { + return nil, errors.New("acme/autocert: private key does not match public key") + } + default: + return nil, errors.New("acme/autocert: unknown public key algorithm") + } + return leaf, nil +} + +func retryAfter(v string) time.Duration { + if i, err := strconv.Atoi(v); err == nil { + return time.Duration(i) * time.Second + } + if t, err := http.ParseTime(v); err == nil { + return t.Sub(timeNow()) + } + return time.Second +} + +type lockedMathRand struct { + sync.Mutex + rnd *mathrand.Rand +} + +func (r *lockedMathRand) int63n(max int64) int64 { + r.Lock() + n := r.rnd.Int63n(max) + r.Unlock() + return n +} + +// For easier testing. +var ( + timeNow = time.Now + + // Called when a state is removed. + testDidRemoveState = func(domain string) {} +) diff --git a/vendor/golang.org/x/crypto/acme/autocert/autocert_test.go b/vendor/golang.org/x/crypto/acme/autocert/autocert_test.go new file mode 100644 index 0000000000000000000000000000000000000000..2da1912e9696e3f44c47dccaff7c8eab449c7984 --- /dev/null +++ b/vendor/golang.org/x/crypto/acme/autocert/autocert_test.go @@ -0,0 +1,757 @@ +// Copyright 2016 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 autocert + +import ( + "context" + "crypto" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/rsa" + "crypto/tls" + "crypto/x509" + "crypto/x509/pkix" + "encoding/base64" + "encoding/json" + "fmt" + "html/template" + "io" + "math/big" + "net/http" + "net/http/httptest" + "reflect" + "strings" + "sync" + "testing" + "time" + + "golang.org/x/crypto/acme" +) + +var discoTmpl = template.Must(template.New("disco").Parse(`{ + "new-reg": "{{.}}/new-reg", + "new-authz": "{{.}}/new-authz", + "new-cert": "{{.}}/new-cert" +}`)) + +var authzTmpl = template.Must(template.New("authz").Parse(`{ + "status": "pending", + "challenges": [ + { + "uri": "{{.}}/challenge/1", + "type": "tls-sni-01", + "token": "token-01" + }, + { + "uri": "{{.}}/challenge/2", + "type": "tls-sni-02", + "token": "token-02" + }, + { + "uri": "{{.}}/challenge/dns-01", + "type": "dns-01", + "token": "token-dns-01" + }, + { + "uri": "{{.}}/challenge/http-01", + "type": "http-01", + "token": "token-http-01" + } + ] +}`)) + +type memCache struct { + mu sync.Mutex + keyData map[string][]byte +} + +func (m *memCache) Get(ctx context.Context, key string) ([]byte, error) { + m.mu.Lock() + defer m.mu.Unlock() + + v, ok := m.keyData[key] + if !ok { + return nil, ErrCacheMiss + } + return v, nil +} + +func (m *memCache) Put(ctx context.Context, key string, data []byte) error { + m.mu.Lock() + defer m.mu.Unlock() + + m.keyData[key] = data + return nil +} + +func (m *memCache) Delete(ctx context.Context, key string) error { + m.mu.Lock() + defer m.mu.Unlock() + + delete(m.keyData, key) + return nil +} + +func newMemCache() *memCache { + return &memCache{ + keyData: make(map[string][]byte), + } +} + +func dummyCert(pub interface{}, san ...string) ([]byte, error) { + return dateDummyCert(pub, time.Now(), time.Now().Add(90*24*time.Hour), san...) +} + +func dateDummyCert(pub interface{}, start, end time.Time, san ...string) ([]byte, error) { + // use EC key to run faster on 386 + key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + return nil, err + } + t := &x509.Certificate{ + SerialNumber: big.NewInt(1), + NotBefore: start, + NotAfter: end, + BasicConstraintsValid: true, + KeyUsage: x509.KeyUsageKeyEncipherment, + DNSNames: san, + } + if pub == nil { + pub = &key.PublicKey + } + return x509.CreateCertificate(rand.Reader, t, t, pub, key) +} + +func decodePayload(v interface{}, r io.Reader) error { + var req struct{ Payload string } + if err := json.NewDecoder(r).Decode(&req); err != nil { + return err + } + payload, err := base64.RawURLEncoding.DecodeString(req.Payload) + if err != nil { + return err + } + return json.Unmarshal(payload, v) +} + +func TestGetCertificate(t *testing.T) { + man := &Manager{Prompt: AcceptTOS} + defer man.stopRenew() + hello := &tls.ClientHelloInfo{ServerName: "example.org"} + testGetCertificate(t, man, "example.org", hello) +} + +func TestGetCertificate_trailingDot(t *testing.T) { + man := &Manager{Prompt: AcceptTOS} + defer man.stopRenew() + hello := &tls.ClientHelloInfo{ServerName: "example.org."} + testGetCertificate(t, man, "example.org", hello) +} + +func TestGetCertificate_ForceRSA(t *testing.T) { + man := &Manager{ + Prompt: AcceptTOS, + Cache: newMemCache(), + ForceRSA: true, + } + defer man.stopRenew() + hello := &tls.ClientHelloInfo{ServerName: "example.org"} + testGetCertificate(t, man, "example.org", hello) + + cert, err := man.cacheGet(context.Background(), "example.org") + if err != nil { + t.Fatalf("man.cacheGet: %v", err) + } + if _, ok := cert.PrivateKey.(*rsa.PrivateKey); !ok { + t.Errorf("cert.PrivateKey is %T; want *rsa.PrivateKey", cert.PrivateKey) + } +} + +func TestGetCertificate_nilPrompt(t *testing.T) { + man := &Manager{} + defer man.stopRenew() + url, finish := startACMEServerStub(t, man, "example.org") + defer finish() + key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + t.Fatal(err) + } + man.Client = &acme.Client{ + Key: key, + DirectoryURL: url, + } + hello := &tls.ClientHelloInfo{ServerName: "example.org"} + if _, err := man.GetCertificate(hello); err == nil { + t.Error("got certificate for example.org; wanted error") + } +} + +func TestGetCertificate_expiredCache(t *testing.T) { + // Make an expired cert and cache it. + pk, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + t.Fatal(err) + } + tmpl := &x509.Certificate{ + SerialNumber: big.NewInt(1), + Subject: pkix.Name{CommonName: "example.org"}, + NotAfter: time.Now(), + } + pub, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &pk.PublicKey, pk) + if err != nil { + t.Fatal(err) + } + tlscert := &tls.Certificate{ + Certificate: [][]byte{pub}, + PrivateKey: pk, + } + + man := &Manager{Prompt: AcceptTOS, Cache: newMemCache()} + defer man.stopRenew() + if err := man.cachePut(context.Background(), "example.org", tlscert); err != nil { + t.Fatalf("man.cachePut: %v", err) + } + + // The expired cached cert should trigger a new cert issuance + // and return without an error. + hello := &tls.ClientHelloInfo{ServerName: "example.org"} + testGetCertificate(t, man, "example.org", hello) +} + +func TestGetCertificate_failedAttempt(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusBadRequest) + })) + defer ts.Close() + + const example = "example.org" + d := createCertRetryAfter + f := testDidRemoveState + defer func() { + createCertRetryAfter = d + testDidRemoveState = f + }() + createCertRetryAfter = 0 + done := make(chan struct{}) + testDidRemoveState = func(domain string) { + if domain != example { + t.Errorf("testDidRemoveState: domain = %q; want %q", domain, example) + } + close(done) + } + + key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + t.Fatal(err) + } + man := &Manager{ + Prompt: AcceptTOS, + Client: &acme.Client{ + Key: key, + DirectoryURL: ts.URL, + }, + } + defer man.stopRenew() + hello := &tls.ClientHelloInfo{ServerName: example} + if _, err := man.GetCertificate(hello); err == nil { + t.Error("GetCertificate: err is nil") + } + select { + case <-time.After(5 * time.Second): + t.Errorf("took too long to remove the %q state", example) + case <-done: + man.stateMu.Lock() + defer man.stateMu.Unlock() + if v, exist := man.state[example]; exist { + t.Errorf("state exists for %q: %+v", example, v) + } + } +} + +// startACMEServerStub runs an ACME server +// The domain argument is the expected domain name of a certificate request. +func startACMEServerStub(t *testing.T, man *Manager, domain string) (url string, finish func()) { + // echo token-02 | shasum -a 256 + // then divide result in 2 parts separated by dot + tokenCertName := "4e8eb87631187e9ff2153b56b13a4dec.13a35d002e485d60ff37354b32f665d9.token.acme.invalid" + verifyTokenCert := func() { + hello := &tls.ClientHelloInfo{ServerName: tokenCertName} + _, err := man.GetCertificate(hello) + if err != nil { + t.Errorf("verifyTokenCert: GetCertificate(%q): %v", tokenCertName, err) + return + } + } + + // ACME CA server stub + var ca *httptest.Server + ca = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Replay-Nonce", "nonce") + if r.Method == "HEAD" { + // a nonce request + return + } + + switch r.URL.Path { + // discovery + case "/": + if err := discoTmpl.Execute(w, ca.URL); err != nil { + t.Errorf("discoTmpl: %v", err) + } + // client key registration + case "/new-reg": + w.Write([]byte("{}")) + // domain authorization + case "/new-authz": + w.Header().Set("Location", ca.URL+"/authz/1") + w.WriteHeader(http.StatusCreated) + if err := authzTmpl.Execute(w, ca.URL); err != nil { + t.Errorf("authzTmpl: %v", err) + } + // accept tls-sni-02 challenge + case "/challenge/2": + verifyTokenCert() + w.Write([]byte("{}")) + // authorization status + case "/authz/1": + w.Write([]byte(`{"status": "valid"}`)) + // cert request + case "/new-cert": + var req struct { + CSR string `json:"csr"` + } + decodePayload(&req, r.Body) + b, _ := base64.RawURLEncoding.DecodeString(req.CSR) + csr, err := x509.ParseCertificateRequest(b) + if err != nil { + t.Errorf("new-cert: CSR: %v", err) + } + if csr.Subject.CommonName != domain { + t.Errorf("CommonName in CSR = %q; want %q", csr.Subject.CommonName, domain) + } + der, err := dummyCert(csr.PublicKey, domain) + if err != nil { + t.Errorf("new-cert: dummyCert: %v", err) + } + chainUp := fmt.Sprintf("<%s/ca-cert>; rel=up", ca.URL) + w.Header().Set("Link", chainUp) + w.WriteHeader(http.StatusCreated) + w.Write(der) + // CA chain cert + case "/ca-cert": + der, err := dummyCert(nil, "ca") + if err != nil { + t.Errorf("ca-cert: dummyCert: %v", err) + } + w.Write(der) + default: + t.Errorf("unrecognized r.URL.Path: %s", r.URL.Path) + } + })) + finish = func() { + ca.Close() + + // make sure token cert was removed + cancel := make(chan struct{}) + done := make(chan struct{}) + go func() { + defer close(done) + tick := time.NewTicker(100 * time.Millisecond) + defer tick.Stop() + for { + hello := &tls.ClientHelloInfo{ServerName: tokenCertName} + if _, err := man.GetCertificate(hello); err != nil { + return + } + select { + case <-tick.C: + case <-cancel: + return + } + } + }() + select { + case <-done: + case <-time.After(5 * time.Second): + close(cancel) + t.Error("token cert was not removed") + <-done + } + } + return ca.URL, finish +} + +// tests man.GetCertificate flow using the provided hello argument. +// The domain argument is the expected domain name of a certificate request. +func testGetCertificate(t *testing.T, man *Manager, domain string, hello *tls.ClientHelloInfo) { + url, finish := startACMEServerStub(t, man, domain) + defer finish() + + // use EC key to run faster on 386 + key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + t.Fatal(err) + } + man.Client = &acme.Client{ + Key: key, + DirectoryURL: url, + } + + // simulate tls.Config.GetCertificate + var tlscert *tls.Certificate + done := make(chan struct{}) + go func() { + tlscert, err = man.GetCertificate(hello) + close(done) + }() + select { + case <-time.After(time.Minute): + t.Fatal("man.GetCertificate took too long to return") + case <-done: + } + if err != nil { + t.Fatalf("man.GetCertificate: %v", err) + } + + // verify the tlscert is the same we responded with from the CA stub + if len(tlscert.Certificate) == 0 { + t.Fatal("len(tlscert.Certificate) is 0") + } + cert, err := x509.ParseCertificate(tlscert.Certificate[0]) + if err != nil { + t.Fatalf("x509.ParseCertificate: %v", err) + } + if len(cert.DNSNames) == 0 || cert.DNSNames[0] != domain { + t.Errorf("cert.DNSNames = %v; want %q", cert.DNSNames, domain) + } + +} + +func TestVerifyHTTP01(t *testing.T) { + var ( + http01 http.Handler + + authzCount int // num. of created authorizations + didAcceptHTTP01 bool + ) + + verifyHTTPToken := func() { + r := httptest.NewRequest("GET", "/.well-known/acme-challenge/token-http-01", nil) + w := httptest.NewRecorder() + http01.ServeHTTP(w, r) + if w.Code != http.StatusOK { + t.Errorf("http token: w.Code = %d; want %d", w.Code, http.StatusOK) + } + if v := string(w.Body.Bytes()); !strings.HasPrefix(v, "token-http-01.") { + t.Errorf("http token value = %q; want 'token-http-01.' prefix", v) + } + } + + // ACME CA server stub, only the needed bits. + // TODO: Merge this with startACMEServerStub, making it a configurable CA for testing. + var ca *httptest.Server + ca = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Replay-Nonce", "nonce") + if r.Method == "HEAD" { + // a nonce request + return + } + + switch r.URL.Path { + // Discovery. + case "/": + if err := discoTmpl.Execute(w, ca.URL); err != nil { + t.Errorf("discoTmpl: %v", err) + } + // Client key registration. + case "/new-reg": + w.Write([]byte("{}")) + // New domain authorization. + case "/new-authz": + authzCount++ + w.Header().Set("Location", fmt.Sprintf("%s/authz/%d", ca.URL, authzCount)) + w.WriteHeader(http.StatusCreated) + if err := authzTmpl.Execute(w, ca.URL); err != nil { + t.Errorf("authzTmpl: %v", err) + } + // Accept tls-sni-02. + case "/challenge/2": + w.Write([]byte("{}")) + // Reject tls-sni-01. + case "/challenge/1": + http.Error(w, "won't accept tls-sni-01", http.StatusBadRequest) + // Should not accept dns-01. + case "/challenge/dns-01": + t.Errorf("dns-01 challenge was accepted") + http.Error(w, "won't accept dns-01", http.StatusBadRequest) + // Accept http-01. + case "/challenge/http-01": + didAcceptHTTP01 = true + verifyHTTPToken() + w.Write([]byte("{}")) + // Authorization statuses. + // Make tls-sni-xxx invalid. + case "/authz/1", "/authz/2": + w.Write([]byte(`{"status": "invalid"}`)) + case "/authz/3", "/authz/4": + w.Write([]byte(`{"status": "valid"}`)) + default: + http.NotFound(w, r) + t.Errorf("unrecognized r.URL.Path: %s", r.URL.Path) + } + })) + defer ca.Close() + + key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + t.Fatal(err) + } + m := &Manager{ + Client: &acme.Client{ + Key: key, + DirectoryURL: ca.URL, + }, + } + http01 = m.HTTPHandler(nil) + if err := m.verify(context.Background(), m.Client, "example.org"); err != nil { + t.Errorf("m.verify: %v", err) + } + // Only tls-sni-01, tls-sni-02 and http-01 must be accepted + // The dns-01 challenge is unsupported. + if authzCount != 3 { + t.Errorf("authzCount = %d; want 3", authzCount) + } + if !didAcceptHTTP01 { + t.Error("did not accept http-01 challenge") + } +} + +func TestHTTPHandlerDefaultFallback(t *testing.T) { + tt := []struct { + method, url string + wantCode int + wantLocation string + }{ + {"GET", "http://example.org", 302, "https://example.org/"}, + {"GET", "http://example.org/foo", 302, "https://example.org/foo"}, + {"GET", "http://example.org/foo/bar/", 302, "https://example.org/foo/bar/"}, + {"GET", "http://example.org/?a=b", 302, "https://example.org/?a=b"}, + {"GET", "http://example.org/foo?a=b", 302, "https://example.org/foo?a=b"}, + {"GET", "http://example.org:80/foo?a=b", 302, "https://example.org:443/foo?a=b"}, + {"GET", "http://example.org:80/foo%20bar", 302, "https://example.org:443/foo%20bar"}, + {"GET", "http://[2602:d1:xxxx::c60a]:1234", 302, "https://[2602:d1:xxxx::c60a]:443/"}, + {"GET", "http://[2602:d1:xxxx::c60a]", 302, "https://[2602:d1:xxxx::c60a]/"}, + {"GET", "http://[2602:d1:xxxx::c60a]/foo?a=b", 302, "https://[2602:d1:xxxx::c60a]/foo?a=b"}, + {"HEAD", "http://example.org", 302, "https://example.org/"}, + {"HEAD", "http://example.org/foo", 302, "https://example.org/foo"}, + {"HEAD", "http://example.org/foo/bar/", 302, "https://example.org/foo/bar/"}, + {"HEAD", "http://example.org/?a=b", 302, "https://example.org/?a=b"}, + {"HEAD", "http://example.org/foo?a=b", 302, "https://example.org/foo?a=b"}, + {"POST", "http://example.org", 400, ""}, + {"PUT", "http://example.org", 400, ""}, + {"GET", "http://example.org/.well-known/acme-challenge/x", 404, ""}, + } + var m Manager + h := m.HTTPHandler(nil) + for i, test := range tt { + r := httptest.NewRequest(test.method, test.url, nil) + w := httptest.NewRecorder() + h.ServeHTTP(w, r) + if w.Code != test.wantCode { + t.Errorf("%d: w.Code = %d; want %d", i, w.Code, test.wantCode) + t.Errorf("%d: body: %s", i, w.Body.Bytes()) + } + if v := w.Header().Get("Location"); v != test.wantLocation { + t.Errorf("%d: Location = %q; want %q", i, v, test.wantLocation) + } + } +} + +func TestAccountKeyCache(t *testing.T) { + m := Manager{Cache: newMemCache()} + ctx := context.Background() + k1, err := m.accountKey(ctx) + if err != nil { + t.Fatal(err) + } + k2, err := m.accountKey(ctx) + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(k1, k2) { + t.Errorf("account keys don't match: k1 = %#v; k2 = %#v", k1, k2) + } +} + +func TestCache(t *testing.T) { + privKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + t.Fatal(err) + } + tmpl := &x509.Certificate{ + SerialNumber: big.NewInt(1), + Subject: pkix.Name{CommonName: "example.org"}, + NotAfter: time.Now().Add(time.Hour), + } + pub, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &privKey.PublicKey, privKey) + if err != nil { + t.Fatal(err) + } + tlscert := &tls.Certificate{ + Certificate: [][]byte{pub}, + PrivateKey: privKey, + } + + man := &Manager{Cache: newMemCache()} + defer man.stopRenew() + ctx := context.Background() + if err := man.cachePut(ctx, "example.org", tlscert); err != nil { + t.Fatalf("man.cachePut: %v", err) + } + res, err := man.cacheGet(ctx, "example.org") + if err != nil { + t.Fatalf("man.cacheGet: %v", err) + } + if res == nil { + t.Fatal("res is nil") + } +} + +func TestHostWhitelist(t *testing.T) { + policy := HostWhitelist("example.com", "example.org", "*.example.net") + tt := []struct { + host string + allow bool + }{ + {"example.com", true}, + {"example.org", true}, + {"one.example.com", false}, + {"two.example.org", false}, + {"three.example.net", false}, + {"dummy", false}, + } + for i, test := range tt { + err := policy(nil, test.host) + if err != nil && test.allow { + t.Errorf("%d: policy(%q): %v; want nil", i, test.host, err) + } + if err == nil && !test.allow { + t.Errorf("%d: policy(%q): nil; want an error", i, test.host) + } + } +} + +func TestValidCert(t *testing.T) { + key1, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + t.Fatal(err) + } + key2, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + t.Fatal(err) + } + key3, err := rsa.GenerateKey(rand.Reader, 512) + if err != nil { + t.Fatal(err) + } + cert1, err := dummyCert(key1.Public(), "example.org") + if err != nil { + t.Fatal(err) + } + cert2, err := dummyCert(key2.Public(), "example.org") + if err != nil { + t.Fatal(err) + } + cert3, err := dummyCert(key3.Public(), "example.org") + if err != nil { + t.Fatal(err) + } + now := time.Now() + early, err := dateDummyCert(key1.Public(), now.Add(time.Hour), now.Add(2*time.Hour), "example.org") + if err != nil { + t.Fatal(err) + } + expired, err := dateDummyCert(key1.Public(), now.Add(-2*time.Hour), now.Add(-time.Hour), "example.org") + if err != nil { + t.Fatal(err) + } + + tt := []struct { + domain string + key crypto.Signer + cert [][]byte + ok bool + }{ + {"example.org", key1, [][]byte{cert1}, true}, + {"example.org", key3, [][]byte{cert3}, true}, + {"example.org", key1, [][]byte{cert1, cert2, cert3}, true}, + {"example.org", key1, [][]byte{cert1, {1}}, false}, + {"example.org", key1, [][]byte{{1}}, false}, + {"example.org", key1, [][]byte{cert2}, false}, + {"example.org", key2, [][]byte{cert1}, false}, + {"example.org", key1, [][]byte{cert3}, false}, + {"example.org", key3, [][]byte{cert1}, false}, + {"example.net", key1, [][]byte{cert1}, false}, + {"example.org", key1, [][]byte{early}, false}, + {"example.org", key1, [][]byte{expired}, false}, + } + for i, test := range tt { + leaf, err := validCert(test.domain, test.cert, test.key) + if err != nil && test.ok { + t.Errorf("%d: err = %v", i, err) + } + if err == nil && !test.ok { + t.Errorf("%d: err is nil", i) + } + if err == nil && test.ok && leaf == nil { + t.Errorf("%d: leaf is nil", i) + } + } +} + +type cacheGetFunc func(ctx context.Context, key string) ([]byte, error) + +func (f cacheGetFunc) Get(ctx context.Context, key string) ([]byte, error) { + return f(ctx, key) +} + +func (f cacheGetFunc) Put(ctx context.Context, key string, data []byte) error { + return fmt.Errorf("unsupported Put of %q = %q", key, data) +} + +func (f cacheGetFunc) Delete(ctx context.Context, key string) error { + return fmt.Errorf("unsupported Delete of %q", key) +} + +func TestManagerGetCertificateBogusSNI(t *testing.T) { + m := Manager{ + Prompt: AcceptTOS, + Cache: cacheGetFunc(func(ctx context.Context, key string) ([]byte, error) { + return nil, fmt.Errorf("cache.Get of %s", key) + }), + } + tests := []struct { + name string + wantErr string + }{ + {"foo.com", "cache.Get of foo.com"}, + {"foo.com.", "cache.Get of foo.com"}, + {`a\b.com`, "acme/autocert: server name contains invalid character"}, + {`a/b.com`, "acme/autocert: server name contains invalid character"}, + {"", "acme/autocert: missing server name"}, + {"foo", "acme/autocert: server name component count invalid"}, + {".foo", "acme/autocert: server name component count invalid"}, + {"foo.", "acme/autocert: server name component count invalid"}, + {"fo.o", "cache.Get of fo.o"}, + } + for _, tt := range tests { + _, err := m.GetCertificate(&tls.ClientHelloInfo{ServerName: tt.name}) + got := fmt.Sprint(err) + if got != tt.wantErr { + t.Errorf("GetCertificate(SNI = %q) = %q; want %q", tt.name, got, tt.wantErr) + } + } +} diff --git a/vendor/golang.org/x/crypto/acme/autocert/cache.go b/vendor/golang.org/x/crypto/acme/autocert/cache.go new file mode 100644 index 0000000000000000000000000000000000000000..61a5fd239a80208244c06aa8b283e615d1641c04 --- /dev/null +++ b/vendor/golang.org/x/crypto/acme/autocert/cache.go @@ -0,0 +1,130 @@ +// Copyright 2016 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 autocert + +import ( + "context" + "errors" + "io/ioutil" + "os" + "path/filepath" +) + +// ErrCacheMiss is returned when a certificate is not found in cache. +var ErrCacheMiss = errors.New("acme/autocert: certificate cache miss") + +// Cache is used by Manager to store and retrieve previously obtained certificates +// as opaque data. +// +// The key argument of the methods refers to a domain name but need not be an FQDN. +// Cache implementations should not rely on the key naming pattern. +type Cache interface { + // Get returns a certificate data for the specified key. + // If there's no such key, Get returns ErrCacheMiss. + Get(ctx context.Context, key string) ([]byte, error) + + // Put stores the data in the cache under the specified key. + // Underlying implementations may use any data storage format, + // as long as the reverse operation, Get, results in the original data. + Put(ctx context.Context, key string, data []byte) error + + // Delete removes a certificate data from the cache under the specified key. + // If there's no such key in the cache, Delete returns nil. + Delete(ctx context.Context, key string) error +} + +// DirCache implements Cache using a directory on the local filesystem. +// If the directory does not exist, it will be created with 0700 permissions. +type DirCache string + +// Get reads a certificate data from the specified file name. +func (d DirCache) Get(ctx context.Context, name string) ([]byte, error) { + name = filepath.Join(string(d), name) + var ( + data []byte + err error + done = make(chan struct{}) + ) + go func() { + data, err = ioutil.ReadFile(name) + close(done) + }() + select { + case <-ctx.Done(): + return nil, ctx.Err() + case <-done: + } + if os.IsNotExist(err) { + return nil, ErrCacheMiss + } + return data, err +} + +// Put writes the certificate data to the specified file name. +// The file will be created with 0600 permissions. +func (d DirCache) Put(ctx context.Context, name string, data []byte) error { + if err := os.MkdirAll(string(d), 0700); err != nil { + return err + } + + done := make(chan struct{}) + var err error + go func() { + defer close(done) + var tmp string + if tmp, err = d.writeTempFile(name, data); err != nil { + return + } + select { + case <-ctx.Done(): + // Don't overwrite the file if the context was canceled. + default: + newName := filepath.Join(string(d), name) + err = os.Rename(tmp, newName) + } + }() + select { + case <-ctx.Done(): + return ctx.Err() + case <-done: + } + return err +} + +// Delete removes the specified file name. +func (d DirCache) Delete(ctx context.Context, name string) error { + name = filepath.Join(string(d), name) + var ( + err error + done = make(chan struct{}) + ) + go func() { + err = os.Remove(name) + close(done) + }() + select { + case <-ctx.Done(): + return ctx.Err() + case <-done: + } + if err != nil && !os.IsNotExist(err) { + return err + } + return nil +} + +// writeTempFile writes b to a temporary file, closes the file and returns its path. +func (d DirCache) writeTempFile(prefix string, b []byte) (string, error) { + // TempFile uses 0600 permissions + f, err := ioutil.TempFile(string(d), prefix) + if err != nil { + return "", err + } + if _, err := f.Write(b); err != nil { + f.Close() + return "", err + } + return f.Name(), f.Close() +} diff --git a/vendor/golang.org/x/crypto/acme/autocert/cache_test.go b/vendor/golang.org/x/crypto/acme/autocert/cache_test.go new file mode 100644 index 0000000000000000000000000000000000000000..653b05bed037a020f61df9e2a61d1587e8f24171 --- /dev/null +++ b/vendor/golang.org/x/crypto/acme/autocert/cache_test.go @@ -0,0 +1,58 @@ +// Copyright 2016 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 autocert + +import ( + "context" + "io/ioutil" + "os" + "path/filepath" + "reflect" + "testing" +) + +// make sure DirCache satisfies Cache interface +var _ Cache = DirCache("/") + +func TestDirCache(t *testing.T) { + dir, err := ioutil.TempDir("", "autocert") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + dir = filepath.Join(dir, "certs") // a nonexistent dir + cache := DirCache(dir) + ctx := context.Background() + + // test cache miss + if _, err := cache.Get(ctx, "nonexistent"); err != ErrCacheMiss { + t.Errorf("get: %v; want ErrCacheMiss", err) + } + + // test put/get + b1 := []byte{1} + if err := cache.Put(ctx, "dummy", b1); err != nil { + t.Fatalf("put: %v", err) + } + b2, err := cache.Get(ctx, "dummy") + if err != nil { + t.Fatalf("get: %v", err) + } + if !reflect.DeepEqual(b1, b2) { + t.Errorf("b1 = %v; want %v", b1, b2) + } + name := filepath.Join(dir, "dummy") + if _, err := os.Stat(name); err != nil { + t.Error(err) + } + + // test delete + if err := cache.Delete(ctx, "dummy"); err != nil { + t.Fatalf("delete: %v", err) + } + if _, err := cache.Get(ctx, "dummy"); err != ErrCacheMiss { + t.Errorf("get: %v; want ErrCacheMiss", err) + } +} diff --git a/vendor/golang.org/x/crypto/acme/autocert/example_test.go b/vendor/golang.org/x/crypto/acme/autocert/example_test.go new file mode 100644 index 0000000000000000000000000000000000000000..552a62549c4ee17d3891482c9719bf2f3ffe75bd --- /dev/null +++ b/vendor/golang.org/x/crypto/acme/autocert/example_test.go @@ -0,0 +1,36 @@ +// Copyright 2017 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 autocert_test + +import ( + "crypto/tls" + "fmt" + "log" + "net/http" + + "golang.org/x/crypto/acme/autocert" +) + +func ExampleNewListener() { + mux := http.NewServeMux() + mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + fmt.Fprintf(w, "Hello, TLS user! Your config: %+v", r.TLS) + }) + log.Fatal(http.Serve(autocert.NewListener("example.com"), mux)) +} + +func ExampleManager() { + m := &autocert.Manager{ + Cache: autocert.DirCache("secret-dir"), + Prompt: autocert.AcceptTOS, + HostPolicy: autocert.HostWhitelist("example.org"), + } + go http.ListenAndServe(":http", m.HTTPHandler(nil)) + s := &http.Server{ + Addr: ":https", + TLSConfig: &tls.Config{GetCertificate: m.GetCertificate}, + } + s.ListenAndServeTLS("", "") +} diff --git a/vendor/golang.org/x/crypto/acme/autocert/listener.go b/vendor/golang.org/x/crypto/acme/autocert/listener.go new file mode 100644 index 0000000000000000000000000000000000000000..d744df0ed04b802612fc7aa933f75d75fc56f228 --- /dev/null +++ b/vendor/golang.org/x/crypto/acme/autocert/listener.go @@ -0,0 +1,160 @@ +// Copyright 2017 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 autocert + +import ( + "crypto/tls" + "log" + "net" + "os" + "path/filepath" + "runtime" + "time" +) + +// NewListener returns a net.Listener that listens on the standard TLS +// port (443) on all interfaces and returns *tls.Conn connections with +// LetsEncrypt certificates for the provided domain or domains. +// +// It enables one-line HTTPS servers: +// +// log.Fatal(http.Serve(autocert.NewListener("example.com"), handler)) +// +// NewListener is a convenience function for a common configuration. +// More complex or custom configurations can use the autocert.Manager +// type instead. +// +// Use of this function implies acceptance of the LetsEncrypt Terms of +// Service. If domains is not empty, the provided domains are passed +// to HostWhitelist. If domains is empty, the listener will do +// LetsEncrypt challenges for any requested domain, which is not +// recommended. +// +// Certificates are cached in a "golang-autocert" directory under an +// operating system-specific cache or temp directory. This may not +// be suitable for servers spanning multiple machines. +// +// The returned listener uses a *tls.Config that enables HTTP/2, and +// should only be used with servers that support HTTP/2. +// +// The returned Listener also enables TCP keep-alives on the accepted +// connections. The returned *tls.Conn are returned before their TLS +// handshake has completed. +func NewListener(domains ...string) net.Listener { + m := &Manager{ + Prompt: AcceptTOS, + } + if len(domains) > 0 { + m.HostPolicy = HostWhitelist(domains...) + } + dir := cacheDir() + if err := os.MkdirAll(dir, 0700); err != nil { + log.Printf("warning: autocert.NewListener not using a cache: %v", err) + } else { + m.Cache = DirCache(dir) + } + return m.Listener() +} + +// Listener listens on the standard TLS port (443) on all interfaces +// and returns a net.Listener returning *tls.Conn connections. +// +// The returned listener uses a *tls.Config that enables HTTP/2, and +// should only be used with servers that support HTTP/2. +// +// The returned Listener also enables TCP keep-alives on the accepted +// connections. The returned *tls.Conn are returned before their TLS +// handshake has completed. +// +// Unlike NewListener, it is the caller's responsibility to initialize +// the Manager m's Prompt, Cache, HostPolicy, and other desired options. +func (m *Manager) Listener() net.Listener { + ln := &listener{ + m: m, + conf: &tls.Config{ + GetCertificate: m.GetCertificate, // bonus: panic on nil m + NextProtos: []string{"h2", "http/1.1"}, // Enable HTTP/2 + }, + } + ln.tcpListener, ln.tcpListenErr = net.Listen("tcp", ":443") + return ln +} + +type listener struct { + m *Manager + conf *tls.Config + + tcpListener net.Listener + tcpListenErr error +} + +func (ln *listener) Accept() (net.Conn, error) { + if ln.tcpListenErr != nil { + return nil, ln.tcpListenErr + } + conn, err := ln.tcpListener.Accept() + if err != nil { + return nil, err + } + tcpConn := conn.(*net.TCPConn) + + // Because Listener is a convenience function, help out with + // this too. This is not possible for the caller to set once + // we return a *tcp.Conn wrapping an inaccessible net.Conn. + // If callers don't want this, they can do things the manual + // way and tweak as needed. But this is what net/http does + // itself, so copy that. If net/http changes, we can change + // here too. + tcpConn.SetKeepAlive(true) + tcpConn.SetKeepAlivePeriod(3 * time.Minute) + + return tls.Server(tcpConn, ln.conf), nil +} + +func (ln *listener) Addr() net.Addr { + if ln.tcpListener != nil { + return ln.tcpListener.Addr() + } + // net.Listen failed. Return something non-nil in case callers + // call Addr before Accept: + return &net.TCPAddr{IP: net.IP{0, 0, 0, 0}, Port: 443} +} + +func (ln *listener) Close() error { + if ln.tcpListenErr != nil { + return ln.tcpListenErr + } + return ln.tcpListener.Close() +} + +func homeDir() string { + if runtime.GOOS == "windows" { + return os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH") + } + if h := os.Getenv("HOME"); h != "" { + return h + } + return "/" +} + +func cacheDir() string { + const base = "golang-autocert" + switch runtime.GOOS { + case "darwin": + return filepath.Join(homeDir(), "Library", "Caches", base) + case "windows": + for _, ev := range []string{"APPDATA", "CSIDL_APPDATA", "TEMP", "TMP"} { + if v := os.Getenv(ev); v != "" { + return filepath.Join(v, base) + } + } + // Worst case: + return filepath.Join(homeDir(), base) + } + if xdg := os.Getenv("XDG_CACHE_HOME"); xdg != "" { + return filepath.Join(xdg, base) + } + return filepath.Join(homeDir(), ".cache", base) +} diff --git a/vendor/golang.org/x/crypto/acme/autocert/renewal.go b/vendor/golang.org/x/crypto/acme/autocert/renewal.go new file mode 100644 index 0000000000000000000000000000000000000000..6c5da2bc8c8c14152cba13a2239cc69c44aa3333 --- /dev/null +++ b/vendor/golang.org/x/crypto/acme/autocert/renewal.go @@ -0,0 +1,124 @@ +// Copyright 2016 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 autocert + +import ( + "context" + "crypto" + "sync" + "time" +) + +// renewJitter is the maximum deviation from Manager.RenewBefore. +const renewJitter = time.Hour + +// domainRenewal tracks the state used by the periodic timers +// renewing a single domain's cert. +type domainRenewal struct { + m *Manager + domain string + key crypto.Signer + + timerMu sync.Mutex + timer *time.Timer +} + +// start starts a cert renewal timer at the time +// defined by the certificate expiration time exp. +// +// If the timer is already started, calling start is a noop. +func (dr *domainRenewal) start(exp time.Time) { + dr.timerMu.Lock() + defer dr.timerMu.Unlock() + if dr.timer != nil { + return + } + dr.timer = time.AfterFunc(dr.next(exp), dr.renew) +} + +// stop stops the cert renewal timer. +// If the timer is already stopped, calling stop is a noop. +func (dr *domainRenewal) stop() { + dr.timerMu.Lock() + defer dr.timerMu.Unlock() + if dr.timer == nil { + return + } + dr.timer.Stop() + dr.timer = nil +} + +// renew is called periodically by a timer. +// The first renew call is kicked off by dr.start. +func (dr *domainRenewal) renew() { + dr.timerMu.Lock() + defer dr.timerMu.Unlock() + if dr.timer == nil { + return + } + + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) + defer cancel() + // TODO: rotate dr.key at some point? + next, err := dr.do(ctx) + if err != nil { + next = renewJitter / 2 + next += time.Duration(pseudoRand.int63n(int64(next))) + } + dr.timer = time.AfterFunc(next, dr.renew) + testDidRenewLoop(next, err) +} + +// do is similar to Manager.createCert but it doesn't lock a Manager.state item. +// Instead, it requests a new certificate independently and, upon success, +// replaces dr.m.state item with a new one and updates cache for the given domain. +// +// It may return immediately if the expiration date of the currently cached cert +// is far enough in the future. +// +// The returned value is a time interval after which the renewal should occur again. +func (dr *domainRenewal) do(ctx context.Context) (time.Duration, error) { + // a race is likely unavoidable in a distributed environment + // but we try nonetheless + if tlscert, err := dr.m.cacheGet(ctx, dr.domain); err == nil { + next := dr.next(tlscert.Leaf.NotAfter) + if next > dr.m.renewBefore()+renewJitter { + return next, nil + } + } + + der, leaf, err := dr.m.authorizedCert(ctx, dr.key, dr.domain) + if err != nil { + return 0, err + } + state := &certState{ + key: dr.key, + cert: der, + leaf: leaf, + } + tlscert, err := state.tlscert() + if err != nil { + return 0, err + } + dr.m.cachePut(ctx, dr.domain, tlscert) + dr.m.stateMu.Lock() + defer dr.m.stateMu.Unlock() + // m.state is guaranteed to be non-nil at this point + dr.m.state[dr.domain] = state + return dr.next(leaf.NotAfter), nil +} + +func (dr *domainRenewal) next(expiry time.Time) time.Duration { + d := expiry.Sub(timeNow()) - dr.m.renewBefore() + // add a bit of randomness to renew deadline + n := pseudoRand.int63n(int64(renewJitter)) + d -= time.Duration(n) + if d < 0 { + return 0 + } + return d +} + +var testDidRenewLoop = func(next time.Duration, err error) {} diff --git a/vendor/golang.org/x/crypto/acme/autocert/renewal_test.go b/vendor/golang.org/x/crypto/acme/autocert/renewal_test.go new file mode 100644 index 0000000000000000000000000000000000000000..11d40ff5d2f7e4e6df092a9a1d09d969714e1b7e --- /dev/null +++ b/vendor/golang.org/x/crypto/acme/autocert/renewal_test.go @@ -0,0 +1,191 @@ +// Copyright 2016 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 autocert + +import ( + "context" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/tls" + "crypto/x509" + "encoding/base64" + "fmt" + "net/http" + "net/http/httptest" + "testing" + "time" + + "golang.org/x/crypto/acme" +) + +func TestRenewalNext(t *testing.T) { + now := time.Now() + timeNow = func() time.Time { return now } + defer func() { timeNow = time.Now }() + + man := &Manager{RenewBefore: 7 * 24 * time.Hour} + defer man.stopRenew() + tt := []struct { + expiry time.Time + min, max time.Duration + }{ + {now.Add(90 * 24 * time.Hour), 83*24*time.Hour - renewJitter, 83 * 24 * time.Hour}, + {now.Add(time.Hour), 0, 1}, + {now, 0, 1}, + {now.Add(-time.Hour), 0, 1}, + } + + dr := &domainRenewal{m: man} + for i, test := range tt { + next := dr.next(test.expiry) + if next < test.min || test.max < next { + t.Errorf("%d: next = %v; want between %v and %v", i, next, test.min, test.max) + } + } +} + +func TestRenewFromCache(t *testing.T) { + const domain = "example.org" + + // ACME CA server stub + var ca *httptest.Server + ca = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Replay-Nonce", "nonce") + if r.Method == "HEAD" { + // a nonce request + return + } + + switch r.URL.Path { + // discovery + case "/": + if err := discoTmpl.Execute(w, ca.URL); err != nil { + t.Fatalf("discoTmpl: %v", err) + } + // client key registration + case "/new-reg": + w.Write([]byte("{}")) + // domain authorization + case "/new-authz": + w.Header().Set("Location", ca.URL+"/authz/1") + w.WriteHeader(http.StatusCreated) + w.Write([]byte(`{"status": "valid"}`)) + // cert request + case "/new-cert": + var req struct { + CSR string `json:"csr"` + } + decodePayload(&req, r.Body) + b, _ := base64.RawURLEncoding.DecodeString(req.CSR) + csr, err := x509.ParseCertificateRequest(b) + if err != nil { + t.Fatalf("new-cert: CSR: %v", err) + } + der, err := dummyCert(csr.PublicKey, domain) + if err != nil { + t.Fatalf("new-cert: dummyCert: %v", err) + } + chainUp := fmt.Sprintf("<%s/ca-cert>; rel=up", ca.URL) + w.Header().Set("Link", chainUp) + w.WriteHeader(http.StatusCreated) + w.Write(der) + // CA chain cert + case "/ca-cert": + der, err := dummyCert(nil, "ca") + if err != nil { + t.Fatalf("ca-cert: dummyCert: %v", err) + } + w.Write(der) + default: + t.Errorf("unrecognized r.URL.Path: %s", r.URL.Path) + } + })) + defer ca.Close() + + // use EC key to run faster on 386 + key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + t.Fatal(err) + } + man := &Manager{ + Prompt: AcceptTOS, + Cache: newMemCache(), + RenewBefore: 24 * time.Hour, + Client: &acme.Client{ + Key: key, + DirectoryURL: ca.URL, + }, + } + defer man.stopRenew() + + // cache an almost expired cert + now := time.Now() + cert, err := dateDummyCert(key.Public(), now.Add(-2*time.Hour), now.Add(time.Minute), domain) + if err != nil { + t.Fatal(err) + } + tlscert := &tls.Certificate{PrivateKey: key, Certificate: [][]byte{cert}} + if err := man.cachePut(context.Background(), domain, tlscert); err != nil { + t.Fatal(err) + } + + // veriy the renewal happened + defer func() { + testDidRenewLoop = func(next time.Duration, err error) {} + }() + done := make(chan struct{}) + testDidRenewLoop = func(next time.Duration, err error) { + defer close(done) + if err != nil { + t.Errorf("testDidRenewLoop: %v", err) + } + // Next should be about 90 days: + // dummyCert creates 90days expiry + account for man.RenewBefore. + // Previous expiration was within 1 min. + future := 88 * 24 * time.Hour + if next < future { + t.Errorf("testDidRenewLoop: next = %v; want >= %v", next, future) + } + + // ensure the new cert is cached + after := time.Now().Add(future) + tlscert, err := man.cacheGet(context.Background(), domain) + if err != nil { + t.Fatalf("man.cacheGet: %v", err) + } + if !tlscert.Leaf.NotAfter.After(after) { + t.Errorf("cache leaf.NotAfter = %v; want > %v", tlscert.Leaf.NotAfter, after) + } + + // verify the old cert is also replaced in memory + man.stateMu.Lock() + defer man.stateMu.Unlock() + s := man.state[domain] + if s == nil { + t.Fatalf("m.state[%q] is nil", domain) + } + tlscert, err = s.tlscert() + if err != nil { + t.Fatalf("s.tlscert: %v", err) + } + if !tlscert.Leaf.NotAfter.After(after) { + t.Errorf("state leaf.NotAfter = %v; want > %v", tlscert.Leaf.NotAfter, after) + } + } + + // trigger renew + hello := &tls.ClientHelloInfo{ServerName: domain} + if _, err := man.GetCertificate(hello); err != nil { + t.Fatal(err) + } + + // wait for renew loop + select { + case <-time.After(10 * time.Second): + t.Fatal("renew took too long to occur") + case <-done: + } +} diff --git a/vendor/golang.org/x/crypto/acme/jws.go b/vendor/golang.org/x/crypto/acme/jws.go new file mode 100644 index 0000000000000000000000000000000000000000..6cbca25de973a247f8349d11c893fc3c15552ac9 --- /dev/null +++ b/vendor/golang.org/x/crypto/acme/jws.go @@ -0,0 +1,153 @@ +// Copyright 2015 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 acme + +import ( + "crypto" + "crypto/ecdsa" + "crypto/rand" + "crypto/rsa" + "crypto/sha256" + _ "crypto/sha512" // need for EC keys + "encoding/base64" + "encoding/json" + "fmt" + "math/big" +) + +// jwsEncodeJSON signs claimset using provided key and a nonce. +// The result is serialized in JSON format. +// See https://tools.ietf.org/html/rfc7515#section-7. +func jwsEncodeJSON(claimset interface{}, key crypto.Signer, nonce string) ([]byte, error) { + jwk, err := jwkEncode(key.Public()) + if err != nil { + return nil, err + } + alg, sha := jwsHasher(key) + if alg == "" || !sha.Available() { + return nil, ErrUnsupportedKey + } + phead := fmt.Sprintf(`{"alg":%q,"jwk":%s,"nonce":%q}`, alg, jwk, nonce) + phead = base64.RawURLEncoding.EncodeToString([]byte(phead)) + cs, err := json.Marshal(claimset) + if err != nil { + return nil, err + } + payload := base64.RawURLEncoding.EncodeToString(cs) + hash := sha.New() + hash.Write([]byte(phead + "." + payload)) + sig, err := jwsSign(key, sha, hash.Sum(nil)) + if err != nil { + return nil, err + } + + enc := struct { + Protected string `json:"protected"` + Payload string `json:"payload"` + Sig string `json:"signature"` + }{ + Protected: phead, + Payload: payload, + Sig: base64.RawURLEncoding.EncodeToString(sig), + } + return json.Marshal(&enc) +} + +// jwkEncode encodes public part of an RSA or ECDSA key into a JWK. +// The result is also suitable for creating a JWK thumbprint. +// https://tools.ietf.org/html/rfc7517 +func jwkEncode(pub crypto.PublicKey) (string, error) { + switch pub := pub.(type) { + case *rsa.PublicKey: + // https://tools.ietf.org/html/rfc7518#section-6.3.1 + n := pub.N + e := big.NewInt(int64(pub.E)) + // Field order is important. + // See https://tools.ietf.org/html/rfc7638#section-3.3 for details. + return fmt.Sprintf(`{"e":"%s","kty":"RSA","n":"%s"}`, + base64.RawURLEncoding.EncodeToString(e.Bytes()), + base64.RawURLEncoding.EncodeToString(n.Bytes()), + ), nil + case *ecdsa.PublicKey: + // https://tools.ietf.org/html/rfc7518#section-6.2.1 + p := pub.Curve.Params() + n := p.BitSize / 8 + if p.BitSize%8 != 0 { + n++ + } + x := pub.X.Bytes() + if n > len(x) { + x = append(make([]byte, n-len(x)), x...) + } + y := pub.Y.Bytes() + if n > len(y) { + y = append(make([]byte, n-len(y)), y...) + } + // Field order is important. + // See https://tools.ietf.org/html/rfc7638#section-3.3 for details. + return fmt.Sprintf(`{"crv":"%s","kty":"EC","x":"%s","y":"%s"}`, + p.Name, + base64.RawURLEncoding.EncodeToString(x), + base64.RawURLEncoding.EncodeToString(y), + ), nil + } + return "", ErrUnsupportedKey +} + +// jwsSign signs the digest using the given key. +// It returns ErrUnsupportedKey if the key type is unknown. +// The hash is used only for RSA keys. +func jwsSign(key crypto.Signer, hash crypto.Hash, digest []byte) ([]byte, error) { + switch key := key.(type) { + case *rsa.PrivateKey: + return key.Sign(rand.Reader, digest, hash) + case *ecdsa.PrivateKey: + r, s, err := ecdsa.Sign(rand.Reader, key, digest) + if err != nil { + return nil, err + } + rb, sb := r.Bytes(), s.Bytes() + size := key.Params().BitSize / 8 + if size%8 > 0 { + size++ + } + sig := make([]byte, size*2) + copy(sig[size-len(rb):], rb) + copy(sig[size*2-len(sb):], sb) + return sig, nil + } + return nil, ErrUnsupportedKey +} + +// jwsHasher indicates suitable JWS algorithm name and a hash function +// to use for signing a digest with the provided key. +// It returns ("", 0) if the key is not supported. +func jwsHasher(key crypto.Signer) (string, crypto.Hash) { + switch key := key.(type) { + case *rsa.PrivateKey: + return "RS256", crypto.SHA256 + case *ecdsa.PrivateKey: + switch key.Params().Name { + case "P-256": + return "ES256", crypto.SHA256 + case "P-384": + return "ES384", crypto.SHA384 + case "P-521": + return "ES512", crypto.SHA512 + } + } + return "", 0 +} + +// JWKThumbprint creates a JWK thumbprint out of pub +// as specified in https://tools.ietf.org/html/rfc7638. +func JWKThumbprint(pub crypto.PublicKey) (string, error) { + jwk, err := jwkEncode(pub) + if err != nil { + return "", err + } + b := sha256.Sum256([]byte(jwk)) + return base64.RawURLEncoding.EncodeToString(b[:]), nil +} diff --git a/vendor/golang.org/x/crypto/acme/jws_test.go b/vendor/golang.org/x/crypto/acme/jws_test.go new file mode 100644 index 0000000000000000000000000000000000000000..0ff0fb5a31e315a90091c662f981cd44343d5e89 --- /dev/null +++ b/vendor/golang.org/x/crypto/acme/jws_test.go @@ -0,0 +1,319 @@ +// Copyright 2015 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 acme + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rsa" + "crypto/x509" + "encoding/base64" + "encoding/json" + "encoding/pem" + "fmt" + "math/big" + "testing" +) + +const ( + testKeyPEM = ` +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEA4xgZ3eRPkwoRvy7qeRUbmMDe0V+xH9eWLdu0iheeLlrmD2mq +WXfP9IeSKApbn34g8TuAS9g5zhq8ELQ3kmjr+KV86GAMgI6VAcGlq3QrzpTCf/30 +Ab7+zawrfRaFONa1HwEzPY1KHnGVkxJc85gNkwYI9SY2RHXtvln3zs5wITNrdosq +EXeaIkVYBEhbhNu54pp3kxo6TuWLi9e6pXeWetEwmlBwtWZlPoib2j3TxLBksKZf +oyFyek380mHgJAumQ/I2fjj98/97mk3ihOY4AgVdCDj1z/GCoZkG5Rq7nbCGyosy +KWyDX00Zs+nNqVhoLeIvXC4nnWdJMZ6rogxyQQIDAQABAoIBACIEZTOI1Kao9nmV +9IeIsuaR1Y61b9neOF/MLmIVIZu+AAJFCMB4Iw11FV6sFodwpEyeZhx2WkpWVN+H +r19eGiLX3zsL0DOdqBJoSIHDWCCMxgnYJ6nvS0nRxX3qVrBp8R2g12Ub+gNPbmFm +ecf/eeERIVxfifd9VsyRu34eDEvcmKFuLYbElFcPh62xE3x12UZvV/sN7gXbawpP +G+w255vbE5MoaKdnnO83cTFlcHvhn24M/78qP7Te5OAeelr1R89kYxQLpuGe4fbS +zc6E3ym5Td6urDetGGrSY1Eu10/8sMusX+KNWkm+RsBRbkyKq72ks/qKpOxOa+c6 +9gm+Y8ECgYEA/iNUyg1ubRdH11p82l8KHtFC1DPE0V1gSZsX29TpM5jS4qv46K+s +8Ym1zmrORM8x+cynfPx1VQZQ34EYeCMIX212ryJ+zDATl4NE0I4muMvSiH9vx6Xc +7FmhNnaYzPsBL5Tm9nmtQuP09YEn8poiOJFiDs/4olnD5ogA5O4THGkCgYEA5MIL +qWYBUuqbEWLRtMruUtpASclrBqNNsJEsMGbeqBJmoMxdHeSZckbLOrqm7GlMyNRJ +Ne/5uWRGSzaMYuGmwsPpERzqEvYFnSrpjW5YtXZ+JtxFXNVfm9Z1gLLgvGpOUCIU +RbpoDckDe1vgUuk3y5+DjZihs+rqIJ45XzXTzBkCgYBWuf3segruJZy5rEKhTv+o +JqeUvRn0jNYYKFpLBeyTVBrbie6GkbUGNIWbrK05pC+c3K9nosvzuRUOQQL1tJbd +4gA3oiD9U4bMFNr+BRTHyZ7OQBcIXdz3t1qhuHVKtnngIAN1p25uPlbRFUNpshnt +jgeVoHlsBhApcs5DUc+pyQKBgDzeHPg/+g4z+nrPznjKnktRY1W+0El93kgi+J0Q +YiJacxBKEGTJ1MKBb8X6sDurcRDm22wMpGfd9I5Cv2v4GsUsF7HD/cx5xdih+G73 +c4clNj/k0Ff5Nm1izPUno4C+0IOl7br39IPmfpSuR6wH/h6iHQDqIeybjxyKvT1G +N0rRAoGBAKGD+4ZI/E1MoJ5CXB8cDDMHagbE3cq/DtmYzE2v1DFpQYu5I4PCm5c7 +EQeIP6dZtv8IMgtGIb91QX9pXvP0aznzQKwYIA8nZgoENCPfiMTPiEDT9e/0lObO +9XWsXpbSTsRPj0sv1rB+UzBJ0PgjK4q2zOF0sNo7b1+6nlM3BWPx +-----END RSA PRIVATE KEY----- +` + + // This thumbprint is for the testKey defined above. + testKeyThumbprint = "6nicxzh6WETQlrvdchkz-U3e3DOQZ4heJKU63rfqMqQ" + + // openssl ecparam -name secp256k1 -genkey -noout + testKeyECPEM = ` +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIK07hGLr0RwyUdYJ8wbIiBS55CjnkMD23DWr+ccnypWLoAoGCCqGSM49 +AwEHoUQDQgAE5lhEug5xK4xBDZ2nAbaxLtaLiv85bxJ7ePd1dkO23HThqIrvawF5 +QAaS/RNouybCiRhRjI3EaxLkQwgrCw0gqQ== +-----END EC PRIVATE KEY----- +` + // openssl ecparam -name secp384r1 -genkey -noout + testKeyEC384PEM = ` +-----BEGIN EC PRIVATE KEY----- +MIGkAgEBBDAQ4lNtXRORWr1bgKR1CGysr9AJ9SyEk4jiVnlUWWUChmSNL+i9SLSD +Oe/naPqXJ6CgBwYFK4EEACKhZANiAAQzKtj+Ms0vHoTX5dzv3/L5YMXOWuI5UKRj +JigpahYCqXD2BA1j0E/2xt5vlPf+gm0PL+UHSQsCokGnIGuaHCsJAp3ry0gHQEke +WYXapUUFdvaK1R2/2hn5O+eiQM8YzCg= +-----END EC PRIVATE KEY----- +` + // openssl ecparam -name secp521r1 -genkey -noout + testKeyEC512PEM = ` +-----BEGIN EC PRIVATE KEY----- +MIHcAgEBBEIBSNZKFcWzXzB/aJClAb305ibalKgtDA7+70eEkdPt28/3LZMM935Z +KqYHh/COcxuu3Kt8azRAUz3gyr4zZKhlKUSgBwYFK4EEACOhgYkDgYYABAHUNKbx +7JwC7H6pa2sV0tERWhHhB3JmW+OP6SUgMWryvIKajlx73eS24dy4QPGrWO9/ABsD +FqcRSkNVTXnIv6+0mAF25knqIBIg5Q8M9BnOu9GGAchcwt3O7RDHmqewnJJDrbjd +GGnm6rb+NnWR9DIopM0nKNkToWoF/hzopxu4Ae/GsQ== +-----END EC PRIVATE KEY----- +` + // 1. openssl ec -in key.pem -noout -text + // 2. remove first byte, 04 (the header); the rest is X and Y + // 3. convert each with: echo | xxd -r -p | base64 -w 100 | tr -d '=' | tr '/+' '_-' + testKeyECPubX = "5lhEug5xK4xBDZ2nAbaxLtaLiv85bxJ7ePd1dkO23HQ" + testKeyECPubY = "4aiK72sBeUAGkv0TaLsmwokYUYyNxGsS5EMIKwsNIKk" + testKeyEC384PubX = "MyrY_jLNLx6E1-Xc79_y-WDFzlriOVCkYyYoKWoWAqlw9gQNY9BP9sbeb5T3_oJt" + testKeyEC384PubY = "Dy_lB0kLAqJBpyBrmhwrCQKd68tIB0BJHlmF2qVFBXb2itUdv9oZ-TvnokDPGMwo" + testKeyEC512PubX = "AdQ0pvHsnALsfqlraxXS0RFaEeEHcmZb44_pJSAxavK8gpqOXHvd5Lbh3LhA8atY738AGwMWpxFKQ1VNeci_r7SY" + testKeyEC512PubY = "AXbmSeogEiDlDwz0Gc670YYByFzC3c7tEMeap7CckkOtuN0Yaebqtv42dZH0MiikzSco2ROhagX-HOinG7gB78ax" + + // echo -n '{"crv":"P-256","kty":"EC","x":"","y":""}' | \ + // openssl dgst -binary -sha256 | base64 | tr -d '=' | tr '/+' '_-' + testKeyECThumbprint = "zedj-Bd1Zshp8KLePv2MB-lJ_Hagp7wAwdkA0NUTniU" +) + +var ( + testKey *rsa.PrivateKey + testKeyEC *ecdsa.PrivateKey + testKeyEC384 *ecdsa.PrivateKey + testKeyEC512 *ecdsa.PrivateKey +) + +func init() { + testKey = parseRSA(testKeyPEM, "testKeyPEM") + testKeyEC = parseEC(testKeyECPEM, "testKeyECPEM") + testKeyEC384 = parseEC(testKeyEC384PEM, "testKeyEC384PEM") + testKeyEC512 = parseEC(testKeyEC512PEM, "testKeyEC512PEM") +} + +func decodePEM(s, name string) []byte { + d, _ := pem.Decode([]byte(s)) + if d == nil { + panic("no block found in " + name) + } + return d.Bytes +} + +func parseRSA(s, name string) *rsa.PrivateKey { + b := decodePEM(s, name) + k, err := x509.ParsePKCS1PrivateKey(b) + if err != nil { + panic(fmt.Sprintf("%s: %v", name, err)) + } + return k +} + +func parseEC(s, name string) *ecdsa.PrivateKey { + b := decodePEM(s, name) + k, err := x509.ParseECPrivateKey(b) + if err != nil { + panic(fmt.Sprintf("%s: %v", name, err)) + } + return k +} + +func TestJWSEncodeJSON(t *testing.T) { + claims := struct{ Msg string }{"Hello JWS"} + // JWS signed with testKey and "nonce" as the nonce value + // JSON-serialized JWS fields are split for easier testing + const ( + // {"alg":"RS256","jwk":{"e":"AQAB","kty":"RSA","n":"..."},"nonce":"nonce"} + protected = "eyJhbGciOiJSUzI1NiIsImp3ayI6eyJlIjoiQVFBQiIsImt0eSI6" + + "IlJTQSIsIm4iOiI0eGdaM2VSUGt3b1J2eTdxZVJVYm1NRGUwVi14" + + "SDllV0xkdTBpaGVlTGxybUQybXFXWGZQOUllU0tBcGJuMzRnOFR1" + + "QVM5ZzV6aHE4RUxRM2ttanItS1Y4NkdBTWdJNlZBY0dscTNRcnpw" + + "VENmXzMwQWI3LXphd3JmUmFGT05hMUh3RXpQWTFLSG5HVmt4SmM4" + + "NWdOa3dZSTlTWTJSSFh0dmxuM3pzNXdJVE5yZG9zcUVYZWFJa1ZZ" + + "QkVoYmhOdTU0cHAza3hvNlR1V0xpOWU2cFhlV2V0RXdtbEJ3dFda" + + "bFBvaWIyajNUeExCa3NLWmZveUZ5ZWszODBtSGdKQXVtUV9JMmZq" + + "ajk4Xzk3bWszaWhPWTRBZ1ZkQ0RqMXpfR0NvWmtHNVJxN25iQ0d5" + + "b3N5S1d5RFgwMFpzLW5OcVZob0xlSXZYQzRubldkSk1aNnJvZ3h5" + + "UVEifSwibm9uY2UiOiJub25jZSJ9" + // {"Msg":"Hello JWS"} + payload = "eyJNc2ciOiJIZWxsbyBKV1MifQ" + signature = "eAGUikStX_UxyiFhxSLMyuyBcIB80GeBkFROCpap2sW3EmkU_ggF" + + "knaQzxrTfItICSAXsCLIquZ5BbrSWA_4vdEYrwWtdUj7NqFKjHRa" + + "zpLHcoR7r1rEHvkoP1xj49lS5fc3Wjjq8JUhffkhGbWZ8ZVkgPdC" + + "4tMBWiQDoth-x8jELP_3LYOB_ScUXi2mETBawLgOT2K8rA0Vbbmx" + + "hWNlOWuUf-8hL5YX4IOEwsS8JK_TrTq5Zc9My0zHJmaieqDV0UlP" + + "k0onFjPFkGm7MrPSgd0MqRG-4vSAg2O4hDo7rKv4n8POjjXlNQvM" + + "9IPLr8qZ7usYBKhEGwX3yq_eicAwBw" + ) + + b, err := jwsEncodeJSON(claims, testKey, "nonce") + if err != nil { + t.Fatal(err) + } + var jws struct{ Protected, Payload, Signature string } + if err := json.Unmarshal(b, &jws); err != nil { + t.Fatal(err) + } + if jws.Protected != protected { + t.Errorf("protected:\n%s\nwant:\n%s", jws.Protected, protected) + } + if jws.Payload != payload { + t.Errorf("payload:\n%s\nwant:\n%s", jws.Payload, payload) + } + if jws.Signature != signature { + t.Errorf("signature:\n%s\nwant:\n%s", jws.Signature, signature) + } +} + +func TestJWSEncodeJSONEC(t *testing.T) { + tt := []struct { + key *ecdsa.PrivateKey + x, y string + alg, crv string + }{ + {testKeyEC, testKeyECPubX, testKeyECPubY, "ES256", "P-256"}, + {testKeyEC384, testKeyEC384PubX, testKeyEC384PubY, "ES384", "P-384"}, + {testKeyEC512, testKeyEC512PubX, testKeyEC512PubY, "ES512", "P-521"}, + } + for i, test := range tt { + claims := struct{ Msg string }{"Hello JWS"} + b, err := jwsEncodeJSON(claims, test.key, "nonce") + if err != nil { + t.Errorf("%d: %v", i, err) + continue + } + var jws struct{ Protected, Payload, Signature string } + if err := json.Unmarshal(b, &jws); err != nil { + t.Errorf("%d: %v", i, err) + continue + } + + b, err = base64.RawURLEncoding.DecodeString(jws.Protected) + if err != nil { + t.Errorf("%d: jws.Protected: %v", i, err) + } + var head struct { + Alg string + Nonce string + JWK struct { + Crv string + Kty string + X string + Y string + } `json:"jwk"` + } + if err := json.Unmarshal(b, &head); err != nil { + t.Errorf("%d: jws.Protected: %v", i, err) + } + if head.Alg != test.alg { + t.Errorf("%d: head.Alg = %q; want %q", i, head.Alg, test.alg) + } + if head.Nonce != "nonce" { + t.Errorf("%d: head.Nonce = %q; want nonce", i, head.Nonce) + } + if head.JWK.Crv != test.crv { + t.Errorf("%d: head.JWK.Crv = %q; want %q", i, head.JWK.Crv, test.crv) + } + if head.JWK.Kty != "EC" { + t.Errorf("%d: head.JWK.Kty = %q; want EC", i, head.JWK.Kty) + } + if head.JWK.X != test.x { + t.Errorf("%d: head.JWK.X = %q; want %q", i, head.JWK.X, test.x) + } + if head.JWK.Y != test.y { + t.Errorf("%d: head.JWK.Y = %q; want %q", i, head.JWK.Y, test.y) + } + } +} + +func TestJWKThumbprintRSA(t *testing.T) { + // Key example from RFC 7638 + const base64N = "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAt" + + "VT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn6" + + "4tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FD" + + "W2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n9" + + "1CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINH" + + "aQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw" + const base64E = "AQAB" + const expected = "NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs" + + b, err := base64.RawURLEncoding.DecodeString(base64N) + if err != nil { + t.Fatalf("Error parsing example key N: %v", err) + } + n := new(big.Int).SetBytes(b) + + b, err = base64.RawURLEncoding.DecodeString(base64E) + if err != nil { + t.Fatalf("Error parsing example key E: %v", err) + } + e := new(big.Int).SetBytes(b) + + pub := &rsa.PublicKey{N: n, E: int(e.Uint64())} + th, err := JWKThumbprint(pub) + if err != nil { + t.Error(err) + } + if th != expected { + t.Errorf("thumbprint = %q; want %q", th, expected) + } +} + +func TestJWKThumbprintEC(t *testing.T) { + // Key example from RFC 7520 + // expected was computed with + // echo -n '{"crv":"P-521","kty":"EC","x":"","y":""}' | \ + // openssl dgst -binary -sha256 | \ + // base64 | \ + // tr -d '=' | tr '/+' '_-' + const ( + base64X = "AHKZLLOsCOzz5cY97ewNUajB957y-C-U88c3v13nmGZx6sYl_oJXu9A5RkT" + + "KqjqvjyekWF-7ytDyRXYgCF5cj0Kt" + base64Y = "AdymlHvOiLxXkEhayXQnNCvDX4h9htZaCJN34kfmC6pV5OhQHiraVySsUda" + + "QkAgDPrwQrJmbnX9cwlGfP-HqHZR1" + expected = "dHri3SADZkrush5HU_50AoRhcKFryN-PI6jPBtPL55M" + ) + + b, err := base64.RawURLEncoding.DecodeString(base64X) + if err != nil { + t.Fatalf("Error parsing example key X: %v", err) + } + x := new(big.Int).SetBytes(b) + + b, err = base64.RawURLEncoding.DecodeString(base64Y) + if err != nil { + t.Fatalf("Error parsing example key Y: %v", err) + } + y := new(big.Int).SetBytes(b) + + pub := &ecdsa.PublicKey{Curve: elliptic.P521(), X: x, Y: y} + th, err := JWKThumbprint(pub) + if err != nil { + t.Error(err) + } + if th != expected { + t.Errorf("thumbprint = %q; want %q", th, expected) + } +} + +func TestJWKThumbprintErrUnsupportedKey(t *testing.T) { + _, err := JWKThumbprint(struct{}{}) + if err != ErrUnsupportedKey { + t.Errorf("err = %q; want %q", err, ErrUnsupportedKey) + } +} diff --git a/vendor/golang.org/x/crypto/acme/types.go b/vendor/golang.org/x/crypto/acme/types.go new file mode 100644 index 0000000000000000000000000000000000000000..3e199749ecb7eb9a8366506a5d4a82dd305ec5a4 --- /dev/null +++ b/vendor/golang.org/x/crypto/acme/types.go @@ -0,0 +1,329 @@ +// Copyright 2016 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 acme + +import ( + "crypto" + "crypto/x509" + "errors" + "fmt" + "net/http" + "strings" + "time" +) + +// ACME server response statuses used to describe Authorization and Challenge states. +const ( + StatusUnknown = "unknown" + StatusPending = "pending" + StatusProcessing = "processing" + StatusValid = "valid" + StatusInvalid = "invalid" + StatusRevoked = "revoked" +) + +// CRLReasonCode identifies the reason for a certificate revocation. +type CRLReasonCode int + +// CRL reason codes as defined in RFC 5280. +const ( + CRLReasonUnspecified CRLReasonCode = 0 + CRLReasonKeyCompromise CRLReasonCode = 1 + CRLReasonCACompromise CRLReasonCode = 2 + CRLReasonAffiliationChanged CRLReasonCode = 3 + CRLReasonSuperseded CRLReasonCode = 4 + CRLReasonCessationOfOperation CRLReasonCode = 5 + CRLReasonCertificateHold CRLReasonCode = 6 + CRLReasonRemoveFromCRL CRLReasonCode = 8 + CRLReasonPrivilegeWithdrawn CRLReasonCode = 9 + CRLReasonAACompromise CRLReasonCode = 10 +) + +// ErrUnsupportedKey is returned when an unsupported key type is encountered. +var ErrUnsupportedKey = errors.New("acme: unknown key type; only RSA and ECDSA are supported") + +// Error is an ACME error, defined in Problem Details for HTTP APIs doc +// http://tools.ietf.org/html/draft-ietf-appsawg-http-problem. +type Error struct { + // StatusCode is The HTTP status code generated by the origin server. + StatusCode int + // ProblemType is a URI reference that identifies the problem type, + // typically in a "urn:acme:error:xxx" form. + ProblemType string + // Detail is a human-readable explanation specific to this occurrence of the problem. + Detail string + // Header is the original server error response headers. + // It may be nil. + Header http.Header +} + +func (e *Error) Error() string { + return fmt.Sprintf("%d %s: %s", e.StatusCode, e.ProblemType, e.Detail) +} + +// AuthorizationError indicates that an authorization for an identifier +// did not succeed. +// It contains all errors from Challenge items of the failed Authorization. +type AuthorizationError struct { + // URI uniquely identifies the failed Authorization. + URI string + + // Identifier is an AuthzID.Value of the failed Authorization. + Identifier string + + // Errors is a collection of non-nil error values of Challenge items + // of the failed Authorization. + Errors []error +} + +func (a *AuthorizationError) Error() string { + e := make([]string, len(a.Errors)) + for i, err := range a.Errors { + e[i] = err.Error() + } + return fmt.Sprintf("acme: authorization error for %s: %s", a.Identifier, strings.Join(e, "; ")) +} + +// RateLimit reports whether err represents a rate limit error and +// any Retry-After duration returned by the server. +// +// See the following for more details on rate limiting: +// https://tools.ietf.org/html/draft-ietf-acme-acme-05#section-5.6 +func RateLimit(err error) (time.Duration, bool) { + e, ok := err.(*Error) + if !ok { + return 0, false + } + // Some CA implementations may return incorrect values. + // Use case-insensitive comparison. + if !strings.HasSuffix(strings.ToLower(e.ProblemType), ":ratelimited") { + return 0, false + } + if e.Header == nil { + return 0, true + } + return retryAfter(e.Header.Get("Retry-After"), 0), true +} + +// Account is a user account. It is associated with a private key. +type Account struct { + // URI is the account unique ID, which is also a URL used to retrieve + // account data from the CA. + URI string + + // Contact is a slice of contact info used during registration. + Contact []string + + // The terms user has agreed to. + // A value not matching CurrentTerms indicates that the user hasn't agreed + // to the actual Terms of Service of the CA. + AgreedTerms string + + // Actual terms of a CA. + CurrentTerms string + + // Authz is the authorization URL used to initiate a new authz flow. + Authz string + + // Authorizations is a URI from which a list of authorizations + // granted to this account can be fetched via a GET request. + Authorizations string + + // Certificates is a URI from which a list of certificates + // issued for this account can be fetched via a GET request. + Certificates string +} + +// Directory is ACME server discovery data. +type Directory struct { + // RegURL is an account endpoint URL, allowing for creating new + // and modifying existing accounts. + RegURL string + + // AuthzURL is used to initiate Identifier Authorization flow. + AuthzURL string + + // CertURL is a new certificate issuance endpoint URL. + CertURL string + + // RevokeURL is used to initiate a certificate revocation flow. + RevokeURL string + + // Term is a URI identifying the current terms of service. + Terms string + + // Website is an HTTP or HTTPS URL locating a website + // providing more information about the ACME server. + Website string + + // CAA consists of lowercase hostname elements, which the ACME server + // recognises as referring to itself for the purposes of CAA record validation + // as defined in RFC6844. + CAA []string +} + +// Challenge encodes a returned CA challenge. +// Its Error field may be non-nil if the challenge is part of an Authorization +// with StatusInvalid. +type Challenge struct { + // Type is the challenge type, e.g. "http-01", "tls-sni-02", "dns-01". + Type string + + // URI is where a challenge response can be posted to. + URI string + + // Token is a random value that uniquely identifies the challenge. + Token string + + // Status identifies the status of this challenge. + Status string + + // Error indicates the reason for an authorization failure + // when this challenge was used. + // The type of a non-nil value is *Error. + Error error +} + +// Authorization encodes an authorization response. +type Authorization struct { + // URI uniquely identifies a authorization. + URI string + + // Status identifies the status of an authorization. + Status string + + // Identifier is what the account is authorized to represent. + Identifier AuthzID + + // Challenges that the client needs to fulfill in order to prove possession + // of the identifier (for pending authorizations). + // For final authorizations, the challenges that were used. + Challenges []*Challenge + + // A collection of sets of challenges, each of which would be sufficient + // to prove possession of the identifier. + // Clients must complete a set of challenges that covers at least one set. + // Challenges are identified by their indices in the challenges array. + // If this field is empty, the client needs to complete all challenges. + Combinations [][]int +} + +// AuthzID is an identifier that an account is authorized to represent. +type AuthzID struct { + Type string // The type of identifier, e.g. "dns". + Value string // The identifier itself, e.g. "example.org". +} + +// wireAuthz is ACME JSON representation of Authorization objects. +type wireAuthz struct { + Status string + Challenges []wireChallenge + Combinations [][]int + Identifier struct { + Type string + Value string + } +} + +func (z *wireAuthz) authorization(uri string) *Authorization { + a := &Authorization{ + URI: uri, + Status: z.Status, + Identifier: AuthzID{Type: z.Identifier.Type, Value: z.Identifier.Value}, + Combinations: z.Combinations, // shallow copy + Challenges: make([]*Challenge, len(z.Challenges)), + } + for i, v := range z.Challenges { + a.Challenges[i] = v.challenge() + } + return a +} + +func (z *wireAuthz) error(uri string) *AuthorizationError { + err := &AuthorizationError{ + URI: uri, + Identifier: z.Identifier.Value, + } + for _, raw := range z.Challenges { + if raw.Error != nil { + err.Errors = append(err.Errors, raw.Error.error(nil)) + } + } + return err +} + +// wireChallenge is ACME JSON challenge representation. +type wireChallenge struct { + URI string `json:"uri"` + Type string + Token string + Status string + Error *wireError +} + +func (c *wireChallenge) challenge() *Challenge { + v := &Challenge{ + URI: c.URI, + Type: c.Type, + Token: c.Token, + Status: c.Status, + } + if v.Status == "" { + v.Status = StatusPending + } + if c.Error != nil { + v.Error = c.Error.error(nil) + } + return v +} + +// wireError is a subset of fields of the Problem Details object +// as described in https://tools.ietf.org/html/rfc7807#section-3.1. +type wireError struct { + Status int + Type string + Detail string +} + +func (e *wireError) error(h http.Header) *Error { + return &Error{ + StatusCode: e.Status, + ProblemType: e.Type, + Detail: e.Detail, + Header: h, + } +} + +// CertOption is an optional argument type for the TLSSNIxChallengeCert methods for +// customizing a temporary certificate for TLS-SNI challenges. +type CertOption interface { + privateCertOpt() +} + +// WithKey creates an option holding a private/public key pair. +// The private part signs a certificate, and the public part represents the signee. +func WithKey(key crypto.Signer) CertOption { + return &certOptKey{key} +} + +type certOptKey struct { + key crypto.Signer +} + +func (*certOptKey) privateCertOpt() {} + +// WithTemplate creates an option for specifying a certificate template. +// See x509.CreateCertificate for template usage details. +// +// In TLSSNIxChallengeCert methods, the template is also used as parent, +// resulting in a self-signed certificate. +// The DNSNames field of t is always overwritten for tls-sni challenge certs. +func WithTemplate(t *x509.Certificate) CertOption { + return (*certOptTemplate)(t) +} + +type certOptTemplate x509.Certificate + +func (*certOptTemplate) privateCertOpt() {} diff --git a/vendor/golang.org/x/crypto/acme/types_test.go b/vendor/golang.org/x/crypto/acme/types_test.go new file mode 100644 index 0000000000000000000000000000000000000000..a7553e6b70f48d94b7cd54d62484c7603e1f9588 --- /dev/null +++ b/vendor/golang.org/x/crypto/acme/types_test.go @@ -0,0 +1,63 @@ +// Copyright 2017 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 acme + +import ( + "errors" + "net/http" + "testing" + "time" +) + +func TestRateLimit(t *testing.T) { + now := time.Date(2017, 04, 27, 10, 0, 0, 0, time.UTC) + f := timeNow + defer func() { timeNow = f }() + timeNow = func() time.Time { return now } + + h120, hTime := http.Header{}, http.Header{} + h120.Set("Retry-After", "120") + hTime.Set("Retry-After", "Tue Apr 27 11:00:00 2017") + + err1 := &Error{ + ProblemType: "urn:ietf:params:acme:error:nolimit", + Header: h120, + } + err2 := &Error{ + ProblemType: "urn:ietf:params:acme:error:rateLimited", + Header: h120, + } + err3 := &Error{ + ProblemType: "urn:ietf:params:acme:error:rateLimited", + Header: nil, + } + err4 := &Error{ + ProblemType: "urn:ietf:params:acme:error:rateLimited", + Header: hTime, + } + + tt := []struct { + err error + res time.Duration + ok bool + }{ + {nil, 0, false}, + {errors.New("dummy"), 0, false}, + {err1, 0, false}, + {err2, 2 * time.Minute, true}, + {err3, 0, true}, + {err4, time.Hour, true}, + } + for i, test := range tt { + res, ok := RateLimit(test.err) + if ok != test.ok { + t.Errorf("%d: RateLimit(%+v): ok = %v; want %v", i, test.err, ok, test.ok) + continue + } + if res != test.res { + t.Errorf("%d: RateLimit(%+v) = %v; want %v", i, test.err, res, test.res) + } + } +} diff --git a/vendor/golang.org/x/crypto/argon2/argon2.go b/vendor/golang.org/x/crypto/argon2/argon2.go new file mode 100644 index 0000000000000000000000000000000000000000..71cf8c556c108d1a99fde66c77925bfa6d9595d7 --- /dev/null +++ b/vendor/golang.org/x/crypto/argon2/argon2.go @@ -0,0 +1,228 @@ +// Copyright 2017 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 argon2 implements the key derivation function Argon2. +// Argon2 was selected as the winner of the Password Hashing Competition and can +// be used to derive cryptographic keys from passwords. +// Argon2 is specfifed at https://github.com/P-H-C/phc-winner-argon2/blob/master/argon2-specs.pdf +package argon2 + +import ( + "encoding/binary" + "sync" + + "golang.org/x/crypto/blake2b" +) + +// The Argon2 version implemented by this package. +const Version = 0x13 + +const ( + argon2d = iota + argon2i + argon2id +) + +// Key derives a key from the password, salt, and cost parameters using Argon2i +// returning a byte slice of length keyLen that can be used as cryptographic key. +// The CPU cost and parallism degree must be greater than zero. +// +// For example, you can get a derived key for e.g. AES-256 (which needs a 32-byte key) by doing: +// `key := argon2.Key([]byte("some password"), salt, 4, 32*1024, 4, 32)` +// +// The recommended parameters for interactive logins as of 2017 are time=4, memory=32*1024. +// The number of threads can be adjusted to the numbers of available CPUs. +// The time parameter specifies the number of passes over the memory and the memory +// parameter specifies the size of the memory in KiB. For example memory=32*1024 sets the +// memory cost to ~32 MB. +// The cost parameters should be increased as memory latency and CPU parallelism increases. +// Remember to get a good random salt. +func Key(password, salt []byte, time, memory uint32, threads uint8, keyLen uint32) []byte { + return deriveKey(argon2i, password, salt, nil, nil, time, memory, threads, keyLen) +} + +func deriveKey(mode int, password, salt, secret, data []byte, time, memory uint32, threads uint8, keyLen uint32) []byte { + if time < 1 { + panic("argon2: number of rounds too small") + } + if threads < 1 { + panic("argon2: parallelism degree too low") + } + h0 := initHash(password, salt, secret, data, time, memory, uint32(threads), keyLen, mode) + + memory = memory / (syncPoints * uint32(threads)) * (syncPoints * uint32(threads)) + if memory < 2*syncPoints*uint32(threads) { + memory = 2 * syncPoints * uint32(threads) + } + B := initBlocks(&h0, memory, uint32(threads)) + processBlocks(B, time, memory, uint32(threads), mode) + return extractKey(B, memory, uint32(threads), keyLen) +} + +const ( + blockLength = 128 + syncPoints = 4 +) + +type block [blockLength]uint64 + +func initHash(password, salt, key, data []byte, time, memory, threads, keyLen uint32, mode int) [blake2b.Size + 8]byte { + var ( + h0 [blake2b.Size + 8]byte + params [24]byte + tmp [4]byte + ) + + b2, _ := blake2b.New512(nil) + binary.LittleEndian.PutUint32(params[0:4], threads) + binary.LittleEndian.PutUint32(params[4:8], keyLen) + binary.LittleEndian.PutUint32(params[8:12], memory) + binary.LittleEndian.PutUint32(params[12:16], time) + binary.LittleEndian.PutUint32(params[16:20], uint32(Version)) + binary.LittleEndian.PutUint32(params[20:24], uint32(mode)) + b2.Write(params[:]) + binary.LittleEndian.PutUint32(tmp[:], uint32(len(password))) + b2.Write(tmp[:]) + b2.Write(password) + binary.LittleEndian.PutUint32(tmp[:], uint32(len(salt))) + b2.Write(tmp[:]) + b2.Write(salt) + binary.LittleEndian.PutUint32(tmp[:], uint32(len(key))) + b2.Write(tmp[:]) + b2.Write(key) + binary.LittleEndian.PutUint32(tmp[:], uint32(len(data))) + b2.Write(tmp[:]) + b2.Write(data) + b2.Sum(h0[:0]) + return h0 +} + +func initBlocks(h0 *[blake2b.Size + 8]byte, memory, threads uint32) []block { + var block0 [1024]byte + B := make([]block, memory) + for lane := uint32(0); lane < threads; lane++ { + j := lane * (memory / threads) + binary.LittleEndian.PutUint32(h0[blake2b.Size+4:], lane) + + binary.LittleEndian.PutUint32(h0[blake2b.Size:], 0) + blake2bHash(block0[:], h0[:]) + for i := range B[j+0] { + B[j+0][i] = binary.LittleEndian.Uint64(block0[i*8:]) + } + + binary.LittleEndian.PutUint32(h0[blake2b.Size:], 1) + blake2bHash(block0[:], h0[:]) + for i := range B[j+1] { + B[j+1][i] = binary.LittleEndian.Uint64(block0[i*8:]) + } + } + return B +} + +func processBlocks(B []block, time, memory, threads uint32, mode int) { + lanes := memory / threads + segments := lanes / syncPoints + + processSegment := func(n, slice, lane uint32, wg *sync.WaitGroup) { + var addresses, in, zero block + if mode == argon2i || (mode == argon2id && n == 0 && slice < syncPoints/2) { + in[0] = uint64(n) + in[1] = uint64(lane) + in[2] = uint64(slice) + in[3] = uint64(memory) + in[4] = uint64(time) + in[5] = uint64(mode) + } + + index := uint32(0) + if n == 0 && slice == 0 { + index = 2 // we have already generated the first two blocks + if mode == argon2i || mode == argon2id { + in[6]++ + processBlock(&addresses, &in, &zero) + processBlock(&addresses, &addresses, &zero) + } + } + + offset := lane*lanes + slice*segments + index + var random uint64 + for index < segments { + prev := offset - 1 + if index == 0 && slice == 0 { + prev += lanes // last block in lane + } + if mode == argon2i || (mode == argon2id && n == 0 && slice < syncPoints/2) { + if index%blockLength == 0 { + in[6]++ + processBlock(&addresses, &in, &zero) + processBlock(&addresses, &addresses, &zero) + } + random = addresses[index%blockLength] + } else { + random = B[prev][0] + } + newOffset := indexAlpha(random, lanes, segments, threads, n, slice, lane, index) + processBlockXOR(&B[offset], &B[prev], &B[newOffset]) + index, offset = index+1, offset+1 + } + wg.Done() + } + + for n := uint32(0); n < time; n++ { + for slice := uint32(0); slice < syncPoints; slice++ { + var wg sync.WaitGroup + for lane := uint32(0); lane < threads; lane++ { + wg.Add(1) + go processSegment(n, slice, lane, &wg) + } + wg.Wait() + } + } + +} + +func extractKey(B []block, memory, threads, keyLen uint32) []byte { + lanes := memory / threads + for lane := uint32(0); lane < threads-1; lane++ { + for i, v := range B[(lane*lanes)+lanes-1] { + B[memory-1][i] ^= v + } + } + + var block [1024]byte + for i, v := range B[memory-1] { + binary.LittleEndian.PutUint64(block[i*8:], v) + } + key := make([]byte, keyLen) + blake2bHash(key, block[:]) + return key +} + +func indexAlpha(rand uint64, lanes, segments, threads, n, slice, lane, index uint32) uint32 { + refLane := uint32(rand>>32) % threads + if n == 0 && slice == 0 { + refLane = lane + } + m, s := 3*segments, ((slice+1)%syncPoints)*segments + if lane == refLane { + m += index + } + if n == 0 { + m, s = slice*segments, 0 + if slice == 0 || lane == refLane { + m += index + } + } + if index == 0 || lane == refLane { + m-- + } + return phi(rand, uint64(m), uint64(s), refLane, lanes) +} + +func phi(rand, m, s uint64, lane, lanes uint32) uint32 { + p := rand & 0xFFFFFFFF + p = (p * p) >> 32 + p = (p * m) >> 32 + return lane*lanes + uint32((s+m-(p+1))%uint64(lanes)) +} diff --git a/vendor/golang.org/x/crypto/argon2/argon2_test.go b/vendor/golang.org/x/crypto/argon2/argon2_test.go new file mode 100644 index 0000000000000000000000000000000000000000..775b97a4048d6db730aca5e2f7de4d469519474b --- /dev/null +++ b/vendor/golang.org/x/crypto/argon2/argon2_test.go @@ -0,0 +1,233 @@ +// Copyright 2017 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 argon2 + +import ( + "bytes" + "encoding/hex" + "testing" +) + +var ( + genKatPassword = []byte{ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + } + genKatSalt = []byte{0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02} + genKatSecret = []byte{0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03} + genKatAAD = []byte{0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04} +) + +func TestArgon2(t *testing.T) { + defer func(sse4 bool) { useSSE4 = sse4 }(useSSE4) + + if useSSE4 { + t.Log("SSE4.1 version") + testArgon2i(t) + testArgon2d(t) + testArgon2id(t) + useSSE4 = false + } + t.Log("generic version") + testArgon2i(t) + testArgon2d(t) + testArgon2id(t) +} + +func testArgon2d(t *testing.T) { + want := []byte{ + 0x51, 0x2b, 0x39, 0x1b, 0x6f, 0x11, 0x62, 0x97, + 0x53, 0x71, 0xd3, 0x09, 0x19, 0x73, 0x42, 0x94, + 0xf8, 0x68, 0xe3, 0xbe, 0x39, 0x84, 0xf3, 0xc1, + 0xa1, 0x3a, 0x4d, 0xb9, 0xfa, 0xbe, 0x4a, 0xcb, + } + hash := deriveKey(argon2d, genKatPassword, genKatSalt, genKatSecret, genKatAAD, 3, 32, 4, 32) + if !bytes.Equal(hash, want) { + t.Errorf("derived key does not match - got: %s , want: %s", hex.EncodeToString(hash), hex.EncodeToString(want)) + } +} + +func testArgon2i(t *testing.T) { + want := []byte{ + 0xc8, 0x14, 0xd9, 0xd1, 0xdc, 0x7f, 0x37, 0xaa, + 0x13, 0xf0, 0xd7, 0x7f, 0x24, 0x94, 0xbd, 0xa1, + 0xc8, 0xde, 0x6b, 0x01, 0x6d, 0xd3, 0x88, 0xd2, + 0x99, 0x52, 0xa4, 0xc4, 0x67, 0x2b, 0x6c, 0xe8, + } + hash := deriveKey(argon2i, genKatPassword, genKatSalt, genKatSecret, genKatAAD, 3, 32, 4, 32) + if !bytes.Equal(hash, want) { + t.Errorf("derived key does not match - got: %s , want: %s", hex.EncodeToString(hash), hex.EncodeToString(want)) + } +} + +func testArgon2id(t *testing.T) { + want := []byte{ + 0x0d, 0x64, 0x0d, 0xf5, 0x8d, 0x78, 0x76, 0x6c, + 0x08, 0xc0, 0x37, 0xa3, 0x4a, 0x8b, 0x53, 0xc9, + 0xd0, 0x1e, 0xf0, 0x45, 0x2d, 0x75, 0xb6, 0x5e, + 0xb5, 0x25, 0x20, 0xe9, 0x6b, 0x01, 0xe6, 0x59, + } + hash := deriveKey(argon2id, genKatPassword, genKatSalt, genKatSecret, genKatAAD, 3, 32, 4, 32) + if !bytes.Equal(hash, want) { + t.Errorf("derived key does not match - got: %s , want: %s", hex.EncodeToString(hash), hex.EncodeToString(want)) + } +} + +func TestVectors(t *testing.T) { + password, salt := []byte("password"), []byte("somesalt") + for i, v := range testVectors { + want, err := hex.DecodeString(v.hash) + if err != nil { + t.Fatalf("Test %d: failed to decode hash: %v", i, err) + } + hash := deriveKey(v.mode, password, salt, nil, nil, v.time, v.memory, v.threads, uint32(len(want))) + if !bytes.Equal(hash, want) { + t.Errorf("Test %d - got: %s want: %s", i, hex.EncodeToString(hash), hex.EncodeToString(want)) + } + } +} + +func benchmarkArgon2(mode int, time, memory uint32, threads uint8, keyLen uint32, b *testing.B) { + password := []byte("password") + salt := []byte("choosing random salts is hard") + b.ReportAllocs() + for i := 0; i < b.N; i++ { + deriveKey(mode, password, salt, nil, nil, time, memory, threads, keyLen) + } +} + +func BenchmarkArgon2i(b *testing.B) { + b.Run(" Time: 3 Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2i, 3, 32*1024, 1, 32, b) }) + b.Run(" Time: 4 Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2i, 4, 32*1024, 1, 32, b) }) + b.Run(" Time: 5 Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2i, 5, 32*1024, 1, 32, b) }) + b.Run(" Time: 3 Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2i, 3, 64*1024, 4, 32, b) }) + b.Run(" Time: 4 Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2i, 4, 64*1024, 4, 32, b) }) + b.Run(" Time: 5 Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2i, 5, 64*1024, 4, 32, b) }) +} + +func BenchmarkArgon2d(b *testing.B) { + b.Run(" Time: 3, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2d, 3, 32*1024, 1, 32, b) }) + b.Run(" Time: 4, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2d, 4, 32*1024, 1, 32, b) }) + b.Run(" Time: 5, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2d, 5, 32*1024, 1, 32, b) }) + b.Run(" Time: 3, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2d, 3, 64*1024, 4, 32, b) }) + b.Run(" Time: 4, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2d, 4, 64*1024, 4, 32, b) }) + b.Run(" Time: 5, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2d, 5, 64*1024, 4, 32, b) }) +} + +func BenchmarkArgon2id(b *testing.B) { + b.Run(" Time: 3, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2id, 3, 32*1024, 1, 32, b) }) + b.Run(" Time: 4, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2id, 4, 32*1024, 1, 32, b) }) + b.Run(" Time: 5, Memory: 32 MB, Threads: 1", func(b *testing.B) { benchmarkArgon2(argon2id, 5, 32*1024, 1, 32, b) }) + b.Run(" Time: 3, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2id, 3, 64*1024, 4, 32, b) }) + b.Run(" Time: 4, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2id, 4, 64*1024, 4, 32, b) }) + b.Run(" Time: 5, Memory: 64 MB, Threads: 4", func(b *testing.B) { benchmarkArgon2(argon2id, 5, 64*1024, 4, 32, b) }) +} + +// Generated with the CLI of https://github.com/P-H-C/phc-winner-argon2/blob/master/argon2-specs.pdf +var testVectors = []struct { + mode int + time, memory uint32 + threads uint8 + hash string +}{ + { + mode: argon2i, time: 1, memory: 64, threads: 1, + hash: "b9c401d1844a67d50eae3967dc28870b22e508092e861a37", + }, + { + mode: argon2d, time: 1, memory: 64, threads: 1, + hash: "8727405fd07c32c78d64f547f24150d3f2e703a89f981a19", + }, + { + mode: argon2id, time: 1, memory: 64, threads: 1, + hash: "655ad15eac652dc59f7170a7332bf49b8469be1fdb9c28bb", + }, + { + mode: argon2i, time: 2, memory: 64, threads: 1, + hash: "8cf3d8f76a6617afe35fac48eb0b7433a9a670ca4a07ed64", + }, + { + mode: argon2d, time: 2, memory: 64, threads: 1, + hash: "3be9ec79a69b75d3752acb59a1fbb8b295a46529c48fbb75", + }, + { + mode: argon2id, time: 2, memory: 64, threads: 1, + hash: "068d62b26455936aa6ebe60060b0a65870dbfa3ddf8d41f7", + }, + { + mode: argon2i, time: 2, memory: 64, threads: 2, + hash: "2089f3e78a799720f80af806553128f29b132cafe40d059f", + }, + { + mode: argon2d, time: 2, memory: 64, threads: 2, + hash: "68e2462c98b8bc6bb60ec68db418ae2c9ed24fc6748a40e9", + }, + { + mode: argon2id, time: 2, memory: 64, threads: 2, + hash: "350ac37222f436ccb5c0972f1ebd3bf6b958bf2071841362", + }, + { + mode: argon2i, time: 3, memory: 256, threads: 2, + hash: "f5bbf5d4c3836af13193053155b73ec7476a6a2eb93fd5e6", + }, + { + mode: argon2d, time: 3, memory: 256, threads: 2, + hash: "f4f0669218eaf3641f39cc97efb915721102f4b128211ef2", + }, + { + mode: argon2id, time: 3, memory: 256, threads: 2, + hash: "4668d30ac4187e6878eedeacf0fd83c5a0a30db2cc16ef0b", + }, + { + mode: argon2i, time: 4, memory: 4096, threads: 4, + hash: "a11f7b7f3f93f02ad4bddb59ab62d121e278369288a0d0e7", + }, + { + mode: argon2d, time: 4, memory: 4096, threads: 4, + hash: "935598181aa8dc2b720914aa6435ac8d3e3a4210c5b0fb2d", + }, + { + mode: argon2id, time: 4, memory: 4096, threads: 4, + hash: "145db9733a9f4ee43edf33c509be96b934d505a4efb33c5a", + }, + { + mode: argon2i, time: 4, memory: 1024, threads: 8, + hash: "0cdd3956aa35e6b475a7b0c63488822f774f15b43f6e6e17", + }, + { + mode: argon2d, time: 4, memory: 1024, threads: 8, + hash: "83604fc2ad0589b9d055578f4d3cc55bc616df3578a896e9", + }, + { + mode: argon2id, time: 4, memory: 1024, threads: 8, + hash: "8dafa8e004f8ea96bf7c0f93eecf67a6047476143d15577f", + }, + { + mode: argon2i, time: 2, memory: 64, threads: 3, + hash: "5cab452fe6b8479c8661def8cd703b611a3905a6d5477fe6", + }, + { + mode: argon2d, time: 2, memory: 64, threads: 3, + hash: "22474a423bda2ccd36ec9afd5119e5c8949798cadf659f51", + }, + { + mode: argon2id, time: 2, memory: 64, threads: 3, + hash: "4a15b31aec7c2590b87d1f520be7d96f56658172deaa3079", + }, + { + mode: argon2i, time: 3, memory: 1024, threads: 6, + hash: "d236b29c2b2a09babee842b0dec6aa1e83ccbdea8023dced", + }, + { + mode: argon2d, time: 3, memory: 1024, threads: 6, + hash: "a3351b0319a53229152023d9206902f4ef59661cdca89481", + }, + { + mode: argon2id, time: 3, memory: 1024, threads: 6, + hash: "1640b932f4b60e272f5d2207b9a9c626ffa1bd88d2349016", + }, +} diff --git a/vendor/golang.org/x/crypto/argon2/blake2b.go b/vendor/golang.org/x/crypto/argon2/blake2b.go new file mode 100644 index 0000000000000000000000000000000000000000..10f46948dc1053083178c9818fc15408ad19e488 --- /dev/null +++ b/vendor/golang.org/x/crypto/argon2/blake2b.go @@ -0,0 +1,53 @@ +// Copyright 2017 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 argon2 + +import ( + "encoding/binary" + "hash" + + "golang.org/x/crypto/blake2b" +) + +// blake2bHash computes an arbitrary long hash value of in +// and writes the hash to out. +func blake2bHash(out []byte, in []byte) { + var b2 hash.Hash + if n := len(out); n < blake2b.Size { + b2, _ = blake2b.New(n, nil) + } else { + b2, _ = blake2b.New512(nil) + } + + var buffer [blake2b.Size]byte + binary.LittleEndian.PutUint32(buffer[:4], uint32(len(out))) + b2.Write(buffer[:4]) + b2.Write(in) + + if len(out) <= blake2b.Size { + b2.Sum(out[:0]) + return + } + + outLen := len(out) + b2.Sum(buffer[:0]) + b2.Reset() + copy(out, buffer[:32]) + out = out[32:] + for len(out) > blake2b.Size { + b2.Write(buffer[:]) + b2.Sum(buffer[:0]) + copy(out, buffer[:32]) + out = out[32:] + b2.Reset() + } + + if outLen%blake2b.Size > 0 { // outLen > 64 + r := ((outLen + 31) / 32) - 2 // ⌈τ /32⌉-2 + b2, _ = blake2b.New(outLen-32*r, nil) + } + b2.Write(buffer[:]) + b2.Sum(out[:0]) +} diff --git a/vendor/golang.org/x/crypto/argon2/blamka_amd64.go b/vendor/golang.org/x/crypto/argon2/blamka_amd64.go new file mode 100644 index 0000000000000000000000000000000000000000..bb2b0d8b4152cb555c2d906855dc317254de3255 --- /dev/null +++ b/vendor/golang.org/x/crypto/argon2/blamka_amd64.go @@ -0,0 +1,61 @@ +// Copyright 2017 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,!appengine + +package argon2 + +func init() { + useSSE4 = supportsSSE4() +} + +//go:noescape +func supportsSSE4() bool + +//go:noescape +func mixBlocksSSE2(out, a, b, c *block) + +//go:noescape +func xorBlocksSSE2(out, a, b, c *block) + +//go:noescape +func blamkaSSE4(b *block) + +func processBlockSSE(out, in1, in2 *block, xor bool) { + var t block + mixBlocksSSE2(&t, in1, in2, &t) + if useSSE4 { + blamkaSSE4(&t) + } else { + for i := 0; i < blockLength; i += 16 { + blamkaGeneric( + &t[i+0], &t[i+1], &t[i+2], &t[i+3], + &t[i+4], &t[i+5], &t[i+6], &t[i+7], + &t[i+8], &t[i+9], &t[i+10], &t[i+11], + &t[i+12], &t[i+13], &t[i+14], &t[i+15], + ) + } + for i := 0; i < blockLength/8; i += 2 { + blamkaGeneric( + &t[i], &t[i+1], &t[16+i], &t[16+i+1], + &t[32+i], &t[32+i+1], &t[48+i], &t[48+i+1], + &t[64+i], &t[64+i+1], &t[80+i], &t[80+i+1], + &t[96+i], &t[96+i+1], &t[112+i], &t[112+i+1], + ) + } + } + if xor { + xorBlocksSSE2(out, in1, in2, &t) + } else { + mixBlocksSSE2(out, in1, in2, &t) + } +} + +func processBlock(out, in1, in2 *block) { + processBlockSSE(out, in1, in2, false) +} + +func processBlockXOR(out, in1, in2 *block) { + processBlockSSE(out, in1, in2, true) +} diff --git a/vendor/golang.org/x/crypto/argon2/blamka_amd64.s b/vendor/golang.org/x/crypto/argon2/blamka_amd64.s new file mode 100644 index 0000000000000000000000000000000000000000..8a83f7c73985a16a84fbf829d51cb93ef64b1532 --- /dev/null +++ b/vendor/golang.org/x/crypto/argon2/blamka_amd64.s @@ -0,0 +1,252 @@ +// Copyright 2017 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,!appengine + +#include "textflag.h" + +DATA ·c40<>+0x00(SB)/8, $0x0201000706050403 +DATA ·c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b +GLOBL ·c40<>(SB), (NOPTR+RODATA), $16 + +DATA ·c48<>+0x00(SB)/8, $0x0100070605040302 +DATA ·c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a +GLOBL ·c48<>(SB), (NOPTR+RODATA), $16 + +#define SHUFFLE(v2, v3, v4, v5, v6, v7, t1, t2) \ + MOVO v4, t1; \ + MOVO v5, v4; \ + MOVO t1, v5; \ + MOVO v6, t1; \ + PUNPCKLQDQ v6, t2; \ + PUNPCKHQDQ v7, v6; \ + PUNPCKHQDQ t2, v6; \ + PUNPCKLQDQ v7, t2; \ + MOVO t1, v7; \ + MOVO v2, t1; \ + PUNPCKHQDQ t2, v7; \ + PUNPCKLQDQ v3, t2; \ + PUNPCKHQDQ t2, v2; \ + PUNPCKLQDQ t1, t2; \ + PUNPCKHQDQ t2, v3 + +#define SHUFFLE_INV(v2, v3, v4, v5, v6, v7, t1, t2) \ + MOVO v4, t1; \ + MOVO v5, v4; \ + MOVO t1, v5; \ + MOVO v2, t1; \ + PUNPCKLQDQ v2, t2; \ + PUNPCKHQDQ v3, v2; \ + PUNPCKHQDQ t2, v2; \ + PUNPCKLQDQ v3, t2; \ + MOVO t1, v3; \ + MOVO v6, t1; \ + PUNPCKHQDQ t2, v3; \ + PUNPCKLQDQ v7, t2; \ + PUNPCKHQDQ t2, v6; \ + PUNPCKLQDQ t1, t2; \ + PUNPCKHQDQ t2, v7 + +#define HALF_ROUND(v0, v1, v2, v3, v4, v5, v6, v7, t0, c40, c48) \ + MOVO v0, t0; \ + PMULULQ v2, t0; \ + PADDQ v2, v0; \ + PADDQ t0, v0; \ + PADDQ t0, v0; \ + PXOR v0, v6; \ + PSHUFD $0xB1, v6, v6; \ + MOVO v4, t0; \ + PMULULQ v6, t0; \ + PADDQ v6, v4; \ + PADDQ t0, v4; \ + PADDQ t0, v4; \ + PXOR v4, v2; \ + PSHUFB c40, v2; \ + MOVO v0, t0; \ + PMULULQ v2, t0; \ + PADDQ v2, v0; \ + PADDQ t0, v0; \ + PADDQ t0, v0; \ + PXOR v0, v6; \ + PSHUFB c48, v6; \ + MOVO v4, t0; \ + PMULULQ v6, t0; \ + PADDQ v6, v4; \ + PADDQ t0, v4; \ + PADDQ t0, v4; \ + PXOR v4, v2; \ + MOVO v2, t0; \ + PADDQ v2, t0; \ + PSRLQ $63, v2; \ + PXOR t0, v2; \ + MOVO v1, t0; \ + PMULULQ v3, t0; \ + PADDQ v3, v1; \ + PADDQ t0, v1; \ + PADDQ t0, v1; \ + PXOR v1, v7; \ + PSHUFD $0xB1, v7, v7; \ + MOVO v5, t0; \ + PMULULQ v7, t0; \ + PADDQ v7, v5; \ + PADDQ t0, v5; \ + PADDQ t0, v5; \ + PXOR v5, v3; \ + PSHUFB c40, v3; \ + MOVO v1, t0; \ + PMULULQ v3, t0; \ + PADDQ v3, v1; \ + PADDQ t0, v1; \ + PADDQ t0, v1; \ + PXOR v1, v7; \ + PSHUFB c48, v7; \ + MOVO v5, t0; \ + PMULULQ v7, t0; \ + PADDQ v7, v5; \ + PADDQ t0, v5; \ + PADDQ t0, v5; \ + PXOR v5, v3; \ + MOVO v3, t0; \ + PADDQ v3, t0; \ + PSRLQ $63, v3; \ + PXOR t0, v3 + +#define LOAD_MSG_0(block, off) \ + MOVOU 8*(off+0)(block), X0; \ + MOVOU 8*(off+2)(block), X1; \ + MOVOU 8*(off+4)(block), X2; \ + MOVOU 8*(off+6)(block), X3; \ + MOVOU 8*(off+8)(block), X4; \ + MOVOU 8*(off+10)(block), X5; \ + MOVOU 8*(off+12)(block), X6; \ + MOVOU 8*(off+14)(block), X7 + +#define STORE_MSG_0(block, off) \ + MOVOU X0, 8*(off+0)(block); \ + MOVOU X1, 8*(off+2)(block); \ + MOVOU X2, 8*(off+4)(block); \ + MOVOU X3, 8*(off+6)(block); \ + MOVOU X4, 8*(off+8)(block); \ + MOVOU X5, 8*(off+10)(block); \ + MOVOU X6, 8*(off+12)(block); \ + MOVOU X7, 8*(off+14)(block) + +#define LOAD_MSG_1(block, off) \ + MOVOU 8*off+0*8(block), X0; \ + MOVOU 8*off+16*8(block), X1; \ + MOVOU 8*off+32*8(block), X2; \ + MOVOU 8*off+48*8(block), X3; \ + MOVOU 8*off+64*8(block), X4; \ + MOVOU 8*off+80*8(block), X5; \ + MOVOU 8*off+96*8(block), X6; \ + MOVOU 8*off+112*8(block), X7 + +#define STORE_MSG_1(block, off) \ + MOVOU X0, 8*off+0*8(block); \ + MOVOU X1, 8*off+16*8(block); \ + MOVOU X2, 8*off+32*8(block); \ + MOVOU X3, 8*off+48*8(block); \ + MOVOU X4, 8*off+64*8(block); \ + MOVOU X5, 8*off+80*8(block); \ + MOVOU X6, 8*off+96*8(block); \ + MOVOU X7, 8*off+112*8(block) + +#define BLAMKA_ROUND_0(block, off, t0, t1, c40, c48) \ + LOAD_MSG_0(block, off); \ + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, t0, c40, c48); \ + SHUFFLE(X2, X3, X4, X5, X6, X7, t0, t1); \ + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, t0, c40, c48); \ + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, t0, t1); \ + STORE_MSG_0(block, off) + +#define BLAMKA_ROUND_1(block, off, t0, t1, c40, c48) \ + LOAD_MSG_1(block, off); \ + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, t0, c40, c48); \ + SHUFFLE(X2, X3, X4, X5, X6, X7, t0, t1); \ + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, t0, c40, c48); \ + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, t0, t1); \ + STORE_MSG_1(block, off) + +// func blamkaSSE4(b *block) +TEXT ·blamkaSSE4(SB), 4, $0-8 + MOVQ b+0(FP), AX + + MOVOU ·c40<>(SB), X10 + MOVOU ·c48<>(SB), X11 + + BLAMKA_ROUND_0(AX, 0, X8, X9, X10, X11) + BLAMKA_ROUND_0(AX, 16, X8, X9, X10, X11) + BLAMKA_ROUND_0(AX, 32, X8, X9, X10, X11) + BLAMKA_ROUND_0(AX, 48, X8, X9, X10, X11) + BLAMKA_ROUND_0(AX, 64, X8, X9, X10, X11) + BLAMKA_ROUND_0(AX, 80, X8, X9, X10, X11) + BLAMKA_ROUND_0(AX, 96, X8, X9, X10, X11) + BLAMKA_ROUND_0(AX, 112, X8, X9, X10, X11) + + BLAMKA_ROUND_1(AX, 0, X8, X9, X10, X11) + BLAMKA_ROUND_1(AX, 2, X8, X9, X10, X11) + BLAMKA_ROUND_1(AX, 4, X8, X9, X10, X11) + BLAMKA_ROUND_1(AX, 6, X8, X9, X10, X11) + BLAMKA_ROUND_1(AX, 8, X8, X9, X10, X11) + BLAMKA_ROUND_1(AX, 10, X8, X9, X10, X11) + BLAMKA_ROUND_1(AX, 12, X8, X9, X10, X11) + BLAMKA_ROUND_1(AX, 14, X8, X9, X10, X11) + RET + +// func mixBlocksSSE2(out, a, b, c *block) +TEXT ·mixBlocksSSE2(SB), 4, $0-32 + MOVQ out+0(FP), DX + MOVQ a+8(FP), AX + MOVQ b+16(FP), BX + MOVQ a+24(FP), CX + MOVQ $128, BP + +loop: + MOVOU 0(AX), X0 + MOVOU 0(BX), X1 + MOVOU 0(CX), X2 + PXOR X1, X0 + PXOR X2, X0 + MOVOU X0, 0(DX) + ADDQ $16, AX + ADDQ $16, BX + ADDQ $16, CX + ADDQ $16, DX + SUBQ $2, BP + JA loop + RET + +// func xorBlocksSSE2(out, a, b, c *block) +TEXT ·xorBlocksSSE2(SB), 4, $0-32 + MOVQ out+0(FP), DX + MOVQ a+8(FP), AX + MOVQ b+16(FP), BX + MOVQ a+24(FP), CX + MOVQ $128, BP + +loop: + MOVOU 0(AX), X0 + MOVOU 0(BX), X1 + MOVOU 0(CX), X2 + MOVOU 0(DX), X3 + PXOR X1, X0 + PXOR X2, X0 + PXOR X3, X0 + MOVOU X0, 0(DX) + ADDQ $16, AX + ADDQ $16, BX + ADDQ $16, CX + ADDQ $16, DX + SUBQ $2, BP + JA loop + RET + +// func supportsSSE4() bool +TEXT ·supportsSSE4(SB), 4, $0-1 + MOVL $1, AX + CPUID + SHRL $19, CX // Bit 19 indicates SSE4 support + ANDL $1, CX // CX != 0 if support SSE4 + MOVB CX, ret+0(FP) + RET diff --git a/vendor/golang.org/x/crypto/argon2/blamka_generic.go b/vendor/golang.org/x/crypto/argon2/blamka_generic.go new file mode 100644 index 0000000000000000000000000000000000000000..a481b2243f855fda59f2d0cb3092061d36d14eb9 --- /dev/null +++ b/vendor/golang.org/x/crypto/argon2/blamka_generic.go @@ -0,0 +1,163 @@ +// Copyright 2017 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 argon2 + +var useSSE4 bool + +func processBlockGeneric(out, in1, in2 *block, xor bool) { + var t block + for i := range t { + t[i] = in1[i] ^ in2[i] + } + for i := 0; i < blockLength; i += 16 { + blamkaGeneric( + &t[i+0], &t[i+1], &t[i+2], &t[i+3], + &t[i+4], &t[i+5], &t[i+6], &t[i+7], + &t[i+8], &t[i+9], &t[i+10], &t[i+11], + &t[i+12], &t[i+13], &t[i+14], &t[i+15], + ) + } + for i := 0; i < blockLength/8; i += 2 { + blamkaGeneric( + &t[i], &t[i+1], &t[16+i], &t[16+i+1], + &t[32+i], &t[32+i+1], &t[48+i], &t[48+i+1], + &t[64+i], &t[64+i+1], &t[80+i], &t[80+i+1], + &t[96+i], &t[96+i+1], &t[112+i], &t[112+i+1], + ) + } + if xor { + for i := range t { + out[i] ^= in1[i] ^ in2[i] ^ t[i] + } + } else { + for i := range t { + out[i] = in1[i] ^ in2[i] ^ t[i] + } + } +} + +func blamkaGeneric(t00, t01, t02, t03, t04, t05, t06, t07, t08, t09, t10, t11, t12, t13, t14, t15 *uint64) { + v00, v01, v02, v03 := *t00, *t01, *t02, *t03 + v04, v05, v06, v07 := *t04, *t05, *t06, *t07 + v08, v09, v10, v11 := *t08, *t09, *t10, *t11 + v12, v13, v14, v15 := *t12, *t13, *t14, *t15 + + v00 += v04 + 2*uint64(uint32(v00))*uint64(uint32(v04)) + v12 ^= v00 + v12 = v12>>32 | v12<<32 + v08 += v12 + 2*uint64(uint32(v08))*uint64(uint32(v12)) + v04 ^= v08 + v04 = v04>>24 | v04<<40 + + v00 += v04 + 2*uint64(uint32(v00))*uint64(uint32(v04)) + v12 ^= v00 + v12 = v12>>16 | v12<<48 + v08 += v12 + 2*uint64(uint32(v08))*uint64(uint32(v12)) + v04 ^= v08 + v04 = v04>>63 | v04<<1 + + v01 += v05 + 2*uint64(uint32(v01))*uint64(uint32(v05)) + v13 ^= v01 + v13 = v13>>32 | v13<<32 + v09 += v13 + 2*uint64(uint32(v09))*uint64(uint32(v13)) + v05 ^= v09 + v05 = v05>>24 | v05<<40 + + v01 += v05 + 2*uint64(uint32(v01))*uint64(uint32(v05)) + v13 ^= v01 + v13 = v13>>16 | v13<<48 + v09 += v13 + 2*uint64(uint32(v09))*uint64(uint32(v13)) + v05 ^= v09 + v05 = v05>>63 | v05<<1 + + v02 += v06 + 2*uint64(uint32(v02))*uint64(uint32(v06)) + v14 ^= v02 + v14 = v14>>32 | v14<<32 + v10 += v14 + 2*uint64(uint32(v10))*uint64(uint32(v14)) + v06 ^= v10 + v06 = v06>>24 | v06<<40 + + v02 += v06 + 2*uint64(uint32(v02))*uint64(uint32(v06)) + v14 ^= v02 + v14 = v14>>16 | v14<<48 + v10 += v14 + 2*uint64(uint32(v10))*uint64(uint32(v14)) + v06 ^= v10 + v06 = v06>>63 | v06<<1 + + v03 += v07 + 2*uint64(uint32(v03))*uint64(uint32(v07)) + v15 ^= v03 + v15 = v15>>32 | v15<<32 + v11 += v15 + 2*uint64(uint32(v11))*uint64(uint32(v15)) + v07 ^= v11 + v07 = v07>>24 | v07<<40 + + v03 += v07 + 2*uint64(uint32(v03))*uint64(uint32(v07)) + v15 ^= v03 + v15 = v15>>16 | v15<<48 + v11 += v15 + 2*uint64(uint32(v11))*uint64(uint32(v15)) + v07 ^= v11 + v07 = v07>>63 | v07<<1 + + v00 += v05 + 2*uint64(uint32(v00))*uint64(uint32(v05)) + v15 ^= v00 + v15 = v15>>32 | v15<<32 + v10 += v15 + 2*uint64(uint32(v10))*uint64(uint32(v15)) + v05 ^= v10 + v05 = v05>>24 | v05<<40 + + v00 += v05 + 2*uint64(uint32(v00))*uint64(uint32(v05)) + v15 ^= v00 + v15 = v15>>16 | v15<<48 + v10 += v15 + 2*uint64(uint32(v10))*uint64(uint32(v15)) + v05 ^= v10 + v05 = v05>>63 | v05<<1 + + v01 += v06 + 2*uint64(uint32(v01))*uint64(uint32(v06)) + v12 ^= v01 + v12 = v12>>32 | v12<<32 + v11 += v12 + 2*uint64(uint32(v11))*uint64(uint32(v12)) + v06 ^= v11 + v06 = v06>>24 | v06<<40 + + v01 += v06 + 2*uint64(uint32(v01))*uint64(uint32(v06)) + v12 ^= v01 + v12 = v12>>16 | v12<<48 + v11 += v12 + 2*uint64(uint32(v11))*uint64(uint32(v12)) + v06 ^= v11 + v06 = v06>>63 | v06<<1 + + v02 += v07 + 2*uint64(uint32(v02))*uint64(uint32(v07)) + v13 ^= v02 + v13 = v13>>32 | v13<<32 + v08 += v13 + 2*uint64(uint32(v08))*uint64(uint32(v13)) + v07 ^= v08 + v07 = v07>>24 | v07<<40 + + v02 += v07 + 2*uint64(uint32(v02))*uint64(uint32(v07)) + v13 ^= v02 + v13 = v13>>16 | v13<<48 + v08 += v13 + 2*uint64(uint32(v08))*uint64(uint32(v13)) + v07 ^= v08 + v07 = v07>>63 | v07<<1 + + v03 += v04 + 2*uint64(uint32(v03))*uint64(uint32(v04)) + v14 ^= v03 + v14 = v14>>32 | v14<<32 + v09 += v14 + 2*uint64(uint32(v09))*uint64(uint32(v14)) + v04 ^= v09 + v04 = v04>>24 | v04<<40 + + v03 += v04 + 2*uint64(uint32(v03))*uint64(uint32(v04)) + v14 ^= v03 + v14 = v14>>16 | v14<<48 + v09 += v14 + 2*uint64(uint32(v09))*uint64(uint32(v14)) + v04 ^= v09 + v04 = v04>>63 | v04<<1 + + *t00, *t01, *t02, *t03 = v00, v01, v02, v03 + *t04, *t05, *t06, *t07 = v04, v05, v06, v07 + *t08, *t09, *t10, *t11 = v08, v09, v10, v11 + *t12, *t13, *t14, *t15 = v12, v13, v14, v15 +} diff --git a/vendor/golang.org/x/crypto/argon2/blamka_ref.go b/vendor/golang.org/x/crypto/argon2/blamka_ref.go new file mode 100644 index 0000000000000000000000000000000000000000..baf7b551daf7d41a9190268ab7b07cdabb9b18aa --- /dev/null +++ b/vendor/golang.org/x/crypto/argon2/blamka_ref.go @@ -0,0 +1,15 @@ +// Copyright 2017 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 appengine gccgo + +package argon2 + +func processBlock(out, in1, in2 *block) { + processBlockGeneric(out, in1, in2, false) +} + +func processBlockXOR(out, in1, in2 *block) { + processBlockGeneric(out, in1, in2, true) +} diff --git a/vendor/golang.org/x/crypto/bcrypt/base64.go b/vendor/golang.org/x/crypto/bcrypt/base64.go new file mode 100644 index 0000000000000000000000000000000000000000..fc311609081849d379013a25310456fbb1a6e66a --- /dev/null +++ b/vendor/golang.org/x/crypto/bcrypt/base64.go @@ -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 +} diff --git a/vendor/golang.org/x/crypto/bcrypt/bcrypt.go b/vendor/golang.org/x/crypto/bcrypt/bcrypt.go new file mode 100644 index 0000000000000000000000000000000000000000..aeb73f81a14c8567262ecf3f0363c20addabdcfc --- /dev/null +++ b/vendor/golang.org/x/crypto/bcrypt/bcrypt.go @@ -0,0 +1,295 @@ +// 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" + "io" + "strconv" + + "golang.org/x/crypto/blowfish" +) + +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. + // We copy the key to prevent changing the underlying array. + ckey := append(key[:len(key):len(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++ + copy(arr[n:], []byte(fmt.Sprintf("%02d", p.cost))) + n += 2 + arr[n] = '$' + n++ + 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 +} diff --git a/vendor/golang.org/x/crypto/bcrypt/bcrypt_test.go b/vendor/golang.org/x/crypto/bcrypt/bcrypt_test.go new file mode 100644 index 0000000000000000000000000000000000000000..aecf759eb13a35f5c0ed1426b48f55ee053594c4 --- /dev/null +++ b/vendor/golang.org/x/crypto/bcrypt/bcrypt_test.go @@ -0,0 +1,243 @@ +// 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) + } +} + +// See Issue https://github.com/golang/go/issues/20425. +func TestNoSideEffectsFromCompare(t *testing.T) { + source := []byte("passw0rd123456") + password := source[:len(source)-6] + token := source[len(source)-6:] + want := make([]byte, len(source)) + copy(want, source) + + wantHash := []byte("$2a$10$LK9XRuhNxHHCvjX3tdkRKei1QiCDUKrJRhZv7WWZPuQGRUM92rOUa") + _ = CompareHashAndPassword(wantHash, password) + + got := bytes.Join([][]byte{password, token}, []byte("")) + if !bytes.Equal(got, want) { + t.Errorf("got=%q want=%q", got, want) + } +} diff --git a/vendor/golang.org/x/crypto/blake2b/blake2b.go b/vendor/golang.org/x/crypto/blake2b/blake2b.go new file mode 100644 index 0000000000000000000000000000000000000000..6dedb89467ae18a9824fca2cc7874c590a128739 --- /dev/null +++ b/vendor/golang.org/x/crypto/blake2b/blake2b.go @@ -0,0 +1,221 @@ +// Copyright 2016 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 blake2b implements the BLAKE2b hash algorithm defined by RFC 7693 +// and the extendable output function (XOF) BLAKE2Xb. +// +// For a detailed specification of BLAKE2b see https://blake2.net/blake2.pdf +// and for BLAKE2Xb see https://blake2.net/blake2x.pdf +// +// If you aren't sure which function you need, use BLAKE2b (Sum512 or New512). +// If you need a secret-key MAC (message authentication code), use the New512 +// function with a non-nil key. +// +// BLAKE2X is a construction to compute hash values larger than 64 bytes. It +// can produce hash values between 0 and 4 GiB. +package blake2b + +import ( + "encoding/binary" + "errors" + "hash" +) + +const ( + // The blocksize of BLAKE2b in bytes. + BlockSize = 128 + // The hash size of BLAKE2b-512 in bytes. + Size = 64 + // The hash size of BLAKE2b-384 in bytes. + Size384 = 48 + // The hash size of BLAKE2b-256 in bytes. + Size256 = 32 +) + +var ( + useAVX2 bool + useAVX bool + useSSE4 bool +) + +var ( + errKeySize = errors.New("blake2b: invalid key size") + errHashSize = errors.New("blake2b: invalid hash size") +) + +var iv = [8]uint64{ + 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, + 0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179, +} + +// Sum512 returns the BLAKE2b-512 checksum of the data. +func Sum512(data []byte) [Size]byte { + var sum [Size]byte + checkSum(&sum, Size, data) + return sum +} + +// Sum384 returns the BLAKE2b-384 checksum of the data. +func Sum384(data []byte) [Size384]byte { + var sum [Size]byte + var sum384 [Size384]byte + checkSum(&sum, Size384, data) + copy(sum384[:], sum[:Size384]) + return sum384 +} + +// Sum256 returns the BLAKE2b-256 checksum of the data. +func Sum256(data []byte) [Size256]byte { + var sum [Size]byte + var sum256 [Size256]byte + checkSum(&sum, Size256, data) + copy(sum256[:], sum[:Size256]) + return sum256 +} + +// New512 returns a new hash.Hash computing the BLAKE2b-512 checksum. A non-nil +// key turns the hash into a MAC. The key must between zero and 64 bytes long. +func New512(key []byte) (hash.Hash, error) { return newDigest(Size, key) } + +// New384 returns a new hash.Hash computing the BLAKE2b-384 checksum. A non-nil +// key turns the hash into a MAC. The key must between zero and 64 bytes long. +func New384(key []byte) (hash.Hash, error) { return newDigest(Size384, key) } + +// New256 returns a new hash.Hash computing the BLAKE2b-256 checksum. A non-nil +// key turns the hash into a MAC. The key must between zero and 64 bytes long. +func New256(key []byte) (hash.Hash, error) { return newDigest(Size256, key) } + +// New returns a new hash.Hash computing the BLAKE2b checksum with a custom length. +// A non-nil key turns the hash into a MAC. The key must between zero and 64 bytes long. +// The hash size can be a value between 1 and 64 but it is highly recommended to use +// values equal or greater than: +// - 32 if BLAKE2b is used as a hash function (The key is zero bytes long). +// - 16 if BLAKE2b is used as a MAC function (The key is at least 16 bytes long). +func New(size int, key []byte) (hash.Hash, error) { return newDigest(size, key) } + +func newDigest(hashSize int, key []byte) (*digest, error) { + if hashSize < 1 || hashSize > Size { + return nil, errHashSize + } + if len(key) > Size { + return nil, errKeySize + } + d := &digest{ + size: hashSize, + keyLen: len(key), + } + copy(d.key[:], key) + d.Reset() + return d, nil +} + +func checkSum(sum *[Size]byte, hashSize int, data []byte) { + h := iv + h[0] ^= uint64(hashSize) | (1 << 16) | (1 << 24) + var c [2]uint64 + + if length := len(data); length > BlockSize { + n := length &^ (BlockSize - 1) + if length == n { + n -= BlockSize + } + hashBlocks(&h, &c, 0, data[:n]) + data = data[n:] + } + + var block [BlockSize]byte + offset := copy(block[:], data) + remaining := uint64(BlockSize - offset) + if c[0] < remaining { + c[1]-- + } + c[0] -= remaining + + hashBlocks(&h, &c, 0xFFFFFFFFFFFFFFFF, block[:]) + + for i, v := range h[:(hashSize+7)/8] { + binary.LittleEndian.PutUint64(sum[8*i:], v) + } +} + +type digest struct { + h [8]uint64 + c [2]uint64 + size int + block [BlockSize]byte + offset int + + key [BlockSize]byte + keyLen int +} + +func (d *digest) BlockSize() int { return BlockSize } + +func (d *digest) Size() int { return d.size } + +func (d *digest) Reset() { + d.h = iv + d.h[0] ^= uint64(d.size) | (uint64(d.keyLen) << 8) | (1 << 16) | (1 << 24) + d.offset, d.c[0], d.c[1] = 0, 0, 0 + if d.keyLen > 0 { + d.block = d.key + d.offset = BlockSize + } +} + +func (d *digest) Write(p []byte) (n int, err error) { + n = len(p) + + if d.offset > 0 { + remaining := BlockSize - d.offset + if n <= remaining { + d.offset += copy(d.block[d.offset:], p) + return + } + copy(d.block[d.offset:], p[:remaining]) + hashBlocks(&d.h, &d.c, 0, d.block[:]) + d.offset = 0 + p = p[remaining:] + } + + if length := len(p); length > BlockSize { + nn := length &^ (BlockSize - 1) + if length == nn { + nn -= BlockSize + } + hashBlocks(&d.h, &d.c, 0, p[:nn]) + p = p[nn:] + } + + if len(p) > 0 { + d.offset += copy(d.block[:], p) + } + + return +} + +func (d *digest) Sum(sum []byte) []byte { + var hash [Size]byte + d.finalize(&hash) + return append(sum, hash[:d.size]...) +} + +func (d *digest) finalize(hash *[Size]byte) { + var block [BlockSize]byte + copy(block[:], d.block[:d.offset]) + remaining := uint64(BlockSize - d.offset) + + c := d.c + if c[0] < remaining { + c[1]-- + } + c[0] -= remaining + + h := d.h + hashBlocks(&h, &c, 0xFFFFFFFFFFFFFFFF, block[:]) + + for i, v := range h { + binary.LittleEndian.PutUint64(hash[8*i:], v) + } +} diff --git a/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go b/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go new file mode 100644 index 0000000000000000000000000000000000000000..8c41cf6c79ea75463e00b94c94b5b3f5f46b48e1 --- /dev/null +++ b/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go @@ -0,0 +1,43 @@ +// Copyright 2016 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 go1.7,amd64,!gccgo,!appengine + +package blake2b + +func init() { + useAVX2 = supportsAVX2() + useAVX = supportsAVX() + useSSE4 = supportsSSE4() +} + +//go:noescape +func supportsSSE4() bool + +//go:noescape +func supportsAVX() bool + +//go:noescape +func supportsAVX2() bool + +//go:noescape +func hashBlocksAVX2(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) + +//go:noescape +func hashBlocksAVX(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) + +//go:noescape +func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) + +func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) { + if useAVX2 { + hashBlocksAVX2(h, c, flag, blocks) + } else if useAVX { + hashBlocksAVX(h, c, flag, blocks) + } else if useSSE4 { + hashBlocksSSE4(h, c, flag, blocks) + } else { + hashBlocksGeneric(h, c, flag, blocks) + } +} diff --git a/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s b/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s new file mode 100644 index 0000000000000000000000000000000000000000..784bce6a9c43c57aedc008747e90aefd240c485c --- /dev/null +++ b/vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s @@ -0,0 +1,762 @@ +// Copyright 2016 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 go1.7,amd64,!gccgo,!appengine + +#include "textflag.h" + +DATA ·AVX2_iv0<>+0x00(SB)/8, $0x6a09e667f3bcc908 +DATA ·AVX2_iv0<>+0x08(SB)/8, $0xbb67ae8584caa73b +DATA ·AVX2_iv0<>+0x10(SB)/8, $0x3c6ef372fe94f82b +DATA ·AVX2_iv0<>+0x18(SB)/8, $0xa54ff53a5f1d36f1 +GLOBL ·AVX2_iv0<>(SB), (NOPTR+RODATA), $32 + +DATA ·AVX2_iv1<>+0x00(SB)/8, $0x510e527fade682d1 +DATA ·AVX2_iv1<>+0x08(SB)/8, $0x9b05688c2b3e6c1f +DATA ·AVX2_iv1<>+0x10(SB)/8, $0x1f83d9abfb41bd6b +DATA ·AVX2_iv1<>+0x18(SB)/8, $0x5be0cd19137e2179 +GLOBL ·AVX2_iv1<>(SB), (NOPTR+RODATA), $32 + +DATA ·AVX2_c40<>+0x00(SB)/8, $0x0201000706050403 +DATA ·AVX2_c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b +DATA ·AVX2_c40<>+0x10(SB)/8, $0x0201000706050403 +DATA ·AVX2_c40<>+0x18(SB)/8, $0x0a09080f0e0d0c0b +GLOBL ·AVX2_c40<>(SB), (NOPTR+RODATA), $32 + +DATA ·AVX2_c48<>+0x00(SB)/8, $0x0100070605040302 +DATA ·AVX2_c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a +DATA ·AVX2_c48<>+0x10(SB)/8, $0x0100070605040302 +DATA ·AVX2_c48<>+0x18(SB)/8, $0x09080f0e0d0c0b0a +GLOBL ·AVX2_c48<>(SB), (NOPTR+RODATA), $32 + +DATA ·AVX_iv0<>+0x00(SB)/8, $0x6a09e667f3bcc908 +DATA ·AVX_iv0<>+0x08(SB)/8, $0xbb67ae8584caa73b +GLOBL ·AVX_iv0<>(SB), (NOPTR+RODATA), $16 + +DATA ·AVX_iv1<>+0x00(SB)/8, $0x3c6ef372fe94f82b +DATA ·AVX_iv1<>+0x08(SB)/8, $0xa54ff53a5f1d36f1 +GLOBL ·AVX_iv1<>(SB), (NOPTR+RODATA), $16 + +DATA ·AVX_iv2<>+0x00(SB)/8, $0x510e527fade682d1 +DATA ·AVX_iv2<>+0x08(SB)/8, $0x9b05688c2b3e6c1f +GLOBL ·AVX_iv2<>(SB), (NOPTR+RODATA), $16 + +DATA ·AVX_iv3<>+0x00(SB)/8, $0x1f83d9abfb41bd6b +DATA ·AVX_iv3<>+0x08(SB)/8, $0x5be0cd19137e2179 +GLOBL ·AVX_iv3<>(SB), (NOPTR+RODATA), $16 + +DATA ·AVX_c40<>+0x00(SB)/8, $0x0201000706050403 +DATA ·AVX_c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b +GLOBL ·AVX_c40<>(SB), (NOPTR+RODATA), $16 + +DATA ·AVX_c48<>+0x00(SB)/8, $0x0100070605040302 +DATA ·AVX_c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a +GLOBL ·AVX_c48<>(SB), (NOPTR+RODATA), $16 + +#define VPERMQ_0x39_Y1_Y1 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9; BYTE $0x39 +#define VPERMQ_0x93_Y1_Y1 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9; BYTE $0x93 +#define VPERMQ_0x4E_Y2_Y2 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xd2; BYTE $0x4e +#define VPERMQ_0x93_Y3_Y3 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb; BYTE $0x93 +#define VPERMQ_0x39_Y3_Y3 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb; BYTE $0x39 + +#define ROUND_AVX2(m0, m1, m2, m3, t, c40, c48) \ + VPADDQ m0, Y0, Y0; \ + VPADDQ Y1, Y0, Y0; \ + VPXOR Y0, Y3, Y3; \ + VPSHUFD $-79, Y3, Y3; \ + VPADDQ Y3, Y2, Y2; \ + VPXOR Y2, Y1, Y1; \ + VPSHUFB c40, Y1, Y1; \ + VPADDQ m1, Y0, Y0; \ + VPADDQ Y1, Y0, Y0; \ + VPXOR Y0, Y3, Y3; \ + VPSHUFB c48, Y3, Y3; \ + VPADDQ Y3, Y2, Y2; \ + VPXOR Y2, Y1, Y1; \ + VPADDQ Y1, Y1, t; \ + VPSRLQ $63, Y1, Y1; \ + VPXOR t, Y1, Y1; \ + VPERMQ_0x39_Y1_Y1; \ + VPERMQ_0x4E_Y2_Y2; \ + VPERMQ_0x93_Y3_Y3; \ + VPADDQ m2, Y0, Y0; \ + VPADDQ Y1, Y0, Y0; \ + VPXOR Y0, Y3, Y3; \ + VPSHUFD $-79, Y3, Y3; \ + VPADDQ Y3, Y2, Y2; \ + VPXOR Y2, Y1, Y1; \ + VPSHUFB c40, Y1, Y1; \ + VPADDQ m3, Y0, Y0; \ + VPADDQ Y1, Y0, Y0; \ + VPXOR Y0, Y3, Y3; \ + VPSHUFB c48, Y3, Y3; \ + VPADDQ Y3, Y2, Y2; \ + VPXOR Y2, Y1, Y1; \ + VPADDQ Y1, Y1, t; \ + VPSRLQ $63, Y1, Y1; \ + VPXOR t, Y1, Y1; \ + VPERMQ_0x39_Y3_Y3; \ + VPERMQ_0x4E_Y2_Y2; \ + VPERMQ_0x93_Y1_Y1 + +#define VMOVQ_SI_X11_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x1E +#define VMOVQ_SI_X12_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x26 +#define VMOVQ_SI_X13_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x2E +#define VMOVQ_SI_X14_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x36 +#define VMOVQ_SI_X15_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x3E + +#define VMOVQ_SI_X11(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x5E; BYTE $n +#define VMOVQ_SI_X12(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x66; BYTE $n +#define VMOVQ_SI_X13(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x6E; BYTE $n +#define VMOVQ_SI_X14(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x76; BYTE $n +#define VMOVQ_SI_X15(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x7E; BYTE $n + +#define VPINSRQ_1_SI_X11_0 BYTE $0xC4; BYTE $0x63; BYTE $0xA1; BYTE $0x22; BYTE $0x1E; BYTE $0x01 +#define VPINSRQ_1_SI_X12_0 BYTE $0xC4; BYTE $0x63; BYTE $0x99; BYTE $0x22; BYTE $0x26; BYTE $0x01 +#define VPINSRQ_1_SI_X13_0 BYTE $0xC4; BYTE $0x63; BYTE $0x91; BYTE $0x22; BYTE $0x2E; BYTE $0x01 +#define VPINSRQ_1_SI_X14_0 BYTE $0xC4; BYTE $0x63; BYTE $0x89; BYTE $0x22; BYTE $0x36; BYTE $0x01 +#define VPINSRQ_1_SI_X15_0 BYTE $0xC4; BYTE $0x63; BYTE $0x81; BYTE $0x22; BYTE $0x3E; BYTE $0x01 + +#define VPINSRQ_1_SI_X11(n) BYTE $0xC4; BYTE $0x63; BYTE $0xA1; BYTE $0x22; BYTE $0x5E; BYTE $n; BYTE $0x01 +#define VPINSRQ_1_SI_X12(n) BYTE $0xC4; BYTE $0x63; BYTE $0x99; BYTE $0x22; BYTE $0x66; BYTE $n; BYTE $0x01 +#define VPINSRQ_1_SI_X13(n) BYTE $0xC4; BYTE $0x63; BYTE $0x91; BYTE $0x22; BYTE $0x6E; BYTE $n; BYTE $0x01 +#define VPINSRQ_1_SI_X14(n) BYTE $0xC4; BYTE $0x63; BYTE $0x89; BYTE $0x22; BYTE $0x76; BYTE $n; BYTE $0x01 +#define VPINSRQ_1_SI_X15(n) BYTE $0xC4; BYTE $0x63; BYTE $0x81; BYTE $0x22; BYTE $0x7E; BYTE $n; BYTE $0x01 + +#define VMOVQ_R8_X15 BYTE $0xC4; BYTE $0x41; BYTE $0xF9; BYTE $0x6E; BYTE $0xF8 +#define VPINSRQ_1_R9_X15 BYTE $0xC4; BYTE $0x43; BYTE $0x81; BYTE $0x22; BYTE $0xF9; BYTE $0x01 + +// load msg: Y12 = (i0, i1, i2, i3) +// i0, i1, i2, i3 must not be 0 +#define LOAD_MSG_AVX2_Y12(i0, i1, i2, i3) \ + VMOVQ_SI_X12(i0*8); \ + VMOVQ_SI_X11(i2*8); \ + VPINSRQ_1_SI_X12(i1*8); \ + VPINSRQ_1_SI_X11(i3*8); \ + VINSERTI128 $1, X11, Y12, Y12 + +// load msg: Y13 = (i0, i1, i2, i3) +// i0, i1, i2, i3 must not be 0 +#define LOAD_MSG_AVX2_Y13(i0, i1, i2, i3) \ + VMOVQ_SI_X13(i0*8); \ + VMOVQ_SI_X11(i2*8); \ + VPINSRQ_1_SI_X13(i1*8); \ + VPINSRQ_1_SI_X11(i3*8); \ + VINSERTI128 $1, X11, Y13, Y13 + +// load msg: Y14 = (i0, i1, i2, i3) +// i0, i1, i2, i3 must not be 0 +#define LOAD_MSG_AVX2_Y14(i0, i1, i2, i3) \ + VMOVQ_SI_X14(i0*8); \ + VMOVQ_SI_X11(i2*8); \ + VPINSRQ_1_SI_X14(i1*8); \ + VPINSRQ_1_SI_X11(i3*8); \ + VINSERTI128 $1, X11, Y14, Y14 + +// load msg: Y15 = (i0, i1, i2, i3) +// i0, i1, i2, i3 must not be 0 +#define LOAD_MSG_AVX2_Y15(i0, i1, i2, i3) \ + VMOVQ_SI_X15(i0*8); \ + VMOVQ_SI_X11(i2*8); \ + VPINSRQ_1_SI_X15(i1*8); \ + VPINSRQ_1_SI_X11(i3*8); \ + VINSERTI128 $1, X11, Y15, Y15 + +#define LOAD_MSG_AVX2_0_2_4_6_1_3_5_7_8_10_12_14_9_11_13_15() \ + VMOVQ_SI_X12_0; \ + VMOVQ_SI_X11(4*8); \ + VPINSRQ_1_SI_X12(2*8); \ + VPINSRQ_1_SI_X11(6*8); \ + VINSERTI128 $1, X11, Y12, Y12; \ + LOAD_MSG_AVX2_Y13(1, 3, 5, 7); \ + LOAD_MSG_AVX2_Y14(8, 10, 12, 14); \ + LOAD_MSG_AVX2_Y15(9, 11, 13, 15) + +#define LOAD_MSG_AVX2_14_4_9_13_10_8_15_6_1_0_11_5_12_2_7_3() \ + LOAD_MSG_AVX2_Y12(14, 4, 9, 13); \ + LOAD_MSG_AVX2_Y13(10, 8, 15, 6); \ + VMOVQ_SI_X11(11*8); \ + VPSHUFD $0x4E, 0*8(SI), X14; \ + VPINSRQ_1_SI_X11(5*8); \ + VINSERTI128 $1, X11, Y14, Y14; \ + LOAD_MSG_AVX2_Y15(12, 2, 7, 3) + +#define LOAD_MSG_AVX2_11_12_5_15_8_0_2_13_10_3_7_9_14_6_1_4() \ + VMOVQ_SI_X11(5*8); \ + VMOVDQU 11*8(SI), X12; \ + VPINSRQ_1_SI_X11(15*8); \ + VINSERTI128 $1, X11, Y12, Y12; \ + VMOVQ_SI_X13(8*8); \ + VMOVQ_SI_X11(2*8); \ + VPINSRQ_1_SI_X13_0; \ + VPINSRQ_1_SI_X11(13*8); \ + VINSERTI128 $1, X11, Y13, Y13; \ + LOAD_MSG_AVX2_Y14(10, 3, 7, 9); \ + LOAD_MSG_AVX2_Y15(14, 6, 1, 4) + +#define LOAD_MSG_AVX2_7_3_13_11_9_1_12_14_2_5_4_15_6_10_0_8() \ + LOAD_MSG_AVX2_Y12(7, 3, 13, 11); \ + LOAD_MSG_AVX2_Y13(9, 1, 12, 14); \ + LOAD_MSG_AVX2_Y14(2, 5, 4, 15); \ + VMOVQ_SI_X15(6*8); \ + VMOVQ_SI_X11_0; \ + VPINSRQ_1_SI_X15(10*8); \ + VPINSRQ_1_SI_X11(8*8); \ + VINSERTI128 $1, X11, Y15, Y15 + +#define LOAD_MSG_AVX2_9_5_2_10_0_7_4_15_14_11_6_3_1_12_8_13() \ + LOAD_MSG_AVX2_Y12(9, 5, 2, 10); \ + VMOVQ_SI_X13_0; \ + VMOVQ_SI_X11(4*8); \ + VPINSRQ_1_SI_X13(7*8); \ + VPINSRQ_1_SI_X11(15*8); \ + VINSERTI128 $1, X11, Y13, Y13; \ + LOAD_MSG_AVX2_Y14(14, 11, 6, 3); \ + LOAD_MSG_AVX2_Y15(1, 12, 8, 13) + +#define LOAD_MSG_AVX2_2_6_0_8_12_10_11_3_4_7_15_1_13_5_14_9() \ + VMOVQ_SI_X12(2*8); \ + VMOVQ_SI_X11_0; \ + VPINSRQ_1_SI_X12(6*8); \ + VPINSRQ_1_SI_X11(8*8); \ + VINSERTI128 $1, X11, Y12, Y12; \ + LOAD_MSG_AVX2_Y13(12, 10, 11, 3); \ + LOAD_MSG_AVX2_Y14(4, 7, 15, 1); \ + LOAD_MSG_AVX2_Y15(13, 5, 14, 9) + +#define LOAD_MSG_AVX2_12_1_14_4_5_15_13_10_0_6_9_8_7_3_2_11() \ + LOAD_MSG_AVX2_Y12(12, 1, 14, 4); \ + LOAD_MSG_AVX2_Y13(5, 15, 13, 10); \ + VMOVQ_SI_X14_0; \ + VPSHUFD $0x4E, 8*8(SI), X11; \ + VPINSRQ_1_SI_X14(6*8); \ + VINSERTI128 $1, X11, Y14, Y14; \ + LOAD_MSG_AVX2_Y15(7, 3, 2, 11) + +#define LOAD_MSG_AVX2_13_7_12_3_11_14_1_9_5_15_8_2_0_4_6_10() \ + LOAD_MSG_AVX2_Y12(13, 7, 12, 3); \ + LOAD_MSG_AVX2_Y13(11, 14, 1, 9); \ + LOAD_MSG_AVX2_Y14(5, 15, 8, 2); \ + VMOVQ_SI_X15_0; \ + VMOVQ_SI_X11(6*8); \ + VPINSRQ_1_SI_X15(4*8); \ + VPINSRQ_1_SI_X11(10*8); \ + VINSERTI128 $1, X11, Y15, Y15 + +#define LOAD_MSG_AVX2_6_14_11_0_15_9_3_8_12_13_1_10_2_7_4_5() \ + VMOVQ_SI_X12(6*8); \ + VMOVQ_SI_X11(11*8); \ + VPINSRQ_1_SI_X12(14*8); \ + VPINSRQ_1_SI_X11_0; \ + VINSERTI128 $1, X11, Y12, Y12; \ + LOAD_MSG_AVX2_Y13(15, 9, 3, 8); \ + VMOVQ_SI_X11(1*8); \ + VMOVDQU 12*8(SI), X14; \ + VPINSRQ_1_SI_X11(10*8); \ + VINSERTI128 $1, X11, Y14, Y14; \ + VMOVQ_SI_X15(2*8); \ + VMOVDQU 4*8(SI), X11; \ + VPINSRQ_1_SI_X15(7*8); \ + VINSERTI128 $1, X11, Y15, Y15 + +#define LOAD_MSG_AVX2_10_8_7_1_2_4_6_5_15_9_3_13_11_14_12_0() \ + LOAD_MSG_AVX2_Y12(10, 8, 7, 1); \ + VMOVQ_SI_X13(2*8); \ + VPSHUFD $0x4E, 5*8(SI), X11; \ + VPINSRQ_1_SI_X13(4*8); \ + VINSERTI128 $1, X11, Y13, Y13; \ + LOAD_MSG_AVX2_Y14(15, 9, 3, 13); \ + VMOVQ_SI_X15(11*8); \ + VMOVQ_SI_X11(12*8); \ + VPINSRQ_1_SI_X15(14*8); \ + VPINSRQ_1_SI_X11_0; \ + VINSERTI128 $1, X11, Y15, Y15 + +// func hashBlocksAVX2(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) +TEXT ·hashBlocksAVX2(SB), 4, $320-48 // frame size = 288 + 32 byte alignment + MOVQ h+0(FP), AX + MOVQ c+8(FP), BX + MOVQ flag+16(FP), CX + MOVQ blocks_base+24(FP), SI + MOVQ blocks_len+32(FP), DI + + MOVQ SP, DX + MOVQ SP, R9 + ADDQ $31, R9 + ANDQ $~31, R9 + MOVQ R9, SP + + MOVQ CX, 16(SP) + XORQ CX, CX + MOVQ CX, 24(SP) + + VMOVDQU ·AVX2_c40<>(SB), Y4 + VMOVDQU ·AVX2_c48<>(SB), Y5 + + VMOVDQU 0(AX), Y8 + VMOVDQU 32(AX), Y9 + VMOVDQU ·AVX2_iv0<>(SB), Y6 + VMOVDQU ·AVX2_iv1<>(SB), Y7 + + MOVQ 0(BX), R8 + MOVQ 8(BX), R9 + MOVQ R9, 8(SP) + +loop: + ADDQ $128, R8 + MOVQ R8, 0(SP) + CMPQ R8, $128 + JGE noinc + INCQ R9 + MOVQ R9, 8(SP) + +noinc: + VMOVDQA Y8, Y0 + VMOVDQA Y9, Y1 + VMOVDQA Y6, Y2 + VPXOR 0(SP), Y7, Y3 + + LOAD_MSG_AVX2_0_2_4_6_1_3_5_7_8_10_12_14_9_11_13_15() + VMOVDQA Y12, 32(SP) + VMOVDQA Y13, 64(SP) + VMOVDQA Y14, 96(SP) + VMOVDQA Y15, 128(SP) + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + LOAD_MSG_AVX2_14_4_9_13_10_8_15_6_1_0_11_5_12_2_7_3() + VMOVDQA Y12, 160(SP) + VMOVDQA Y13, 192(SP) + VMOVDQA Y14, 224(SP) + VMOVDQA Y15, 256(SP) + + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + LOAD_MSG_AVX2_11_12_5_15_8_0_2_13_10_3_7_9_14_6_1_4() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + LOAD_MSG_AVX2_7_3_13_11_9_1_12_14_2_5_4_15_6_10_0_8() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + LOAD_MSG_AVX2_9_5_2_10_0_7_4_15_14_11_6_3_1_12_8_13() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + LOAD_MSG_AVX2_2_6_0_8_12_10_11_3_4_7_15_1_13_5_14_9() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + LOAD_MSG_AVX2_12_1_14_4_5_15_13_10_0_6_9_8_7_3_2_11() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + LOAD_MSG_AVX2_13_7_12_3_11_14_1_9_5_15_8_2_0_4_6_10() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + LOAD_MSG_AVX2_6_14_11_0_15_9_3_8_12_13_1_10_2_7_4_5() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + LOAD_MSG_AVX2_10_8_7_1_2_4_6_5_15_9_3_13_11_14_12_0() + ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5) + + ROUND_AVX2(32(SP), 64(SP), 96(SP), 128(SP), Y10, Y4, Y5) + ROUND_AVX2(160(SP), 192(SP), 224(SP), 256(SP), Y10, Y4, Y5) + + VPXOR Y0, Y8, Y8 + VPXOR Y1, Y9, Y9 + VPXOR Y2, Y8, Y8 + VPXOR Y3, Y9, Y9 + + LEAQ 128(SI), SI + SUBQ $128, DI + JNE loop + + MOVQ R8, 0(BX) + MOVQ R9, 8(BX) + + VMOVDQU Y8, 0(AX) + VMOVDQU Y9, 32(AX) + VZEROUPPER + + MOVQ DX, SP + RET + +#define VPUNPCKLQDQ_X2_X2_X15 BYTE $0xC5; BYTE $0x69; BYTE $0x6C; BYTE $0xFA +#define VPUNPCKLQDQ_X3_X3_X15 BYTE $0xC5; BYTE $0x61; BYTE $0x6C; BYTE $0xFB +#define VPUNPCKLQDQ_X7_X7_X15 BYTE $0xC5; BYTE $0x41; BYTE $0x6C; BYTE $0xFF +#define VPUNPCKLQDQ_X13_X13_X15 BYTE $0xC4; BYTE $0x41; BYTE $0x11; BYTE $0x6C; BYTE $0xFD +#define VPUNPCKLQDQ_X14_X14_X15 BYTE $0xC4; BYTE $0x41; BYTE $0x09; BYTE $0x6C; BYTE $0xFE + +#define VPUNPCKHQDQ_X15_X2_X2 BYTE $0xC4; BYTE $0xC1; BYTE $0x69; BYTE $0x6D; BYTE $0xD7 +#define VPUNPCKHQDQ_X15_X3_X3 BYTE $0xC4; BYTE $0xC1; BYTE $0x61; BYTE $0x6D; BYTE $0xDF +#define VPUNPCKHQDQ_X15_X6_X6 BYTE $0xC4; BYTE $0xC1; BYTE $0x49; BYTE $0x6D; BYTE $0xF7 +#define VPUNPCKHQDQ_X15_X7_X7 BYTE $0xC4; BYTE $0xC1; BYTE $0x41; BYTE $0x6D; BYTE $0xFF +#define VPUNPCKHQDQ_X15_X3_X2 BYTE $0xC4; BYTE $0xC1; BYTE $0x61; BYTE $0x6D; BYTE $0xD7 +#define VPUNPCKHQDQ_X15_X7_X6 BYTE $0xC4; BYTE $0xC1; BYTE $0x41; BYTE $0x6D; BYTE $0xF7 +#define VPUNPCKHQDQ_X15_X13_X3 BYTE $0xC4; BYTE $0xC1; BYTE $0x11; BYTE $0x6D; BYTE $0xDF +#define VPUNPCKHQDQ_X15_X13_X7 BYTE $0xC4; BYTE $0xC1; BYTE $0x11; BYTE $0x6D; BYTE $0xFF + +#define SHUFFLE_AVX() \ + VMOVDQA X6, X13; \ + VMOVDQA X2, X14; \ + VMOVDQA X4, X6; \ + VPUNPCKLQDQ_X13_X13_X15; \ + VMOVDQA X5, X4; \ + VMOVDQA X6, X5; \ + VPUNPCKHQDQ_X15_X7_X6; \ + VPUNPCKLQDQ_X7_X7_X15; \ + VPUNPCKHQDQ_X15_X13_X7; \ + VPUNPCKLQDQ_X3_X3_X15; \ + VPUNPCKHQDQ_X15_X2_X2; \ + VPUNPCKLQDQ_X14_X14_X15; \ + VPUNPCKHQDQ_X15_X3_X3; \ + +#define SHUFFLE_AVX_INV() \ + VMOVDQA X2, X13; \ + VMOVDQA X4, X14; \ + VPUNPCKLQDQ_X2_X2_X15; \ + VMOVDQA X5, X4; \ + VPUNPCKHQDQ_X15_X3_X2; \ + VMOVDQA X14, X5; \ + VPUNPCKLQDQ_X3_X3_X15; \ + VMOVDQA X6, X14; \ + VPUNPCKHQDQ_X15_X13_X3; \ + VPUNPCKLQDQ_X7_X7_X15; \ + VPUNPCKHQDQ_X15_X6_X6; \ + VPUNPCKLQDQ_X14_X14_X15; \ + VPUNPCKHQDQ_X15_X7_X7; \ + +#define HALF_ROUND_AVX(v0, v1, v2, v3, v4, v5, v6, v7, m0, m1, m2, m3, t0, c40, c48) \ + VPADDQ m0, v0, v0; \ + VPADDQ v2, v0, v0; \ + VPADDQ m1, v1, v1; \ + VPADDQ v3, v1, v1; \ + VPXOR v0, v6, v6; \ + VPXOR v1, v7, v7; \ + VPSHUFD $-79, v6, v6; \ + VPSHUFD $-79, v7, v7; \ + VPADDQ v6, v4, v4; \ + VPADDQ v7, v5, v5; \ + VPXOR v4, v2, v2; \ + VPXOR v5, v3, v3; \ + VPSHUFB c40, v2, v2; \ + VPSHUFB c40, v3, v3; \ + VPADDQ m2, v0, v0; \ + VPADDQ v2, v0, v0; \ + VPADDQ m3, v1, v1; \ + VPADDQ v3, v1, v1; \ + VPXOR v0, v6, v6; \ + VPXOR v1, v7, v7; \ + VPSHUFB c48, v6, v6; \ + VPSHUFB c48, v7, v7; \ + VPADDQ v6, v4, v4; \ + VPADDQ v7, v5, v5; \ + VPXOR v4, v2, v2; \ + VPXOR v5, v3, v3; \ + VPADDQ v2, v2, t0; \ + VPSRLQ $63, v2, v2; \ + VPXOR t0, v2, v2; \ + VPADDQ v3, v3, t0; \ + VPSRLQ $63, v3, v3; \ + VPXOR t0, v3, v3 + +// load msg: X12 = (i0, i1), X13 = (i2, i3), X14 = (i4, i5), X15 = (i6, i7) +// i0, i1, i2, i3, i4, i5, i6, i7 must not be 0 +#define LOAD_MSG_AVX(i0, i1, i2, i3, i4, i5, i6, i7) \ + VMOVQ_SI_X12(i0*8); \ + VMOVQ_SI_X13(i2*8); \ + VMOVQ_SI_X14(i4*8); \ + VMOVQ_SI_X15(i6*8); \ + VPINSRQ_1_SI_X12(i1*8); \ + VPINSRQ_1_SI_X13(i3*8); \ + VPINSRQ_1_SI_X14(i5*8); \ + VPINSRQ_1_SI_X15(i7*8) + +// load msg: X12 = (0, 2), X13 = (4, 6), X14 = (1, 3), X15 = (5, 7) +#define LOAD_MSG_AVX_0_2_4_6_1_3_5_7() \ + VMOVQ_SI_X12_0; \ + VMOVQ_SI_X13(4*8); \ + VMOVQ_SI_X14(1*8); \ + VMOVQ_SI_X15(5*8); \ + VPINSRQ_1_SI_X12(2*8); \ + VPINSRQ_1_SI_X13(6*8); \ + VPINSRQ_1_SI_X14(3*8); \ + VPINSRQ_1_SI_X15(7*8) + +// load msg: X12 = (1, 0), X13 = (11, 5), X14 = (12, 2), X15 = (7, 3) +#define LOAD_MSG_AVX_1_0_11_5_12_2_7_3() \ + VPSHUFD $0x4E, 0*8(SI), X12; \ + VMOVQ_SI_X13(11*8); \ + VMOVQ_SI_X14(12*8); \ + VMOVQ_SI_X15(7*8); \ + VPINSRQ_1_SI_X13(5*8); \ + VPINSRQ_1_SI_X14(2*8); \ + VPINSRQ_1_SI_X15(3*8) + +// load msg: X12 = (11, 12), X13 = (5, 15), X14 = (8, 0), X15 = (2, 13) +#define LOAD_MSG_AVX_11_12_5_15_8_0_2_13() \ + VMOVDQU 11*8(SI), X12; \ + VMOVQ_SI_X13(5*8); \ + VMOVQ_SI_X14(8*8); \ + VMOVQ_SI_X15(2*8); \ + VPINSRQ_1_SI_X13(15*8); \ + VPINSRQ_1_SI_X14_0; \ + VPINSRQ_1_SI_X15(13*8) + +// load msg: X12 = (2, 5), X13 = (4, 15), X14 = (6, 10), X15 = (0, 8) +#define LOAD_MSG_AVX_2_5_4_15_6_10_0_8() \ + VMOVQ_SI_X12(2*8); \ + VMOVQ_SI_X13(4*8); \ + VMOVQ_SI_X14(6*8); \ + VMOVQ_SI_X15_0; \ + VPINSRQ_1_SI_X12(5*8); \ + VPINSRQ_1_SI_X13(15*8); \ + VPINSRQ_1_SI_X14(10*8); \ + VPINSRQ_1_SI_X15(8*8) + +// load msg: X12 = (9, 5), X13 = (2, 10), X14 = (0, 7), X15 = (4, 15) +#define LOAD_MSG_AVX_9_5_2_10_0_7_4_15() \ + VMOVQ_SI_X12(9*8); \ + VMOVQ_SI_X13(2*8); \ + VMOVQ_SI_X14_0; \ + VMOVQ_SI_X15(4*8); \ + VPINSRQ_1_SI_X12(5*8); \ + VPINSRQ_1_SI_X13(10*8); \ + VPINSRQ_1_SI_X14(7*8); \ + VPINSRQ_1_SI_X15(15*8) + +// load msg: X12 = (2, 6), X13 = (0, 8), X14 = (12, 10), X15 = (11, 3) +#define LOAD_MSG_AVX_2_6_0_8_12_10_11_3() \ + VMOVQ_SI_X12(2*8); \ + VMOVQ_SI_X13_0; \ + VMOVQ_SI_X14(12*8); \ + VMOVQ_SI_X15(11*8); \ + VPINSRQ_1_SI_X12(6*8); \ + VPINSRQ_1_SI_X13(8*8); \ + VPINSRQ_1_SI_X14(10*8); \ + VPINSRQ_1_SI_X15(3*8) + +// load msg: X12 = (0, 6), X13 = (9, 8), X14 = (7, 3), X15 = (2, 11) +#define LOAD_MSG_AVX_0_6_9_8_7_3_2_11() \ + MOVQ 0*8(SI), X12; \ + VPSHUFD $0x4E, 8*8(SI), X13; \ + MOVQ 7*8(SI), X14; \ + MOVQ 2*8(SI), X15; \ + VPINSRQ_1_SI_X12(6*8); \ + VPINSRQ_1_SI_X14(3*8); \ + VPINSRQ_1_SI_X15(11*8) + +// load msg: X12 = (6, 14), X13 = (11, 0), X14 = (15, 9), X15 = (3, 8) +#define LOAD_MSG_AVX_6_14_11_0_15_9_3_8() \ + MOVQ 6*8(SI), X12; \ + MOVQ 11*8(SI), X13; \ + MOVQ 15*8(SI), X14; \ + MOVQ 3*8(SI), X15; \ + VPINSRQ_1_SI_X12(14*8); \ + VPINSRQ_1_SI_X13_0; \ + VPINSRQ_1_SI_X14(9*8); \ + VPINSRQ_1_SI_X15(8*8) + +// load msg: X12 = (5, 15), X13 = (8, 2), X14 = (0, 4), X15 = (6, 10) +#define LOAD_MSG_AVX_5_15_8_2_0_4_6_10() \ + MOVQ 5*8(SI), X12; \ + MOVQ 8*8(SI), X13; \ + MOVQ 0*8(SI), X14; \ + MOVQ 6*8(SI), X15; \ + VPINSRQ_1_SI_X12(15*8); \ + VPINSRQ_1_SI_X13(2*8); \ + VPINSRQ_1_SI_X14(4*8); \ + VPINSRQ_1_SI_X15(10*8) + +// load msg: X12 = (12, 13), X13 = (1, 10), X14 = (2, 7), X15 = (4, 5) +#define LOAD_MSG_AVX_12_13_1_10_2_7_4_5() \ + VMOVDQU 12*8(SI), X12; \ + MOVQ 1*8(SI), X13; \ + MOVQ 2*8(SI), X14; \ + VPINSRQ_1_SI_X13(10*8); \ + VPINSRQ_1_SI_X14(7*8); \ + VMOVDQU 4*8(SI), X15 + +// load msg: X12 = (15, 9), X13 = (3, 13), X14 = (11, 14), X15 = (12, 0) +#define LOAD_MSG_AVX_15_9_3_13_11_14_12_0() \ + MOVQ 15*8(SI), X12; \ + MOVQ 3*8(SI), X13; \ + MOVQ 11*8(SI), X14; \ + MOVQ 12*8(SI), X15; \ + VPINSRQ_1_SI_X12(9*8); \ + VPINSRQ_1_SI_X13(13*8); \ + VPINSRQ_1_SI_X14(14*8); \ + VPINSRQ_1_SI_X15_0 + +// func hashBlocksAVX(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) +TEXT ·hashBlocksAVX(SB), 4, $288-48 // frame size = 272 + 16 byte alignment + MOVQ h+0(FP), AX + MOVQ c+8(FP), BX + MOVQ flag+16(FP), CX + MOVQ blocks_base+24(FP), SI + MOVQ blocks_len+32(FP), DI + + MOVQ SP, BP + MOVQ SP, R9 + ADDQ $15, R9 + ANDQ $~15, R9 + MOVQ R9, SP + + VMOVDQU ·AVX_c40<>(SB), X0 + VMOVDQU ·AVX_c48<>(SB), X1 + VMOVDQA X0, X8 + VMOVDQA X1, X9 + + VMOVDQU ·AVX_iv3<>(SB), X0 + VMOVDQA X0, 0(SP) + XORQ CX, 0(SP) // 0(SP) = ·AVX_iv3 ^ (CX || 0) + + VMOVDQU 0(AX), X10 + VMOVDQU 16(AX), X11 + VMOVDQU 32(AX), X2 + VMOVDQU 48(AX), X3 + + MOVQ 0(BX), R8 + MOVQ 8(BX), R9 + +loop: + ADDQ $128, R8 + CMPQ R8, $128 + JGE noinc + INCQ R9 + +noinc: + VMOVQ_R8_X15 + VPINSRQ_1_R9_X15 + + VMOVDQA X10, X0 + VMOVDQA X11, X1 + VMOVDQU ·AVX_iv0<>(SB), X4 + VMOVDQU ·AVX_iv1<>(SB), X5 + VMOVDQU ·AVX_iv2<>(SB), X6 + + VPXOR X15, X6, X6 + VMOVDQA 0(SP), X7 + + LOAD_MSG_AVX_0_2_4_6_1_3_5_7() + VMOVDQA X12, 16(SP) + VMOVDQA X13, 32(SP) + VMOVDQA X14, 48(SP) + VMOVDQA X15, 64(SP) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX(8, 10, 12, 14, 9, 11, 13, 15) + VMOVDQA X12, 80(SP) + VMOVDQA X13, 96(SP) + VMOVDQA X14, 112(SP) + VMOVDQA X15, 128(SP) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + LOAD_MSG_AVX(14, 4, 9, 13, 10, 8, 15, 6) + VMOVDQA X12, 144(SP) + VMOVDQA X13, 160(SP) + VMOVDQA X14, 176(SP) + VMOVDQA X15, 192(SP) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX_1_0_11_5_12_2_7_3() + VMOVDQA X12, 208(SP) + VMOVDQA X13, 224(SP) + VMOVDQA X14, 240(SP) + VMOVDQA X15, 256(SP) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + LOAD_MSG_AVX_11_12_5_15_8_0_2_13() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX(10, 3, 7, 9, 14, 6, 1, 4) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + LOAD_MSG_AVX(7, 3, 13, 11, 9, 1, 12, 14) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX_2_5_4_15_6_10_0_8() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + LOAD_MSG_AVX_9_5_2_10_0_7_4_15() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX(14, 11, 6, 3, 1, 12, 8, 13) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + LOAD_MSG_AVX_2_6_0_8_12_10_11_3() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX(4, 7, 15, 1, 13, 5, 14, 9) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + LOAD_MSG_AVX(12, 1, 14, 4, 5, 15, 13, 10) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX_0_6_9_8_7_3_2_11() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + LOAD_MSG_AVX(13, 7, 12, 3, 11, 14, 1, 9) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX_5_15_8_2_0_4_6_10() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + LOAD_MSG_AVX_6_14_11_0_15_9_3_8() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX_12_13_1_10_2_7_4_5() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + LOAD_MSG_AVX(10, 8, 7, 1, 2, 4, 6, 5) + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX() + LOAD_MSG_AVX_15_9_3_13_11_14_12_0() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9) + SHUFFLE_AVX_INV() + + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 16(SP), 32(SP), 48(SP), 64(SP), X15, X8, X9) + SHUFFLE_AVX() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 80(SP), 96(SP), 112(SP), 128(SP), X15, X8, X9) + SHUFFLE_AVX_INV() + + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 144(SP), 160(SP), 176(SP), 192(SP), X15, X8, X9) + SHUFFLE_AVX() + HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 208(SP), 224(SP), 240(SP), 256(SP), X15, X8, X9) + SHUFFLE_AVX_INV() + + VMOVDQU 32(AX), X14 + VMOVDQU 48(AX), X15 + VPXOR X0, X10, X10 + VPXOR X1, X11, X11 + VPXOR X2, X14, X14 + VPXOR X3, X15, X15 + VPXOR X4, X10, X10 + VPXOR X5, X11, X11 + VPXOR X6, X14, X2 + VPXOR X7, X15, X3 + VMOVDQU X2, 32(AX) + VMOVDQU X3, 48(AX) + + LEAQ 128(SI), SI + SUBQ $128, DI + JNE loop + + VMOVDQU X10, 0(AX) + VMOVDQU X11, 16(AX) + + MOVQ R8, 0(BX) + MOVQ R9, 8(BX) + VZEROUPPER + + MOVQ BP, SP + RET + +// func supportsAVX2() bool +TEXT ·supportsAVX2(SB), 4, $0-1 + MOVQ runtime·support_avx2(SB), AX + MOVB AX, ret+0(FP) + RET + +// func supportsAVX() bool +TEXT ·supportsAVX(SB), 4, $0-1 + MOVQ runtime·support_avx(SB), AX + MOVB AX, ret+0(FP) + RET diff --git a/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.go b/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.go new file mode 100644 index 0000000000000000000000000000000000000000..2ab7c30fc2ba58eea0cdefdc24cd75a9fd6626c5 --- /dev/null +++ b/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.go @@ -0,0 +1,25 @@ +// Copyright 2016 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 !go1.7,amd64,!gccgo,!appengine + +package blake2b + +func init() { + useSSE4 = supportsSSE4() +} + +//go:noescape +func supportsSSE4() bool + +//go:noescape +func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) + +func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) { + if useSSE4 { + hashBlocksSSE4(h, c, flag, blocks) + } else { + hashBlocksGeneric(h, c, flag, blocks) + } +} diff --git a/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s b/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s new file mode 100644 index 0000000000000000000000000000000000000000..64530740b40f8407917af35a127c0c9739f339e3 --- /dev/null +++ b/vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s @@ -0,0 +1,290 @@ +// Copyright 2016 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,!appengine + +#include "textflag.h" + +DATA ·iv0<>+0x00(SB)/8, $0x6a09e667f3bcc908 +DATA ·iv0<>+0x08(SB)/8, $0xbb67ae8584caa73b +GLOBL ·iv0<>(SB), (NOPTR+RODATA), $16 + +DATA ·iv1<>+0x00(SB)/8, $0x3c6ef372fe94f82b +DATA ·iv1<>+0x08(SB)/8, $0xa54ff53a5f1d36f1 +GLOBL ·iv1<>(SB), (NOPTR+RODATA), $16 + +DATA ·iv2<>+0x00(SB)/8, $0x510e527fade682d1 +DATA ·iv2<>+0x08(SB)/8, $0x9b05688c2b3e6c1f +GLOBL ·iv2<>(SB), (NOPTR+RODATA), $16 + +DATA ·iv3<>+0x00(SB)/8, $0x1f83d9abfb41bd6b +DATA ·iv3<>+0x08(SB)/8, $0x5be0cd19137e2179 +GLOBL ·iv3<>(SB), (NOPTR+RODATA), $16 + +DATA ·c40<>+0x00(SB)/8, $0x0201000706050403 +DATA ·c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b +GLOBL ·c40<>(SB), (NOPTR+RODATA), $16 + +DATA ·c48<>+0x00(SB)/8, $0x0100070605040302 +DATA ·c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a +GLOBL ·c48<>(SB), (NOPTR+RODATA), $16 + +#define SHUFFLE(v2, v3, v4, v5, v6, v7, t1, t2) \ + MOVO v4, t1; \ + MOVO v5, v4; \ + MOVO t1, v5; \ + MOVO v6, t1; \ + PUNPCKLQDQ v6, t2; \ + PUNPCKHQDQ v7, v6; \ + PUNPCKHQDQ t2, v6; \ + PUNPCKLQDQ v7, t2; \ + MOVO t1, v7; \ + MOVO v2, t1; \ + PUNPCKHQDQ t2, v7; \ + PUNPCKLQDQ v3, t2; \ + PUNPCKHQDQ t2, v2; \ + PUNPCKLQDQ t1, t2; \ + PUNPCKHQDQ t2, v3 + +#define SHUFFLE_INV(v2, v3, v4, v5, v6, v7, t1, t2) \ + MOVO v4, t1; \ + MOVO v5, v4; \ + MOVO t1, v5; \ + MOVO v2, t1; \ + PUNPCKLQDQ v2, t2; \ + PUNPCKHQDQ v3, v2; \ + PUNPCKHQDQ t2, v2; \ + PUNPCKLQDQ v3, t2; \ + MOVO t1, v3; \ + MOVO v6, t1; \ + PUNPCKHQDQ t2, v3; \ + PUNPCKLQDQ v7, t2; \ + PUNPCKHQDQ t2, v6; \ + PUNPCKLQDQ t1, t2; \ + PUNPCKHQDQ t2, v7 + +#define HALF_ROUND(v0, v1, v2, v3, v4, v5, v6, v7, m0, m1, m2, m3, t0, c40, c48) \ + PADDQ m0, v0; \ + PADDQ m1, v1; \ + PADDQ v2, v0; \ + PADDQ v3, v1; \ + PXOR v0, v6; \ + PXOR v1, v7; \ + PSHUFD $0xB1, v6, v6; \ + PSHUFD $0xB1, v7, v7; \ + PADDQ v6, v4; \ + PADDQ v7, v5; \ + PXOR v4, v2; \ + PXOR v5, v3; \ + PSHUFB c40, v2; \ + PSHUFB c40, v3; \ + PADDQ m2, v0; \ + PADDQ m3, v1; \ + PADDQ v2, v0; \ + PADDQ v3, v1; \ + PXOR v0, v6; \ + PXOR v1, v7; \ + PSHUFB c48, v6; \ + PSHUFB c48, v7; \ + PADDQ v6, v4; \ + PADDQ v7, v5; \ + PXOR v4, v2; \ + PXOR v5, v3; \ + MOVOU v2, t0; \ + PADDQ v2, t0; \ + PSRLQ $63, v2; \ + PXOR t0, v2; \ + MOVOU v3, t0; \ + PADDQ v3, t0; \ + PSRLQ $63, v3; \ + PXOR t0, v3 + +#define LOAD_MSG(m0, m1, m2, m3, src, i0, i1, i2, i3, i4, i5, i6, i7) \ + MOVQ i0*8(src), m0; \ + PINSRQ $1, i1*8(src), m0; \ + MOVQ i2*8(src), m1; \ + PINSRQ $1, i3*8(src), m1; \ + MOVQ i4*8(src), m2; \ + PINSRQ $1, i5*8(src), m2; \ + MOVQ i6*8(src), m3; \ + PINSRQ $1, i7*8(src), m3 + +// func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) +TEXT ·hashBlocksSSE4(SB), 4, $288-48 // frame size = 272 + 16 byte alignment + MOVQ h+0(FP), AX + MOVQ c+8(FP), BX + MOVQ flag+16(FP), CX + MOVQ blocks_base+24(FP), SI + MOVQ blocks_len+32(FP), DI + + MOVQ SP, BP + MOVQ SP, R9 + ADDQ $15, R9 + ANDQ $~15, R9 + MOVQ R9, SP + + MOVOU ·iv3<>(SB), X0 + MOVO X0, 0(SP) + XORQ CX, 0(SP) // 0(SP) = ·iv3 ^ (CX || 0) + + MOVOU ·c40<>(SB), X13 + MOVOU ·c48<>(SB), X14 + + MOVOU 0(AX), X12 + MOVOU 16(AX), X15 + + MOVQ 0(BX), R8 + MOVQ 8(BX), R9 + +loop: + ADDQ $128, R8 + CMPQ R8, $128 + JGE noinc + INCQ R9 + +noinc: + MOVQ R8, X8 + PINSRQ $1, R9, X8 + + MOVO X12, X0 + MOVO X15, X1 + MOVOU 32(AX), X2 + MOVOU 48(AX), X3 + MOVOU ·iv0<>(SB), X4 + MOVOU ·iv1<>(SB), X5 + MOVOU ·iv2<>(SB), X6 + + PXOR X8, X6 + MOVO 0(SP), X7 + + LOAD_MSG(X8, X9, X10, X11, SI, 0, 2, 4, 6, 1, 3, 5, 7) + MOVO X8, 16(SP) + MOVO X9, 32(SP) + MOVO X10, 48(SP) + MOVO X11, 64(SP) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 8, 10, 12, 14, 9, 11, 13, 15) + MOVO X8, 80(SP) + MOVO X9, 96(SP) + MOVO X10, 112(SP) + MOVO X11, 128(SP) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + LOAD_MSG(X8, X9, X10, X11, SI, 14, 4, 9, 13, 10, 8, 15, 6) + MOVO X8, 144(SP) + MOVO X9, 160(SP) + MOVO X10, 176(SP) + MOVO X11, 192(SP) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 1, 0, 11, 5, 12, 2, 7, 3) + MOVO X8, 208(SP) + MOVO X9, 224(SP) + MOVO X10, 240(SP) + MOVO X11, 256(SP) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + LOAD_MSG(X8, X9, X10, X11, SI, 11, 12, 5, 15, 8, 0, 2, 13) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 10, 3, 7, 9, 14, 6, 1, 4) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + LOAD_MSG(X8, X9, X10, X11, SI, 7, 3, 13, 11, 9, 1, 12, 14) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 2, 5, 4, 15, 6, 10, 0, 8) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + LOAD_MSG(X8, X9, X10, X11, SI, 9, 5, 2, 10, 0, 7, 4, 15) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 14, 11, 6, 3, 1, 12, 8, 13) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + LOAD_MSG(X8, X9, X10, X11, SI, 2, 6, 0, 8, 12, 10, 11, 3) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 4, 7, 15, 1, 13, 5, 14, 9) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + LOAD_MSG(X8, X9, X10, X11, SI, 12, 1, 14, 4, 5, 15, 13, 10) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 0, 6, 9, 8, 7, 3, 2, 11) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + LOAD_MSG(X8, X9, X10, X11, SI, 13, 7, 12, 3, 11, 14, 1, 9) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 5, 15, 8, 2, 0, 4, 6, 10) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + LOAD_MSG(X8, X9, X10, X11, SI, 6, 14, 11, 0, 15, 9, 3, 8) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 12, 13, 1, 10, 2, 7, 4, 5) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + LOAD_MSG(X8, X9, X10, X11, SI, 10, 8, 7, 1, 2, 4, 6, 5) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + LOAD_MSG(X8, X9, X10, X11, SI, 15, 9, 3, 13, 11, 14, 12, 0) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, 16(SP), 32(SP), 48(SP), 64(SP), X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, 80(SP), 96(SP), 112(SP), 128(SP), X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, 144(SP), 160(SP), 176(SP), 192(SP), X11, X13, X14) + SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) + HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, 208(SP), 224(SP), 240(SP), 256(SP), X11, X13, X14) + SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) + + MOVOU 32(AX), X10 + MOVOU 48(AX), X11 + PXOR X0, X12 + PXOR X1, X15 + PXOR X2, X10 + PXOR X3, X11 + PXOR X4, X12 + PXOR X5, X15 + PXOR X6, X10 + PXOR X7, X11 + MOVOU X10, 32(AX) + MOVOU X11, 48(AX) + + LEAQ 128(SI), SI + SUBQ $128, DI + JNE loop + + MOVOU X12, 0(AX) + MOVOU X15, 16(AX) + + MOVQ R8, 0(BX) + MOVQ R9, 8(BX) + + MOVQ BP, SP + RET + +// func supportsSSE4() bool +TEXT ·supportsSSE4(SB), 4, $0-1 + MOVL $1, AX + CPUID + SHRL $19, CX // Bit 19 indicates SSE4 support + ANDL $1, CX // CX != 0 if support SSE4 + MOVB CX, ret+0(FP) + RET diff --git a/vendor/golang.org/x/crypto/blake2b/blake2b_generic.go b/vendor/golang.org/x/crypto/blake2b/blake2b_generic.go new file mode 100644 index 0000000000000000000000000000000000000000..4bd2abc91635801151e49f2c50b35b04db03060d --- /dev/null +++ b/vendor/golang.org/x/crypto/blake2b/blake2b_generic.go @@ -0,0 +1,179 @@ +// Copyright 2016 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 blake2b + +import "encoding/binary" + +// the precomputed values for BLAKE2b +// there are 12 16-byte arrays - one for each round +// the entries are calculated from the sigma constants. +var precomputed = [12][16]byte{ + {0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15}, + {14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3}, + {11, 12, 5, 15, 8, 0, 2, 13, 10, 3, 7, 9, 14, 6, 1, 4}, + {7, 3, 13, 11, 9, 1, 12, 14, 2, 5, 4, 15, 6, 10, 0, 8}, + {9, 5, 2, 10, 0, 7, 4, 15, 14, 11, 6, 3, 1, 12, 8, 13}, + {2, 6, 0, 8, 12, 10, 11, 3, 4, 7, 15, 1, 13, 5, 14, 9}, + {12, 1, 14, 4, 5, 15, 13, 10, 0, 6, 9, 8, 7, 3, 2, 11}, + {13, 7, 12, 3, 11, 14, 1, 9, 5, 15, 8, 2, 0, 4, 6, 10}, + {6, 14, 11, 0, 15, 9, 3, 8, 12, 13, 1, 10, 2, 7, 4, 5}, + {10, 8, 7, 1, 2, 4, 6, 5, 15, 9, 3, 13, 11, 14, 12, 0}, + {0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15}, // equal to the first + {14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3}, // equal to the second +} + +func hashBlocksGeneric(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) { + var m [16]uint64 + c0, c1 := c[0], c[1] + + for i := 0; i < len(blocks); { + c0 += BlockSize + if c0 < BlockSize { + c1++ + } + + v0, v1, v2, v3, v4, v5, v6, v7 := h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7] + v8, v9, v10, v11, v12, v13, v14, v15 := iv[0], iv[1], iv[2], iv[3], iv[4], iv[5], iv[6], iv[7] + v12 ^= c0 + v13 ^= c1 + v14 ^= flag + + for j := range m { + m[j] = binary.LittleEndian.Uint64(blocks[i:]) + i += 8 + } + + for j := range precomputed { + s := &(precomputed[j]) + + v0 += m[s[0]] + v0 += v4 + v12 ^= v0 + v12 = v12<<(64-32) | v12>>32 + v8 += v12 + v4 ^= v8 + v4 = v4<<(64-24) | v4>>24 + v1 += m[s[1]] + v1 += v5 + v13 ^= v1 + v13 = v13<<(64-32) | v13>>32 + v9 += v13 + v5 ^= v9 + v5 = v5<<(64-24) | v5>>24 + v2 += m[s[2]] + v2 += v6 + v14 ^= v2 + v14 = v14<<(64-32) | v14>>32 + v10 += v14 + v6 ^= v10 + v6 = v6<<(64-24) | v6>>24 + v3 += m[s[3]] + v3 += v7 + v15 ^= v3 + v15 = v15<<(64-32) | v15>>32 + v11 += v15 + v7 ^= v11 + v7 = v7<<(64-24) | v7>>24 + + v0 += m[s[4]] + v0 += v4 + v12 ^= v0 + v12 = v12<<(64-16) | v12>>16 + v8 += v12 + v4 ^= v8 + v4 = v4<<(64-63) | v4>>63 + v1 += m[s[5]] + v1 += v5 + v13 ^= v1 + v13 = v13<<(64-16) | v13>>16 + v9 += v13 + v5 ^= v9 + v5 = v5<<(64-63) | v5>>63 + v2 += m[s[6]] + v2 += v6 + v14 ^= v2 + v14 = v14<<(64-16) | v14>>16 + v10 += v14 + v6 ^= v10 + v6 = v6<<(64-63) | v6>>63 + v3 += m[s[7]] + v3 += v7 + v15 ^= v3 + v15 = v15<<(64-16) | v15>>16 + v11 += v15 + v7 ^= v11 + v7 = v7<<(64-63) | v7>>63 + + v0 += m[s[8]] + v0 += v5 + v15 ^= v0 + v15 = v15<<(64-32) | v15>>32 + v10 += v15 + v5 ^= v10 + v5 = v5<<(64-24) | v5>>24 + v1 += m[s[9]] + v1 += v6 + v12 ^= v1 + v12 = v12<<(64-32) | v12>>32 + v11 += v12 + v6 ^= v11 + v6 = v6<<(64-24) | v6>>24 + v2 += m[s[10]] + v2 += v7 + v13 ^= v2 + v13 = v13<<(64-32) | v13>>32 + v8 += v13 + v7 ^= v8 + v7 = v7<<(64-24) | v7>>24 + v3 += m[s[11]] + v3 += v4 + v14 ^= v3 + v14 = v14<<(64-32) | v14>>32 + v9 += v14 + v4 ^= v9 + v4 = v4<<(64-24) | v4>>24 + + v0 += m[s[12]] + v0 += v5 + v15 ^= v0 + v15 = v15<<(64-16) | v15>>16 + v10 += v15 + v5 ^= v10 + v5 = v5<<(64-63) | v5>>63 + v1 += m[s[13]] + v1 += v6 + v12 ^= v1 + v12 = v12<<(64-16) | v12>>16 + v11 += v12 + v6 ^= v11 + v6 = v6<<(64-63) | v6>>63 + v2 += m[s[14]] + v2 += v7 + v13 ^= v2 + v13 = v13<<(64-16) | v13>>16 + v8 += v13 + v7 ^= v8 + v7 = v7<<(64-63) | v7>>63 + v3 += m[s[15]] + v3 += v4 + v14 ^= v3 + v14 = v14<<(64-16) | v14>>16 + v9 += v14 + v4 ^= v9 + v4 = v4<<(64-63) | v4>>63 + + } + + h[0] ^= v0 ^ v8 + h[1] ^= v1 ^ v9 + h[2] ^= v2 ^ v10 + h[3] ^= v3 ^ v11 + h[4] ^= v4 ^ v12 + h[5] ^= v5 ^ v13 + h[6] ^= v6 ^ v14 + h[7] ^= v7 ^ v15 + } + c[0], c[1] = c0, c1 +} diff --git a/vendor/golang.org/x/crypto/blake2b/blake2b_ref.go b/vendor/golang.org/x/crypto/blake2b/blake2b_ref.go new file mode 100644 index 0000000000000000000000000000000000000000..da156a1ba62cc43f299c41937eb196f8333c9ee1 --- /dev/null +++ b/vendor/golang.org/x/crypto/blake2b/blake2b_ref.go @@ -0,0 +1,11 @@ +// Copyright 2016 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 appengine gccgo + +package blake2b + +func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) { + hashBlocksGeneric(h, c, flag, blocks) +} diff --git a/vendor/golang.org/x/crypto/blake2b/blake2b_test.go b/vendor/golang.org/x/crypto/blake2b/blake2b_test.go new file mode 100644 index 0000000000000000000000000000000000000000..5d68bbf6044637422ffb1bd2eb8267842e048021 --- /dev/null +++ b/vendor/golang.org/x/crypto/blake2b/blake2b_test.go @@ -0,0 +1,798 @@ +// Copyright 2016 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 blake2b + +import ( + "bytes" + "encoding/hex" + "fmt" + "hash" + "io" + "testing" +) + +func fromHex(s string) []byte { + b, err := hex.DecodeString(s) + if err != nil { + panic(err) + } + return b +} + +func TestHashes(t *testing.T) { + defer func(sse4, avx, avx2 bool) { + useSSE4, useAVX, useAVX2 = sse4, avx, avx2 + }(useSSE4, useAVX, useAVX2) + + if useAVX2 { + t.Log("AVX2 version") + testHashes(t) + useAVX2 = false + } + if useAVX { + t.Log("AVX version") + testHashes(t) + useAVX = false + } + if useSSE4 { + t.Log("SSE4 version") + testHashes(t) + useSSE4 = false + } + t.Log("generic version") + testHashes(t) +} + +func TestHashes2X(t *testing.T) { + defer func(sse4, avx, avx2 bool) { + useSSE4, useAVX, useAVX2 = sse4, avx, avx2 + }(useSSE4, useAVX, useAVX2) + + if useAVX2 { + t.Log("AVX2 version") + testHashes2X(t) + useAVX2 = false + } + if useAVX { + t.Log("AVX version") + testHashes2X(t) + useAVX = false + } + if useSSE4 { + t.Log("SSE4 version") + testHashes2X(t) + useSSE4 = false + } + t.Log("generic version") + testHashes2X(t) +} + +func testHashes(t *testing.T) { + key, _ := hex.DecodeString("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f") + + input := make([]byte, 255) + for i := range input { + input[i] = byte(i) + } + + for i, expectedHex := range hashes { + h, err := New512(key) + if err != nil { + t.Fatalf("#%d: error from New512: %v", i, err) + } + + h.Write(input[:i]) + sum := h.Sum(nil) + + if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex { + t.Fatalf("#%d (single write): got %s, wanted %s", i, gotHex, expectedHex) + } + + h.Reset() + for j := 0; j < i; j++ { + h.Write(input[j : j+1]) + } + + sum = h.Sum(sum[:0]) + if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex { + t.Fatalf("#%d (byte-by-byte): got %s, wanted %s", i, gotHex, expectedHex) + } + } +} + +func testHashes2X(t *testing.T) { + key, _ := hex.DecodeString("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f") + + input := make([]byte, 256) + for i := range input { + input[i] = byte(i) + } + + for i, expectedHex := range hashes2X { + length := uint32(len(expectedHex) / 2) + sum := make([]byte, int(length)) + + h, err := NewXOF(length, key) + if err != nil { + t.Fatalf("#%d: error from NewXOF: %v", i, err) + } + + if _, err := h.Write(input); err != nil { + t.Fatalf("#%d (single write): error from Write: %v", i, err) + } + if _, err := h.Read(sum); err != nil { + t.Fatalf("#%d (single write): error from Read: %v", i, err) + } + if n, err := h.Read(sum); n != 0 || err != io.EOF { + t.Fatalf("#%d (single write): Read did not return (0, io.EOF) after exhaustion, got (%v, %v)", i, n, err) + } + if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex { + t.Fatalf("#%d (single write): got %s, wanted %s", i, gotHex, expectedHex) + } + + h.Reset() + for j := 0; j < len(input); j++ { + h.Write(input[j : j+1]) + } + for j := 0; j < len(sum); j++ { + h = h.Clone() + if _, err := h.Read(sum[j : j+1]); err != nil { + t.Fatalf("#%d (byte-by-byte) - Read %d: error from Read: %v", i, j, err) + } + } + if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex { + t.Fatalf("#%d (byte-by-byte): got %s, wanted %s", i, gotHex, expectedHex) + } + } + + h, err := NewXOF(OutputLengthUnknown, key) + if err != nil { + t.Fatalf("#unknown length: error from NewXOF: %v", err) + } + if _, err := h.Write(input); err != nil { + t.Fatalf("#unknown length: error from Write: %v", err) + } + + var result [64]byte + if n, err := h.Read(result[:]); err != nil { + t.Fatalf("#unknown length: error from Read: %v", err) + } else if n != len(result) { + t.Fatalf("#unknown length: Read returned %d bytes, want %d", n, len(result)) + } + + const expected = "3dbba8516da76bf7330055c66ea36cf1005e92714262b24d9710f51d9e126406e1bcd6497059f9331f1091c3634b695428d475ed432f987040575520a1c29f5e" + if fmt.Sprintf("%x", result) != expected { + t.Fatalf("#unknown length: bad result %x, wanted %s", result, expected) + } +} + +func generateSequence(out []byte, seed uint32) { + a := 0xDEAD4BAD * seed // prime + b := uint32(1) + + for i := range out { // fill the buf + a, b = b, a+b + out[i] = byte(b >> 24) + } +} + +func computeMAC(msg []byte, hashSize int, key []byte) (sum []byte) { + var h hash.Hash + switch hashSize { + case Size: + h, _ = New512(key) + case Size384: + h, _ = New384(key) + case Size256: + h, _ = New256(key) + case 20: + h, _ = newDigest(20, key) + default: + panic("unexpected hashSize") + } + + h.Write(msg) + return h.Sum(sum) +} + +func computeHash(msg []byte, hashSize int) (sum []byte) { + switch hashSize { + case Size: + hash := Sum512(msg) + return hash[:] + case Size384: + hash := Sum384(msg) + return hash[:] + case Size256: + hash := Sum256(msg) + return hash[:] + case 20: + var hash [64]byte + checkSum(&hash, 20, msg) + return hash[:20] + default: + panic("unexpected hashSize") + } +} + +// Test function from RFC 7693. +func TestSelfTest(t *testing.T) { + hashLens := [4]int{20, 32, 48, 64} + msgLens := [6]int{0, 3, 128, 129, 255, 1024} + + msg := make([]byte, 1024) + key := make([]byte, 64) + + h, _ := New256(nil) + for _, hashSize := range hashLens { + for _, msgLength := range msgLens { + generateSequence(msg[:msgLength], uint32(msgLength)) // unkeyed hash + + md := computeHash(msg[:msgLength], hashSize) + h.Write(md) + + generateSequence(key[:], uint32(hashSize)) // keyed hash + md = computeMAC(msg[:msgLength], hashSize, key[:hashSize]) + h.Write(md) + } + } + + sum := h.Sum(nil) + expected := [32]byte{ + 0xc2, 0x3a, 0x78, 0x00, 0xd9, 0x81, 0x23, 0xbd, + 0x10, 0xf5, 0x06, 0xc6, 0x1e, 0x29, 0xda, 0x56, + 0x03, 0xd7, 0x63, 0xb8, 0xbb, 0xad, 0x2e, 0x73, + 0x7f, 0x5e, 0x76, 0x5a, 0x7b, 0xcc, 0xd4, 0x75, + } + if !bytes.Equal(sum, expected[:]) { + t.Fatalf("got %x, wanted %x", sum, expected) + } +} + +// Benchmarks + +func benchmarkSum(b *testing.B, size int) { + data := make([]byte, size) + b.SetBytes(int64(size)) + b.ResetTimer() + for i := 0; i < b.N; i++ { + Sum512(data) + } +} + +func benchmarkWrite(b *testing.B, size int) { + data := make([]byte, size) + h, _ := New512(nil) + b.SetBytes(int64(size)) + b.ResetTimer() + for i := 0; i < b.N; i++ { + h.Write(data) + } +} + +func BenchmarkWrite128(b *testing.B) { benchmarkWrite(b, 128) } +func BenchmarkWrite1K(b *testing.B) { benchmarkWrite(b, 1024) } + +func BenchmarkSum128(b *testing.B) { benchmarkSum(b, 128) } +func BenchmarkSum1K(b *testing.B) { benchmarkSum(b, 1024) } + +// These values were taken from https://blake2.net/blake2b-test.txt. +var hashes = []string{ + "10ebb67700b1868efb4417987acf4690ae9d972fb7a590c2f02871799aaa4786b5e996e8f0f4eb981fc214b005f42d2ff4233499391653df7aefcbc13fc51568", + "961f6dd1e4dd30f63901690c512e78e4b45e4742ed197c3c5e45c549fd25f2e4187b0bc9fe30492b16b0d0bc4ef9b0f34c7003fac09a5ef1532e69430234cebd", + "da2cfbe2d8409a0f38026113884f84b50156371ae304c4430173d08a99d9fb1b983164a3770706d537f49e0c916d9f32b95cc37a95b99d857436f0232c88a965", + "33d0825dddf7ada99b0e7e307104ad07ca9cfd9692214f1561356315e784f3e5a17e364ae9dbb14cb2036df932b77f4b292761365fb328de7afdc6d8998f5fc1", + "beaa5a3d08f3807143cf621d95cd690514d0b49efff9c91d24b59241ec0eefa5f60196d407048bba8d2146828ebcb0488d8842fd56bb4f6df8e19c4b4daab8ac", + "098084b51fd13deae5f4320de94a688ee07baea2800486689a8636117b46c1f4c1f6af7f74ae7c857600456a58a3af251dc4723a64cc7c0a5ab6d9cac91c20bb", + "6044540d560853eb1c57df0077dd381094781cdb9073e5b1b3d3f6c7829e12066bbaca96d989a690de72ca3133a83652ba284a6d62942b271ffa2620c9e75b1f", + "7a8cfe9b90f75f7ecb3acc053aaed6193112b6f6a4aeeb3f65d3de541942deb9e2228152a3c4bbbe72fc3b12629528cfbb09fe630f0474339f54abf453e2ed52", + "380beaf6ea7cc9365e270ef0e6f3a64fb902acae51dd5512f84259ad2c91f4bc4108db73192a5bbfb0cbcf71e46c3e21aee1c5e860dc96e8eb0b7b8426e6abe9", + "60fe3c4535e1b59d9a61ea8500bfac41a69dffb1ceadd9aca323e9a625b64da5763bad7226da02b9c8c4f1a5de140ac5a6c1124e4f718ce0b28ea47393aa6637", + "4fe181f54ad63a2983feaaf77d1e7235c2beb17fa328b6d9505bda327df19fc37f02c4b6f0368ce23147313a8e5738b5fa2a95b29de1c7f8264eb77b69f585cd", + "f228773ce3f3a42b5f144d63237a72d99693adb8837d0e112a8a0f8ffff2c362857ac49c11ec740d1500749dac9b1f4548108bf3155794dcc9e4082849e2b85b", + "962452a8455cc56c8511317e3b1f3b2c37df75f588e94325fdd77070359cf63a9ae6e930936fdf8e1e08ffca440cfb72c28f06d89a2151d1c46cd5b268ef8563", + "43d44bfa18768c59896bf7ed1765cb2d14af8c260266039099b25a603e4ddc5039d6ef3a91847d1088d401c0c7e847781a8a590d33a3c6cb4df0fab1c2f22355", + "dcffa9d58c2a4ca2cdbb0c7aa4c4c1d45165190089f4e983bb1c2cab4aaeff1fa2b5ee516fecd780540240bf37e56c8bcca7fab980e1e61c9400d8a9a5b14ac6", + "6fbf31b45ab0c0b8dad1c0f5f4061379912dde5aa922099a030b725c73346c524291adef89d2f6fd8dfcda6d07dad811a9314536c2915ed45da34947e83de34e", + "a0c65bddde8adef57282b04b11e7bc8aab105b99231b750c021f4a735cb1bcfab87553bba3abb0c3e64a0b6955285185a0bd35fb8cfde557329bebb1f629ee93", + "f99d815550558e81eca2f96718aed10d86f3f1cfb675cce06b0eff02f617c5a42c5aa760270f2679da2677c5aeb94f1142277f21c7f79f3c4f0cce4ed8ee62b1", + "95391da8fc7b917a2044b3d6f5374e1ca072b41454d572c7356c05fd4bc1e0f40b8bb8b4a9f6bce9be2c4623c399b0dca0dab05cb7281b71a21b0ebcd9e55670", + "04b9cd3d20d221c09ac86913d3dc63041989a9a1e694f1e639a3ba7e451840f750c2fc191d56ad61f2e7936bc0ac8e094b60caeed878c18799045402d61ceaf9", + "ec0e0ef707e4ed6c0c66f9e089e4954b058030d2dd86398fe84059631f9ee591d9d77375355149178c0cf8f8e7c49ed2a5e4f95488a2247067c208510fadc44c", + "9a37cce273b79c09913677510eaf7688e89b3314d3532fd2764c39de022a2945b5710d13517af8ddc0316624e73bec1ce67df15228302036f330ab0cb4d218dd", + "4cf9bb8fb3d4de8b38b2f262d3c40f46dfe747e8fc0a414c193d9fcf753106ce47a18f172f12e8a2f1c26726545358e5ee28c9e2213a8787aafbc516d2343152", + "64e0c63af9c808fd893137129867fd91939d53f2af04be4fa268006100069b2d69daa5c5d8ed7fddcb2a70eeecdf2b105dd46a1e3b7311728f639ab489326bc9", + "5e9c93158d659b2def06b0c3c7565045542662d6eee8a96a89b78ade09fe8b3dcc096d4fe48815d88d8f82620156602af541955e1f6ca30dce14e254c326b88f", + "7775dff889458dd11aef417276853e21335eb88e4dec9cfb4e9edb49820088551a2ca60339f12066101169f0dfe84b098fddb148d9da6b3d613df263889ad64b", + "f0d2805afbb91f743951351a6d024f9353a23c7ce1fc2b051b3a8b968c233f46f50f806ecb1568ffaa0b60661e334b21dde04f8fa155ac740eeb42e20b60d764", + "86a2af316e7d7754201b942e275364ac12ea8962ab5bd8d7fb276dc5fbffc8f9a28cae4e4867df6780d9b72524160927c855da5b6078e0b554aa91e31cb9ca1d", + "10bdf0caa0802705e706369baf8a3f79d72c0a03a80675a7bbb00be3a45e516424d1ee88efb56f6d5777545ae6e27765c3a8f5e493fc308915638933a1dfee55", + "b01781092b1748459e2e4ec178696627bf4ebafebba774ecf018b79a68aeb84917bf0b84bb79d17b743151144cd66b7b33a4b9e52c76c4e112050ff5385b7f0b", + "c6dbc61dec6eaeac81e3d5f755203c8e220551534a0b2fd105a91889945a638550204f44093dd998c076205dffad703a0e5cd3c7f438a7e634cd59fededb539e", + "eba51acffb4cea31db4b8d87e9bf7dd48fe97b0253ae67aa580f9ac4a9d941f2bea518ee286818cc9f633f2a3b9fb68e594b48cdd6d515bf1d52ba6c85a203a7", + "86221f3ada52037b72224f105d7999231c5e5534d03da9d9c0a12acb68460cd375daf8e24386286f9668f72326dbf99ba094392437d398e95bb8161d717f8991", + "5595e05c13a7ec4dc8f41fb70cb50a71bce17c024ff6de7af618d0cc4e9c32d9570d6d3ea45b86525491030c0d8f2b1836d5778c1ce735c17707df364d054347", + "ce0f4f6aca89590a37fe034dd74dd5fa65eb1cbd0a41508aaddc09351a3cea6d18cb2189c54b700c009f4cbf0521c7ea01be61c5ae09cb54f27bc1b44d658c82", + "7ee80b06a215a3bca970c77cda8761822bc103d44fa4b33f4d07dcb997e36d55298bceae12241b3fa07fa63be5576068da387b8d5859aeab701369848b176d42", + "940a84b6a84d109aab208c024c6ce9647676ba0aaa11f86dbb7018f9fd2220a6d901a9027f9abcf935372727cbf09ebd61a2a2eeb87653e8ecad1bab85dc8327", + "2020b78264a82d9f4151141adba8d44bf20c5ec062eee9b595a11f9e84901bf148f298e0c9f8777dcdbc7cc4670aac356cc2ad8ccb1629f16f6a76bcefbee760", + "d1b897b0e075ba68ab572adf9d9c436663e43eb3d8e62d92fc49c9be214e6f27873fe215a65170e6bea902408a25b49506f47babd07cecf7113ec10c5dd31252", + "b14d0c62abfa469a357177e594c10c194243ed2025ab8aa5ad2fa41ad318e0ff48cd5e60bec07b13634a711d2326e488a985f31e31153399e73088efc86a5c55", + "4169c5cc808d2697dc2a82430dc23e3cd356dc70a94566810502b8d655b39abf9e7f902fe717e0389219859e1945df1af6ada42e4ccda55a197b7100a30c30a1", + "258a4edb113d66c839c8b1c91f15f35ade609f11cd7f8681a4045b9fef7b0b24c82cda06a5f2067b368825e3914e53d6948ede92efd6e8387fa2e537239b5bee", + "79d2d8696d30f30fb34657761171a11e6c3f1e64cbe7bebee159cb95bfaf812b4f411e2f26d9c421dc2c284a3342d823ec293849e42d1e46b0a4ac1e3c86abaa", + "8b9436010dc5dee992ae38aea97f2cd63b946d94fedd2ec9671dcde3bd4ce9564d555c66c15bb2b900df72edb6b891ebcadfeff63c9ea4036a998be7973981e7", + "c8f68e696ed28242bf997f5b3b34959508e42d613810f1e2a435c96ed2ff560c7022f361a9234b9837feee90bf47922ee0fd5f8ddf823718d86d1e16c6090071", + "b02d3eee4860d5868b2c39ce39bfe81011290564dd678c85e8783f29302dfc1399ba95b6b53cd9ebbf400cca1db0ab67e19a325f2d115812d25d00978ad1bca4", + "7693ea73af3ac4dad21ca0d8da85b3118a7d1c6024cfaf557699868217bc0c2f44a199bc6c0edd519798ba05bd5b1b4484346a47c2cadf6bf30b785cc88b2baf", + "a0e5c1c0031c02e48b7f09a5e896ee9aef2f17fc9e18e997d7f6cac7ae316422c2b1e77984e5f3a73cb45deed5d3f84600105e6ee38f2d090c7d0442ea34c46d", + "41daa6adcfdb69f1440c37b596440165c15ada596813e2e22f060fcd551f24dee8e04ba6890387886ceec4a7a0d7fc6b44506392ec3822c0d8c1acfc7d5aebe8", + "14d4d40d5984d84c5cf7523b7798b254e275a3a8cc0a1bd06ebc0bee726856acc3cbf516ff667cda2058ad5c3412254460a82c92187041363cc77a4dc215e487", + "d0e7a1e2b9a447fee83e2277e9ff8010c2f375ae12fa7aaa8ca5a6317868a26a367a0b69fbc1cf32a55d34eb370663016f3d2110230eba754028a56f54acf57c", + "e771aa8db5a3e043e8178f39a0857ba04a3f18e4aa05743cf8d222b0b095825350ba422f63382a23d92e4149074e816a36c1cd28284d146267940b31f8818ea2", + "feb4fd6f9e87a56bef398b3284d2bda5b5b0e166583a66b61e538457ff0584872c21a32962b9928ffab58de4af2edd4e15d8b35570523207ff4e2a5aa7754caa", + "462f17bf005fb1c1b9e671779f665209ec2873e3e411f98dabf240a1d5ec3f95ce6796b6fc23fe171903b502023467dec7273ff74879b92967a2a43a5a183d33", + "d3338193b64553dbd38d144bea71c5915bb110e2d88180dbc5db364fd6171df317fc7268831b5aef75e4342b2fad8797ba39eddcef80e6ec08159350b1ad696d", + "e1590d585a3d39f7cb599abd479070966409a6846d4377acf4471d065d5db94129cc9be92573b05ed226be1e9b7cb0cabe87918589f80dadd4ef5ef25a93d28e", + "f8f3726ac5a26cc80132493a6fedcb0e60760c09cfc84cad178175986819665e76842d7b9fedf76dddebf5d3f56faaad4477587af21606d396ae570d8e719af2", + "30186055c07949948183c850e9a756cc09937e247d9d928e869e20bafc3cd9721719d34e04a0899b92c736084550186886efba2e790d8be6ebf040b209c439a4", + "f3c4276cb863637712c241c444c5cc1e3554e0fddb174d035819dd83eb700b4ce88df3ab3841ba02085e1a99b4e17310c5341075c0458ba376c95a6818fbb3e2", + "0aa007c4dd9d5832393040a1583c930bca7dc5e77ea53add7e2b3f7c8e231368043520d4a3ef53c969b6bbfd025946f632bd7f765d53c21003b8f983f75e2a6a", + "08e9464720533b23a04ec24f7ae8c103145f765387d738777d3d343477fd1c58db052142cab754ea674378e18766c53542f71970171cc4f81694246b717d7564", + "d37ff7ad297993e7ec21e0f1b4b5ae719cdc83c5db687527f27516cbffa822888a6810ee5c1ca7bfe3321119be1ab7bfa0a502671c8329494df7ad6f522d440f", + "dd9042f6e464dcf86b1262f6accfafbd8cfd902ed3ed89abf78ffa482dbdeeb6969842394c9a1168ae3d481a017842f660002d42447c6b22f7b72f21aae021c9", + "bd965bf31e87d70327536f2a341cebc4768eca275fa05ef98f7f1b71a0351298de006fba73fe6733ed01d75801b4a928e54231b38e38c562b2e33ea1284992fa", + "65676d800617972fbd87e4b9514e1c67402b7a331096d3bfac22f1abb95374abc942f16e9ab0ead33b87c91968a6e509e119ff07787b3ef483e1dcdccf6e3022", + "939fa189699c5d2c81ddd1ffc1fa207c970b6a3685bb29ce1d3e99d42f2f7442da53e95a72907314f4588399a3ff5b0a92beb3f6be2694f9f86ecf2952d5b41c", + "c516541701863f91005f314108ceece3c643e04fc8c42fd2ff556220e616aaa6a48aeb97a84bad74782e8dff96a1a2fa949339d722edcaa32b57067041df88cc", + "987fd6e0d6857c553eaebb3d34970a2c2f6e89a3548f492521722b80a1c21a153892346d2cba6444212d56da9a26e324dccbc0dcde85d4d2ee4399eec5a64e8f", + "ae56deb1c2328d9c4017706bce6e99d41349053ba9d336d677c4c27d9fd50ae6aee17e853154e1f4fe7672346da2eaa31eea53fcf24a22804f11d03da6abfc2b", + "49d6a608c9bde4491870498572ac31aac3fa40938b38a7818f72383eb040ad39532bc06571e13d767e6945ab77c0bdc3b0284253343f9f6c1244ebf2ff0df866", + "da582ad8c5370b4469af862aa6467a2293b2b28bd80ae0e91f425ad3d47249fdf98825cc86f14028c3308c9804c78bfeeeee461444ce243687e1a50522456a1d", + "d5266aa3331194aef852eed86d7b5b2633a0af1c735906f2e13279f14931a9fc3b0eac5ce9245273bd1aa92905abe16278ef7efd47694789a7283b77da3c70f8", + "2962734c28252186a9a1111c732ad4de4506d4b4480916303eb7991d659ccda07a9911914bc75c418ab7a4541757ad054796e26797feaf36e9f6ad43f14b35a4", + "e8b79ec5d06e111bdfafd71e9f5760f00ac8ac5d8bf768f9ff6f08b8f026096b1cc3a4c973333019f1e3553e77da3f98cb9f542e0a90e5f8a940cc58e59844b3", + "dfb320c44f9d41d1efdcc015f08dd5539e526e39c87d509ae6812a969e5431bf4fa7d91ffd03b981e0d544cf72d7b1c0374f8801482e6dea2ef903877eba675e", + "d88675118fdb55a5fb365ac2af1d217bf526ce1ee9c94b2f0090b2c58a06ca58187d7fe57c7bed9d26fca067b4110eefcd9a0a345de872abe20de368001b0745", + "b893f2fc41f7b0dd6e2f6aa2e0370c0cff7df09e3acfcc0e920b6e6fad0ef747c40668417d342b80d2351e8c175f20897a062e9765e6c67b539b6ba8b9170545", + "6c67ec5697accd235c59b486d7b70baeedcbd4aa64ebd4eef3c7eac189561a726250aec4d48cadcafbbe2ce3c16ce2d691a8cce06e8879556d4483ed7165c063", + "f1aa2b044f8f0c638a3f362e677b5d891d6fd2ab0765f6ee1e4987de057ead357883d9b405b9d609eea1b869d97fb16d9b51017c553f3b93c0a1e0f1296fedcd", + "cbaa259572d4aebfc1917acddc582b9f8dfaa928a198ca7acd0f2aa76a134a90252e6298a65b08186a350d5b7626699f8cb721a3ea5921b753ae3a2dce24ba3a", + "fa1549c9796cd4d303dcf452c1fbd5744fd9b9b47003d920b92de34839d07ef2a29ded68f6fc9e6c45e071a2e48bd50c5084e96b657dd0404045a1ddefe282ed", + "5cf2ac897ab444dcb5c8d87c495dbdb34e1838b6b629427caa51702ad0f9688525f13bec503a3c3a2c80a65e0b5715e8afab00ffa56ec455a49a1ad30aa24fcd", + "9aaf80207bace17bb7ab145757d5696bde32406ef22b44292ef65d4519c3bb2ad41a59b62cc3e94b6fa96d32a7faadae28af7d35097219aa3fd8cda31e40c275", + "af88b163402c86745cb650c2988fb95211b94b03ef290eed9662034241fd51cf398f8073e369354c43eae1052f9b63b08191caa138aa54fea889cc7024236897", + "48fa7d64e1ceee27b9864db5ada4b53d00c9bc7626555813d3cd6730ab3cc06ff342d727905e33171bde6e8476e77fb1720861e94b73a2c538d254746285f430", + "0e6fd97a85e904f87bfe85bbeb34f69e1f18105cf4ed4f87aec36c6e8b5f68bd2a6f3dc8a9ecb2b61db4eedb6b2ea10bf9cb0251fb0f8b344abf7f366b6de5ab", + "06622da5787176287fdc8fed440bad187d830099c94e6d04c8e9c954cda70c8bb9e1fc4a6d0baa831b9b78ef6648681a4867a11da93ee36e5e6a37d87fc63f6f", + "1da6772b58fabf9c61f68d412c82f182c0236d7d575ef0b58dd22458d643cd1dfc93b03871c316d8430d312995d4197f0874c99172ba004a01ee295abac24e46", + "3cd2d9320b7b1d5fb9aab951a76023fa667be14a9124e394513918a3f44096ae4904ba0ffc150b63bc7ab1eeb9a6e257e5c8f000a70394a5afd842715de15f29", + "04cdc14f7434e0b4be70cb41db4c779a88eaef6accebcb41f2d42fffe7f32a8e281b5c103a27021d0d08362250753cdf70292195a53a48728ceb5844c2d98bab", + "9071b7a8a075d0095b8fb3ae5113785735ab98e2b52faf91d5b89e44aac5b5d4ebbf91223b0ff4c71905da55342e64655d6ef8c89a4768c3f93a6dc0366b5bc8", + "ebb30240dd96c7bc8d0abe49aa4edcbb4afdc51ff9aaf720d3f9e7fbb0f9c6d6571350501769fc4ebd0b2141247ff400d4fd4be414edf37757bb90a32ac5c65a", + "8532c58bf3c8015d9d1cbe00eef1f5082f8f3632fbe9f1ed4f9dfb1fa79e8283066d77c44c4af943d76b300364aecbd0648c8a8939bd204123f4b56260422dec", + "fe9846d64f7c7708696f840e2d76cb4408b6595c2f81ec6a28a7f2f20cb88cfe6ac0b9e9b8244f08bd7095c350c1d0842f64fb01bb7f532dfcd47371b0aeeb79", + "28f17ea6fb6c42092dc264257e29746321fb5bdaea9873c2a7fa9d8f53818e899e161bc77dfe8090afd82bf2266c5c1bc930a8d1547624439e662ef695f26f24", + "ec6b7d7f030d4850acae3cb615c21dd25206d63e84d1db8d957370737ba0e98467ea0ce274c66199901eaec18a08525715f53bfdb0aacb613d342ebdceeddc3b", + "b403d3691c03b0d3418df327d5860d34bbfcc4519bfbce36bf33b208385fadb9186bc78a76c489d89fd57e7dc75412d23bcd1dae8470ce9274754bb8585b13c5", + "31fc79738b8772b3f55cd8178813b3b52d0db5a419d30ba9495c4b9da0219fac6df8e7c23a811551a62b827f256ecdb8124ac8a6792ccfecc3b3012722e94463", + "bb2039ec287091bcc9642fc90049e73732e02e577e2862b32216ae9bedcd730c4c284ef3968c368b7d37584f97bd4b4dc6ef6127acfe2e6ae2509124e66c8af4", + "f53d68d13f45edfcb9bd415e2831e938350d5380d3432278fc1c0c381fcb7c65c82dafe051d8c8b0d44e0974a0e59ec7bf7ed0459f86e96f329fc79752510fd3", + "8d568c7984f0ecdf7640fbc483b5d8c9f86634f6f43291841b309a350ab9c1137d24066b09da9944bac54d5bb6580d836047aac74ab724b887ebf93d4b32eca9", + "c0b65ce5a96ff774c456cac3b5f2c4cd359b4ff53ef93a3da0778be4900d1e8da1601e769e8f1b02d2a2f8c5b9fa10b44f1c186985468feeb008730283a6657d", + "4900bba6f5fb103ece8ec96ada13a5c3c85488e05551da6b6b33d988e611ec0fe2e3c2aa48ea6ae8986a3a231b223c5d27cec2eadde91ce07981ee652862d1e4", + "c7f5c37c7285f927f76443414d4357ff789647d7a005a5a787e03c346b57f49f21b64fa9cf4b7e45573e23049017567121a9c3d4b2b73ec5e9413577525db45a", + "ec7096330736fdb2d64b5653e7475da746c23a4613a82687a28062d3236364284ac01720ffb406cfe265c0df626a188c9e5963ace5d3d5bb363e32c38c2190a6", + "82e744c75f4649ec52b80771a77d475a3bc091989556960e276a5f9ead92a03f718742cdcfeaee5cb85c44af198adc43a4a428f5f0c2ddb0be36059f06d7df73", + "2834b7a7170f1f5b68559ab78c1050ec21c919740b784a9072f6e5d69f828d70c919c5039fb148e39e2c8a52118378b064ca8d5001cd10a5478387b966715ed6", + "16b4ada883f72f853bb7ef253efcab0c3e2161687ad61543a0d2824f91c1f81347d86be709b16996e17f2dd486927b0288ad38d13063c4a9672c39397d3789b6", + "78d048f3a69d8b54ae0ed63a573ae350d89f7c6cf1f3688930de899afa037697629b314e5cd303aa62feea72a25bf42b304b6c6bcb27fae21c16d925e1fbdac3", + "0f746a48749287ada77a82961f05a4da4abdb7d77b1220f836d09ec814359c0ec0239b8c7b9ff9e02f569d1b301ef67c4612d1de4f730f81c12c40cc063c5caa", + "f0fc859d3bd195fbdc2d591e4cdac15179ec0f1dc821c11df1f0c1d26e6260aaa65b79fafacafd7d3ad61e600f250905f5878c87452897647a35b995bcadc3a3", + "2620f687e8625f6a412460b42e2cef67634208ce10a0cbd4dff7044a41b7880077e9f8dc3b8d1216d3376a21e015b58fb279b521d83f9388c7382c8505590b9b", + "227e3aed8d2cb10b918fcb04f9de3e6d0a57e08476d93759cd7b2ed54a1cbf0239c528fb04bbf288253e601d3bc38b21794afef90b17094a182cac557745e75f", + "1a929901b09c25f27d6b35be7b2f1c4745131fdebca7f3e2451926720434e0db6e74fd693ad29b777dc3355c592a361c4873b01133a57c2e3b7075cbdb86f4fc", + "5fd7968bc2fe34f220b5e3dc5af9571742d73b7d60819f2888b629072b96a9d8ab2d91b82d0a9aaba61bbd39958132fcc4257023d1eca591b3054e2dc81c8200", + "dfcce8cf32870cc6a503eadafc87fd6f78918b9b4d0737db6810be996b5497e7e5cc80e312f61e71ff3e9624436073156403f735f56b0b01845c18f6caf772e6", + "02f7ef3a9ce0fff960f67032b296efca3061f4934d690749f2d01c35c81c14f39a67fa350bc8a0359bf1724bffc3bca6d7c7bba4791fd522a3ad353c02ec5aa8", + "64be5c6aba65d594844ae78bb022e5bebe127fd6b6ffa5a13703855ab63b624dcd1a363f99203f632ec386f3ea767fc992e8ed9686586aa27555a8599d5b808f", + "f78585505c4eaa54a8b5be70a61e735e0ff97af944ddb3001e35d86c4e2199d976104b6ae31750a36a726ed285064f5981b503889fef822fcdc2898dddb7889a", + "e4b5566033869572edfd87479a5bb73c80e8759b91232879d96b1dda36c012076ee5a2ed7ae2de63ef8406a06aea82c188031b560beafb583fb3de9e57952a7e", + "e1b3e7ed867f6c9484a2a97f7715f25e25294e992e41f6a7c161ffc2adc6daaeb7113102d5e6090287fe6ad94ce5d6b739c6ca240b05c76fb73f25dd024bf935", + "85fd085fdc12a080983df07bd7012b0d402a0f4043fcb2775adf0bad174f9b08d1676e476985785c0a5dcc41dbff6d95ef4d66a3fbdc4a74b82ba52da0512b74", + "aed8fa764b0fbff821e05233d2f7b0900ec44d826f95e93c343c1bc3ba5a24374b1d616e7e7aba453a0ada5e4fab5382409e0d42ce9c2bc7fb39a99c340c20f0", + "7ba3b2e297233522eeb343bd3ebcfd835a04007735e87f0ca300cbee6d416565162171581e4020ff4cf176450f1291ea2285cb9ebffe4c56660627685145051c", + "de748bcf89ec88084721e16b85f30adb1a6134d664b5843569babc5bbd1a15ca9b61803c901a4fef32965a1749c9f3a4e243e173939dc5a8dc495c671ab52145", + "aaf4d2bdf200a919706d9842dce16c98140d34bc433df320aba9bd429e549aa7a3397652a4d768277786cf993cde2338673ed2e6b66c961fefb82cd20c93338f", + "c408218968b788bf864f0997e6bc4c3dba68b276e2125a4843296052ff93bf5767b8cdce7131f0876430c1165fec6c4f47adaa4fd8bcfacef463b5d3d0fa61a0", + "76d2d819c92bce55fa8e092ab1bf9b9eab237a25267986cacf2b8ee14d214d730dc9a5aa2d7b596e86a1fd8fa0804c77402d2fcd45083688b218b1cdfa0dcbcb", + "72065ee4dd91c2d8509fa1fc28a37c7fc9fa7d5b3f8ad3d0d7a25626b57b1b44788d4caf806290425f9890a3a2a35a905ab4b37acfd0da6e4517b2525c9651e4", + "64475dfe7600d7171bea0b394e27c9b00d8e74dd1e416a79473682ad3dfdbb706631558055cfc8a40e07bd015a4540dcdea15883cbbf31412df1de1cd4152b91", + "12cd1674a4488a5d7c2b3160d2e2c4b58371bedad793418d6f19c6ee385d70b3e06739369d4df910edb0b0a54cbff43d54544cd37ab3a06cfa0a3ddac8b66c89", + "60756966479dedc6dd4bcff8ea7d1d4ce4d4af2e7b097e32e3763518441147cc12b3c0ee6d2ecabf1198cec92e86a3616fba4f4e872f5825330adbb4c1dee444", + "a7803bcb71bc1d0f4383dde1e0612e04f872b715ad30815c2249cf34abb8b024915cb2fc9f4e7cc4c8cfd45be2d5a91eab0941c7d270e2da4ca4a9f7ac68663a", + "b84ef6a7229a34a750d9a98ee2529871816b87fbe3bc45b45fa5ae82d5141540211165c3c5d7a7476ba5a4aa06d66476f0d9dc49a3f1ee72c3acabd498967414", + "fae4b6d8efc3f8c8e64d001dabec3a21f544e82714745251b2b4b393f2f43e0da3d403c64db95a2cb6e23ebb7b9e94cdd5ddac54f07c4a61bd3cb10aa6f93b49", + "34f7286605a122369540141ded79b8957255da2d4155abbf5a8dbb89c8eb7ede8eeef1daa46dc29d751d045dc3b1d658bb64b80ff8589eddb3824b13da235a6b", + "3b3b48434be27b9eababba43bf6b35f14b30f6a88dc2e750c358470d6b3aa3c18e47db4017fa55106d8252f016371a00f5f8b070b74ba5f23cffc5511c9f09f0", + "ba289ebd6562c48c3e10a8ad6ce02e73433d1e93d7c9279d4d60a7e879ee11f441a000f48ed9f7c4ed87a45136d7dccdca482109c78a51062b3ba4044ada2469", + "022939e2386c5a37049856c850a2bb10a13dfea4212b4c732a8840a9ffa5faf54875c5448816b2785a007da8a8d2bc7d71a54e4e6571f10b600cbdb25d13ede3", + "e6fec19d89ce8717b1a087024670fe026f6c7cbda11caef959bb2d351bf856f8055d1c0ebdaaa9d1b17886fc2c562b5e99642fc064710c0d3488a02b5ed7f6fd", + "94c96f02a8f576aca32ba61c2b206f907285d9299b83ac175c209a8d43d53bfe683dd1d83e7549cb906c28f59ab7c46f8751366a28c39dd5fe2693c9019666c8", + "31a0cd215ebd2cb61de5b9edc91e6195e31c59a5648d5c9f737e125b2605708f2e325ab3381c8dce1a3e958886f1ecdc60318f882cfe20a24191352e617b0f21", + "91ab504a522dce78779f4c6c6ba2e6b6db5565c76d3e7e7c920caf7f757ef9db7c8fcf10e57f03379ea9bf75eb59895d96e149800b6aae01db778bb90afbc989", + "d85cabc6bd5b1a01a5afd8c6734740da9fd1c1acc6db29bfc8a2e5b668b028b6b3154bfb8703fa3180251d589ad38040ceb707c4bad1b5343cb426b61eaa49c1", + "d62efbec2ca9c1f8bd66ce8b3f6a898cb3f7566ba6568c618ad1feb2b65b76c3ce1dd20f7395372faf28427f61c9278049cf0140df434f5633048c86b81e0399", + "7c8fdc6175439e2c3db15bafa7fb06143a6a23bc90f449e79deef73c3d492a671715c193b6fea9f036050b946069856b897e08c00768f5ee5ddcf70b7cd6d0e0", + "58602ee7468e6bc9df21bd51b23c005f72d6cb013f0a1b48cbec5eca299299f97f09f54a9a01483eaeb315a6478bad37ba47ca1347c7c8fc9e6695592c91d723", + "27f5b79ed256b050993d793496edf4807c1d85a7b0a67c9c4fa99860750b0ae66989670a8ffd7856d7ce411599e58c4d77b232a62bef64d15275be46a68235ff", + "3957a976b9f1887bf004a8dca942c92d2b37ea52600f25e0c9bc5707d0279c00c6e85a839b0d2d8eb59c51d94788ebe62474a791cadf52cccf20f5070b6573fc", + "eaa2376d55380bf772ecca9cb0aa4668c95c707162fa86d518c8ce0ca9bf7362b9f2a0adc3ff59922df921b94567e81e452f6c1a07fc817cebe99604b3505d38", + "c1e2c78b6b2734e2480ec550434cb5d613111adcc21d475545c3b1b7e6ff12444476e5c055132e2229dc0f807044bb919b1a5662dd38a9ee65e243a3911aed1a", + "8ab48713389dd0fcf9f965d3ce66b1e559a1f8c58741d67683cd971354f452e62d0207a65e436c5d5d8f8ee71c6abfe50e669004c302b31a7ea8311d4a916051", + "24ce0addaa4c65038bd1b1c0f1452a0b128777aabc94a29df2fd6c7e2f85f8ab9ac7eff516b0e0a825c84a24cfe492eaad0a6308e46dd42fe8333ab971bb30ca", + "5154f929ee03045b6b0c0004fa778edee1d139893267cc84825ad7b36c63de32798e4a166d24686561354f63b00709a1364b3c241de3febf0754045897467cd4", + "e74e907920fd87bd5ad636dd11085e50ee70459c443e1ce5809af2bc2eba39f9e6d7128e0e3712c316da06f4705d78a4838e28121d4344a2c79c5e0db307a677", + "bf91a22334bac20f3fd80663b3cd06c4e8802f30e6b59f90d3035cc9798a217ed5a31abbda7fa6842827bdf2a7a1c21f6fcfccbb54c6c52926f32da816269be1", + "d9d5c74be5121b0bd742f26bffb8c89f89171f3f934913492b0903c271bbe2b3395ef259669bef43b57f7fcc3027db01823f6baee66e4f9fead4d6726c741fce", + "50c8b8cf34cd879f80e2faab3230b0c0e1cc3e9dcadeb1b9d97ab923415dd9a1fe38addd5c11756c67990b256e95ad6d8f9fedce10bf1c90679cde0ecf1be347", + "0a386e7cd5dd9b77a035e09fe6fee2c8ce61b5383c87ea43205059c5e4cd4f4408319bb0a82360f6a58e6c9ce3f487c446063bf813bc6ba535e17fc1826cfc91", + "1f1459cb6b61cbac5f0efe8fc487538f42548987fcd56221cfa7beb22504769e792c45adfb1d6b3d60d7b749c8a75b0bdf14e8ea721b95dca538ca6e25711209", + "e58b3836b7d8fedbb50ca5725c6571e74c0785e97821dab8b6298c10e4c079d4a6cdf22f0fedb55032925c16748115f01a105e77e00cee3d07924dc0d8f90659", + "b929cc6505f020158672deda56d0db081a2ee34c00c1100029bdf8ea98034fa4bf3e8655ec697fe36f40553c5bb46801644a627d3342f4fc92b61f03290fb381", + "72d353994b49d3e03153929a1e4d4f188ee58ab9e72ee8e512f29bc773913819ce057ddd7002c0433ee0a16114e3d156dd2c4a7e80ee53378b8670f23e33ef56", + "c70ef9bfd775d408176737a0736d68517ce1aaad7e81a93c8c1ed967ea214f56c8a377b1763e676615b60f3988241eae6eab9685a5124929d28188f29eab06f7", + "c230f0802679cb33822ef8b3b21bf7a9a28942092901d7dac3760300831026cf354c9232df3e084d9903130c601f63c1f4a4a4b8106e468cd443bbe5a734f45f", + "6f43094cafb5ebf1f7a4937ec50f56a4c9da303cbb55ac1f27f1f1976cd96beda9464f0e7b9c54620b8a9fba983164b8be3578425a024f5fe199c36356b88972", + "3745273f4c38225db2337381871a0c6aafd3af9b018c88aa02025850a5dc3a42a1a3e03e56cbf1b0876d63a441f1d2856a39b8801eb5af325201c415d65e97fe", + "c50c44cca3ec3edaae779a7e179450ebdda2f97067c690aa6c5a4ac7c30139bb27c0df4db3220e63cb110d64f37ffe078db72653e2daacf93ae3f0a2d1a7eb2e", + "8aef263e385cbc61e19b28914243262af5afe8726af3ce39a79c27028cf3ecd3f8d2dfd9cfc9ad91b58f6f20778fd5f02894a3d91c7d57d1e4b866a7f364b6be", + "28696141de6e2d9bcb3235578a66166c1448d3e905a1b482d423be4bc5369bc8c74dae0acc9cc123e1d8ddce9f97917e8c019c552da32d39d2219b9abf0fa8c8", + "2fb9eb2085830181903a9dafe3db428ee15be7662224efd643371fb25646aee716e531eca69b2bdc8233f1a8081fa43da1500302975a77f42fa592136710e9dc", + "66f9a7143f7a3314a669bf2e24bbb35014261d639f495b6c9c1f104fe8e320aca60d4550d69d52edbd5a3cdeb4014ae65b1d87aa770b69ae5c15f4330b0b0ad8", + "f4c4dd1d594c3565e3e25ca43dad82f62abea4835ed4cd811bcd975e46279828d44d4c62c3679f1b7f7b9dd4571d7b49557347b8c5460cbdc1bef690fb2a08c0", + "8f1dc9649c3a84551f8f6e91cac68242a43b1f8f328ee92280257387fa7559aa6db12e4aeadc2d26099178749c6864b357f3f83b2fb3efa8d2a8db056bed6bcc", + "3139c1a7f97afd1675d460ebbc07f2728aa150df849624511ee04b743ba0a833092f18c12dc91b4dd243f333402f59fe28abdbbbae301e7b659c7a26d5c0f979", + "06f94a2996158a819fe34c40de3cf0379fd9fb85b3e363ba3926a0e7d960e3f4c2e0c70c7ce0ccb2a64fc29869f6e7ab12bd4d3f14fce943279027e785fb5c29", + "c29c399ef3eee8961e87565c1ce263925fc3d0ce267d13e48dd9e732ee67b0f69fad56401b0f10fcaac119201046cca28c5b14abdea3212ae65562f7f138db3d", + "4cec4c9df52eef05c3f6faaa9791bc7445937183224ecc37a1e58d0132d35617531d7e795f52af7b1eb9d147de1292d345fe341823f8e6bc1e5badca5c656108", + "898bfbae93b3e18d00697eab7d9704fa36ec339d076131cefdf30edbe8d9cc81c3a80b129659b163a323bab9793d4feed92d54dae966c77529764a09be88db45", + "ee9bd0469d3aaf4f14035be48a2c3b84d9b4b1fff1d945e1f1c1d38980a951be197b25fe22c731f20aeacc930ba9c4a1f4762227617ad350fdabb4e80273a0f4", + "3d4d3113300581cd96acbf091c3d0f3c310138cd6979e6026cde623e2dd1b24d4a8638bed1073344783ad0649cc6305ccec04beb49f31c633088a99b65130267", + "95c0591ad91f921ac7be6d9ce37e0663ed8011c1cfd6d0162a5572e94368bac02024485e6a39854aa46fe38e97d6c6b1947cd272d86b06bb5b2f78b9b68d559d", + "227b79ded368153bf46c0a3ca978bfdbef31f3024a5665842468490b0ff748ae04e7832ed4c9f49de9b1706709d623e5c8c15e3caecae8d5e433430ff72f20eb", + "5d34f3952f0105eef88ae8b64c6ce95ebfade0e02c69b08762a8712d2e4911ad3f941fc4034dc9b2e479fdbcd279b902faf5d838bb2e0c6495d372b5b7029813", + "7f939bf8353abce49e77f14f3750af20b7b03902e1a1e7fb6aaf76d0259cd401a83190f15640e74f3e6c5a90e839c7821f6474757f75c7bf9002084ddc7a62dc", + "062b61a2f9a33a71d7d0a06119644c70b0716a504de7e5e1be49bd7b86e7ed6817714f9f0fc313d06129597e9a2235ec8521de36f7290a90ccfc1ffa6d0aee29", + "f29e01eeae64311eb7f1c6422f946bf7bea36379523e7b2bbaba7d1d34a22d5ea5f1c5a09d5ce1fe682cced9a4798d1a05b46cd72dff5c1b355440b2a2d476bc", + "ec38cd3bbab3ef35d7cb6d5c914298351d8a9dc97fcee051a8a02f58e3ed6184d0b7810a5615411ab1b95209c3c810114fdeb22452084e77f3f847c6dbaafe16", + "c2aef5e0ca43e82641565b8cb943aa8ba53550caef793b6532fafad94b816082f0113a3ea2f63608ab40437ecc0f0229cb8fa224dcf1c478a67d9b64162b92d1", + "15f534efff7105cd1c254d074e27d5898b89313b7d366dc2d7d87113fa7d53aae13f6dba487ad8103d5e854c91fdb6e1e74b2ef6d1431769c30767dde067a35c", + "89acbca0b169897a0a2714c2df8c95b5b79cb69390142b7d6018bb3e3076b099b79a964152a9d912b1b86412b7e372e9cecad7f25d4cbab8a317be36492a67d7", + "e3c0739190ed849c9c962fd9dbb55e207e624fcac1eb417691515499eea8d8267b7e8f1287a63633af5011fde8c4ddf55bfdf722edf88831414f2cfaed59cb9a", + "8d6cf87c08380d2d1506eee46fd4222d21d8c04e585fbfd08269c98f702833a156326a0724656400ee09351d57b440175e2a5de93cc5f80db6daf83576cf75fa", + "da24bede383666d563eeed37f6319baf20d5c75d1635a6ba5ef4cfa1ac95487e96f8c08af600aab87c986ebad49fc70a58b4890b9c876e091016daf49e1d322e", + "f9d1d1b1e87ea7ae753a029750cc1cf3d0157d41805e245c5617bb934e732f0ae3180b78e05bfe76c7c3051e3e3ac78b9b50c05142657e1e03215d6ec7bfd0fc", + "11b7bc1668032048aa43343de476395e814bbbc223678db951a1b03a021efac948cfbe215f97fe9a72a2f6bc039e3956bfa417c1a9f10d6d7ba5d3d32ff323e5", + "b8d9000e4fc2b066edb91afee8e7eb0f24e3a201db8b6793c0608581e628ed0bcc4e5aa6787992a4bcc44e288093e63ee83abd0bc3ec6d0934a674a4da13838a", + "ce325e294f9b6719d6b61278276ae06a2564c03bb0b783fafe785bdf89c7d5acd83e78756d301b445699024eaeb77b54d477336ec2a4f332f2b3f88765ddb0c3", + "29acc30e9603ae2fccf90bf97e6cc463ebe28c1b2f9b4b765e70537c25c702a29dcbfbf14c99c54345ba2b51f17b77b5f15db92bbad8fa95c471f5d070a137cc", + "3379cbaae562a87b4c0425550ffdd6bfe1203f0d666cc7ea095be407a5dfe61ee91441cd5154b3e53b4f5fb31ad4c7a9ad5c7af4ae679aa51a54003a54ca6b2d", + "3095a349d245708c7cf550118703d7302c27b60af5d4e67fc978f8a4e60953c7a04f92fcf41aee64321ccb707a895851552b1e37b00bc5e6b72fa5bcef9e3fff", + "07262d738b09321f4dbccec4bb26f48cb0f0ed246ce0b31b9a6e7bc683049f1f3e5545f28ce932dd985c5ab0f43bd6de0770560af329065ed2e49d34624c2cbb", + "b6405eca8ee3316c87061cc6ec18dba53e6c250c63ba1f3bae9e55dd3498036af08cd272aa24d713c6020d77ab2f3919af1a32f307420618ab97e73953994fb4", + "7ee682f63148ee45f6e5315da81e5c6e557c2c34641fc509c7a5701088c38a74756168e2cd8d351e88fd1a451f360a01f5b2580f9b5a2e8cfc138f3dd59a3ffc", + "1d263c179d6b268f6fa016f3a4f29e943891125ed8593c81256059f5a7b44af2dcb2030d175c00e62ecaf7ee96682aa07ab20a611024a28532b1c25b86657902", + "106d132cbdb4cd2597812846e2bc1bf732fec5f0a5f65dbb39ec4e6dc64ab2ce6d24630d0f15a805c3540025d84afa98e36703c3dbee713e72dde8465bc1be7e", + "0e79968226650667a8d862ea8da4891af56a4e3a8b6d1750e394f0dea76d640d85077bcec2cc86886e506751b4f6a5838f7f0b5fef765d9dc90dcdcbaf079f08", + "521156a82ab0c4e566e5844d5e31ad9aaf144bbd5a464fdca34dbd5717e8ff711d3ffebbfa085d67fe996a34f6d3e4e60b1396bf4b1610c263bdbb834d560816", + "1aba88befc55bc25efbce02db8b9933e46f57661baeabeb21cc2574d2a518a3cba5dc5a38e49713440b25f9c744e75f6b85c9d8f4681f676160f6105357b8406", + "5a9949fcb2c473cda968ac1b5d08566dc2d816d960f57e63b898fa701cf8ebd3f59b124d95bfbbedc5f1cf0e17d5eaed0c02c50b69d8a402cabcca4433b51fd4", + "b0cead09807c672af2eb2b0f06dde46cf5370e15a4096b1a7d7cbb36ec31c205fbefca00b7a4162fa89fb4fb3eb78d79770c23f44e7206664ce3cd931c291e5d", + "bb6664931ec97044e45b2ae420ae1c551a8874bc937d08e969399c3964ebdba8346cdd5d09caafe4c28ba7ec788191ceca65ddd6f95f18583e040d0f30d0364d", + "65bc770a5faa3792369803683e844b0be7ee96f29f6d6a35568006bd5590f9a4ef639b7a8061c7b0424b66b60ac34af3119905f33a9d8c3ae18382ca9b689900", + "ea9b4dca333336aaf839a45c6eaa48b8cb4c7ddabffea4f643d6357ea6628a480a5b45f2b052c1b07d1fedca918b6f1139d80f74c24510dcbaa4be70eacc1b06", + "e6342fb4a780ad975d0e24bce149989b91d360557e87994f6b457b895575cc02d0c15bad3ce7577f4c63927ff13f3e381ff7e72bdbe745324844a9d27e3f1c01", + "3e209c9b33e8e461178ab46b1c64b49a07fb745f1c8bc95fbfb94c6b87c69516651b264ef980937fad41238b91ddc011a5dd777c7efd4494b4b6ecd3a9c22ac0", + "fd6a3d5b1875d80486d6e69694a56dbb04a99a4d051f15db2689776ba1c4882e6d462a603b7015dc9f4b7450f05394303b8652cfb404a266962c41bae6e18a94", + "951e27517e6bad9e4195fc8671dee3e7e9be69cee1422cb9fecfce0dba875f7b310b93ee3a3d558f941f635f668ff832d2c1d033c5e2f0997e4c66f147344e02", + "8eba2f874f1ae84041903c7c4253c82292530fc8509550bfdc34c95c7e2889d5650b0ad8cb988e5c4894cb87fbfbb19612ea93ccc4c5cad17158b9763464b492", + "16f712eaa1b7c6354719a8e7dbdfaf55e4063a4d277d947550019b38dfb564830911057d50506136e2394c3b28945cc964967d54e3000c2181626cfb9b73efd2", + "c39639e7d5c7fb8cdd0fd3e6a52096039437122f21c78f1679cea9d78a734c56ecbeb28654b4f18e342c331f6f7229ec4b4bc281b2d80a6eb50043f31796c88c", + "72d081af99f8a173dcc9a0ac4eb3557405639a29084b54a40172912a2f8a395129d5536f0918e902f9e8fa6000995f4168ddc5f893011be6a0dbc9b8a1a3f5bb", + "c11aa81e5efd24d5fc27ee586cfd8847fbb0e27601ccece5ecca0198e3c7765393bb74457c7e7a27eb9170350e1fb53857177506be3e762cc0f14d8c3afe9077", + "c28f2150b452e6c0c424bcde6f8d72007f9310fed7f2f87de0dbb64f4479d6c1441ba66f44b2accee61609177ed340128b407ecec7c64bbe50d63d22d8627727", + "f63d88122877ec30b8c8b00d22e89000a966426112bd44166e2f525b769ccbe9b286d437a0129130dde1a86c43e04bedb594e671d98283afe64ce331de9828fd", + "348b0532880b88a6614a8d7408c3f913357fbb60e995c60205be9139e74998aede7f4581e42f6b52698f7fa1219708c14498067fd1e09502de83a77dd281150c", + "5133dc8bef725359dff59792d85eaf75b7e1dcd1978b01c35b1b85fcebc63388ad99a17b6346a217dc1a9622ebd122ecf6913c4d31a6b52a695b86af00d741a0", + "2753c4c0e98ecad806e88780ec27fccd0f5c1ab547f9e4bf1659d192c23aa2cc971b58b6802580baef8adc3b776ef7086b2545c2987f348ee3719cdef258c403", + "b1663573ce4b9d8caefc865012f3e39714b9898a5da6ce17c25a6a47931a9ddb9bbe98adaa553beed436e89578455416c2a52a525cf2862b8d1d49a2531b7391", + "64f58bd6bfc856f5e873b2a2956ea0eda0d6db0da39c8c7fc67c9f9feefcff3072cdf9e6ea37f69a44f0c61aa0da3693c2db5b54960c0281a088151db42b11e8", + "0764c7be28125d9065c4b98a69d60aede703547c66a12e17e1c618994132f5ef82482c1e3fe3146cc65376cc109f0138ed9a80e49f1f3c7d610d2f2432f20605", + "f748784398a2ff03ebeb07e155e66116a839741a336e32da71ec696001f0ad1b25cd48c69cfca7265eca1dd71904a0ce748ac4124f3571076dfa7116a9cf00e9", + "3f0dbc0186bceb6b785ba78d2a2a013c910be157bdaffae81bb6663b1a73722f7f1228795f3ecada87cf6ef0078474af73f31eca0cc200ed975b6893f761cb6d", + "d4762cd4599876ca75b2b8fe249944dbd27ace741fdab93616cbc6e425460feb51d4e7adcc38180e7fc47c89024a7f56191adb878dfde4ead62223f5a2610efe", + "cd36b3d5b4c91b90fcbba79513cfee1907d8645a162afd0cd4cf4192d4a5f4c892183a8eacdb2b6b6a9d9aa8c11ac1b261b380dbee24ca468f1bfd043c58eefe", + "98593452281661a53c48a9d8cd790826c1a1ce567738053d0bee4a91a3d5bd92eefdbabebe3204f2031ca5f781bda99ef5d8ae56e5b04a9e1ecd21b0eb05d3e1", + "771f57dd2775ccdab55921d3e8e30ccf484d61fe1c1b9c2ae819d0fb2a12fab9be70c4a7a138da84e8280435daade5bbe66af0836a154f817fb17f3397e725a3", + "c60897c6f828e21f16fbb5f15b323f87b6c8955eabf1d38061f707f608abdd993fac3070633e286cf8339ce295dd352df4b4b40b2f29da1dd50b3a05d079e6bb", + "8210cd2c2d3b135c2cf07fa0d1433cd771f325d075c6469d9c7f1ba0943cd4ab09808cabf4acb9ce5bb88b498929b4b847f681ad2c490d042db2aec94214b06b", + "1d4edfffd8fd80f7e4107840fa3aa31e32598491e4af7013c197a65b7f36dd3ac4b478456111cd4309d9243510782fa31b7c4c95fa951520d020eb7e5c36e4ef", + "af8e6e91fab46ce4873e1a50a8ef448cc29121f7f74deef34a71ef89cc00d9274bc6c2454bbb3230d8b2ec94c62b1dec85f3593bfa30ea6f7a44d7c09465a253", + "29fd384ed4906f2d13aa9fe7af905990938bed807f1832454a372ab412eea1f5625a1fcc9ac8343b7c67c5aba6e0b1cc4644654913692c6b39eb9187ceacd3ec", + "a268c7885d9874a51c44dffed8ea53e94f78456e0b2ed99ff5a3924760813826d960a15edbedbb5de5226ba4b074e71b05c55b9756bb79e55c02754c2c7b6c8a", + "0cf8545488d56a86817cd7ecb10f7116b7ea530a45b6ea497b6c72c997e09e3d0da8698f46bb006fc977c2cd3d1177463ac9057fdd1662c85d0c126443c10473", + "b39614268fdd8781515e2cfebf89b4d5402bab10c226e6344e6b9ae000fb0d6c79cb2f3ec80e80eaeb1980d2f8698916bd2e9f747236655116649cd3ca23a837", + "74bef092fc6f1e5dba3663a3fb003b2a5ba257496536d99f62b9d73f8f9eb3ce9ff3eec709eb883655ec9eb896b9128f2afc89cf7d1ab58a72f4a3bf034d2b4a", + "3a988d38d75611f3ef38b8774980b33e573b6c57bee0469ba5eed9b44f29945e7347967fba2c162e1c3be7f310f2f75ee2381e7bfd6b3f0baea8d95dfb1dafb1", + "58aedfce6f67ddc85a28c992f1c0bd0969f041e66f1ee88020a125cbfcfebcd61709c9c4eba192c15e69f020d462486019fa8dea0cd7a42921a19d2fe546d43d", + "9347bd291473e6b4e368437b8e561e065f649a6d8ada479ad09b1999a8f26b91cf6120fd3bfe014e83f23acfa4c0ad7b3712b2c3c0733270663112ccd9285cd9", + "b32163e7c5dbb5f51fdc11d2eac875efbbcb7e7699090a7e7ff8a8d50795af5d74d9ff98543ef8cdf89ac13d0485278756e0ef00c817745661e1d59fe38e7537", + "1085d78307b1c4b008c57a2e7e5b234658a0a82e4ff1e4aaac72b312fda0fe27d233bc5b10e9cc17fdc7697b540c7d95eb215a19a1a0e20e1abfa126efd568c7", + "4e5c734c7dde011d83eac2b7347b373594f92d7091b9ca34cb9c6f39bdf5a8d2f134379e16d822f6522170ccf2ddd55c84b9e6c64fc927ac4cf8dfb2a17701f2", + "695d83bd990a1117b3d0ce06cc888027d12a054c2677fd82f0d4fbfc93575523e7991a5e35a3752e9b70ce62992e268a877744cdd435f5f130869c9a2074b338", + "a6213743568e3b3158b9184301f3690847554c68457cb40fc9a4b8cfd8d4a118c301a07737aeda0f929c68913c5f51c80394f53bff1c3e83b2e40ca97eba9e15", + "d444bfa2362a96df213d070e33fa841f51334e4e76866b8139e8af3bb3398be2dfaddcbc56b9146de9f68118dc5829e74b0c28d7711907b121f9161cb92b69a9", + "142709d62e28fcccd0af97fad0f8465b971e82201dc51070faa0372aa43e92484be1c1e73ba10906d5d1853db6a4106e0a7bf9800d373d6dee2d46d62ef2a461", +} + +var hashes2X = []string{ + "64", + "f457", + "e8c045", + "a74c6d0d", + "eb02ae482a", + "be65b981275e", + "8540ccd083a455", + "074a02fa58d7c7c0", + "da6da05e10db3022b6", + "542a5aae2f28f2c3b68c", + "ca3af2afc4afe891da78b1", + "e0f66b8dcebf4edc85f12c85", + "744224d383733b3fa2c53bfcf5", + "b09b653e85b72ef5cdf8fcfa95f3", + "dd51877f31f1cf7b9f68bbb09064a3", + "f5ebf68e7ebed6ad445ffc0c47e82650", + "ebdcfe03bcb7e21a9091202c5938c0a1bb", + "860fa5a72ff92efafc48a89df1632a4e2809", + "0d6d49daa26ae2818041108df3ce0a4db48c8d", + "e5d7e1bc5715f5ae991e4043e39533af5d53e47f", + "5232028a43b9d4dfa7f37439b49495926481ab8a29", + "c118803c922f9ae2397fb676a2ab7603dd9c29c21fe4", + "2af924f48b9bd7076bfd68794bba6402e2a7ae048de3ea", + "61255ac38231087c79ea1a0fa14538c26be1c851b6f318c0", + "f9712b8e42f0532162822f142cb946c40369f2f0e77b6b186e", + "76da0b89558df66f9b1e66a61d1e795b178ce77a359087793ff2", + "9036fd1eb32061bdecebc4a32aa524b343b8098a16768ee774d93c", + "f4ce5a05934e125d159678bea521f585574bcf9572629f155f63efcc", + "5e1c0d9fae56393445d3024d6b82692d1339f7b5936f68b062c691d3bf", + "538e35f3e11111d7c4bab69f83b30ade4f67addf1f45cdd2ac74bf299509", + "17572c4dcbb17faf8785f3bba9f6903895394352eae79b01ebd758377694cc", + "29f6bb55de7f8868e053176c878c9fe6c2055c4c5413b51ab0386c277fdbac75", + "bad026c8b2bd3d294907f2280a7145253ec2117d76e3800357be6d431b16366e41", + "386b7cb6e0fd4b27783125cbe80065af8eb9981fafc3ed18d8120863d972fa7427d9", + "06e8e6e26e756fff0b83b226dce974c21f970e44fb5b3e5bbada6e4b12f81cca666f48", + "2f9bd300244f5bc093ba6dcdb4a89fa29da22b1de9d2c9762af919b5fedf6998fbda305b", + "cf6bdcc46d788074511f9e8f0a4b86704365b2d3f98340b8db53920c385b959a38c8869ae7", + "1171e603e5cdeb4cda8fd7890222dd8390ede87b6f3284cac0f0d832d8250c9200715af7913d", + "bda7b2ad5d02bd35ffb009bdd72b7d7bc9c28b3a32f32b0ba31d6cbd3ee87c60b7b98c03404621", + "2001455324e748503aa08eff2fb2e52ae0170e81a6e9368ada054a36ca340fb779393fb045ac72b3", + "45f0761aefafbf87a68f9f1f801148d9bba52616ad5ee8e8ac9207e9846a782f487d5cca8b20355a18", + "3a7e05708be62f087f17b41ac9f20e4ef8115c5ab6d08e84d46af8c273fb46d3ce1aabebae5eea14e018", + "ea318da9d042ca337ccdfb2bee3e96ecb8f907876c8d143e8e44569178353c2e593e4a82c265931ba1dd79", + "e0f7c08f5bd712f87094b04528fadb283d83c9ceb82a3e39ec31c19a42a1a1c3bee5613b5640abe069b0d690", + "d35e63fb1f3f52ab8f7c6cd7c8247e9799042e53922fbaea808ab979fa0c096588cfea3009181d2f93002dfc11", + "b8b0ab69e3ae55a8699eb481dd665b6a2424c89bc6b7cca02d15fdf1b9854139cab49d34de498b50b2c7e8b910cf", + "fb65e3222a2950eae1701d4cdd4736266f65bf2c0d2e77968996eadb60ef74fb786f6234973a2524bdfe32d100aa0e", + "f28b4bb3a2e2c4d5c01a23ff134558559a2d3d704b75402983ee4e0f71d273ae056842c4153b18ee5c47e2bfa54313d4", + "7bb78794e58a53c3e4b1aeb161e756af051583d14e0a5a3205e094b7c9a8cf62d098fa9ea1db12f330a51ab9852c17f983", + "a879a8ebae4d0987789bcc58ec3448e35ba1fa1ee58c668d8295aba4eaeaf2762b053a677e25404f635a53037996974d418a", + "695865b353ec701ecc1cb38f3154489eed0d39829fc192bb68db286d20fa0a64235cde5639137819f7e99f86bd89afcef84a0f", + "a6ec25f369f71176952fb9b33305dc768589a6070463ee4c35996e1ced4964a865a5c3dc8f0d809eab71366450de702318e4834d", + "604749f7bfadb069a036409ffac5ba291fa05be8cba2f141554132f56d9bcb88d1ce12f2004cd3ade1aa66a26e6ef64e327514096d", + "daf9fa7dc2464a899533594e7916fc9bc585bd29dd60c930f3bfa78bc47f6c8439448043a45119fc9228c15bce5fd24f46baf9de736b", + "943ea5647a8666763084da6a6f15dcf0e8dc24f27fd0d9194805d25180fe3a6d98f4b2b5e0d6a04e9b41869817030f16ae975dd41fc35c", + "af4f73cbfc093760dfeb52d57ef45207bbd1a515f5523404e5d95a73c237d97ae65bd195b472de6d514c2c448b12fafc282166da132258e9", + "605f4ed72ed7f5046a342fe4cf6808100d4632e610d59f7ebb016e367d0ff0a95cf45b02c727ba71f147e95212f52046804d376c918cadd260", + "3750d8ab0a6b13f78e51d321dfd1aa801680e958de45b7b977d05732ee39f856b27cb2bcce8fbf3db6666d35e21244c2881fdcc27fbfea6b1672", + "8f1b929e80ab752b58abe9731b7b34eb61369536995abef1c0980d93903c1880da3637d367456895f0cb4769d6de3a979e38ed6f5f6ac4d48e9b32", + "d8469b7aa538b36cdc711a591d60dafecca22bd421973a70e2deef72f69d8014a6f0064eabfbebf5383cbb90f452c6e113d2110e4b1092c54a38b857", + "7d1f1ad2029f4880e1898af8289c23bc933a40863cc4ab697fead79c58b6b8e25b68cf5324579b0fe879fe7a12e6d03907f0140dfe7b29d33d6109ecf1", + "87a77aca6d551642288a0dff66078225ae39d288801607429d6725ca949eed7a6f199dd8a65523b4ee7cfa4187400e96597bfffc3e38ade0ae0ab88536a9", + "e101f43179d8e8546e5ce6a96d7556b7e6b9d4a7d00e7aade5579d085d527ce34a9329551ebcaf6ba946949bbe38e30a62ae344c1950b4bde55306b3bac432", + "4324561d76c370ef35ac36a4adf8f3773a50d86504bd284f71f7ce9e2bc4c1f1d34a7fb2d67561d101955d448b67577eb30dfee96a95c7f921ef53e20be8bc44", + "78f0ed6e220b3da3cc9381563b2f72c8dc830cb0f39a48c6ae479a6a78dcfa94002631dec467e9e9b47cc8f0887eb680e340aec3ec009d4a33d241533c76c8ca8c", + "9f6589c31a472e0a736f4eb22b6c70a9d332cc15304ccb66a6b97cd051b6ed82f8990e1d9bee2e4bb1c3c45e550ae0e7b96e93ae23f2fb8f63b309131e72b36cba6a", + "c138077ee4ed3d7ffa85ba851dfdf6e9843fc1dc00889d117237bfaad9aa757192f73556b959f98e6d24886ce48869f2a01a48c371785f12b6484eb2078f08c22066e1", + "f83e7c9e0954a500576ea1fc90a3db2cbd7994eaef647dab5b34e88ab9dc0b47addbc807b21c8e6dd3d0bd357f008471d4f3e0abb18450e1d4919e03a34545b9643f870e", + "3277a11f2628544fc66f50428f1ad56bcba6ee36ba2ca6ecdf7e255effc0c30235c039d13e01f04cf1efe95b5c2033ab72adda30994b62f2851d17c9920eadca9a251752dc", + "c2a834281a06fe7b730d3a03f90761daf02714c066e33fc07e1f59ac801ec2f4433486b5a2da8faa51a0cf3c34e29b2960cd0013378938dbd47c3a3d12d70db01d7d06c3e91e", + "47680182924a51cabe142a6175c9253e8ba7ea579ece8d9bcb78b1e9ca00db844fa08abcf41702bd758ee2c608d9612fed50e85854469cb4ef3038acf1e35b6ba4390561d8ae82", + "cec45830cd71869e83b109a99a3cd7d935f83a95de7c582f3adbd34e4938fa2f3f922f52f14f169c38cc6618d3f306a8a4d607b345b8a9c48017136fbf825aecf7b620e85f837fae", + "46fb53c70ab105079d5d78dc60eaa30d938f26e4d0b9df122e21ec85deda94744c1daf8038b8a6652d1ff3e7e15376f5abd30e564784a999f665078340d66b0e939e0c2ef03f9c08bb", + "7b0dcb52791a170cc52f2e8b95d8956f325c3751d3ef3b2b83b41d82d4496b46228a750d02b71a96012e56b0720949ca77dc68be9b1ef1ad6d6a5ceb86bf565cb972279039e209dddcdc", + "7153fd43e6b05f5e1a4401e0fef954a737ed142ec2f60bc4daeef9ce73ea1b40a0fcaf1a1e03a3513f930dd5335723632f59f7297fe3a98b68e125eadf478eb045ed9fc4ee566d13f537f5", + "c7f569c79c801dab50e9d9ca6542f25774b3841e49c83efe0b89109f569509ce7887bc0d2b57b50320eb81fab9017f16c4c870e59edb6c26620d93748500231d70a36f48a7c60747ca2d5986", + "0a81e0c547648595adca65623ce783411aac7f7d30c3ad269efafab288e7186f6895261972f5137877669c550f34f5128850ebb50e1884814ea1055ee29a866afd04b2087abed02d9592573428", + "6a7b6769e1f1c95314b0c7fe77013567891bd23416374f23e4f43e27bc4c55cfada13b53b1581948e07fb96a50676baa2756db0988077b0f27d36ac088e0ff0fe72eda1e8eb4b8facff3218d9af0", + "a399474595cb1ccab6107f18e80f03b1707745c7bf769fc9f260094dc9f8bc6fe09271cb0b131ebb2acd073de4a6521c8368e664278be86be216d1622393f23435fae4fbc6a2e7c961282a777c2d75", + "4f0fc590b2755a515ae6b46e9628092369d9c8e589e3239320639aa8f7aa44f8111c7c4b3fdbe6e55e036fbf5ebc9c0aa87a4e66851c11e86f6cbf0bd9eb1c98a378c7a7d3af900f55ee108b59bc9e5c", + "ed96a046f08dd675107331d267379c6fce3c352a9f8d7b243008a74cb4e9410836afaabe871dab6038ca94ce5f6d41fa922ce08aba58169f94cfc86d9f688f396abd24c11a6a9b0830572105a477c33e92", + "379955f539abf0eb2972ee99ed9546c4bbee363403991833005dc27904c271ef22a799bc32cb39f08d2e4ba6717d55153feb692d7c5efae70890bf29d96df02333c7b05ccc314e4835b018fec9141a82c745", + "e16cc8d41b96547ede0d0cf4d908c5fa393399daa4a9696e76a4c1f6a2a9fef70f17fb53551a8145ed88f18db8fe780a079d94732437023f7c1d1849ef69ad536a76204239e8ba5d97e507c36c7d042f87fe0e", + "a81de50750ece3f84536728f227208bf01ec5b7721579d007de72c88ee20663318332efe5bc7c09ad1fa8342be51f0609046ccf760a7957a7d8dc88941adb93666a4521ebe76618e5ddc2dd3261493d400b50073", + "b72c5fb7c7f60d243928fa41a2d711157b96aef290185c64b4de3dcfa3d644da67a8f37c2ac55caad79ec695a473e8b481f658c497edb8a191526592b11a412282d2a4010c90ef4647bd6ce745ebc9244a71d4876b", + "9550703877079c90e200e830f277b605624954c549e729c359ee01ee2b07741ecc4255cb37f96682dafcdbaade1063e2c5ccbd1918fb669926a67744101fb6de3ac016be4c74165a1e5a696b704ba2ebf4a953d44b95", + "a17eb44d4de502dc04a80d5a5e9507d17f27c96467f24c79b06bc98a4c410741d4ac2db98ec02c2a976d788531f1a4451b6c6204cef6dae1b6ebbcd0bde23e6fffb02754043c8fd3c783d90a670b16879ce68b5554fe1c", + "41d3ea1eaba5be4a206732dbb5b70b79b66a6e5908795ad4fb7cf9e67efb13f06fef8f90acb080ce082aadec6a1b543af759ab63fa6f1d3941186482b0c2b312f1151ea8386253a13ed3708093279b8eb04185636488b226", + "5e7cdd8373dc42a243c96013cd29df9283b5f28bb50453a903c85e2ce57f35861bf93f03029072b70dac0804e7d51fd0c578c8d9fa619f1e9ce3d8044f65d55634dba611280c1d5cfb59c836a595c803124f696b07ddfac718", + "26a14c4aa168907cb5de0d12a82e1373a128fb21f2ed11feba108b1bebce934ad63ed89f4ed7ea5e0bc8846e4fc10142f82de0bebd39d68f7874f615c3a9c896bab34190e85df05aaa316e14820b5e478d838fa89dfc94a7fc1e", + "0211dfc3c35881adc170e4ba6daab1b702dff88933db9a6829a76b8f4a7c2a6d658117132a974f0a0b3a38ceea1efc2488da21905345909e1d859921dc2b5054f09bce8eeb91fa2fc6d048ce00b9cd655e6aafbdaa3a2f19270a16", + "ddf015b01b68c4f5f72c3145d54049867d99ee6bef24282abf0eecdb506e295bacf8f23ffa65a4cd891f76a046b9dd82cae43a8d01e18a8dff3b50aeb92672be69d7c087ec1fa2d3b2a39196ea5b49b7baede37a586fea71aded587f", + "6ee721f71ca4dd5c9ce7873c5c04c6ce76a2c824b984251c15535afc96adc9a4d48ca314bfeb6b8ee65092f14cf2a7ca9614e1dcf24c2a7f0f0c11207d3d8aed4af92873b56e8b9ba2fbd659c3f4ca90fa24f113f74a37181bf0fdf758", + "689bd150e65ac123612524f720f54def78c095eaab8a87b8bcc72b443408e3227f5c8e2bd5af9bcac684d497bc3e41b7a022c28fb5458b95e8dfa2e8caccde0492936ff1902476bb7b4ef2125b19aca2cd3384d922d9f36dddbcd96ae0d6", + "3a3c0ef066fa4390ec76ad6be1dc9c31ddf45fef43fbfa1f49b439caa2eb9f3042253a9853e96a9cf86b4f873785a5d2c5d3b05f6501bc876e09031188e05f48937bf3c9b667d14800db62437590b84ce96aa70bb5141ee2ea41b55a6fd944", + "741ce384e5e0edaebb136701ce38b3d33215415197758ae81235307a4115777d4dab23891db530c6d28f63a957428391421f742789a0e04c99c828373d9903b64dd57f26b3a38b67df829ae243feef731ead0abfca049924667fdec49d40f665", + "a513f450d66cd5a48a115aee862c65b26e836f35a5eb6894a80519e2cd96cc4cad8ed7eb922b4fc9bbc55c973089d627b1da9c3a95f6c019ef1d47143cc545b15e4244424be28199c51a5efc7234dcd94e72d229897c392af85f523c2633427825", + "71f1554d2d49bb7bd9e62e71fa049fb54a2c097032f61ebda669b3e1d4593962e47fc62a0ab5d85706aebd6a2f9a192c88aa1ee2f6a46710cf4af6d3c25b7e68ad5c3db23ac009c8f13625ff85dc8e50a9a1b2682d3329330b973ec8cbb7bb73b2bd", + "167cc1067bc08a8d2c1a0c10041ebe1fc327b37043f6bd8f1c63569e9d36ded58519e66b162f34b6d8f1107ef1e3de199d97b36b44141a1fc4f49b883f40507ff11f909a017869dc8a2357fc7336ae68703d25f75710b0ff5f9765321c0fa53a51675c", + "cb859b35dc70e264efaad2a809fea1e71cd4a3f924be3b5a13f8687a1166b538c40b2ad51d5c3e47b0de482497382673140f547068ff0b3b0fb7501209e1bf36082509ae85f60bb98fd02ac50d883a1a8daa704952d83c1f6da60c9624bc7c99912930bf", + "afb1f0c6b7125b04fa2578dd40f60cb411b35ebc7026c702e25b3f0ae3d4695d44cfdf37cb755691dd9c365edadf21ee44245620e6a24d4c2497135b37cd7ac67e3bd0aaee9f63f107746f9b88859ea902bc7d6895406aa2161f480cad56327d0a5bba2836", + "13e9c0522587460d90c7cb354604de8f1bf850e75b4b176bda92862d35ec810861f7d5e7ff6ba9302f2c2c8642ff8b7776a2f53665790f570fcef3cac069a90d50db42227331c4affb33d6c040d75b9aeafc9086eb83ced38bb02c759e95ba08c92b17031288", + "0549812d62d3ed497307673a4806a21060987a4dbbf43d352b9b170a29240954cf04bc3e1e250476e6800b79e843a8bd8253b7d743de01ab336e978d4bea384eaff700ce020691647411b10a60acacb6f8837fb08ad666b8dcc9eaa87ccb42aef6914a3f3bc30a", + "3a263efbe1f2d463f20526e1d0fd735035fd3f808925f058b32c4d8788aeeab9b8ce233b3c34894731cd73361f465bd350395aebcabd2fb63010298ca025d849c1fa3cd573309b74d7f824bbfe383f09db24bcc565f636b877333206a6ad70815c3bef5574c5fc1c", + "3c6a7d8a84ef7e3eaa812fc1eb8e85105467230d2c9e4562edbfd808f4d1ac15d16b786cc6a02959c2bc17149c2ce74c6f85ee5ef22a8a96b9be1f197cffd214c1ab02a06a9227f37cd432579f8c28ff2b5ac91cca8ffe6240932739d56788c354e92c591e1dd76499", + "b571859294b02af17541a0b5e899a5f67d6f5e36d38255bc417486e69240db56b09cf2607fbf4f95d085a779358a8a8b41f36503438c1860c8f361ce0f2783a08b21bd7232b50ca6d35428335272a5c05b436b2631d8d5c84d60e8040083768ce56a250727fb0579dd5c", + "98ee1b7269d2a0dd490ca38d447279870ea55326571a1b430adbb2cf65c492131136f504145df3ab113a13abfb72c33663266b8bc9c458db4bf5d7ef03e1d3b8a99d5de0c024be8fabc8dc4f5dac82a0342d8ed65c329e7018d6997e69e29a01350516c86beaf153da65ac", + "41c5c95f088df320d35269e5bf86d10248f17aec6776f0fe653f1c356aae409788c938befeb67c86d1c8870e8099ca0ce61a80fbb5a6654c44529368f70fc9b9c2f912f5092047d0ffc339577d24142300e34948e086f62e23ecaca410d24f8a36b5c8c5a80e0926bc8aa16a", + "9f93c41f533b2a82a4df893c78faaaa793c1506974ba2a604cd33101713ca4adfd30819ffd8403402b8d40aff78106f3357f3e2c24312c0d3603a17184d7b999fc9908d14d50192aebabd90d05073da7af4be37dd3d81c90acc80e8333df546f17ab6874f1ec204392d1c0571e", + "3da5207245ac270a915fc91cdb314e5a2577c4f8e269c4e701f0d7493ba716de79935918b917a2bd5db98050dbd1eb3894b65fac5abf13e075abebc011e651c03cafb6127147771a5c8418223e1548137a89206635c26ca9c235ccc108dc25cf846e4732444bd0c2782b197b262b", + "96011af3965bb941dc8f749932ea484eccb9ba94e34b39f24c1e80410f96ce1d4f6e0aa5be606def4f54301e930493d4b55d484d93ab9dd4dc2c9cfb79345363af31ad42f4bd1aa6c77b8afc9f0d551bef7570b13b927afe3e7ac4de7603a0876d5edb1ad9be05e9ee8b53941e8f59", + "51dbbf2a7ca224e524e3454fe82ddc901fafd2120fa8603bc343f129484e9600f688586e040566de0351d1693829045232d04ff31aa6b80125c763faab2a9b233313d931903dcfaba490538b06e4688a35886dc24cdd32a13875e6acf45454a8eb8a315ab95e608ad8b6a49aef0e299a", + "5a6a422529e22104681e8b18d64bc0463a45df19ae2633751c7aae412c250f8fb2cd5e1270d3d0cf009c8aa69688ccd4e2b6536f5747a5bc479b20c135bf4e89d33a26118705a614c6be7ecfe766932471ad4ba01c4f045b1abb5070f90ec78439a27a1788db9327d1c32f939e5fb1d5ba", + "5d26c983642093cb12ff0afabd87b7c56e211d01844ad6da3f623b9f20a0c968034299f2a65e6673530c5980a532beb831c7d0697d12760445986681076dfb6fae5f3a4d8f17a0db5008ce8619f566d2cfe4cf2a6d6f9c3664e3a48564a351c0b3c945c5ee24587521e4112c57e318be1b6a", + "52641dbc6e36be4d905d8d60311e303e8e859cc47901ce30d6f67f152343e3c4030e3a33463793c19effd81fb7c4d631a9479a7505a983a052b1e948ce093b30efa595fab3a00f4cef9a2f664ceeb07ec61719212d58966bca9f00a7d7a8cb4024cf6476bab7fbccee5fd4e7c3f5e2b2975aa2", + "a34ce135b37bf3db1c4aaa4878b4499bd2ee17b85578fcaf605d41e1826b45fdaa1b083d8235dc642787f11469a5493e36806504fe2a2063905e821475e2d5ee217057950370492f5024995e77b82aa51b4f5bd8ea24dc71e0a8a640b0592c0d80c24a726169cf0a10b40944747113d03b52708c", + "46b3cdf4946e15a5334fc3244d6680f5fc132afa67bf43bfade23d0c9e0ec64e7dab76faaeca1870c05f96b7d019411d8b0873d9fed04fa5057c039d5949a4d592827f619471359d6171691cfa8a5d7cb07ef2804f6ccad4821c56d4988bea7765f660f09ef87405f0a80bcf8559efa111f2a0b419", + "8b9fc21691477f11252fca050b121c5334eb4280aa11659e267297de1fec2b2294c7ccee9b59a149b9930b08bd320d3943130930a7d931b71d2f10234f4480c67f1de883d9894ada5ed5071660e221d78ae402f1f05af47761e13fec979f2671e3c63fb0ae7aa1327cf9b8313adab90794a52686bbc4", + "cd6598924ce847de7ff45b20ac940aa6292a8a99b56a74eddc24f2cfb45797188614a21d4e8867e23ff75afd7cd324248d58fcf1ddc73fbd115dfa8c09e62022fab540a59f87c989c12a86ded05130939f00cd2f3b512963dfe0289f0e54acad881c1027d2a0292138fdee902d67d9669c0ca1034a9456", + "594e1cd7337248704e691854af0fdb021067ddf7832b049ba7b684438c32b029eded2df2c89a6ff5f2f2c311522ae2dc6db5a815afc60637b15ec24ef9541f1550409db2a006da3affffe548a1eaee7bd114e9b805d0756c8e90c4dc33cb05226bc2b393b18d953f8730d4c7ae693159cdba758ad28964e2", + "1f0d292453f04406ada8be4c161b82e3cdd69099a8637659e0ee40b8f6da46005cfc6085db9804852decfbe9f7b4dda019a7112612895a144ed430a960c8b2f5458d3d56b7f427cee6358915aee7146278aed2a0296cdd929e4d21ef95a3adf8b7a6beba673cdccdbdcfb2474711732d972ad054b2dc64f38d", + "b65a72d4e1f9f9f75911cc46ad0806b9b18c87d105332a3fe183f45f063a746c892dc6c4b9181b1485b3e3a2cc3b453eba2d4c39d6905a774ed3fb755468beb190925ecd8e57ecb0d985125741650c6b6a1b2a3a50e93e3892c21d47ed5884eed83aa94e1602288f2f49fe286624de9d01fcb54433a0dc4ad70b", + "705ce0ffa469250782aff725248fc88fe98eb76659e8407edc1c4842c9867d61fe64fb86f74e980598b92bc213d06f337bd5654fc28643c7ba769a4c31563427543c00808b627a19c90d86c322f33566ce020121cc322229c3337943d46f68ef939d613dcef0077269f88151d6398b6b009abb763410b154ad76a3", + "7fa881ce87498440ab6af13854f0d851a7e0404de33896999a9b3292a5d2f5b3ad033530c558168fe5d2fdb9b89a2354c46cf32a0e612afc6c6485d789511bfef26800c74bf1a4cfbe30bda310d5f6029c3dccdedb6149e4971274e276dccfabd63bc4b9955e8303feb57f8a688db55ecb4b33d1f9fe1b3a8ba7ac32", + "23a98f71c01c0408ae16843dc03be7db0aeaf055f951709d4e0dfdf64fffbffaf900ee592ee10929648e56f6c1e9f5be5793f7df66453eb56502c7c56c0f0c88da77abc8fa371e434104627ef7c663c49f40998dbad63fa6c7aa4fac17ae138d8bbe081f9bd168cd33c1fbc92fa35ed687679f48a64b87db1fe5bae675", + "7b8970b6a33237e5a7bcb39272703edb92285c55842b30b9a48834b1b507cc02a6764739f2f7ee6ae02a7b715a1c455e59e8c77a1ae98abb10161853f1234d20da99016588cd8602d6b7ec7e177d4011edfa61e6b3766a3c6f8d6e9eac893c568903eb6e6aba9c4725774f6b4343b7acaa6c031593a36eef6c72806ff309", + "f7f4d328ba108b7b1de4443e889a985ed52f485f3ca4e0c246aa5526590cbed344e9f4fe53e4eea0e761c82324649206ca8c2b45152157d4115e68c818644b03b65bb47ad79f94d37cb03c1d953b74c2b8adfa0e1c418bda9c518ddcd7050e0f149044740a2b16479413b63fc13c36144f80c73687513dca761ba8642a8ae0", + "2d7dc80c19a1d12d5fe3963569547a5d1d3e821e6f06c5d5e2c09401f946c9f7e13cd019f2f9a878b62dd850453b6294b99ccaa068e542993524b0f63832d48e865be31e8ec1ee103c718340c904b32efb69170b67f038d50a3252794b1b4076c0620621ab3d91215d55ffea99f23d54e161a90d8d4902fda5931d9f6a27146a", + "77dff4c7ad30c954338c4b23639dae4b275086cbe654d401a2343528065e4c9f1f2eca22aa025d49ca823e76fdbb35df78b1e5075ff2c82b680bca385c6d57f7ea7d1030bb392527b25dd73e9eeff97bea397cf3b9dda0c817a9c870ed12c006cc054968c64000e0da874e9b7d7d621b0679866912243ea096c7b38a1344e98f74", + "83bed0d556798f2b419f7056e6d3ffada06e939b95a688d0ec8c6ac5ea45ab73a4cf01043e0a170766e21395f27ab4b78c435f5f0dfe6e93ab80df38610e41158429ddf20296f53a06a017723359fe22dc08b5da33f0800a4fe50118e8d7eab2f83a85cd764bf8a166903bd0e9dcfeeceba44ff4ca4439846458d31ea2bb564645d1", + "ea12cf5a113543e39504123036f15a5bafa9c555562469f99cd29996a4dfaaab2a34b00557ccf15f37fc0cc1b3be427e725f2cd952e50af7970dda9200cd5ce252b1f29c40067fea3027ed686190803b59d834179d1b8f5b55abe55ad174b2a1188f7753ec0ae2fc01316e7d498b68ee3598a0e9baaaa664a60f7fb4f90edbed494ad7", + "55266358332d8d9e68bd13432088beadf95833aab67a0eb3b10650414255f299e2670c3e1a5b2976159a46c72a7ce57d59b7be14c15798e09ed50fa312a431b0264d7a1396aa6168bde897e208ece53d2cfc83786113b1e6eac5e9bb98984abb6c8d64eebb991903254abc650c999bb9958a5d7937434b869bc940e21b9dc1cc8982f2ba", + "4d6104ded730aefe02873f4c741232c8234a6d66d85393aff57fbf56ba6347666988dfc4d58f3cc895a0da598822edeee4533d24ec0ee292fd5e1ad04898ffbc1ff4bef14dec220babcb0f28fffe32a6e2c28aaaac16442bf4feb02917d18bb3a415d84fa9358d5a9852688d846c92271911f934181c30f82434d915f93f155a1ffbf0b125", + "eb5f579a4c476af554aac11e5719d378549497e613b35a929d6f36bb8831d7a466aa76de9be24ebb55543f1c13924f64cfd648a5b3fa90387315c16174dbf1e9a183c196d9bb8f84af65f1f8212429aadc11ef2426d07d4716062b85c8d5d2dff8e21b9e62b7fa7dbd57d72633054b464fb28583a56ca13ccc5ddc74dae942492f31731e7046", + "ebddec3dcaf18063e45a76ebeac39af85a1adc2818881ccce48c106288f5988365cca2b4b1d7f037322da46840f42bebdcbc7193838d426e101087d8cea03aaff743d573eb4f4e9a71a2c884390769a6503874125d194bee8d46a3a0d5e4fcf28ff8465887d8e9df771d70157e75df3642b331d2778ceb32ceba868640171ab7a5d22eede1ee44", + "26d87ec70b57691e3bb359633d3ddba17f029d62cdfe977f5fd42274d79b444a32494d1c01e9f72d03cce78c806df96e93ea78da3a054209924ed765edc4d570f66168dc25ee3114e4017e387440349c8f0a94804761c3055f88e4fda2a49b860b1486a9609095f6250f268b6a4d1aecc03a505632ebf0b9dc22d0755a736faf7ad7000858b5864b", + "3880f5cc2d08fa70ef44b1f263fcf534d062a298c1bd5ee2eee8c3265806c4ce50b004f3a1fc1fa5b024aaac7f528c023c8181f67c6e1c357425dc4d573bd46b93a542afa3a19bdb140a2ce666e1a01f5c4d2dcd681fa9f5839b797813c394738d5ee4971386c12c7c117d17c7bec324b760aa30cda9ab2aa850284ba6fa97946f710f02449d1883c6", + "3317d2f452105dd3f4a96f9257af8285a80be58066b50f6f54bd633749b49f6ab9d57d45652d2ae852a2f6940cd5ec3159dd7f333358b12f502325df38843508faf7e246352d201280babd90b14fbf7722641c3601d0e458474439973c611bb5502fd0eb3078f87124ca7e1a016fcb6cfeff65f6a565985aca7122cfa8c5a11da0cb47797c5132333179", + "f2c5c955d0224e784a46b9125f8fef8a5e1271e145eb08bbbd07ca8e1cfc848cef14fa3b36221ac62006403dbb7f7d77958ccc54a8566c837858b809f3e310ace8ca682515bc655d2a397cab238a663b464d511f02dc5d033dad4cb5e0e519e94a54b62a3896e460ec70e5716b5921bf8396aa86a60123e6287e34570bb01bdc602e113670bf498af2ff10", + "180e275205691a83630cf4b0c7b80e6df8fad6ef1c23ba8013d2f09aef7abade1827f23af230de90676240b4b3b0673f8afdea0327330055041741f65560d90348de696d34ca80dfe8afae582fe4879d4594b80e9408fb53e800e01ca58552b905c365e7f1416e51c080f517d6bbd30e64ae1535d59decdc76c6624d737868f49f2f719da39ba1344d59eab9", + "c517a84e4631a7f65ace170d1e5c2fdb259841535d88da323e68c0883e6af7b041cfe05908815a5a9d1b14fa712c2c16fadcf1ca54d3aa954d411240df331b2aebdfb65aced84d0b8aace56ec0aa7c13ec7d75ca883b6bcf6db74c9e98463c484a8262684f29910373430651f90ecffe18b072170e61ee58de20e2a6ff67b3ab00fccbb80af943f20b56b98107", + "d1a56a5ee990e02b84b5862fde62f69ec07567be2d7ccb769a461c4989d11fdda6c945d942fb8b2da795ed97e43a5b7dbdde7f8fd2ff7154544336d5c50fb7380341e660d4898c7fbc39b2b782f28defac6873523c7c1de8e52c65e4395c686ba483c35a220b0416d46357a063fa4c33fa9c52d5c207a1304ae141c791e62ba6a7374ed922b8dd94079b72b69302", + "4720b88d6bfb1ab43958e26827730d852d9ec30173ebd0fe0d273edcece2e788558984cd9306fe5978086a5cb6d37975755d2a3daeb16f99a8a11544b8247a8b7ed5587afc5bea1daf85dcea5703c5905cf56ae7cc76408ccabb8fcc25cacc5ff456db3f62fa559c45b9c71505eb5073df1f10fc4c9060843f0cd68bbb4e8edfb48d0fd81d9c21e53b28a2aae4f7ba", + "f4639b511db9e092823d47d2947efacbaae0e5b912dec3b284d2350b9262f3a51796a0cd9f8bc5a65879d6578ec24a060e293100c2e12ad82d5b2a0e9d22965858030e7cdf2ab3562bfa8ac084c6e8237aa22f54b94c4e92d69f22169ced6c85a293f5e16bfc326153bf629cdd6393675c6627cd949cd367eef02e0f54779f4d5210197698e4754a5fe490a3a7521c1c", + "3d9e7a860a718565e3670c29079ce80e381969fea91017cfd5952e0d8a4a79bb08e2cd1e26161f30ee03a24891d1bfa8c212861b51618d07429fb48000ff87ef09c6fca526567777e9c076d58a642d5c521b1caa5fb0fb3a4b8982dc14a444732b72b239b8f01fc8ba8ee86b3013b5d3e98a92b2aeaecd4879fca5d5e9e0bd880dbfffa6f96f94f3998812aac6a714f331", + "4d9bf551d7fd531e7482e2ec875c0651b0bcc6caa738f7497befd11e67ae0e036c9d7ae4301cc3c7906f0d0e1ed4738753f414f9b3cd9b8a71176e325c4c74ce020680ecbfb146889597f5b40487e93f974cd866817fb9fb24c7c7c16177e6e120bfe349e83aa82ba40e59e917565788658a2b254f25cf99bc65070b3794cea2259eb10e42bb54852cba3110baa773dcd70c", + "b91f65ab5bc059bfa5b43b6ebae243b1c46826f3da061338b5af02b2da76bb5ebad2b426de3c3134a633499c7c36a120369727cb48a0c6cbab0acecdda137057159aa117a5d687c4286868f561a272e0c18966b2fec3e55d75abea818ce2d339e26adc005c2658493fe06271ad0cc33fcb25065e6a2a286af45a518aee5e2532f81ec9256f93ff2d0d41c9b9a2efdb1a2af899", + "736f6e387acb9acbee026a6080f8a9eb8dbb5d7c54ac7053ce75dd184b2cb7b942e22a3497419ddb3a04cf9e4eb9340a1a6f9474c06ee1dcfc8513979fee1fc4768087617fd424f4d65f54782c787a1d2de6efc81534343e855f20b3f3589027a5436201eee747d45b9b8375e4294d72ab6a52e04dfbb2914db92ee58f134b026527ed52d4f794459e02a43a17b0d51ea69bd7f3", + "9242d3eb31d26d923b99d66954cfade94f25a18912e6356810b63b971ae74bb53bc58b3c01424208ea1e0b1499936daea27e63d904f9ed65fdf69de40780a3027b2e89d94bdf214f585472613ce328f628f4f0d56217dfb53db5f7a07f54c8d71db16e27de7cdb8d23988837b49b65c12f1771d979e8b192c9f4a16b8d9fba917bcf74ce5a82aac2075608ba6c2d485fa59864b9de", + "5da68704f4b592d41f08aca08f62d85e2e2466e5f3be010315d11d113db674c4b98764a509a2f5aacc7ae72c9deff2bcc42810b47f64d429b35745b9efff0b18c58653461e968aaa3c2c7fc455bc5771a8f10cd184be831040df767201ab8d32cb9a58c89afbebecb524502c9b940c1b838f8361bbcde90d272715017f67609ea39b20fac985332d82daaa023999e3f8bfa5f3758bb8", + "71ea2af9c8ac2e5ae44a176662882e01027ca3cdb41ec2c6785606a07d7231cd4a2bded7155c2feef3d44d8fd42afa73265cef826f6e03aa761c5c51d5b1f129ddc27503ff50d9c2d748322df4b13dd5cdc7d46381528ab22b79b0049011e4d2e57fe2735e0d58d8d56e92c75dbeac8c76c4239d7f3f24fb56697593b3e4afa6671d5bbc96c079a1c154fe20212ade67b05d49ceaa7a84", + "1d133170582fa4bff59a21953ebbc01bc202d43cd79c083d1f5c02fa15a43a0f519e36acb710bdabac880f04bc003800641c2487930de9c03c0e0deb347fa815efca0a38c6c5de694db698743bc955581f6a945deec4ae988ef7cdf40498b77796ddea3fae0ea844891ab751c7ee20917c5a4af53cd4ebd82170078f41ada2795e6eea17593fa90cbf5290a1095e299fc7f507f360f187cd", + "5ec4ac45d48fc15c72471d795066bdf8e99a483d5fdd599511b9cdc408de7c0616491b73924d0266da34a495331a935c4b8884f57d7ad8cce4cbe586875aa52482215ed39d7626cce55d50349c7767981c8bd6890f132a196184247343566fc972b86fe3c5369d6a6519e9f07942f0522b77ad01c751dcf7defe31e471a0ec00963765dd8518144a3b8c3c978ad108056516a25dbe3092e73c", + "0d5e74b78290c689f2b3cfea45fc9b6a84c822639cd438a7f05c07c374adced42cdc12d2a9233a4ffe80307efc1ac13cb04300e165f8d90dd01c0ea955e7657332c6e86ad6b43e78ba4c13c675aed83192d8427866fb6484e6a3071b2369a46fba9005f31232da7ffec7952f831aaaddf63e225263531c2cf387f8cc14fa856c8795137142c3a52ffa69b8e30ebc88ce3bbc227597bcc8dddd89", + "a0fe36f983259921dc2fa7d89002b3066241d63bfc2448caf7e10522a35562be0bfedc3dce49cfce2e614a04d4c64cfc0ab898873a7fc26928dc1927c009d12f6f9b7a278205d3d0057604f4ac746f8b9287c3bc6b929832bf253b6586192ac43fdd29ba585dbd9059aab9c6ff6000a7867c67fec1457b733f6b620881166b8fed92bc8d84f0426002e7be7fcd6ee0abf3755e2babfe5636ca0b37", + "1d29b6d8eca793bb801becf90b7d7de215b17618ec32340da4bac707cdbb58b951d5036ec02e105d83b5960e2a72002d19b7fa8e1128cc7c5049ed1f76b82a59eac6ed09e56eb73d9ade38a6739f0e07155afa6ec0d9f5cf13c4b30f5f9a465b162a9c3ba04b5a0b3363c2a63f13f2a3b57c590ec6aa7f64f4dcf7f1582d0ca157eb3b3e53b20e306b1f24e9bda87397d413f01b453ceffeca1fb1e7", + "6a2860c110cd0fc5a19bcaafcd30762ee10242d34739638e716bd89fd537ea4dc630e6f85d1bd88a25ad3892ca554c232c9830bd56980c9f08d378d28f7fa6fa7df4fcbf6ad98b1adfff3ec1f63310e50f920c99a5200b8e64c2c2ca249399a149942261f737d5d72da949e914c024d57c4b639cb89990fed2b38a37e5bcd24d17ca12dfcd36ce04691fd03c32f6ed5de2a2191ed7c826375ba81f78d0", + "7132aa291ddc9210c60dbe7eb3c19f9053f2dd74742cf57fdc5df98312adbf4710a73245de4a0c3b24e21ab8b466a77ae29d15500d5142555ef3088cbccbe685ed9119a10755148f0b9f0dbcf02b2b9bcadc8517c88346ea4e78285e9cbab122f824cc18faf53b742a87c008bb6aa47eed8e1c8709b8c2b9adb4cc4f07fb423e5830a8e503ab4f7945a2a02ab0a019b65d4fd71dc364d07bdc6e637990e3", + "3e664da330f2c6007bff0d5101d88288aaacd3c07913c09e871cce16e55a39fde1ce4db6b8379977c46cce08983ca686778afe0a77a41baf447854b9aa286c398c2b83c95a127b053101b6799c1638e5efd67273b2618df6ec0b96d8d040e8c1ee01a99b9b5c8fe63fea2f749e6c90d31f6fae4e1469ac09884c4fe1a8539acb313f42c941224a0e79c059e18affc2bcb6724975c436f7bf949ebdd8aef51c", + "7a6ea63a271eb49470f5ce77519ed61ae9b2f1be07a96855726bc3df1d0723af3a703fdfc2e739c9d31d25814daf661a23558b50982e66ee37ad880f5c8f11c8130fac8a5d0250583700d5a324894fae6d61993f6bf9327214f8674649f355b23fd634940b2c467973a839e659169c773119919f5b81ee171edb2e5f6940d7551f9e5a70625d9ea88711ad0ed8ab2da720ad358bef954456cb2d5636425717c2", + "c5106bbda114168c449172e49590c7eeb827fa4e1a2a7a87a3c1f721a9047d0c0a50fbf244731be1b7eb1a2ef30f5ae846a9f38f0df44f32af61b68dbdcd0226e741dfb6ef81a2503691af5e4b3171f48c59ba4ef91eba344b5b697f261df7bbbb734ca6e6daebaa4a179feb17002823281b8534d55a6531c59305f6e3fd3fa63b747bcf0deb654c392a02fe687a269effb1238f38bcaea6b208b221c45fe7fbe7", + "597716a5ebeebc4bf524c15518816f0b5dcda39cc833c3d66b6368ce39f3fd02ceba8d12072bfe6137c68d3acd50c849873150928b320b4fbc31c1456679ea1d0acaeeabf666d1f1bad3e6b9312c5cbdecf9b799d3e30b0316bed5f41245107b693366accc8b2bcef2a6be54209ffabc0bb6f93377abdcd57d1b25a89e046f16d8fd00f99d1c0cd247aafa72234386ae484510c084ee609f08aad32a005a0a5710cb", + "0771ffe789f4135704b6970b617bae41666bc9a6939d47bd04282e140d5a861c44cf05e0aa57190f5b02e298f1431265a365d29e3127d6fccd86ec0df600e26bcdda2d8f487d2e4b38fbb20f1667591f9b5730930788f2691b9ee1564829d1ada15fffc53e785e0c5e5dd11705a5a71e390ca66f4a592785be188fefe89b4bd085b2024b22a210cb7f4a71c2ad215f082ec63746c7367c22aedb5601f513d9f1ffc1f3", + "be6556c94313739c115895a7bad2b620c0708e24f0390daa55521c31d2c6782acf41156271238885c367a57c72b4fe999c160e804ad58d8e565edbce14a2dd90e443eb80626b3eab9d7ab75d6f8a062d7ca89b7af8eb292c98eaf87ad1dfd0db103d1bb6188bd7e7a63502153cf3ce23d43b60c5782602bac8ad92fb2324f5a79453898c5de18415639ecc5c7974d3077f76fc1df5b956723bb19a624d7ea3ec13ba3d86", + "4bc33729f14cd2f1dc2ff459abee8f6860dda1062845e4adab78b53c835d106bdfa35dd9e77219eaef403d4e80488ca6bd1c93dd76ef9d543fbb7c8904dccc5f71509a6214f73d0f4e467c3e038ea639b29e7fc442ee29f57117740576188ada15a739827c647a46b0271817ab235c023c30c90f2115e5c90cd8501e7b286962fc66ffc3fe7e8978746168314908a41998bd83a1eeffda9d714b864f4d490fdeb9c7a6edfa", + "ab12faea205b3d3a803cf6cb32b9698c32301a1e7f7c6c23a20174c95e98b7c3cfe93fffb3c970face8f5751312a261741141b948d777b8a2ea286fe69fc8ac84d34116a4674bb09a1a0b6af90a748e511749de4697908f4acb22be08e96ebc58ab1690acf73914286c198a2b57f1dd70ea8a52325d3045b8bdfe9a09792521526b7564a2a5fcd01e291f1f8894017ce7d3e8a5dba15332fb410fcfc8d62195a48a9e7c86fc4", + "7d421e59a567af70594757a49809a9c22e07fe14061090b9a041875bb77933deae36c823a9b47044fa0599187c75426b6b5ed94982ab1af7882d9e952eca399ee80a8903c4bc8ebe7a0fb035b6b26a2a013536e57fa9c94b16f8c2753c9dd79fb568f638966b06da81ce87cd77ac0793b7a36c45b8687c995bf4414d28289dbee977e77bf05d931b4feaa359a397ca41be529910077c8d498e0e8fb06e8e660cc6ebf07b77a02f", + "0c18ab727725d62fd3a2714b7185c09faca130438eff1675b38beca7f93a6962d7b98cb300ea33067a2035cdd694348784aa2eda2f16c731eca119a050d3b3ce7d5c0fd6c234354a1da98c0642451922f670984d035f8c6f35031d6188bbeb31a95e99e21b26f6eb5e2af3c7f8eea426357b3b5f83e0029f4c4732bca366c9aa625748297f039327c276cd8d9c9bf692a47af098aa50ca97b99961bef8bc2a7a802e0b8cfdb84319", + "92d5909d18a8b2b9971cd1627b461e98a74ba377186a6a9df5bd133635250b300abccb2254cacb775df6d99f7c7d0952653c28e6909b9f9a45adce691f7adc1afffcd9b06e49f775364cc2c62825b9c1a86089080e26b57e732aac98d80d009bfe50df01b95205aa07ed8ec5c873da3b92d00d53af825aa64b3c634c5ece40bff152c331222d3453fd92e0ca17cef19ecb96a6eed4961b627aca48b12fecd091754f770d52ba861546", + "802f22e4a388e874927fef24c797408254e03910bab5bf372320207f8067f2b1ea543917d4a27df89f5bf936ba12e04302bde23119533d0976beca9e20cc16b4dbf17a2ddc44b66aba76c61ad59d5e90de02a88327ead0a8b75463a1a68e307a6e2e53ecc1986274b9ee80bc9f3140671d5285bc5fb57b281042a8978a1175900c6073fd7bd740122956602c1aa773dd2896674d0a6beab24454b107f7c847acb31a0d332b4dfc5e3f2f", + "3844fe65db11c92fb90bf15e2e0cd216b5b5be91604baf3b84a0ca480e41ecfaca3709b32f8c6e8761406a635b88eec91e075c48799a16ca08f295d9766d74475c47f3f2a274eae8a6ee1d191a7f37ee413a4bf42cad52acd5564a651715ae42ac2cddd52f819c692ecdef52ecb763270322cdca7bd5aef71428fa73e844568b96b43c89bf1ed42a0abf209ffad0eeec286c6f141e8af073ba4adfbbdeda253752ae36c9957dfc905b4c49", + "329377f7bf3c8d74991a7d61b0cf39baff5d485d79751b0d5ad017d23bec570fb19810105bab79ab5acb102ab972165224d4ec888ec7de5148077fa9c1bb6820e0d91ae4e2591a21fec2f820606ce4bafc1e377f8dc3a5bd1a9e2772a57abccd0b757164d768872c91d02789545ab5b203f688d71dd08522a3fd2f5bcd7df507aebf1ca27ddff0a82afb7aa9c180008f49d1325adf97d047e77238fc75f56356de4e87d8c961575c9f6362c9", + "f7f269929b0d71ea8eef7120e55ccba691c582dd534692abef35c0fe9dec7dae973cd9702e5ad420d278fe0e653fdcb22fdcb63148109ec7e94f2d0750b28157dd1764376ae10fdb0a4aef3b304bd82793e0595f941226a2d72abbc929f53134dc495b0d65ced409914f94c2523f3dfbbdeeac84ae247ab5d1b9ea33dce1a808885a55be1f3683b46f4be73d9b62eec2585f690056858dfc427aabf591cd276724885bcd4c00b93bb51fb7484d", + "ac022309aa2c4d7fb628255b8b7fb4c3e3ae64b1cb65e0de711a6def1653d95d8088871cb8905fe8ae76423604988a8f77589f3f776dc1e4b30dbe9dd262b2187db02518a132d219bd1a06ebac13132b5164b6c420b37dd2ccee7d69b3b7fa12e54f0a53b853d490a68379ea1fa2d79762830ffb71bf86aab506b51f85c4b6a41b69325c7d0c7aa85b93b7144489d213e8f33dbb879fce22849865337b620b155cb2d2d36a68832889e30194d36d", + "d009c2b78a8f02e5e5dbb586ef71fc324b375092e15913ca1a5bfd22d516baadb96867bee3562e77c4a4852344a1a76c30728be5e22400b4cc41711f66754c246a520498d8c24f0205b9c873748dbeb67fe1ad099ad04cf89f4b517f0aa481136d9f6de2d727df01c6aa4099da59d4382b51e25fd47c33d9842c32b62331e50794bfe8b61b3ba9de1b8b704779c6d65edff3af00f121ab4a7ea384edabe47c6d0098a48991f387ca4444135ec59d46", + "c00bab36cce69899817d1425016d222d7303197ed3e3fdcac744705e7f178a1ac745968900f69299163e19b3161f3e0a4cc55aa2e4e71e0ee6ac427d1f4d14e063f68d303ddfbb18118335cfa7a6a90d99c38319ee76f7a884846a9e0b68030bf28e78bfbd56359b9368842814da42b04cb0e307d5d846dc22f049147bae31b9a956d17676a8cc348dafa3cabc2007a30e730e3894dddf9999fb8819086311f0703e141613ed6dcd7af8510e2dc435b0", + "c9789152a9fc29698d49ed95f09bd11b75f18a8c5615a73dbe54ae5e550027fd0ae6a8b60667040c1b12de3d1ee3f6bf061c78c951a3210effc912e19f482dd4de152063c588c44903bc11761706fd935afa040df085b08144d83d0dde32b46ab52f4fae98ac116c7ff11d7f553450c2e37b9c5f0b1dd9e0b8640a24cba6f2a5246c41f197f46e3dc8a29131c79bef3351c6e277a0a34442274d546ccd058891277473d668420f121750d19cd684267405", + "06a15a0731ce52557e368bcbaa11ef3399299e36fb9f2eda6e5726907c1d29c5c6fc581405ba48c7e2e522206a8f128d7c1c939d1132a00bd7d6366aa82724e968964eb2e373563f607dfa649590dcf5589114df69da5547fef8d1604cc4c6de1ed5783c8746918a4dd31168d6bc8784cd0c769206bd803d6ca8557b66748770402b075ef44b38157d4c0da7c6281725a2065d087b1f7b23455fa673bdeeba45b983311c44eabe9ef4b7bde3420ae9881863", + "d08aacef2d7a41aec09473bd8a44f628e15addb7b9e5b77a1e09c8ab4942f379a0bfcb324d580b774666f18ae78dd36710824ff12393f059068fe4b559c53662c2b0e6c69e23785c8f32554e837ec1714bee902e60737b639dd933af4f68cb9d7de77e1f3b28e5b122891afce62b79acd5b1ab4ba411662cc77d806449e69c5a45a143b742d98ac84a0826d68433b9b700ace6cd472ba2d58a90847f42ce9c43f38ffc017db4bf40450b2eee1f4594dc740c0f", + "6a6058b0a498b7ea76a93c646eb9b8629f0cba4a0c726420c5f67ba9b0412cade356abdf0a4fb94384bad32ce0d5dd9e23dcaae1d6f28ff8683616b30f1392890c67b3a2c04b360893b801f127e527e4da82e239f4c878da13f4a4f1c76db07190e77ec123995168102fb274434a2d1e12913b9b5cbab4aacaad2bd89d88b3ca2b8e60dacf7c22c9379097ff60880f552e320ca3b571994f52534470feee2b39e0dadb5cd88257a3e459a4cc6f12f17b8d54e1bb", + "adeced01fc5671531cbb45679f5ddd42b3a95151677b6125aaf6f5e8f82fbabaa5ecf7c3552c2458587224f0042870f178f5fca5465250e75d71352e652eeed23cdb7f915f5ebb44099b6db116ca1be45530ac8ed32b7f161d60ed4397ad3d7d649ae6bf75ca5bec891d8e595605be9764f3a03965e1fe0eaffbf212e3df4f0fa35e08ff9d0091e6d4ac4748edfe43b611085a6ffec163014655fdd839fd9e81b63b1fa8cae4ec335ec343289758e389a79ceedfae", + "d014592f3a83ba40af366f137c674724916c3cdd3f6cf9d4c5c7c8d6d51ebf26e315e2c12b3546be56fb52382904046ecbd2f5b883aa4ff473de6f0c26ab862c3fa34bf3d880cc1911ce39a4088c6617c179dc5faf68a2c488bbde12d67b50f73abcfab0e3b062e68c95363e11f5f1de8ec36ed01ea21442518089045df67d346135283ad5b3fff80cf57f20876849f6db9fa139728358415a90610f69ec720fc92d8234e3e122551e9df2c644c4a2c4e3734d07de8e", + "c0d0c37838873ba8757d6e41b409605043bc1635edcd731219587676d94217e9f0ab44b71de25000661ce7303b7015f45e6eaa7b7ebef92b8f4a34c902c908d2172185505fa33aca5a41be83079316cdfdd430fc2c45f505f85d867e6d516f7e1bf19c001d9f43018968aab65ec031b3801399231c83ec9e622dab5629922a6b424cab938c135ff7310501c2c02971bfd2f577e25904d1a618baf0859f77f4e8b1d0cde9544e95ec52ff710c0672fdb3d891feeea2b017", + "7022e7f00902219ba97baa0e940e8ac7727f58955aa068c29680fac4a16bcd812c03eeb5adbcfe867a7f7c6b5d89f4641adb9173b76a1a8438866f9b4f640ce2aedf5f1080c890bcf515b4be4e3e512352f1e5323c62ec46cb73f3d71be8235fee55a154763f7c3f9aeb61ffd28f4cd93d3310f608e2133586bf1ab3f102de96f64c68a4668de8acb2a76a7ce0cddddc8fa3df5e9d230823da16ed9ebb402d36e38e6e018795e5a71517ecab5f9ca472b9ced8ff69d2d195", + "acaf4baf3681ab865ab9abfae41697141ead9d5e98523c2e0e1eeb6373dd15405242a3393611e19b693cabaa4e45ac866cc66663a6e898dc73095a4132d43fb78ff7166724f06562fc6c546c78f2d5087467fcfb780478ec871ac38d9516c2f62bdb66c00218747e959b24f1f1795fafe39ee4109a1f84e3f82e96436a3f8e2c74ef1a665b0daaa459c7a80757b52c905e2fb4e30c4a3f882e87bce35d70e2925a1671205c28c89886a49e045e31434abaab4a7aed077ff22c", + "84cb6ec8a2da4f6c3b15edf77f9af9e44e13d67acc17b24bd4c7a33980f37050c0301ba3aa15ad92efe842cd3ebd3636cf945bb1f199fe0682037b9dacf86f162dadabfa625239c37f8b8db9901df0e618ff56fa62a57499f7ba83baebc085eaf3dda850835520344a67e09419368d81012168e5de5ea45158397af9a5c6a1657b26f319b66f816cd2c28996547d697e8df2bb163ccb9dda4d6691dffd102a13667ab9cde60ffbfb872187d9c425a7f67c1d9fffff9276ed0aeb", + "6a52c9bbbba454c14540b2be58230d78ecbeb391646a0c6fcce2f789086a78364b81ae85d5396d7cfa8b46bda41e3083ec5cf7b4c47dc601c8a697df52f557defca248506dbebab25657f5a561d09625b7f4b2f0119a12beeac087efc9d350a735c35d2431c1da7dda99befb17f41a3dc4da0f00bb95366be128538ce27763d81f832fe3c1d4efc07b5b08ad8dc9e65fb5e48546664e18cb2d3bb3fe1f56fa7aae718c5e3bbdeaf70e15023f6a25b72a2d177fcfd04211d40664fe", + "c3c4d3b31f1f5f9538923df3478c84fffaef411520a542da9a220ee4132eabb9d718b5076fb2f985485e8ba058330aed27ddfd3afa3db34aa60301088caec3d0053828c0c2bc87e2e61db5ea5a29f62fdad9c8b5fc5063ec4ee865e5b2e35fac0c7a835d5f57a1b1079833c25fc38fcb14311c54f8a3bd251bca19342d69e5785f9c2e43cf189d421c76c8e8db925d70fa0fae5ee3a28c4047c23a2b8a167ce53f35ced33bec822b88b06f41558c47d4fed1bfa3e21eb060df4d8ba1", + "8d55e92136992ba23856c1aea109766fc44772477efc932b3194af2265e433ed77d63b44d2a1cff2e8680eff120a430fe012f0f09c6201d546e13ad46fc4ce910eab27bb1569879abed2d9c37fae9f1267c2216ec5debcb20d4de58461a621e6ce8946899de81c0add44d35e27b7982a97f2a5e6314901caebe41dbba35f48bc9244ca6dca2bdde7306435892f287036df088633a070c2e385815ab3e2bfc1a47c05a5b9fe0e80dd6e38e4713a70c8f82bd32475eea8400c7bc67f59cf", + "5016284e20362610fa05ca9d789cad25f6d43263787e7e085476764ce4a8908ce99b262b375e9d106170b1bec1f473d5e777e0c1896533040e39c8c1465e07907ef5860e14e4d8310013e35f12090e0bfc687474b1f15f3dd2033a0edac5246102da4deec7e188c3517d84d9c2a0a4497a4c5f82a30f1ba009e45ee6eb3ab4368c720ea6feee428ffd2c4cc52debb8d634a64176572c72368f94a66689f23f8a01218f532117af5a8060d140e7ca435a92882fcb5630ebe14a4805f1dc83", + "05456ec59b8d41bbd736727976b96b38c43827f9e16169be673ff37870c2ecd5f0d1ea1a136be4cc7b047a02a4421d484fd2a12ece418e42ee391a13a0b1df5a0162b29ab70d3fe3e04ba6ab26b37d62b7cf05a5e2f033611bf970b8e1f30e198e483e740fa9618c1e8677e07b61296b94a9787a68fba622d7653b5568f4a8628025939b0f74389ea8fced6098c065bf2a869fd8e07d705eadb53006be2abb716a3114ceb0236d7e916f037cb954cf977720855d12be76d900ca124a2a66bb", + "eb6f60b83fcee77060ff346aaf6ec34d82a8af469947d3b5074cde8eb26566eb1fa039bcc707738df1e95869bd827c246e88436f0614d9834ead5392ef376105c4a9f370071cdeaaff6ca0f18b74c3a48d19a717253c49bd9009ccbfdd5728a08b7d112a2ed8dbafbbb46d7a75dc9a05e09bfde1a0a92d74a51887f9d123d7896e9f9d0057b660ed7d55454c069d3c5260411db4cdc67e7b74f680d7ac4b9dcc2f8baf72e15e6b3cafebcdf449a6436ed2c398b675f79c644747c57553bf7ea2", + "187a88e88514f6c4157c1ba40b442baae1ae563a6c989277443b12a219aa484cb9fa8adbb9a29d429f50155321b15664926317477079c7060dfdaa84c1d74bba78892c34e6f21ad35208d2ae622012401696bff5cd57b6485944b3db7b9071fa5f57fbfb1085d91bb9cff5808d662cdc6c8157249478262c44b7fbc397ed42a4977b202e817717bfccc9f0467294062313f7705251ed09573f16d23429361fada259dfb300369c4198f07341b38e84d02cdb74af5de6aab1fc2026208ea7c418c0", + "be31bc96606d0fab007e5caeded2f1c9f747c759777e9b6eef962bed49e45a1d4fc993e279d024915e600865ecb087b960584be18c41114d3c43f92169b9e0e1f85a0ebcd4e196376ccdc920e66103cd3b1c58407d0aafd0e003c4e341a1daddb9f4faba974362a32f35db83384b05ae8e3322d728893861afd8b1c940de5a17f691e763ce4969b6d94f67fb4a0235d100225bd8602f291388f0ca4a568748ad0d6040f1262eac2aede6cd27419bb78a394c1ffad72c262be8c3f9d9619d633e51d0", + "4d83d85ca838b4518588f2a90228a4dd18f14dd5b4c012d26298a97d848abbd825d221d02cceb6e8c701b4ad00e1dee4889b5c533e4bb60f1f41a4a61ee5478be2c1b1016c30345afd7a5253668260515e70751f22c8b4022d7fe4877d7bbce90b46531507dd3e89549e7fd58ea28f4cb23d33662bd003c1345ba94cc4b06867f778957901a8c441bee0f3b12e16463a51f7e50690356971dd73a686a49fda1eae46c9d54fba262811d698025d0ee053f1c58591c3bb3cbde69de0b31549ef5b69cf10", + "cdeb07d36dc5f9a1cd717a9e9cca37a2ce93caa298eee63571f7d6c5fde2a11c666cf53cf2dcb41ca2ea2319e7230ca68e38c647905928713a13982bf47fe33d7095ebd50b2df976208920a43eb2e29b942f32467403c45cea18bf44e0f6aeb155b48a8e5c471fec972a9d62f7ae093d2758f0aaec7ca50cb4725bfa219f1a3a46ad6bde7361f445f86b94d66b8ece080e56c510250693a5d0ea0ae87b4421860b853bcf0381eae4f1bf7c5c0472a93ad18407bc88475ab8560d344a921d3e86a02da397", + "a598fad52852c5d51ae3b10528fc1f722e21d44fbd42ae5acdf20e85a28532e646a223d27fd907bfd38eb8bb75175636892f8242877aab89e8c0824d368f3339ce7a82aa4e5af6db1f3b588a4d667a00f67bee37cfd2724dde06d2909fb9e58d892f4cfd2c4ca85acdf8256f5458b030a6bda151154ff2e6d7a8da90b54a2884c8a99fab5a4ac211ff23dc0975f4f592fd1b6b9dc7783bdcd2d4ca4e68d2902f2013e122cb62e2bff6b0a98ec55ba25837e21f1cfe67739b568d43e6413dab2bd1dc471e5a", + "17b68c74c9fe4926e8102070916a4e381b9fe25f5973c9bd4b04ce25749fc18931f37a65a356d3f5e5a1ef125d546f4f0ea797c15fb2efea6fbfcc5739c564693d47adeb12dcb3d98a2830719b13247792cb2491dca159a28138c6cff925aca42f4fdb02e73fbd508ec49b25c60703a7595a3e8f44b155b371d525e48e7e5dc84ac7b17c52bf5e526a67e7187234a2f19f57c548c70fc0b27183df73ffa53fa58b658034c896fa791ae9a7fd2620f5e46ce84c842a6e60e9324ae4db224ffc87d9617cb85ca2", + "b9e4267ea39e1de1fed0579f93bb351007c9f8fcdd811053fae33f09e2753d7428f04e1a9efcd45ea701a5d87a35b3afb2e6b65365dee6ead0bbb611b7797b212ac688653f542e604a39df277f12514ddfee3b4e27b98395c2cd97a203f1f1153c50327965770802ec2c9783edc428271762b275471e7ac65ac36523df28b0d7e6e6ccc7674268a132a63411fc82c0738dbb68af003b769a0bf9e6587b36476cb465350fee13f88ea355d47ffac7b0f964f4139db11b7642cb8d75fe1bc74d859b6d9e884f75ac", + "8ca704fe7208fe5f9c23110c0b3b4eee0ef632cae82bda68d8db2436ad409aa05cf159223586e1e6d8bdae9f316ea786809fbe7fe81ec61c61552d3a83cd6beaf652d1263862664df6aae321d0323440430f400f291c3efbe5d5c690b0cc6b0bf871b3933befb40bc870e2ee1ebb68025a2dcc11b68daadef6be29b5f21e440374301bde1e80dcfade4c9d681480e65ec494a6af48df232c3d51447b9d06be714949249c44c43cf73ed13ef0d533e770284e51369d94ae241a5fb2f163893071b2b4c118aeaf9eae", + "4fd8dd01012bb4df82bf42e0683f998e6f52dd9c5617bae33f867d6c0b69798cead8179346d70acc941abbbdd26e3229d5651361d2252c72ff22db2938d06ff6fc29a42fdf800ae967d06479bc7bbb8e71f40b1190a4b7189ffc9a7096cdb76d40aec424e1388e1eb7ef4ac3b34f3f089da8fda7d1927f5d775c0b2801d22dd1265c973158f640cec93edfed06dc80b20ef8c496b98289d54d46ccd205951cbb0f4e7daeb866b60bacb483411e4382b6f04d472843186bd0e31fbaa93e5c901ec028efafeb45fc551a", + "e9ee1b22b04b321a5fdd8301627011f583887d77560fb0f35552e207561f81e38ac58a0d0aeaf832d1ee72d913720d01f75574e9a321864fe95f4d0d8f0b8db97649a53e71e940aede5c40b4b9105daa42a6fb2811b61209247534cbaf830b07abe338d75d2f5f4eb1c3cf151e9edabe2c8d5f6fff08fac1495ef48160b100d30dcb0676700bcceb28723a29980ab0766a93abb8cb3d1963007db8458ed99b689d2a7c28c788743c80e8c1239b20982c81dadd0eed6740c65fbc4ef15c7b5569cb9fc997c6550a34b3b2", + "ec01e3a60964360f7f23ab0b22e021815765ad706f242265ebc19a2bb9e4eac94393952dcf61aae47682671a10f9165f0b20adf83a6706bfbdcf04c6faba6114653a35584267267873291c6fe7ff5f7695243143421509502c8875aafa9e9afe5be5ef2c851c7f35d69be5d3896000ccdbbfab5c238bb34d607cfe2d55d748880545b4aa7ca61137992925189025c62654b1f20d49c3ccd75aa73ce99cd7258dabedd6480a9f5185531fc0118beb68cc0a9cd182f6973287cf9252e12be5b619f15c25b65c71b7a316ebfd", + "db51a2f84704b78414093aa93708ec5e78573595c6e3a16c9e15744fa0f98ec78a1b3ed1e16f9717c01f6cab1bff0d56367ffc516c2e33261074935e0735ccf0d018744b4d28450f9a4db0dcf7ff504d3183aa967f76a507357948da9018fc38f150db53e2df6cea14466f03792f8bc11bdb5266dd6d508cde9e12ff04305c0295de29de19d491ad86e766774bb517e7e65befb1c5e2c267f013e235d8483e177214f89978b4cdc81aa7eff8b39f2825ad3a1b6ac1424e30edd49b067d770f16e74dd7a9c3af2ad74289a676", + "00e40f30ae3746edad0f5dd03d0e640933cf3d1694804c1e1ed6399ac36611d405196ee48f129344a8512feda16a354517871322bd5d9c6a1b592933eab531923efb393ffb23d9109cbe1075cebfa5fb917b40df028a621460ff6783c798792cb1d9635b5a6f84ec13918fa302924649b5c7fcb1f7007f0d2f06e9cfd7c27491e565a96c68a0c3644f92cd8f38857258c33801c5d537a83dfe583cba59d7eec7e394199c0a2660a62fabe3ed2099d57f315a6cd8de1a4ade29d977f15d65759cff433e5ac0c182aef3761163e1", + "3c5ea24d0d9b618294a263f062b2414a722be4eb10dfc346a6ec3b821d7396eba61cd6ef33618b04cd087a811f299d4606820227f16000d7c839062b96d3e3f59cd1a082448d13fc8f56b3fa7fb5f66d0350aa3b72dd7c165d590282f7da2e12cfe9e60e1796122bb8c2d40fdc2997af634b9c6b127a893dfb3467909378300db3da911be1d7b616bb8e0572433e65527e15d936500a2c60e9f9909dcf22ab5e4b6700f0238c205b4a813626fac3d945bab2637fb08203044a73d20c9a3fcf7c3fc4eb7807c3276dd5f73ce89597", + "9271aeeebfac46f4de85df78f1bfd36136aa8905e15835c9e1941176f71e3aa5b1b131843d40479735e23e182a2bd71f66f6149dccb7ed8c16469079dc8590bbf165374951785f4531f7e7361de62f936cfb23a2b5bdf186632e7042a0dd451fdc9b7208f923f3a5f250ae590ec348c63a16c3aacaf7379f53b5dd4152dcd40d23e683e2156e64c592ffc07e2cd6bbeebef4dd590b2f6b2bcbf08fcd111c079f5c4033adb6c17574f8756ecd87be27eff1d7c8e8d0324438d59ae171d5a17128fbcb5533d921bd044a2038a5046b33", + "4e3e533d5bcb15793d1b9d0468aaee801f32fdb486b11027183553a09ddbee8213924296f2815dc61577297459e834bf1c7a53f87d43782209e589b8295219ba7073a8fff18ad647fdb474fa39e1faa69911bf83438d5f64fe52f38ce6a991f25812c8f548de7bf2fdea7e9b4782beb4011d3567184c817521a2ba0ebad75b892f7f8e35d68b099827a1b08a84ec5e8125651d6f260295684d0ab1011a9209d2bdeb75128bf5364774d7df91e0746b7b08bda9185035f4f226e7d0a1946fcaa9c607a66b185d8546aac2800e85b74e67", + "b5d89fa2d94531093365d1259cc6fe8827fea48e6374c8b9a8c4d2209c280fa5c44958a1847222a692a59e6aa2696e6cdc8a543dd89b0ce03bc293b4e78d6ef48e1839694ccd5c65661143095c705b07e3ced84a0f5959114dd89deb956ab3fac8130eb4a878278205b801ae41a29e34146192308c4e759b374757b0c3b00319bce92a1b95a4d2ee179fd6714ff96155d26f693a5bc973f84ac8b3b91e3926276297532d98b46992a3f104c08100bf1671c43134bac280c617da711e90a0100137525375ebb12802a428885ae7fce6514a", + "40e3d8048fc10650cb8a7fc2e7113e26dec34f9ca2d5129cd10a8e8e44d113d61ee48c7d003e19fd307fc6debd70feb30243f298c510ccc4418355ce143066f067ad7c6de7288c3080e7ad46a23c8d34deb55a43e652fe90444ad3c57d3ec1e1c489d63ef915a24bc74a7925a0a7b1e1523f21ca8fee78df24e3d0a68d0013423db97c280799a0618229c0f2c167289a891e5c8d6661ab21285951c31710e3b5fe55f6347fe16d9b40507948a59252efeb616df83e5c098b07d0a7247cd371daff0e50491c582503fd89f79ba94d6af9ed76", + "1fa444de01dd3901e2b4684e3d7a799ffa02d85afd35fb30fe4c9d672837bee6dd8a3b8608b4bb5e589220ad5a854f46b46e41c6d57ad124a46beab4169ff69fee7e3838a6165e19dad8eb5d7bf53d4edd3cd2769daf219510a02fdd2afe0c0e1da3cd30fcd1aa88b68965586f07a25a1720fbd90a096ea30fc8e945e3637d7857c8a9c0ab4154ffb2000e57b5f9adfa4e4eaf8065bc3c2b2e75f495963325588785a6ce417dcddffd299873b15dcccca128d63cd4eeeadb64cda28099a9ad7c80d34844901f26b88b00b9aafeb2f90286d29d", + "fde0a0d9d813983bd1f55cf778a003a2023b34a555322ab280584537bc6bdd844d22a7d6066c18da83ec09f3d8d5a1aab4be0d5ce19b436052f6e259a4b49017a1f47f1fe2bf115d5bc8599fb216351c60dd6b1bedb2e6f4dcadf424b833501b6f099cbfad9e2290680fb69c25032b42a6274f7cb9b5c5950401354838a45f7cb77b95bf54718e2f3d3d9fb91eb2311903980277396398d9736d8e92fd838594ac8a537c6c529db5a8a4f89290e6ba6f20ac0e5ed6fef40901d0e0e8e3e502990811f9acaae555dd54eb1bcd96b513e2fe751bec", + "9f8e0caec87858599f5ab29bff86da78a841a918a023a111098687ecdf2747612d3f3809d9ca400b878bd4f92c43a1004f1c17c7f19a3cd1ce449bd2b23aff551623c37dd8c0be56bf3fd857b500c2b9f9ccea62481944090a3cf3b6ee81d9af8eeb60f65ef150f9fa4d3ed6ce4762d3d4f174ee8ccd460c25cafac0ea5ec8a6a4b2f9e8c0520cb7061155e532cb65f188b01e4b9086db951f504b060c296b326b3fc1c590498ecce594f828f4a10ea416675720ae505295d38a791bd0e93f428448a8f4c1fc0af53604a9e8255384d29ae5c334e2", + "33d1e683a4c97ee6bbaa5f9df1a88cb53b7f3c157b6045d70a56fda0ccbd3a1fa1f049cd564da072b53f415bf5fb843771c1d2551fd075d33377362b2f7c0645f9723123d11975991db8a2b518f02e2c7c30342a044754290bae2c77496d755e5981f12e6b0a0174280b958bf11ed628a9062775993ced04bf752ea8d165e3ac2177d7cd1b9371c44efa98f0b3e68602a839d384eec007979f46429dafb138cbc231ad928a9f65f7d66fac77416395e8f1debaaf76ec2e4e03e8674102cd26f614739f3ec9f949033df1fb97e87c2326d65aef94ed5f", + "180048f09d0b480887af7fd548a85abf605440c1ddde6afe4c30c30670233f7bf928f43b4681f59279ebbda5e8f8f2a1abefdee129e18ac60f9224e90b38b0aabd01308e0a27f41b6fb2ee07ee176ec9048c5fe33c3f7c791469c81f30e28170585b9f3e7e3c8c2e9d74370cb4518f13bf2dee048cbd98ffa32d85e43bcc64a626b40efb51ce712925fdd6fee006dc68b88004a81549d2121986dd1966084cd654a7c6686b3bae32afbd9625e09344e85cf9611ea08dfce835a2e5b3726e69ae8a76a97db60fcc539944ba4b1e8449e4d9802ae99fae86", + "13c0bc2f5eb887cd90eae426143764cf82b3545998c386007cca871890912217aa143ac4ed4ddb5a7495b704aa4de18419b8664b15bc26cfc6596a4d2ae408f98b47a566476d5802d594ba84c2f538def9d016661f6404bb2337a3932a24f6e30073a6c9c274b940c62c727242e24466084a3ea336365d71ea8fa6499c0ea8d59eea505f1126b99c795023c4963aa0d99323d0391e8701110edf551b2d3799e1063ca443f1add162156e445502ca1a052fe70c289838593b58839fc63de128a03e2bbf389e22ae0cf957fd03315ee407b096cc1cfd92dee6", + "6f1eb607d679efef065df08987a1174aab41bdac8aece7726dfa65805d6fff5b3d17a672d96b770dc32165f144f0f7324822a5c87563b7cd9e37a742ae83ef245d09006d91576f435a03476f509ea2936636232f66aa7f6cdf1ac187bbd1fcb8e20f8791866e60ed96c73374c12ac16795e999b891c64507d2dbd97e5fc29fac750ad27f2937cbcd29fdafccf27ab22453834d475f6186eaf975a36fad5c8bd61c21da554e1ded46c4c39765dcf5c8f5ccfb49b6a4dc562c919d0c7d8940ec536ab2448ec3c9a9c8b0e8fd4870cad9de2577c7b0c38563f355", + "dcdd993c94d3acbc555f464871a32c5da6f13b3d5bbc3e34429705e8ad2e76393fdd96a69a94acb652f5dc3c120d41187e9aa919669f727c4868013b0cb6acc165c1b7706c52248e15c3bf81eb6c147619467945c7c48fa14a73e7c3d5bec91706c567145342a026c9d97eff97ec672c5debb9df1a998083b0b0081d65c517b3e5634c95e347e781aa30ca1c8af815e2e494d844e847fdcb41622894a518dc36571123a40bfdbe8c4f4cff44d83c61dd9dcd24c464c53b395edb31efee9f3aa080e87cdc3d22d613ae84a53c9249c32c96f9a3bc4629bb126a70", + "49971f9823e63c3a72574d977953329e813b22a8387cd13f56d8ea77a5d1a8a20012632d1d8732bbcb9f756b9675aab5db927beacab7ca263e5718b8dfa7b2eed9a91bf5ed163b16139d45f7b8cc7e3f7bdda6202106f67dfb23b7c315ee3e17a09d466b1e6b13e7c7428184a979f5358667b4fa8bd40bcc8ea46058db44587a85377ac46bf155136c09ac58cb6c27f28e17028c91e7e8f74d5b500e56293b316974f02b9d9ea205d9b6ac4cfb74eb8eb0c944577fd2f41316368307beab3e327bf7dbaa0a4428836ec4e895dea635234abeaf113ceeadac33c7a3", + "c57a9cc958cee983599b04fe694f15fb470fcbc53e4bfcc00a27351b12d5d2434444253ad4184e87b81b738922ffd7ff1dc1e54f39c5518b49fb8fe50d63e3935f99e4bd125e8dc0ba8a17fd62de709339a43fabe15cf86d96a54010112170c340cfac4132182eed7301402bc7c8276089dec38488af145cb6222525894658f03501204b7a66aba0be1b557b28a2f652d66f7313ed825ecc4d8596c1be7420d4425b86a1a90a5b7f30d0f24e0d1aae0eb619ca457a71699e44be612a4011c597ee80b94d5507e429d7fc6af22579cd6ad642723b05ef169fade526fb", + "0568a672cd1ecbaa947045b712e2ac27995392fbef8f9488f79803cbee561c212287f080eca95adb5ba42739d78e3ba667f06045d87850d3a0499358649caa257ad29f1a9c511e7054db20554d15cbb55ff854afa45cae475c729cea72ede953522031865bc02b95589ed4d9841c552a8cc94904a93ed09ed77222f6c178195056be59bc4e96a815adf534e6b466fb47e262ff79c803c157a21b6e2269c2e0abeb494113cd868d8466e82d4b2f6a28b73645853d96bc9242515d803e33294848d3fe42fdff68da53c03491636beede47ff1399dd3d54a5e914d55d7adf", + "3f19f61a4cd085796731ac9f85a75a8bce77031932c31762d87d8b8d07b8bd19ff78d6b7d1bd1e87f3a4f41aad03b6c4d17a6cbc86be55f7c8b88ada047bb04f8d49f1c34bcf81cc0f3389ad01a758fc7eeb0072aa9ad1481992bfdde82e438e75590a4423832dfbe3756e2229ea873bc3606e6d72174cb2163bf40b5d49c81009dab85ecc03e311351bbf96e32c030a2b276a7698cb25bc2c967acb3213161a1fdde7d912cd6a804490f8056c47da1333f6e35c41e749c2c23919cb9af5eec5652e6e072b034fb1682e9aaa194a9c0bd456ea0b008d14dbce37967a7a8e", + "705f98f632d99d3651793825c38dc4deda56c59eac539da6a0159c83131cf8ab6f2ee0c3b74111fde351f7aa1a8c500a0cecab17c212d2c58ca09eae608c8eefc922b9902ef8d6832f799ba48c3c28aa702b3242107edeba01daafe424406a3822965056cfe8783455a671e93b1e2eae2321364f1871471c82124df33bc09e1b52882bd7e1c4c7d0b2f3dd4a28c2a002a43246768af0700f9659de99d62167be93177aabf19d678e79e9c726ac510d94e74873eda99620a3961930cd91937c88a06d8153d64fd60da7ca38cf26d1d4f04a0df273f52127c53fdc593f0f8df9", + "ea6f8e977c954657b45f25480ff42c36c7a10c77caa26eb1c907062e24fbca5aebc65cacca0de10abea8c78322f08672e13d8ac16996eca1aa17402eaea4c1cc6c800b22dc18cb8d620192d74bac02c07b5cfa61e513c7f28b7e29b9700e0e442720bf4c669d4995da19d19f841d9eb68cc74153592591e3bf059ef616b95305aa453b32fe99a91afb35bd482cf2b7aa42702837a53be3c38883d2963020e347556f841254ec6b85854485fe8c520b05f2ea67a9bf3981555c20991e2bacd4db5b418228b6002d8d41c025cb472bf5443aaa885974a408ea7f2e3f932c600deb", + "408190134ed06556811b1af808ab2d986aff152a28de2c41a2207c0ccc18125ac20f48384de89ea7c80cda1da14e60cc1599943646b4c0082bbcda2d9fa55a13e9df2934edf15eb4fd41f25fa3dd706ab6de522ed351b106321e494e7a27d5f7caf44ec6fadf1122d227eefc0f57aefc140d2c63d07dcbfd65790b1099745ed042cfd1548242076b98e616b76ff0d53db5179df8dd62c06a36a8b9e95a671e2a9b9dd3fb187a31ae5828d218ec5851913e0b52e2532bd4bf9e7b349f32de2b6d5d3cdf9f372d49617b6220c93c05962327e99a0480488443349f0fd54c1860f7c8", + "5f9e5c6f38573a85010a9d84d33f29c057003b2645e3ea6f72cbc7af95d197ce6a06b13fea81722853e6991791b8b15091cd066f5ed913592ed3d3af5370d39ba22beeb2a582a414b16824b77e194a094c2afdcc09aa73ce36f4943cca5ae32c5017dc398801dd92a47382d9327c9f6cffd38ca4167cd836f7855fc5ff048d8efba378cdde224905a0425e6b1de061fc951c5e624a5153b008ad41160a710b3ff2081748d5e02deb9f841f4fc6cf4a15153dd4fe874fd447482696283e79ee0e6bc8c1c0409baa5ab02c5209c319e3169b2476149c0c6e541c6197ca46e004eef533", + "218c6b3508aec69574f2b5039b30b942b72a8349d05f48ff945bbbe5c8957d5a6199492a6bf54bab821c9377e2edfa4c908384664d2c80112d5e805d66e0a551b941021be17dd20bd825bea9a3b6afb1b8c605805b3bda58750f03ea5c953a698494b425d8980c69f34d1c3f6b5866e8717031152a127215c256e08873c21b0f5cc85875d0f7c94601659150c04cd5fe5d381ba29983a2d94fcd3a65a94c53c7279cd000dddd4253d8cff8d7f6ace10247fe3bc30d63ba4bb54f557b3d22a3924369430d71ab37b701e9500bda70b5a643704858beed4726a889b6c9c91584194c68f1", + "dac26aa7273fc25d6e044c79fc2bfa46e59892a42bbca59a86826c91e76ab03e4bd9f7c0b5f08d1931d88b36ea77d94f7ba67cd4f1d3086e529427201119096ae066ae6f170940830ed7900de7bb9d66e09788287403a4ecc93c6da975d2fb08e918840a236c15f5d3a8f7375c2eeebbf6f01a6e7f29ca2b8d42df158414c320777433663c59fdcd1f39ca68e3473db721be7ce8c6dba5fddc024f94fedb286b0477581d451313ca8c737484daf60d67f9b2d56d4bcc271f7e9ae958c7f258efbc74d25753e0516f28282461941bf2dcc7dd8c7df6173b89760cefcac07190243ff863fb", + "c46e6512e6797cc7a54254a1b26b2de29aa83d6c4b1ea5a2786fbcec388270625b12635eae39e1fba013f8a65219421bca8b52a8ddfd431cda60299bdf160734d5a7450ec79620058522702174ae451b9bfa7c4a455fbbee3e1d048c7d4bac5131018228f137c8e130440c7059b4f15eaa34ce872a851a16ce86f982df78a00be4d564da2003a450ddee9ab43ea876b8b4b65c84f0b39265fd5456417afb5bc54997c986e66fc222f2123ba5e719c4d6b9a177b188277df384f1125821cf19d5248cef0be183ccdc84ac194506f740ed2188b2689ea4c9236a9e9e3a2fff85b6af4e9b49a3", + "1ccd4d278d67b65cf2564ecd4de1b55fe07adc80e1f735fe2f08ea53fd3977323689122c29c798957abaff6aba09bdcbf661d77f4dc8913ab1fe2bef38846166e3834785e7105d746484eff8c656af5d8c7854abc1c62b7fadb65521dc6f793d978bda9838eb3800417d32e8a24d8c8cb1d18a5de6ca79d9e1b0ff9aa25e6218fe944cf18666fecc1e31334b390260dbe0997539e1b02f6366b2aea4f4a21efe04f4b97568fcb39e59919d5ebac6543d5d0f48fc66b923c34aac377dc95c20329b837b6ed5e8d9a3d2089cd0d8f025658006ff41cbdaccca618822ca590ab155253f8bc1c7f5", + "9875209588395ee3c9fdd793fd48717cc84c8c3ea622b2ccc4a1be4448e6034b7810569855255031f10be5ffd714b05f9ce01972d712d40abf03d4d0ce175813a7a668f761324996093fc2aa5912f7fc2abdadd8775d2b4d9ad492216293381460ed8f6db3d641d1525f4242c348bbfe504c704f215dc461de51b5c75c1aae967936963848f16c673eca5e78dfd47eb19001d52d1bcf96c98956dad5ddf594a5da757e7ca35f2f69803b784e66ac5a58b75c228b8266ec592505e5d1ca87d81225738855f15bc0914677e81593fd409e77d159f8a908f67788de9eb06c5561547aada96c47c535", + "40c90e375e366f3756d89091eb3eed9fe0fbfc5638700af4617d358812bac53124a2205dd6756456787d49cd6a35e302479a0992288f47532e4ea7ab62fc5ad5adc690a5d9a446f7e035ad4641bd8dae83946aee3338ec984ccb5cc633e1409f2531eeffe05532a8b0062ba99454c9aeabf8ecb94db195af7032bfebc22912f49d39330add47ff8fa5720612d697f0b602738930e060a1bb214efc5e292224cf34e29deaea6b1b1ff847e94ecc997325ac38df61db45d82bf0e74a664d2fe085c20b04c39e90d6a170b68d2f1d373f00c731c524456ada73d659aaac9df3191a7a3865083343fc13", + "e8800d82e072210ca6d7fa2472028974780b76aad4bcb9ad362422dd05ae3232668251d164daa375a43b26a38cce28dbeb3dee1a4a579f70d0fe7febb29b5ece8aa836e050fb3d188c63aa9c3c0da6c717d86458a6096b5effceb964efdec7035960c09ccd10dea3c5f1c7f9f478d5887ebbe2e15c5ff85dbacbc444bb951c4eec7abecb89ed80187e409e2972ffe1a5f01562af109f2cf09471cf72cf83a3bb8f4e2ef38ed0e326b698296394e5b2718a5000c01425708e8ad0461e62462d8819c2377f13ab1be2c7c9f33dc06fe23cad27b87569f2ce2e56e4b2c60c7b1b3d370841d89ebdc1f192", + "796d6d1447d5b7e8c55cd8b2f8b7010db39f27565f907e3fc0e464ea2d4bb52b37f10e7c6dcfc59231b9cdee12c32aeb4adbc42b86e86eb6defb5b69e6ca75e1f4d0dae3e124e5a1b8b6697f7e10b0403f1f0a5ff848eef3752837a9ba17780f16a9a709188a8d5b89a2fa74adb2e651163b1c2b3d261e225c9158dcd9eb7ac3d6704cee290cdff6bcb3cb90cee030aa0d19d4693655c3c30ac6fc06d2ae37787c47126d57ed9a6bef5f8a6c56859aefc08755739a95aac57a4dd916a92ba9f3afbf969df8085949615033365c751a9a3e1a18cee98a69d22e64009bebf8307169b6c61de0617ecfafdf", + "4f9057183566153cf337b07c3f5556006de54c56b2a1e5326c07aaeabd1886ec6f1641358925db232b2f0dbf75229c796a7395b2f934c1f99090bec1123f3c841b1cb3c5b1ec42ed5408f2940f0c48a9470b852c46d6557853d459cecd2c32bbcd8ee21fa11e385eef0857cba4d8545a61b52a484cdd779db4739fbc7aa9860dcabe0488b98fa0b60c3f7d6153db279000a52ffb573dab37d2ab1896a90e5deb7ac6bbe56239085c325d83a917dc6e8a448425b718c2356b9f3066163555ec444f372e184e02c8c4c69b1c1c2ae2b51e45b98f73d933d18750968945ca85d6bbb22014b4c4015262e3c40d", + "79dcca7d8b81a61359e4aece21f3df7b99518ce70bd2f57a18bab5e7114af2add0a0cea7f319d69f231f060e0a539d9a23fb3e95451ce8c6340cfb09edf931df84203a39226dd9eb278f11b691ef612585b973daab373e65d11325898badf6732100371fd759960fa8fec373268421d28bffdb9b12a430b92fe4b07566ca0c89e616e49f8fc75ccd9cdc66db820d7c02e109aa5ed86b89770262918a518f90a2292f6b68d68ae03992e4259a17a23c84ec2a417f082b5abf3a26e44d2278ecb8ba9456965303a75f25394d1aaf5544590e74b14d8a4cc4050be2b0ebcfe4d2db6b12a02c68a3bcdda70301f3", + "848755dc31e25e9a42f9ec12d847d19f292c14c162c9aba49e972cb123b58b8e57bb263a923929833373858594ff52dbc298dbbc078599194e4c07b0e5fc1e10808bbacdb6e93c72b333685cf961f28eb0d5a395c63266b01f130d25db384b356e5da6d01042fc2359581b89c63b3bb2d1ce897fbc9e83fe85d9666cb60e6a8c657f70caad5387b8a045bf91095606802c8424ea8ac52ef29386dc46183378a5fcb2cb927428b8c070f1c42aafd3bc70ca25437807696a46873cfeb7b80ba2ebc3c4272443d445e46343a1465253a9eebd532a0d1d2c18264b91ff45159f245404ae9335f2af55c802772426b4", + "ecaa6e999ef355a0768730edb835db411829a3764f79d764bb5682af6d00f51b313e017b83fffe2e332cd4a3de0a81d6a52084d5748346a1f81eb9b183ff6d93d05edc00e938d001c90872dfe234e8dd085f639af168af4a07e18f1c56ca6c7c1addffc4a70eb4660666dda0321636c3f83479ad3b64e23d749620413a2ecdcc52ad4e6e63f2b817ce99c15b5d2da3792721d7158297cce65e0c04fe810d7e2434b969e4c7892b3840623e153576356e9a696fd9e7a801c25de621a7849da3f99158d3d09bf039f43c510c8ffb00fa3e9a3c12d2c8062dd25b8dabe53d8581e30427e81c3dfc2d455352487e1255", + "23a3fe80e3636313fdf922a1359514d9f31775e1adf24285e8001c04dbce866df055edf25b506e18953492a173ba5aa0c1ec758123406a97025ba9b6b7a97eb14734424d1a7841ec0eaeba0051d6e9734263bea1af9895a3b8c83d8c854da2ae7832bdd7c285b73f8113c3821cced38b3656b4e6369a9f8327cd368f04128f1d78b6b4260f55995277feffa15e34532cd0306c1f47354667c17018ee012a791af2dbbc7afc92c388008c601740cccbbe66f1eb06ea657e9d478066c2bd2093ab62cd94abadc002722f50968e8acf361658fc64f50685a5b1b004888b3b4f64a4ddb67bec7e4ac64c9ee8deeda896b9", + "758f3567cd992228386a1c01930f7c52a9dcce28fdc1aaa54b0fed97d9a54f1df805f31bac12d559e90a2063cd7df8311a148f6904f78c5440f75e49877c0c0855d59c7f7ee52837e6ef3e54a568a7b38a0d5b896e298c8e46a56d24d8cabda8aeff85a622a3e7c87483ba921f34156defd185f608e2241224286e38121a162c2ba7604f68484717196f6628861a948180e8f06c6cc1ec66d032cf8d16da039cd74277cde31e535bc1692a44046e16881c954af3cd91dc49b443a3680e4bc42a954a46ebd1368b1398edd7580f935514b15c7fbfa9b40048a35122283af731f5e460aa85b66e65f49a9d158699bd2870", + "fe511e86971cea2b6af91b2afa898d9b067fa71780790bb409189f5debe719f405e16acf7c4306a6e6ac5cd535290efe088943b9e6c5d25bfc508023c1b105d20d57252fee8cdbddb4d34a6ec2f72e8d55be55afcafd2e922ab8c31888bec4e816d04f0b2cd23df6e04720969c5152b3563c6da37e4608554cc7b8715bc10aba6a2e3b6fbcd35408df0dd73a9076bfad32b741fcdb0edfb563b3f753508b9b26f0a91673255f9bcda2b9a120f6bfa0632b6551ca517d846a747b66ebda1b2170891ece94c19ce8bf682cc94afdf0053fba4e4f0530935c07cdd6f879c999a8c4328ef6d3e0a37974a230ada83910604337", + "a6024f5b959698c0de45f4f29e1803f99dc8112989c536e5a1337e281bc856ff721e986de183d7b0ea9eb61166830ae5d6d6bc857dc833ff189b52889b8e2bd3f35b4937624d9b36dc5f19db44f0772508029784c7dac9568d28609058bc437e2f79f95b12307d8a8fb042d7fd6ee910a9e8df609ede3283f958ba918a9925a0b1d0f9f9f232062315f28a52cbd60e71c09d83e0f6600f508f0ae8ad7642c080ffc618fcd2314e26f67f1529342569f6df37017f7e3b2dac32ad88d56d175ab22205ee7e3ee94720d76933a21132e110fefbb0689a3adbaa4c685f43652136d09b3a359b5c671e38f11915cb5612db2ae294", + "af6de0e227bd78494acb559ddf34d8a7d55a03912384831be21c38376f39cda8a864aff7a48aed758f6bdf777779a669068a75ce82a06f6b3325c855ed83daf5513a078a61f7dc6c1622a633367e5f3a33e765c8ec5d8d54f48494006fdbf8922063e5340013e312871b7f8f8e5ea439c0d4cb78e2f19dd11f010729b692c65dd0d347f0ce53de9d849224666ea2f6487f1c6f953e8f9dbfd3d6de291c3e9d045e633cfd83c89d2f2327d0b2f31f72ac1604a3db1febc5f22cad08153278047210cc2894582c251a014c652e3951593e70e52a5d7451be8924b64f85c8247dab6268d24710b39fc1c07b4ac829fbda34ed79b5", + "d7314e8b1ff82100b8f5870da62b61c31ab37ace9e6a7b6f7d294571523783c1fdedcbc00dd487dd6f848c34aab493507d07071b5eb59d1a2346068c7f356755fbde3d2cab67514f8c3a12d6ff9f96a977a9ac9263491bd33122a904da5386b943d35a6ba383932df07f259b6b45f69e9b27b4ca124fb3ae143d709853eed86690bc2754d5f8865c355a44b5279d8eb31cdc00f7407fb5f5b34edc57fc7ace943565da2222dc80632ccf42f2f125ceb19714ea964c2e50603c9f8960c3f27c2ed0e18a559931c4352bd7422109a28c5e145003f55c9b7c664fdc985168868950396eaf6fefc7b73d815c1aca721d7c67da632925", + "2928b55c0e4d0f5cb4b60af59e9a702e3d616a8cf427c8bb03981fb8c29026d8f7d89161f36c11654f9a5e8ccb703595a58d671ecdc22c6a784abe363158682be4643002a7da5c9d268a30ea9a8d4cc24f562ab59f55c2b43af7dbcecc7e5ebe7494e82d74145a1e7d442125eb0431c5ea0939b27afa47f8ca97849f341f707660c7fbe49b7a0712fbcb6f7562ae2961425f27c7779c7534ecdeb8047ff3cb89a25159f3e1cefe42f9ef16426241f2c4d62c11d7ac43c4500dfcd184436bb4ef33260366f875230f26d81613c334dbda4736ba9d1d2966502914ec01bbe72d885606ec11da7a2cb01b29d35eebedbb0ecc73ed6c35", + "fd993f50e8a68c7b2c7f87511ce65b93c0aa94dcbdf2c9cca93816f0f3b2ab34c62c586fc507b4900a34cf9d0517e0fe10a89d154c5419c1f5e38de00e8834fe3dc1032abdeb10729a81655a69a12856a78ca6e12110580de879b086fd6608726541cfa9616326bdd36064bc0d1e5f9c93b41278bff6a13b2494b81e238c0c45aea1b07d855e8f3fe1478e373bd9d3957cf8a5e5b9003386793d994c7c575cff2322e2428cbbaa4f47560316ae3354a7478842ff7cc5dcbacb6e871e72b36f06d63a9aaeb9044cfb7974afdc238a5816f537dcf33ee40b4e1a5eb3cff2402b46d548264e133008d284f11b7e4e450bc3c5ff9f79b9c4", + "8df21892f5fc303b0de4adef1970186db6fe71bb3ea3094922e13afcfabf1d0be009f36d6f6310c5f9fda51f1a946507a055b645c296370440e5e83d8e906a2fb51f2b42de8856a81a4f28a73a8825c68ea08e5e366730bce8047011cb7d6d9be8c6f4211308fad21856284d5bc47d199988e0abf5badf8693ceeed0a2d98e8ae94b7775a42925edb1f697ffbd8e806af23145054a85e071819cca4cd48875290ca65e5ee72a9a54ff9f19c10ef4adaf8d04c9a9afcc73853fc128bbebc61f78702787c966ca6e1b1a0e4dab646acdfcd3c6bf3e5cfbec5ebe3e06c8abaa1de56e48421d87c46b5c78030afcafd91f27e7d7c85eb4872b", + "48ec6ec520f8e593d7b3f653eb15553de246723b81a6d0c3221aaa42a37420fba98a23796338dff5f845dce6d5a449be5ecc1887356619270461087e08d05fb60433a83d7bd00c002b09ea210b428965124b9b27d9105a71c826c1a2491cfd60e4cfa86c2da0c7100a8dc1c3f2f94b280d54e01e043acf0e966200d9fa8a41daf3b9382820786c75cadbb8841a1b2be5b6cbeb64878e4a231ae063a99b4e2308960ef0c8e2a16bb3545cc43bdf171493fb89a84f47e7973dc60cf75aeeca71e0a7ebe17d161d4fb9fe009941cc438f16a5bae6c99fcad08cac486eb2a48060b023d8730bf1d82fe60a2f036e6f52a5bff95f43bbe088933f", + "f4d84ed3e564c102600a795eaa9b1eaf4ad12f1a4deca1d042a0a2750ddf6201db03073d8bf553cb9dde48a1b0083827a609f7242b86584cc180964ae794b12ce55661e00e36a6ba4dbc389e6a5a85f1b45df9af7ead1b0a54db56e68639b9d438a91504e82c35d40c7bc7e048a53ac0b04accd0dadf4ac9884b0ca0e3cb5ba4336e3581be4c4760a553823ffa283a1120d4e145af56a59f2533903650f0b9e9ad9fe2e8a3c3c3dd03a1fcb709032c8835324839c735b0c051d0cbd8b5d867617c11023432e4bd275d3d0eb98a0b6cf58071a5b712922f2bc751ac7c2588c447444cde2f37a8ea5ec126425bf517e0d17c9e2999f52fee14b3", + "2ccea21bac9c2b70d3923309cbf2d7cb7abd1fcc8b8b002688870a80029c62397350c3c898194e5deea360bb963d26d485cb7963f8167586976ec0556950b2e86135f4a2800991ce8473bfd44a3c5e937a48b5e355ba5141bccf2131a83988d9d2a9e8e7635a956105b3512c05ef708139ced51d7a4e204c12d8a49a21e8dc6de2629a2fd092326885d9f218745fe09f6d91fb6afce250a30a63689534b6be1f26899ffa3767d835cf586aa47776700f94241bc999b1e3deefe188f37ff734f5f16ee6a00914323dc7b8a143c9137cdcc5cd08ae9566f04bb2941532674c97dff6ffa5ce3405ef8e5d27ec403114253dd6394c0167d72a0044c5", + "2b681c6398aee63bf862770341648bbcd31d7de7903c5903fe3d9469311320bb24d914f2af0cdca199c97214c7c679dc32a2800ba484a03c010ea6be3bb9f2c87e30a98b606050b8a3f297f12b8f92caaeceb3e844652115934874e0a1ab093a73d759b53f6a6c3096940dd22c2bb96ce6820a7b9c6d71a208de9892aa6a7209b0fff56a0cafea52b952cdd6f5752cff3309d448800b4e4c878aa595595b56b12b83fcd6ca89520c7da664e449d7b4438fc455888aad5de0fad9a06eed14afd3513b5ebbffe01775549b701181bd26370764f56eba52fdb24286ad1ac0f5418a7c429f7dfc7f3168437fa8eed7a2ed7c723a485e4c3ed14dea2e07", + "aadfd505a89f4aade2c3018258a7e039401b1fc6a7f3d87910dddbb880d372ec8a13c70d92245de5b8e5f9a285c33b99dc82fa2b22decee72b93a72211656ad7a52696c8e570f78be28c0e427a371dafde856e8d5ed24f83b0660b51e7fac05d93a8666dfde6def59af863f80f3e5f6801182c87422203df390dcb736b8f830052a8832eeeb0b4e27e732aaf793d166b5a3ec7745aeef3766937c2b75a276bddd145f6010c29d035e343e267cb2d828436876ec3a7ebe3b6347d4172f7a99d6821ce152e039e53deb33340b324c7f068ffb94b3cde35a8eaa12d15c3806a7ad0acec3e8c7078c1d32a28fd3eec9f32cb86e4c22166ff69e83785e851", + "1605b8cce529a9d6262fd4390d9e4ae5e14e0adc0ec89b028ef68dd0f373ea259aaa96f2967091dd0874c0105385e9e6da9ca68297c31afa44ef834535fb302ce5b4e49edacbbdf359fe1228a8172495b3e57014c27edd58b685110980056c50c398a64f4923f2d720b4df16d75cb36b4233660694182099c35028a972519c24764fc94e18e582b24deb3491535fc06b83837c7958522800e822201d694af0bd0aa3834e17d4b1ba36f470905ae5f8bbeeb6c4c8604d8af02baa347b07086d6989867ddd5e8e8ed7740c3469bfa2810519c55c6add1332c4c54ee9097961d6741cb12a09713a0d07645f784f42f5ad94b48b836b34263130b0483f15e3", + "ff9c6125b2f60bfd6c2427b279df070e430075096647599bdc68c531152c58e13858b82385d78c856092d6c74106e87ccf51ac7e673936332d9b223444eaa0e762ee258d8a733d3a515ec68ed73285e5ca183ae3278b4820b0ab2797feb1e7d8cc864df585dfb5ebe02a993325a9ad5e2d7d49d3132cf66013898351d044e0fe908ccdfeeebf651983601e3673a1f92d36510c0cc19b2e75856db8e4a41f92a51efa66d6cc22e414944c2c34a5a89ccde0be76f51410824e330d8e7c613194338c93732e8aea651fca18bcf1ac1824340c5553aff1e58d4ab8d7c8842b4712021e517cd6c140f6743c69c7bee05b10a8f24050a8caa4f96d1664909c5a06", + "6e85c2f8e1fdc3aaeb969da1258cb504bbf0070cd03d23b3fb5ee08feea5ee2e0ee1c71a5d0f4f701b351f4e4b4d74cb1e2ae6184814f77b62d2f08134b7236ebf6b67d8a6c9f01b4248b30667c555f5d8646dbfe291151b23c9c9857e33a4d5c847be29a5ee7b402e03bac02d1a4319acc0dd8f25e9c7a266f5e5c896cc11b5b238df96a0963ae806cb277abc515c298a3e61a3036b177acf87a56ca4478c4c6d0d468913de602ec891318bbaf52c97a77c35c5b7d164816cf24e4c4b0b5f45853882f716d61eb947a45ce2efa78f1c70a918512af1ad536cbe6148083385b34e207f5f690d7a954021e4b5f4258a385fd8a87809a481f34202af4caccb82", + "1e9b2c454e9de3a2d723d850331037dbf54133dbe27488ff757dd255833a27d8eb8a128ad12d0978b6884e25737086a704fb289aaaccf930d5b582ab4df1f55f0c429b6875edec3fe45464fa74164be056a55e243c4222c586bec5b18f39036aa903d98180f24f83d09a454dfa1e03a60e6a3ba4613e99c35f874d790174ee48a557f4f021ade4d1b278d7997ef094569b37b3db0505951e9ee8400adaea275c6db51b325ee730c69df97745b556ae41cd98741e28aa3a49544541eeb3da1b1e8fa4e8e9100d66dd0c7f5e2c271b1ecc077de79c462b9fe4c273543ecd82a5bea63c5acc01eca5fb780c7d7c8c9fe208ae8bd50cad1769693d92c6c8649d20d8", +} diff --git a/vendor/golang.org/x/crypto/blake2b/blake2x.go b/vendor/golang.org/x/crypto/blake2b/blake2x.go new file mode 100644 index 0000000000000000000000000000000000000000..c814496a76b2d97ae96667dd0ed77e6790fb9ce9 --- /dev/null +++ b/vendor/golang.org/x/crypto/blake2b/blake2x.go @@ -0,0 +1,177 @@ +// Copyright 2017 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 blake2b + +import ( + "encoding/binary" + "errors" + "io" +) + +// XOF defines the interface to hash functions that +// support arbitrary-length output. +type XOF interface { + // Write absorbs more data into the hash's state. It panics if called + // after Read. + io.Writer + + // Read reads more output from the hash. It returns io.EOF if the limit + // has been reached. + io.Reader + + // Clone returns a copy of the XOF in its current state. + Clone() XOF + + // Reset resets the XOF to its initial state. + Reset() +} + +// OutputLengthUnknown can be used as the size argument to NewXOF to indicate +// the the length of the output is not known in advance. +const OutputLengthUnknown = 0 + +// magicUnknownOutputLength is a magic value for the output size that indicates +// an unknown number of output bytes. +const magicUnknownOutputLength = (1 << 32) - 1 + +// maxOutputLength is the absolute maximum number of bytes to produce when the +// number of output bytes is unknown. +const maxOutputLength = (1 << 32) * 64 + +// NewXOF creates a new variable-output-length hash. The hash either produce a +// known number of bytes (1 <= size < 2**32-1), or an unknown number of bytes +// (size == OutputLengthUnknown). In the latter case, an absolute limit of +// 256GiB applies. +// +// A non-nil key turns the hash into a MAC. The key must between +// zero and 32 bytes long. +func NewXOF(size uint32, key []byte) (XOF, error) { + if len(key) > Size { + return nil, errKeySize + } + if size == magicUnknownOutputLength { + // 2^32-1 indicates an unknown number of bytes and thus isn't a + // valid length. + return nil, errors.New("blake2b: XOF length too large") + } + if size == OutputLengthUnknown { + size = magicUnknownOutputLength + } + x := &xof{ + d: digest{ + size: Size, + keyLen: len(key), + }, + length: size, + } + copy(x.d.key[:], key) + x.Reset() + return x, nil +} + +type xof struct { + d digest + length uint32 + remaining uint64 + cfg, root, block [Size]byte + offset int + nodeOffset uint32 + readMode bool +} + +func (x *xof) Write(p []byte) (n int, err error) { + if x.readMode { + panic("blake2b: write to XOF after read") + } + return x.d.Write(p) +} + +func (x *xof) Clone() XOF { + clone := *x + return &clone +} + +func (x *xof) Reset() { + x.cfg[0] = byte(Size) + binary.LittleEndian.PutUint32(x.cfg[4:], uint32(Size)) // leaf length + binary.LittleEndian.PutUint32(x.cfg[12:], x.length) // XOF length + x.cfg[17] = byte(Size) // inner hash size + + x.d.Reset() + x.d.h[1] ^= uint64(x.length) << 32 + + x.remaining = uint64(x.length) + if x.remaining == magicUnknownOutputLength { + x.remaining = maxOutputLength + } + x.offset, x.nodeOffset = 0, 0 + x.readMode = false +} + +func (x *xof) Read(p []byte) (n int, err error) { + if !x.readMode { + x.d.finalize(&x.root) + x.readMode = true + } + + if x.remaining == 0 { + return 0, io.EOF + } + + n = len(p) + if uint64(n) > x.remaining { + n = int(x.remaining) + p = p[:n] + } + + if x.offset > 0 { + blockRemaining := Size - x.offset + if n < blockRemaining { + x.offset += copy(p, x.block[x.offset:]) + x.remaining -= uint64(n) + return + } + copy(p, x.block[x.offset:]) + p = p[blockRemaining:] + x.offset = 0 + x.remaining -= uint64(blockRemaining) + } + + for len(p) >= Size { + binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset) + x.nodeOffset++ + + x.d.initConfig(&x.cfg) + x.d.Write(x.root[:]) + x.d.finalize(&x.block) + + copy(p, x.block[:]) + p = p[Size:] + x.remaining -= uint64(Size) + } + + if todo := len(p); todo > 0 { + if x.remaining < uint64(Size) { + x.cfg[0] = byte(x.remaining) + } + binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset) + x.nodeOffset++ + + x.d.initConfig(&x.cfg) + x.d.Write(x.root[:]) + x.d.finalize(&x.block) + + x.offset = copy(p, x.block[:todo]) + x.remaining -= uint64(todo) + } + return +} + +func (d *digest) initConfig(cfg *[Size]byte) { + d.offset, d.c[0], d.c[1] = 0, 0, 0 + for i := range d.h { + d.h[i] = iv[i] ^ binary.LittleEndian.Uint64(cfg[i*8:]) + } +} diff --git a/vendor/golang.org/x/crypto/blake2b/register.go b/vendor/golang.org/x/crypto/blake2b/register.go new file mode 100644 index 0000000000000000000000000000000000000000..efd689af4b49cd22a4b42bf865998d3888670613 --- /dev/null +++ b/vendor/golang.org/x/crypto/blake2b/register.go @@ -0,0 +1,32 @@ +// Copyright 2017 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 go1.9 + +package blake2b + +import ( + "crypto" + "hash" +) + +func init() { + newHash256 := func() hash.Hash { + h, _ := New256(nil) + return h + } + newHash384 := func() hash.Hash { + h, _ := New384(nil) + return h + } + + newHash512 := func() hash.Hash { + h, _ := New512(nil) + return h + } + + crypto.RegisterHash(crypto.BLAKE2b_256, newHash256) + crypto.RegisterHash(crypto.BLAKE2b_384, newHash384) + crypto.RegisterHash(crypto.BLAKE2b_512, newHash512) +} diff --git a/vendor/golang.org/x/crypto/blake2s/blake2s.go b/vendor/golang.org/x/crypto/blake2s/blake2s.go new file mode 100644 index 0000000000000000000000000000000000000000..ae0dc922b9fa67ea46546beda168e8e7a3223499 --- /dev/null +++ b/vendor/golang.org/x/crypto/blake2s/blake2s.go @@ -0,0 +1,187 @@ +// Copyright 2016 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 blake2s implements the BLAKE2s hash algorithm defined by RFC 7693 +// and the extendable output function (XOF) BLAKE2Xs. +// +// For a detailed specification of BLAKE2s see https://blake2.net/blake2.pdf +// and for BLAKE2Xs see https://blake2.net/blake2x.pdf +// +// If you aren't sure which function you need, use BLAKE2s (Sum256 or New256). +// If you need a secret-key MAC (message authentication code), use the New256 +// function with a non-nil key. +// +// BLAKE2X is a construction to compute hash values larger than 32 bytes. It +// can produce hash values between 0 and 65535 bytes. +package blake2s // import "golang.org/x/crypto/blake2s" + +import ( + "encoding/binary" + "errors" + "hash" +) + +const ( + // The blocksize of BLAKE2s in bytes. + BlockSize = 64 + + // The hash size of BLAKE2s-256 in bytes. + Size = 32 + + // The hash size of BLAKE2s-128 in bytes. + Size128 = 16 +) + +var errKeySize = errors.New("blake2s: invalid key size") + +var iv = [8]uint32{ + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, + 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19, +} + +// Sum256 returns the BLAKE2s-256 checksum of the data. +func Sum256(data []byte) [Size]byte { + var sum [Size]byte + checkSum(&sum, Size, data) + return sum +} + +// New256 returns a new hash.Hash computing the BLAKE2s-256 checksum. A non-nil +// key turns the hash into a MAC. The key must between zero and 32 bytes long. +func New256(key []byte) (hash.Hash, error) { return newDigest(Size, key) } + +// New128 returns a new hash.Hash computing the BLAKE2s-128 checksum given a +// non-empty key. Note that a 128-bit digest is too small to be secure as a +// cryptographic hash and should only be used as a MAC, thus the key argument +// is not optional. +func New128(key []byte) (hash.Hash, error) { + if len(key) == 0 { + return nil, errors.New("blake2s: a key is required for a 128-bit hash") + } + return newDigest(Size128, key) +} + +func newDigest(hashSize int, key []byte) (*digest, error) { + if len(key) > Size { + return nil, errKeySize + } + d := &digest{ + size: hashSize, + keyLen: len(key), + } + copy(d.key[:], key) + d.Reset() + return d, nil +} + +func checkSum(sum *[Size]byte, hashSize int, data []byte) { + var ( + h [8]uint32 + c [2]uint32 + ) + + h = iv + h[0] ^= uint32(hashSize) | (1 << 16) | (1 << 24) + + if length := len(data); length > BlockSize { + n := length &^ (BlockSize - 1) + if length == n { + n -= BlockSize + } + hashBlocks(&h, &c, 0, data[:n]) + data = data[n:] + } + + var block [BlockSize]byte + offset := copy(block[:], data) + remaining := uint32(BlockSize - offset) + + if c[0] < remaining { + c[1]-- + } + c[0] -= remaining + + hashBlocks(&h, &c, 0xFFFFFFFF, block[:]) + + for i, v := range h { + binary.LittleEndian.PutUint32(sum[4*i:], v) + } +} + +type digest struct { + h [8]uint32 + c [2]uint32 + size int + block [BlockSize]byte + offset int + + key [BlockSize]byte + keyLen int +} + +func (d *digest) BlockSize() int { return BlockSize } + +func (d *digest) Size() int { return d.size } + +func (d *digest) Reset() { + d.h = iv + d.h[0] ^= uint32(d.size) | (uint32(d.keyLen) << 8) | (1 << 16) | (1 << 24) + d.offset, d.c[0], d.c[1] = 0, 0, 0 + if d.keyLen > 0 { + d.block = d.key + d.offset = BlockSize + } +} + +func (d *digest) Write(p []byte) (n int, err error) { + n = len(p) + + if d.offset > 0 { + remaining := BlockSize - d.offset + if n <= remaining { + d.offset += copy(d.block[d.offset:], p) + return + } + copy(d.block[d.offset:], p[:remaining]) + hashBlocks(&d.h, &d.c, 0, d.block[:]) + d.offset = 0 + p = p[remaining:] + } + + if length := len(p); length > BlockSize { + nn := length &^ (BlockSize - 1) + if length == nn { + nn -= BlockSize + } + hashBlocks(&d.h, &d.c, 0, p[:nn]) + p = p[nn:] + } + + d.offset += copy(d.block[:], p) + return +} + +func (d *digest) Sum(sum []byte) []byte { + var hash [Size]byte + d.finalize(&hash) + return append(sum, hash[:d.size]...) +} + +func (d *digest) finalize(hash *[Size]byte) { + var block [BlockSize]byte + h := d.h + c := d.c + + copy(block[:], d.block[:d.offset]) + remaining := uint32(BlockSize - d.offset) + if c[0] < remaining { + c[1]-- + } + c[0] -= remaining + + hashBlocks(&h, &c, 0xFFFFFFFF, block[:]) + for i, v := range h { + binary.LittleEndian.PutUint32(hash[4*i:], v) + } +} diff --git a/vendor/golang.org/x/crypto/blake2s/blake2s_386.go b/vendor/golang.org/x/crypto/blake2s/blake2s_386.go new file mode 100644 index 0000000000000000000000000000000000000000..45ae54614b61a61a39e603113d21264f21691e85 --- /dev/null +++ b/vendor/golang.org/x/crypto/blake2s/blake2s_386.go @@ -0,0 +1,35 @@ +// Copyright 2016 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 386,!gccgo,!appengine + +package blake2s + +var ( + useSSE4 = false + useSSSE3 = supportSSSE3() + useSSE2 = supportSSE2() +) + +//go:noescape +func supportSSE2() bool + +//go:noescape +func supportSSSE3() bool + +//go:noescape +func hashBlocksSSE2(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) + +//go:noescape +func hashBlocksSSSE3(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) + +func hashBlocks(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) { + if useSSSE3 { + hashBlocksSSSE3(h, c, flag, blocks) + } else if useSSE2 { + hashBlocksSSE2(h, c, flag, blocks) + } else { + hashBlocksGeneric(h, c, flag, blocks) + } +} diff --git a/vendor/golang.org/x/crypto/blake2s/blake2s_386.s b/vendor/golang.org/x/crypto/blake2s/blake2s_386.s new file mode 100644 index 0000000000000000000000000000000000000000..0bb65c70f48f4ce2472c6863c97518451c3f8fe3 --- /dev/null +++ b/vendor/golang.org/x/crypto/blake2s/blake2s_386.s @@ -0,0 +1,460 @@ +// Copyright 2016 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 386,!gccgo,!appengine + +#include "textflag.h" + +DATA iv0<>+0x00(SB)/4, $0x6a09e667 +DATA iv0<>+0x04(SB)/4, $0xbb67ae85 +DATA iv0<>+0x08(SB)/4, $0x3c6ef372 +DATA iv0<>+0x0c(SB)/4, $0xa54ff53a +GLOBL iv0<>(SB), (NOPTR+RODATA), $16 + +DATA iv1<>+0x00(SB)/4, $0x510e527f +DATA iv1<>+0x04(SB)/4, $0x9b05688c +DATA iv1<>+0x08(SB)/4, $0x1f83d9ab +DATA iv1<>+0x0c(SB)/4, $0x5be0cd19 +GLOBL iv1<>(SB), (NOPTR+RODATA), $16 + +DATA rol16<>+0x00(SB)/8, $0x0504070601000302 +DATA rol16<>+0x08(SB)/8, $0x0D0C0F0E09080B0A +GLOBL rol16<>(SB), (NOPTR+RODATA), $16 + +DATA rol8<>+0x00(SB)/8, $0x0407060500030201 +DATA rol8<>+0x08(SB)/8, $0x0C0F0E0D080B0A09 +GLOBL rol8<>(SB), (NOPTR+RODATA), $16 + +DATA counter<>+0x00(SB)/8, $0x40 +DATA counter<>+0x08(SB)/8, $0x0 +GLOBL counter<>(SB), (NOPTR+RODATA), $16 + +#define ROTL_SSE2(n, t, v) \ + MOVO v, t; \ + PSLLL $n, t; \ + PSRLL $(32-n), v; \ + PXOR t, v + +#define ROTL_SSSE3(c, v) \ + PSHUFB c, v + +#define ROUND_SSE2(v0, v1, v2, v3, m0, m1, m2, m3, t) \ + PADDL m0, v0; \ + PADDL v1, v0; \ + PXOR v0, v3; \ + ROTL_SSE2(16, t, v3); \ + PADDL v3, v2; \ + PXOR v2, v1; \ + ROTL_SSE2(20, t, v1); \ + PADDL m1, v0; \ + PADDL v1, v0; \ + PXOR v0, v3; \ + ROTL_SSE2(24, t, v3); \ + PADDL v3, v2; \ + PXOR v2, v1; \ + ROTL_SSE2(25, t, v1); \ + PSHUFL $0x39, v1, v1; \ + PSHUFL $0x4E, v2, v2; \ + PSHUFL $0x93, v3, v3; \ + PADDL m2, v0; \ + PADDL v1, v0; \ + PXOR v0, v3; \ + ROTL_SSE2(16, t, v3); \ + PADDL v3, v2; \ + PXOR v2, v1; \ + ROTL_SSE2(20, t, v1); \ + PADDL m3, v0; \ + PADDL v1, v0; \ + PXOR v0, v3; \ + ROTL_SSE2(24, t, v3); \ + PADDL v3, v2; \ + PXOR v2, v1; \ + ROTL_SSE2(25, t, v1); \ + PSHUFL $0x39, v3, v3; \ + PSHUFL $0x4E, v2, v2; \ + PSHUFL $0x93, v1, v1 + +#define ROUND_SSSE3(v0, v1, v2, v3, m0, m1, m2, m3, t, c16, c8) \ + PADDL m0, v0; \ + PADDL v1, v0; \ + PXOR v0, v3; \ + ROTL_SSSE3(c16, v3); \ + PADDL v3, v2; \ + PXOR v2, v1; \ + ROTL_SSE2(20, t, v1); \ + PADDL m1, v0; \ + PADDL v1, v0; \ + PXOR v0, v3; \ + ROTL_SSSE3(c8, v3); \ + PADDL v3, v2; \ + PXOR v2, v1; \ + ROTL_SSE2(25, t, v1); \ + PSHUFL $0x39, v1, v1; \ + PSHUFL $0x4E, v2, v2; \ + PSHUFL $0x93, v3, v3; \ + PADDL m2, v0; \ + PADDL v1, v0; \ + PXOR v0, v3; \ + ROTL_SSSE3(c16, v3); \ + PADDL v3, v2; \ + PXOR v2, v1; \ + ROTL_SSE2(20, t, v1); \ + PADDL m3, v0; \ + PADDL v1, v0; \ + PXOR v0, v3; \ + ROTL_SSSE3(c8, v3); \ + PADDL v3, v2; \ + PXOR v2, v1; \ + ROTL_SSE2(25, t, v1); \ + PSHUFL $0x39, v3, v3; \ + PSHUFL $0x4E, v2, v2; \ + PSHUFL $0x93, v1, v1 + +#define PRECOMPUTE(dst, off, src, t) \ + MOVL 0*4(src), t; \ + MOVL t, 0*4+off+0(dst); \ + MOVL t, 9*4+off+64(dst); \ + MOVL t, 5*4+off+128(dst); \ + MOVL t, 14*4+off+192(dst); \ + MOVL t, 4*4+off+256(dst); \ + MOVL t, 2*4+off+320(dst); \ + MOVL t, 8*4+off+384(dst); \ + MOVL t, 12*4+off+448(dst); \ + MOVL t, 3*4+off+512(dst); \ + MOVL t, 15*4+off+576(dst); \ + MOVL 1*4(src), t; \ + MOVL t, 4*4+off+0(dst); \ + MOVL t, 8*4+off+64(dst); \ + MOVL t, 14*4+off+128(dst); \ + MOVL t, 5*4+off+192(dst); \ + MOVL t, 12*4+off+256(dst); \ + MOVL t, 11*4+off+320(dst); \ + MOVL t, 1*4+off+384(dst); \ + MOVL t, 6*4+off+448(dst); \ + MOVL t, 10*4+off+512(dst); \ + MOVL t, 3*4+off+576(dst); \ + MOVL 2*4(src), t; \ + MOVL t, 1*4+off+0(dst); \ + MOVL t, 13*4+off+64(dst); \ + MOVL t, 6*4+off+128(dst); \ + MOVL t, 8*4+off+192(dst); \ + MOVL t, 2*4+off+256(dst); \ + MOVL t, 0*4+off+320(dst); \ + MOVL t, 14*4+off+384(dst); \ + MOVL t, 11*4+off+448(dst); \ + MOVL t, 12*4+off+512(dst); \ + MOVL t, 4*4+off+576(dst); \ + MOVL 3*4(src), t; \ + MOVL t, 5*4+off+0(dst); \ + MOVL t, 15*4+off+64(dst); \ + MOVL t, 9*4+off+128(dst); \ + MOVL t, 1*4+off+192(dst); \ + MOVL t, 11*4+off+256(dst); \ + MOVL t, 7*4+off+320(dst); \ + MOVL t, 13*4+off+384(dst); \ + MOVL t, 3*4+off+448(dst); \ + MOVL t, 6*4+off+512(dst); \ + MOVL t, 10*4+off+576(dst); \ + MOVL 4*4(src), t; \ + MOVL t, 2*4+off+0(dst); \ + MOVL t, 1*4+off+64(dst); \ + MOVL t, 15*4+off+128(dst); \ + MOVL t, 10*4+off+192(dst); \ + MOVL t, 6*4+off+256(dst); \ + MOVL t, 8*4+off+320(dst); \ + MOVL t, 3*4+off+384(dst); \ + MOVL t, 13*4+off+448(dst); \ + MOVL t, 14*4+off+512(dst); \ + MOVL t, 5*4+off+576(dst); \ + MOVL 5*4(src), t; \ + MOVL t, 6*4+off+0(dst); \ + MOVL t, 11*4+off+64(dst); \ + MOVL t, 2*4+off+128(dst); \ + MOVL t, 9*4+off+192(dst); \ + MOVL t, 1*4+off+256(dst); \ + MOVL t, 13*4+off+320(dst); \ + MOVL t, 4*4+off+384(dst); \ + MOVL t, 8*4+off+448(dst); \ + MOVL t, 15*4+off+512(dst); \ + MOVL t, 7*4+off+576(dst); \ + MOVL 6*4(src), t; \ + MOVL t, 3*4+off+0(dst); \ + MOVL t, 7*4+off+64(dst); \ + MOVL t, 13*4+off+128(dst); \ + MOVL t, 12*4+off+192(dst); \ + MOVL t, 10*4+off+256(dst); \ + MOVL t, 1*4+off+320(dst); \ + MOVL t, 9*4+off+384(dst); \ + MOVL t, 14*4+off+448(dst); \ + MOVL t, 0*4+off+512(dst); \ + MOVL t, 6*4+off+576(dst); \ + MOVL 7*4(src), t; \ + MOVL t, 7*4+off+0(dst); \ + MOVL t, 14*4+off+64(dst); \ + MOVL t, 10*4+off+128(dst); \ + MOVL t, 0*4+off+192(dst); \ + MOVL t, 5*4+off+256(dst); \ + MOVL t, 9*4+off+320(dst); \ + MOVL t, 12*4+off+384(dst); \ + MOVL t, 1*4+off+448(dst); \ + MOVL t, 13*4+off+512(dst); \ + MOVL t, 2*4+off+576(dst); \ + MOVL 8*4(src), t; \ + MOVL t, 8*4+off+0(dst); \ + MOVL t, 5*4+off+64(dst); \ + MOVL t, 4*4+off+128(dst); \ + MOVL t, 15*4+off+192(dst); \ + MOVL t, 14*4+off+256(dst); \ + MOVL t, 3*4+off+320(dst); \ + MOVL t, 11*4+off+384(dst); \ + MOVL t, 10*4+off+448(dst); \ + MOVL t, 7*4+off+512(dst); \ + MOVL t, 1*4+off+576(dst); \ + MOVL 9*4(src), t; \ + MOVL t, 12*4+off+0(dst); \ + MOVL t, 2*4+off+64(dst); \ + MOVL t, 11*4+off+128(dst); \ + MOVL t, 4*4+off+192(dst); \ + MOVL t, 0*4+off+256(dst); \ + MOVL t, 15*4+off+320(dst); \ + MOVL t, 10*4+off+384(dst); \ + MOVL t, 7*4+off+448(dst); \ + MOVL t, 5*4+off+512(dst); \ + MOVL t, 9*4+off+576(dst); \ + MOVL 10*4(src), t; \ + MOVL t, 9*4+off+0(dst); \ + MOVL t, 4*4+off+64(dst); \ + MOVL t, 8*4+off+128(dst); \ + MOVL t, 13*4+off+192(dst); \ + MOVL t, 3*4+off+256(dst); \ + MOVL t, 5*4+off+320(dst); \ + MOVL t, 7*4+off+384(dst); \ + MOVL t, 15*4+off+448(dst); \ + MOVL t, 11*4+off+512(dst); \ + MOVL t, 0*4+off+576(dst); \ + MOVL 11*4(src), t; \ + MOVL t, 13*4+off+0(dst); \ + MOVL t, 10*4+off+64(dst); \ + MOVL t, 0*4+off+128(dst); \ + MOVL t, 3*4+off+192(dst); \ + MOVL t, 9*4+off+256(dst); \ + MOVL t, 6*4+off+320(dst); \ + MOVL t, 15*4+off+384(dst); \ + MOVL t, 4*4+off+448(dst); \ + MOVL t, 2*4+off+512(dst); \ + MOVL t, 12*4+off+576(dst); \ + MOVL 12*4(src), t; \ + MOVL t, 10*4+off+0(dst); \ + MOVL t, 12*4+off+64(dst); \ + MOVL t, 1*4+off+128(dst); \ + MOVL t, 6*4+off+192(dst); \ + MOVL t, 13*4+off+256(dst); \ + MOVL t, 4*4+off+320(dst); \ + MOVL t, 0*4+off+384(dst); \ + MOVL t, 2*4+off+448(dst); \ + MOVL t, 8*4+off+512(dst); \ + MOVL t, 14*4+off+576(dst); \ + MOVL 13*4(src), t; \ + MOVL t, 14*4+off+0(dst); \ + MOVL t, 3*4+off+64(dst); \ + MOVL t, 7*4+off+128(dst); \ + MOVL t, 2*4+off+192(dst); \ + MOVL t, 15*4+off+256(dst); \ + MOVL t, 12*4+off+320(dst); \ + MOVL t, 6*4+off+384(dst); \ + MOVL t, 0*4+off+448(dst); \ + MOVL t, 9*4+off+512(dst); \ + MOVL t, 11*4+off+576(dst); \ + MOVL 14*4(src), t; \ + MOVL t, 11*4+off+0(dst); \ + MOVL t, 0*4+off+64(dst); \ + MOVL t, 12*4+off+128(dst); \ + MOVL t, 7*4+off+192(dst); \ + MOVL t, 8*4+off+256(dst); \ + MOVL t, 14*4+off+320(dst); \ + MOVL t, 2*4+off+384(dst); \ + MOVL t, 5*4+off+448(dst); \ + MOVL t, 1*4+off+512(dst); \ + MOVL t, 13*4+off+576(dst); \ + MOVL 15*4(src), t; \ + MOVL t, 15*4+off+0(dst); \ + MOVL t, 6*4+off+64(dst); \ + MOVL t, 3*4+off+128(dst); \ + MOVL t, 11*4+off+192(dst); \ + MOVL t, 7*4+off+256(dst); \ + MOVL t, 10*4+off+320(dst); \ + MOVL t, 5*4+off+384(dst); \ + MOVL t, 9*4+off+448(dst); \ + MOVL t, 4*4+off+512(dst); \ + MOVL t, 8*4+off+576(dst) + +// func hashBlocksSSE2(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) +TEXT ·hashBlocksSSE2(SB), 0, $672-24 // frame = 656 + 16 byte alignment + MOVL h+0(FP), AX + MOVL c+4(FP), BX + MOVL flag+8(FP), CX + MOVL blocks_base+12(FP), SI + MOVL blocks_len+16(FP), DX + + MOVL SP, BP + MOVL SP, DI + ADDL $15, DI + ANDL $~15, DI + MOVL DI, SP + + MOVL CX, 8(SP) + MOVL 0(BX), CX + MOVL CX, 0(SP) + MOVL 4(BX), CX + MOVL CX, 4(SP) + XORL CX, CX + MOVL CX, 12(SP) + + MOVOU 0(AX), X0 + MOVOU 16(AX), X1 + MOVOU counter<>(SB), X2 + +loop: + MOVO X0, X4 + MOVO X1, X5 + MOVOU iv0<>(SB), X6 + MOVOU iv1<>(SB), X7 + + MOVO 0(SP), X3 + PADDQ X2, X3 + PXOR X3, X7 + MOVO X3, 0(SP) + + PRECOMPUTE(SP, 16, SI, CX) + ROUND_SSE2(X4, X5, X6, X7, 16(SP), 32(SP), 48(SP), 64(SP), X3) + ROUND_SSE2(X4, X5, X6, X7, 16+64(SP), 32+64(SP), 48+64(SP), 64+64(SP), X3) + ROUND_SSE2(X4, X5, X6, X7, 16+128(SP), 32+128(SP), 48+128(SP), 64+128(SP), X3) + ROUND_SSE2(X4, X5, X6, X7, 16+192(SP), 32+192(SP), 48+192(SP), 64+192(SP), X3) + ROUND_SSE2(X4, X5, X6, X7, 16+256(SP), 32+256(SP), 48+256(SP), 64+256(SP), X3) + ROUND_SSE2(X4, X5, X6, X7, 16+320(SP), 32+320(SP), 48+320(SP), 64+320(SP), X3) + ROUND_SSE2(X4, X5, X6, X7, 16+384(SP), 32+384(SP), 48+384(SP), 64+384(SP), X3) + ROUND_SSE2(X4, X5, X6, X7, 16+448(SP), 32+448(SP), 48+448(SP), 64+448(SP), X3) + ROUND_SSE2(X4, X5, X6, X7, 16+512(SP), 32+512(SP), 48+512(SP), 64+512(SP), X3) + ROUND_SSE2(X4, X5, X6, X7, 16+576(SP), 32+576(SP), 48+576(SP), 64+576(SP), X3) + + PXOR X4, X0 + PXOR X5, X1 + PXOR X6, X0 + PXOR X7, X1 + + LEAL 64(SI), SI + SUBL $64, DX + JNE loop + + MOVL 0(SP), CX + MOVL CX, 0(BX) + MOVL 4(SP), CX + MOVL CX, 4(BX) + + MOVOU X0, 0(AX) + MOVOU X1, 16(AX) + + MOVL BP, SP + RET + +// func hashBlocksSSSE3(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) +TEXT ·hashBlocksSSSE3(SB), 0, $704-24 // frame = 688 + 16 byte alignment + MOVL h+0(FP), AX + MOVL c+4(FP), BX + MOVL flag+8(FP), CX + MOVL blocks_base+12(FP), SI + MOVL blocks_len+16(FP), DX + + MOVL SP, BP + MOVL SP, DI + ADDL $15, DI + ANDL $~15, DI + MOVL DI, SP + + MOVL CX, 8(SP) + MOVL 0(BX), CX + MOVL CX, 0(SP) + MOVL 4(BX), CX + MOVL CX, 4(SP) + XORL CX, CX + MOVL CX, 12(SP) + + MOVOU 0(AX), X0 + MOVOU 16(AX), X1 + MOVOU counter<>(SB), X2 + +loop: + MOVO X0, 656(SP) + MOVO X1, 672(SP) + MOVO X0, X4 + MOVO X1, X5 + MOVOU iv0<>(SB), X6 + MOVOU iv1<>(SB), X7 + + MOVO 0(SP), X3 + PADDQ X2, X3 + PXOR X3, X7 + MOVO X3, 0(SP) + + MOVOU rol16<>(SB), X0 + MOVOU rol8<>(SB), X1 + + PRECOMPUTE(SP, 16, SI, CX) + ROUND_SSSE3(X4, X5, X6, X7, 16(SP), 32(SP), 48(SP), 64(SP), X3, X0, X1) + ROUND_SSSE3(X4, X5, X6, X7, 16+64(SP), 32+64(SP), 48+64(SP), 64+64(SP), X3, X0, X1) + ROUND_SSSE3(X4, X5, X6, X7, 16+128(SP), 32+128(SP), 48+128(SP), 64+128(SP), X3, X0, X1) + ROUND_SSSE3(X4, X5, X6, X7, 16+192(SP), 32+192(SP), 48+192(SP), 64+192(SP), X3, X0, X1) + ROUND_SSSE3(X4, X5, X6, X7, 16+256(SP), 32+256(SP), 48+256(SP), 64+256(SP), X3, X0, X1) + ROUND_SSSE3(X4, X5, X6, X7, 16+320(SP), 32+320(SP), 48+320(SP), 64+320(SP), X3, X0, X1) + ROUND_SSSE3(X4, X5, X6, X7, 16+384(SP), 32+384(SP), 48+384(SP), 64+384(SP), X3, X0, X1) + ROUND_SSSE3(X4, X5, X6, X7, 16+448(SP), 32+448(SP), 48+448(SP), 64+448(SP), X3, X0, X1) + ROUND_SSSE3(X4, X5, X6, X7, 16+512(SP), 32+512(SP), 48+512(SP), 64+512(SP), X3, X0, X1) + ROUND_SSSE3(X4, X5, X6, X7, 16+576(SP), 32+576(SP), 48+576(SP), 64+576(SP), X3, X0, X1) + + MOVO 656(SP), X0 + MOVO 672(SP), X1 + PXOR X4, X0 + PXOR X5, X1 + PXOR X6, X0 + PXOR X7, X1 + + LEAL 64(SI), SI + SUBL $64, DX + JNE loop + + MOVL 0(SP), CX + MOVL CX, 0(BX) + MOVL 4(SP), CX + MOVL CX, 4(BX) + + MOVOU X0, 0(AX) + MOVOU X1, 16(AX) + + MOVL BP, SP + RET + +// func supportSSSE3() bool +TEXT ·supportSSSE3(SB), 4, $0-1 + MOVL $1, AX + CPUID + MOVL CX, BX + ANDL $0x1, BX // supports SSE3 + JZ FALSE + ANDL $0x200, CX // supports SSSE3 + JZ FALSE + MOVB $1, ret+0(FP) + RET + +FALSE: + MOVB $0, ret+0(FP) + RET + +// func supportSSE2() bool +TEXT ·supportSSE2(SB), 4, $0-1 + MOVL $1, AX + CPUID + SHRL $26, DX + ANDL $1, DX // DX != 0 if support SSE2 + MOVB DX, ret+0(FP) + RET diff --git a/vendor/golang.org/x/crypto/blake2s/blake2s_amd64.go b/vendor/golang.org/x/crypto/blake2s/blake2s_amd64.go new file mode 100644 index 0000000000000000000000000000000000000000..a925e6b207dab2b739edda728679d5f461b7da71 --- /dev/null +++ b/vendor/golang.org/x/crypto/blake2s/blake2s_amd64.go @@ -0,0 +1,40 @@ +// Copyright 2016 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,!appengine + +package blake2s + +var ( + useSSE4 = supportSSE4() + useSSSE3 = supportSSSE3() + useSSE2 = true // Always available on amd64 +) + +//go:noescape +func supportSSSE3() bool + +//go:noescape +func supportSSE4() bool + +//go:noescape +func hashBlocksSSE2(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) + +//go:noescape +func hashBlocksSSSE3(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) + +//go:noescape +func hashBlocksSSE4(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) + +func hashBlocks(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) { + if useSSE4 { + hashBlocksSSE4(h, c, flag, blocks) + } else if useSSSE3 { + hashBlocksSSSE3(h, c, flag, blocks) + } else if useSSE2 { + hashBlocksSSE2(h, c, flag, blocks) + } else { + hashBlocksGeneric(h, c, flag, blocks) + } +} diff --git a/vendor/golang.org/x/crypto/blake2s/blake2s_amd64.s b/vendor/golang.org/x/crypto/blake2s/blake2s_amd64.s new file mode 100644 index 0000000000000000000000000000000000000000..6cdf5a94cbebd86023211c8d156d7fe493805b4c --- /dev/null +++ b/vendor/golang.org/x/crypto/blake2s/blake2s_amd64.s @@ -0,0 +1,463 @@ +// Copyright 2016 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,!appengine + +#include "textflag.h" + +DATA iv0<>+0x00(SB)/4, $0x6a09e667 +DATA iv0<>+0x04(SB)/4, $0xbb67ae85 +DATA iv0<>+0x08(SB)/4, $0x3c6ef372 +DATA iv0<>+0x0c(SB)/4, $0xa54ff53a +GLOBL iv0<>(SB), (NOPTR+RODATA), $16 + +DATA iv1<>+0x00(SB)/4, $0x510e527f +DATA iv1<>+0x04(SB)/4, $0x9b05688c +DATA iv1<>+0x08(SB)/4, $0x1f83d9ab +DATA iv1<>+0x0c(SB)/4, $0x5be0cd19 +GLOBL iv1<>(SB), (NOPTR+RODATA), $16 + +DATA rol16<>+0x00(SB)/8, $0x0504070601000302 +DATA rol16<>+0x08(SB)/8, $0x0D0C0F0E09080B0A +GLOBL rol16<>(SB), (NOPTR+RODATA), $16 + +DATA rol8<>+0x00(SB)/8, $0x0407060500030201 +DATA rol8<>+0x08(SB)/8, $0x0C0F0E0D080B0A09 +GLOBL rol8<>(SB), (NOPTR+RODATA), $16 + +DATA counter<>+0x00(SB)/8, $0x40 +DATA counter<>+0x08(SB)/8, $0x0 +GLOBL counter<>(SB), (NOPTR+RODATA), $16 + +#define ROTL_SSE2(n, t, v) \ + MOVO v, t; \ + PSLLL $n, t; \ + PSRLL $(32-n), v; \ + PXOR t, v + +#define ROTL_SSSE3(c, v) \ + PSHUFB c, v + +#define ROUND_SSE2(v0, v1, v2, v3, m0, m1, m2, m3, t) \ + PADDL m0, v0; \ + PADDL v1, v0; \ + PXOR v0, v3; \ + ROTL_SSE2(16, t, v3); \ + PADDL v3, v2; \ + PXOR v2, v1; \ + ROTL_SSE2(20, t, v1); \ + PADDL m1, v0; \ + PADDL v1, v0; \ + PXOR v0, v3; \ + ROTL_SSE2(24, t, v3); \ + PADDL v3, v2; \ + PXOR v2, v1; \ + ROTL_SSE2(25, t, v1); \ + PSHUFL $0x39, v1, v1; \ + PSHUFL $0x4E, v2, v2; \ + PSHUFL $0x93, v3, v3; \ + PADDL m2, v0; \ + PADDL v1, v0; \ + PXOR v0, v3; \ + ROTL_SSE2(16, t, v3); \ + PADDL v3, v2; \ + PXOR v2, v1; \ + ROTL_SSE2(20, t, v1); \ + PADDL m3, v0; \ + PADDL v1, v0; \ + PXOR v0, v3; \ + ROTL_SSE2(24, t, v3); \ + PADDL v3, v2; \ + PXOR v2, v1; \ + ROTL_SSE2(25, t, v1); \ + PSHUFL $0x39, v3, v3; \ + PSHUFL $0x4E, v2, v2; \ + PSHUFL $0x93, v1, v1 + +#define ROUND_SSSE3(v0, v1, v2, v3, m0, m1, m2, m3, t, c16, c8) \ + PADDL m0, v0; \ + PADDL v1, v0; \ + PXOR v0, v3; \ + ROTL_SSSE3(c16, v3); \ + PADDL v3, v2; \ + PXOR v2, v1; \ + ROTL_SSE2(20, t, v1); \ + PADDL m1, v0; \ + PADDL v1, v0; \ + PXOR v0, v3; \ + ROTL_SSSE3(c8, v3); \ + PADDL v3, v2; \ + PXOR v2, v1; \ + ROTL_SSE2(25, t, v1); \ + PSHUFL $0x39, v1, v1; \ + PSHUFL $0x4E, v2, v2; \ + PSHUFL $0x93, v3, v3; \ + PADDL m2, v0; \ + PADDL v1, v0; \ + PXOR v0, v3; \ + ROTL_SSSE3(c16, v3); \ + PADDL v3, v2; \ + PXOR v2, v1; \ + ROTL_SSE2(20, t, v1); \ + PADDL m3, v0; \ + PADDL v1, v0; \ + PXOR v0, v3; \ + ROTL_SSSE3(c8, v3); \ + PADDL v3, v2; \ + PXOR v2, v1; \ + ROTL_SSE2(25, t, v1); \ + PSHUFL $0x39, v3, v3; \ + PSHUFL $0x4E, v2, v2; \ + PSHUFL $0x93, v1, v1 + + +#define LOAD_MSG_SSE4(m0, m1, m2, m3, src, i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15) \ + MOVL i0*4(src), m0; \ + PINSRD $1, i1*4(src), m0; \ + PINSRD $2, i2*4(src), m0; \ + PINSRD $3, i3*4(src), m0; \ + MOVL i4*4(src), m1; \ + PINSRD $1, i5*4(src), m1; \ + PINSRD $2, i6*4(src), m1; \ + PINSRD $3, i7*4(src), m1; \ + MOVL i8*4(src), m2; \ + PINSRD $1, i9*4(src), m2; \ + PINSRD $2, i10*4(src), m2; \ + PINSRD $3, i11*4(src), m2; \ + MOVL i12*4(src), m3; \ + PINSRD $1, i13*4(src), m3; \ + PINSRD $2, i14*4(src), m3; \ + PINSRD $3, i15*4(src), m3 + +#define PRECOMPUTE_MSG(dst, off, src, R8, R9, R10, R11, R12, R13, R14, R15) \ + MOVQ 0*4(src), R8; \ + MOVQ 2*4(src), R9; \ + MOVQ 4*4(src), R10; \ + MOVQ 6*4(src), R11; \ + MOVQ 8*4(src), R12; \ + MOVQ 10*4(src), R13; \ + MOVQ 12*4(src), R14; \ + MOVQ 14*4(src), R15; \ + \ + MOVL R8, 0*4+off+0(dst); \ + MOVL R8, 9*4+off+64(dst); \ + MOVL R8, 5*4+off+128(dst); \ + MOVL R8, 14*4+off+192(dst); \ + MOVL R8, 4*4+off+256(dst); \ + MOVL R8, 2*4+off+320(dst); \ + MOVL R8, 8*4+off+384(dst); \ + MOVL R8, 12*4+off+448(dst); \ + MOVL R8, 3*4+off+512(dst); \ + MOVL R8, 15*4+off+576(dst); \ + SHRQ $32, R8; \ + MOVL R8, 4*4+off+0(dst); \ + MOVL R8, 8*4+off+64(dst); \ + MOVL R8, 14*4+off+128(dst); \ + MOVL R8, 5*4+off+192(dst); \ + MOVL R8, 12*4+off+256(dst); \ + MOVL R8, 11*4+off+320(dst); \ + MOVL R8, 1*4+off+384(dst); \ + MOVL R8, 6*4+off+448(dst); \ + MOVL R8, 10*4+off+512(dst); \ + MOVL R8, 3*4+off+576(dst); \ + \ + MOVL R9, 1*4+off+0(dst); \ + MOVL R9, 13*4+off+64(dst); \ + MOVL R9, 6*4+off+128(dst); \ + MOVL R9, 8*4+off+192(dst); \ + MOVL R9, 2*4+off+256(dst); \ + MOVL R9, 0*4+off+320(dst); \ + MOVL R9, 14*4+off+384(dst); \ + MOVL R9, 11*4+off+448(dst); \ + MOVL R9, 12*4+off+512(dst); \ + MOVL R9, 4*4+off+576(dst); \ + SHRQ $32, R9; \ + MOVL R9, 5*4+off+0(dst); \ + MOVL R9, 15*4+off+64(dst); \ + MOVL R9, 9*4+off+128(dst); \ + MOVL R9, 1*4+off+192(dst); \ + MOVL R9, 11*4+off+256(dst); \ + MOVL R9, 7*4+off+320(dst); \ + MOVL R9, 13*4+off+384(dst); \ + MOVL R9, 3*4+off+448(dst); \ + MOVL R9, 6*4+off+512(dst); \ + MOVL R9, 10*4+off+576(dst); \ + \ + MOVL R10, 2*4+off+0(dst); \ + MOVL R10, 1*4+off+64(dst); \ + MOVL R10, 15*4+off+128(dst); \ + MOVL R10, 10*4+off+192(dst); \ + MOVL R10, 6*4+off+256(dst); \ + MOVL R10, 8*4+off+320(dst); \ + MOVL R10, 3*4+off+384(dst); \ + MOVL R10, 13*4+off+448(dst); \ + MOVL R10, 14*4+off+512(dst); \ + MOVL R10, 5*4+off+576(dst); \ + SHRQ $32, R10; \ + MOVL R10, 6*4+off+0(dst); \ + MOVL R10, 11*4+off+64(dst); \ + MOVL R10, 2*4+off+128(dst); \ + MOVL R10, 9*4+off+192(dst); \ + MOVL R10, 1*4+off+256(dst); \ + MOVL R10, 13*4+off+320(dst); \ + MOVL R10, 4*4+off+384(dst); \ + MOVL R10, 8*4+off+448(dst); \ + MOVL R10, 15*4+off+512(dst); \ + MOVL R10, 7*4+off+576(dst); \ + \ + MOVL R11, 3*4+off+0(dst); \ + MOVL R11, 7*4+off+64(dst); \ + MOVL R11, 13*4+off+128(dst); \ + MOVL R11, 12*4+off+192(dst); \ + MOVL R11, 10*4+off+256(dst); \ + MOVL R11, 1*4+off+320(dst); \ + MOVL R11, 9*4+off+384(dst); \ + MOVL R11, 14*4+off+448(dst); \ + MOVL R11, 0*4+off+512(dst); \ + MOVL R11, 6*4+off+576(dst); \ + SHRQ $32, R11; \ + MOVL R11, 7*4+off+0(dst); \ + MOVL R11, 14*4+off+64(dst); \ + MOVL R11, 10*4+off+128(dst); \ + MOVL R11, 0*4+off+192(dst); \ + MOVL R11, 5*4+off+256(dst); \ + MOVL R11, 9*4+off+320(dst); \ + MOVL R11, 12*4+off+384(dst); \ + MOVL R11, 1*4+off+448(dst); \ + MOVL R11, 13*4+off+512(dst); \ + MOVL R11, 2*4+off+576(dst); \ + \ + MOVL R12, 8*4+off+0(dst); \ + MOVL R12, 5*4+off+64(dst); \ + MOVL R12, 4*4+off+128(dst); \ + MOVL R12, 15*4+off+192(dst); \ + MOVL R12, 14*4+off+256(dst); \ + MOVL R12, 3*4+off+320(dst); \ + MOVL R12, 11*4+off+384(dst); \ + MOVL R12, 10*4+off+448(dst); \ + MOVL R12, 7*4+off+512(dst); \ + MOVL R12, 1*4+off+576(dst); \ + SHRQ $32, R12; \ + MOVL R12, 12*4+off+0(dst); \ + MOVL R12, 2*4+off+64(dst); \ + MOVL R12, 11*4+off+128(dst); \ + MOVL R12, 4*4+off+192(dst); \ + MOVL R12, 0*4+off+256(dst); \ + MOVL R12, 15*4+off+320(dst); \ + MOVL R12, 10*4+off+384(dst); \ + MOVL R12, 7*4+off+448(dst); \ + MOVL R12, 5*4+off+512(dst); \ + MOVL R12, 9*4+off+576(dst); \ + \ + MOVL R13, 9*4+off+0(dst); \ + MOVL R13, 4*4+off+64(dst); \ + MOVL R13, 8*4+off+128(dst); \ + MOVL R13, 13*4+off+192(dst); \ + MOVL R13, 3*4+off+256(dst); \ + MOVL R13, 5*4+off+320(dst); \ + MOVL R13, 7*4+off+384(dst); \ + MOVL R13, 15*4+off+448(dst); \ + MOVL R13, 11*4+off+512(dst); \ + MOVL R13, 0*4+off+576(dst); \ + SHRQ $32, R13; \ + MOVL R13, 13*4+off+0(dst); \ + MOVL R13, 10*4+off+64(dst); \ + MOVL R13, 0*4+off+128(dst); \ + MOVL R13, 3*4+off+192(dst); \ + MOVL R13, 9*4+off+256(dst); \ + MOVL R13, 6*4+off+320(dst); \ + MOVL R13, 15*4+off+384(dst); \ + MOVL R13, 4*4+off+448(dst); \ + MOVL R13, 2*4+off+512(dst); \ + MOVL R13, 12*4+off+576(dst); \ + \ + MOVL R14, 10*4+off+0(dst); \ + MOVL R14, 12*4+off+64(dst); \ + MOVL R14, 1*4+off+128(dst); \ + MOVL R14, 6*4+off+192(dst); \ + MOVL R14, 13*4+off+256(dst); \ + MOVL R14, 4*4+off+320(dst); \ + MOVL R14, 0*4+off+384(dst); \ + MOVL R14, 2*4+off+448(dst); \ + MOVL R14, 8*4+off+512(dst); \ + MOVL R14, 14*4+off+576(dst); \ + SHRQ $32, R14; \ + MOVL R14, 14*4+off+0(dst); \ + MOVL R14, 3*4+off+64(dst); \ + MOVL R14, 7*4+off+128(dst); \ + MOVL R14, 2*4+off+192(dst); \ + MOVL R14, 15*4+off+256(dst); \ + MOVL R14, 12*4+off+320(dst); \ + MOVL R14, 6*4+off+384(dst); \ + MOVL R14, 0*4+off+448(dst); \ + MOVL R14, 9*4+off+512(dst); \ + MOVL R14, 11*4+off+576(dst); \ + \ + MOVL R15, 11*4+off+0(dst); \ + MOVL R15, 0*4+off+64(dst); \ + MOVL R15, 12*4+off+128(dst); \ + MOVL R15, 7*4+off+192(dst); \ + MOVL R15, 8*4+off+256(dst); \ + MOVL R15, 14*4+off+320(dst); \ + MOVL R15, 2*4+off+384(dst); \ + MOVL R15, 5*4+off+448(dst); \ + MOVL R15, 1*4+off+512(dst); \ + MOVL R15, 13*4+off+576(dst); \ + SHRQ $32, R15; \ + MOVL R15, 15*4+off+0(dst); \ + MOVL R15, 6*4+off+64(dst); \ + MOVL R15, 3*4+off+128(dst); \ + MOVL R15, 11*4+off+192(dst); \ + MOVL R15, 7*4+off+256(dst); \ + MOVL R15, 10*4+off+320(dst); \ + MOVL R15, 5*4+off+384(dst); \ + MOVL R15, 9*4+off+448(dst); \ + MOVL R15, 4*4+off+512(dst); \ + MOVL R15, 8*4+off+576(dst) + +#define BLAKE2s_SSE2() \ + PRECOMPUTE_MSG(SP, 16, SI, R8, R9, R10, R11, R12, R13, R14, R15); \ + ROUND_SSE2(X4, X5, X6, X7, 16(SP), 32(SP), 48(SP), 64(SP), X8); \ + ROUND_SSE2(X4, X5, X6, X7, 16+64(SP), 32+64(SP), 48+64(SP), 64+64(SP), X8); \ + ROUND_SSE2(X4, X5, X6, X7, 16+128(SP), 32+128(SP), 48+128(SP), 64+128(SP), X8); \ + ROUND_SSE2(X4, X5, X6, X7, 16+192(SP), 32+192(SP), 48+192(SP), 64+192(SP), X8); \ + ROUND_SSE2(X4, X5, X6, X7, 16+256(SP), 32+256(SP), 48+256(SP), 64+256(SP), X8); \ + ROUND_SSE2(X4, X5, X6, X7, 16+320(SP), 32+320(SP), 48+320(SP), 64+320(SP), X8); \ + ROUND_SSE2(X4, X5, X6, X7, 16+384(SP), 32+384(SP), 48+384(SP), 64+384(SP), X8); \ + ROUND_SSE2(X4, X5, X6, X7, 16+448(SP), 32+448(SP), 48+448(SP), 64+448(SP), X8); \ + ROUND_SSE2(X4, X5, X6, X7, 16+512(SP), 32+512(SP), 48+512(SP), 64+512(SP), X8); \ + ROUND_SSE2(X4, X5, X6, X7, 16+576(SP), 32+576(SP), 48+576(SP), 64+576(SP), X8) + +#define BLAKE2s_SSSE3() \ + PRECOMPUTE_MSG(SP, 16, SI, R8, R9, R10, R11, R12, R13, R14, R15); \ + ROUND_SSSE3(X4, X5, X6, X7, 16(SP), 32(SP), 48(SP), 64(SP), X8, X13, X14); \ + ROUND_SSSE3(X4, X5, X6, X7, 16+64(SP), 32+64(SP), 48+64(SP), 64+64(SP), X8, X13, X14); \ + ROUND_SSSE3(X4, X5, X6, X7, 16+128(SP), 32+128(SP), 48+128(SP), 64+128(SP), X8, X13, X14); \ + ROUND_SSSE3(X4, X5, X6, X7, 16+192(SP), 32+192(SP), 48+192(SP), 64+192(SP), X8, X13, X14); \ + ROUND_SSSE3(X4, X5, X6, X7, 16+256(SP), 32+256(SP), 48+256(SP), 64+256(SP), X8, X13, X14); \ + ROUND_SSSE3(X4, X5, X6, X7, 16+320(SP), 32+320(SP), 48+320(SP), 64+320(SP), X8, X13, X14); \ + ROUND_SSSE3(X4, X5, X6, X7, 16+384(SP), 32+384(SP), 48+384(SP), 64+384(SP), X8, X13, X14); \ + ROUND_SSSE3(X4, X5, X6, X7, 16+448(SP), 32+448(SP), 48+448(SP), 64+448(SP), X8, X13, X14); \ + ROUND_SSSE3(X4, X5, X6, X7, 16+512(SP), 32+512(SP), 48+512(SP), 64+512(SP), X8, X13, X14); \ + ROUND_SSSE3(X4, X5, X6, X7, 16+576(SP), 32+576(SP), 48+576(SP), 64+576(SP), X8, X13, X14) + +#define BLAKE2s_SSE4() \ + LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15); \ + ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ + LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3); \ + ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ + LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 11, 12, 5, 15, 8, 0, 2, 13, 10, 3, 7, 9, 14, 6, 1, 4); \ + ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ + LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 7, 3, 13, 11, 9, 1, 12, 14, 2, 5, 4, 15, 6, 10, 0, 8); \ + ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ + LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 9, 5, 2, 10, 0, 7, 4, 15, 14, 11, 6, 3, 1, 12, 8, 13); \ + ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ + LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 2, 6, 0, 8, 12, 10, 11, 3, 4, 7, 15, 1, 13, 5, 14, 9); \ + ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ + LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 12, 1, 14, 4, 5, 15, 13, 10, 0, 6, 9, 8, 7, 3, 2, 11); \ + ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ + LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 13, 7, 12, 3, 11, 14, 1, 9, 5, 15, 8, 2, 0, 4, 6, 10); \ + ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ + LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 6, 14, 11, 0, 15, 9, 3, 8, 12, 13, 1, 10, 2, 7, 4, 5); \ + ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14); \ + LOAD_MSG_SSE4(X8, X9, X10, X11, SI, 10, 8, 7, 1, 2, 4, 6, 5, 15, 9, 3, 13, 11, 14, 12, 0); \ + ROUND_SSSE3(X4, X5, X6, X7, X8, X9, X10, X11, X8, X13, X14) + +#define HASH_BLOCKS(h, c, flag, blocks_base, blocks_len, BLAKE2s_FUNC) \ + MOVQ h, AX; \ + MOVQ c, BX; \ + MOVL flag, CX; \ + MOVQ blocks_base, SI; \ + MOVQ blocks_len, DX; \ + \ + MOVQ SP, BP; \ + MOVQ SP, R9; \ + ADDQ $15, R9; \ + ANDQ $~15, R9; \ + MOVQ R9, SP; \ + \ + MOVQ 0(BX), R9; \ + MOVQ R9, 0(SP); \ + XORQ R9, R9; \ + MOVQ R9, 8(SP); \ + MOVL CX, 8(SP); \ + \ + MOVOU 0(AX), X0; \ + MOVOU 16(AX), X1; \ + MOVOU iv0<>(SB), X2; \ + MOVOU iv1<>(SB), X3 \ + \ + MOVOU counter<>(SB), X12; \ + MOVOU rol16<>(SB), X13; \ + MOVOU rol8<>(SB), X14; \ + MOVO 0(SP), X15; \ + \ + loop: \ + MOVO X0, X4; \ + MOVO X1, X5; \ + MOVO X2, X6; \ + MOVO X3, X7; \ + \ + PADDQ X12, X15; \ + PXOR X15, X7; \ + \ + BLAKE2s_FUNC(); \ + \ + PXOR X4, X0; \ + PXOR X5, X1; \ + PXOR X6, X0; \ + PXOR X7, X1; \ + \ + LEAQ 64(SI), SI; \ + SUBQ $64, DX; \ + JNE loop; \ + \ + MOVO X15, 0(SP); \ + MOVQ 0(SP), R9; \ + MOVQ R9, 0(BX); \ + \ + MOVOU X0, 0(AX); \ + MOVOU X1, 16(AX); \ + \ + MOVQ BP, SP + +// func hashBlocksSSE2(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) +TEXT ·hashBlocksSSE2(SB), 0, $672-48 // frame = 656 + 16 byte alignment + HASH_BLOCKS(h+0(FP), c+8(FP), flag+16(FP), blocks_base+24(FP), blocks_len+32(FP), BLAKE2s_SSE2) + RET + +// func hashBlocksSSSE3(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) +TEXT ·hashBlocksSSSE3(SB), 0, $672-48 // frame = 656 + 16 byte alignment + HASH_BLOCKS(h+0(FP), c+8(FP), flag+16(FP), blocks_base+24(FP), blocks_len+32(FP), BLAKE2s_SSSE3) + RET + +// func hashBlocksSSE4(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) +TEXT ·hashBlocksSSE4(SB), 0, $32-48 // frame = 16 + 16 byte alignment + HASH_BLOCKS(h+0(FP), c+8(FP), flag+16(FP), blocks_base+24(FP), blocks_len+32(FP), BLAKE2s_SSE4) + RET + +// func supportSSE4() bool +TEXT ·supportSSE4(SB), 4, $0-1 + MOVL $1, AX + CPUID + SHRL $19, CX // Bit 19 indicates SSE4.1. + ANDL $1, CX + MOVB CX, ret+0(FP) + RET + +// func supportSSSE3() bool +TEXT ·supportSSSE3(SB), 4, $0-1 + MOVL $1, AX + CPUID + MOVL CX, BX + ANDL $0x1, BX // Bit zero indicates SSE3 support. + JZ FALSE + ANDL $0x200, CX // Bit nine indicates SSSE3 support. + JZ FALSE + MOVB $1, ret+0(FP) + RET + +FALSE: + MOVB $0, ret+0(FP) + RET diff --git a/vendor/golang.org/x/crypto/blake2s/blake2s_generic.go b/vendor/golang.org/x/crypto/blake2s/blake2s_generic.go new file mode 100644 index 0000000000000000000000000000000000000000..f7e065378af257c4b13b54837f0ce113d761c5e6 --- /dev/null +++ b/vendor/golang.org/x/crypto/blake2s/blake2s_generic.go @@ -0,0 +1,174 @@ +// Copyright 2016 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 blake2s + +// the precomputed values for BLAKE2s +// there are 10 16-byte arrays - one for each round +// the entries are calculated from the sigma constants. +var precomputed = [10][16]byte{ + {0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15}, + {14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3}, + {11, 12, 5, 15, 8, 0, 2, 13, 10, 3, 7, 9, 14, 6, 1, 4}, + {7, 3, 13, 11, 9, 1, 12, 14, 2, 5, 4, 15, 6, 10, 0, 8}, + {9, 5, 2, 10, 0, 7, 4, 15, 14, 11, 6, 3, 1, 12, 8, 13}, + {2, 6, 0, 8, 12, 10, 11, 3, 4, 7, 15, 1, 13, 5, 14, 9}, + {12, 1, 14, 4, 5, 15, 13, 10, 0, 6, 9, 8, 7, 3, 2, 11}, + {13, 7, 12, 3, 11, 14, 1, 9, 5, 15, 8, 2, 0, 4, 6, 10}, + {6, 14, 11, 0, 15, 9, 3, 8, 12, 13, 1, 10, 2, 7, 4, 5}, + {10, 8, 7, 1, 2, 4, 6, 5, 15, 9, 3, 13, 11, 14, 12, 0}, +} + +func hashBlocksGeneric(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) { + var m [16]uint32 + c0, c1 := c[0], c[1] + + for i := 0; i < len(blocks); { + c0 += BlockSize + if c0 < BlockSize { + c1++ + } + + v0, v1, v2, v3, v4, v5, v6, v7 := h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7] + v8, v9, v10, v11, v12, v13, v14, v15 := iv[0], iv[1], iv[2], iv[3], iv[4], iv[5], iv[6], iv[7] + v12 ^= c0 + v13 ^= c1 + v14 ^= flag + + for j := range m { + m[j] = uint32(blocks[i]) | uint32(blocks[i+1])<<8 | uint32(blocks[i+2])<<16 | uint32(blocks[i+3])<<24 + i += 4 + } + + for k := range precomputed { + s := &(precomputed[k]) + + v0 += m[s[0]] + v0 += v4 + v12 ^= v0 + v12 = v12<<(32-16) | v12>>16 + v8 += v12 + v4 ^= v8 + v4 = v4<<(32-12) | v4>>12 + v1 += m[s[1]] + v1 += v5 + v13 ^= v1 + v13 = v13<<(32-16) | v13>>16 + v9 += v13 + v5 ^= v9 + v5 = v5<<(32-12) | v5>>12 + v2 += m[s[2]] + v2 += v6 + v14 ^= v2 + v14 = v14<<(32-16) | v14>>16 + v10 += v14 + v6 ^= v10 + v6 = v6<<(32-12) | v6>>12 + v3 += m[s[3]] + v3 += v7 + v15 ^= v3 + v15 = v15<<(32-16) | v15>>16 + v11 += v15 + v7 ^= v11 + v7 = v7<<(32-12) | v7>>12 + + v0 += m[s[4]] + v0 += v4 + v12 ^= v0 + v12 = v12<<(32-8) | v12>>8 + v8 += v12 + v4 ^= v8 + v4 = v4<<(32-7) | v4>>7 + v1 += m[s[5]] + v1 += v5 + v13 ^= v1 + v13 = v13<<(32-8) | v13>>8 + v9 += v13 + v5 ^= v9 + v5 = v5<<(32-7) | v5>>7 + v2 += m[s[6]] + v2 += v6 + v14 ^= v2 + v14 = v14<<(32-8) | v14>>8 + v10 += v14 + v6 ^= v10 + v6 = v6<<(32-7) | v6>>7 + v3 += m[s[7]] + v3 += v7 + v15 ^= v3 + v15 = v15<<(32-8) | v15>>8 + v11 += v15 + v7 ^= v11 + v7 = v7<<(32-7) | v7>>7 + + v0 += m[s[8]] + v0 += v5 + v15 ^= v0 + v15 = v15<<(32-16) | v15>>16 + v10 += v15 + v5 ^= v10 + v5 = v5<<(32-12) | v5>>12 + v1 += m[s[9]] + v1 += v6 + v12 ^= v1 + v12 = v12<<(32-16) | v12>>16 + v11 += v12 + v6 ^= v11 + v6 = v6<<(32-12) | v6>>12 + v2 += m[s[10]] + v2 += v7 + v13 ^= v2 + v13 = v13<<(32-16) | v13>>16 + v8 += v13 + v7 ^= v8 + v7 = v7<<(32-12) | v7>>12 + v3 += m[s[11]] + v3 += v4 + v14 ^= v3 + v14 = v14<<(32-16) | v14>>16 + v9 += v14 + v4 ^= v9 + v4 = v4<<(32-12) | v4>>12 + + v0 += m[s[12]] + v0 += v5 + v15 ^= v0 + v15 = v15<<(32-8) | v15>>8 + v10 += v15 + v5 ^= v10 + v5 = v5<<(32-7) | v5>>7 + v1 += m[s[13]] + v1 += v6 + v12 ^= v1 + v12 = v12<<(32-8) | v12>>8 + v11 += v12 + v6 ^= v11 + v6 = v6<<(32-7) | v6>>7 + v2 += m[s[14]] + v2 += v7 + v13 ^= v2 + v13 = v13<<(32-8) | v13>>8 + v8 += v13 + v7 ^= v8 + v7 = v7<<(32-7) | v7>>7 + v3 += m[s[15]] + v3 += v4 + v14 ^= v3 + v14 = v14<<(32-8) | v14>>8 + v9 += v14 + v4 ^= v9 + v4 = v4<<(32-7) | v4>>7 + } + + h[0] ^= v0 ^ v8 + h[1] ^= v1 ^ v9 + h[2] ^= v2 ^ v10 + h[3] ^= v3 ^ v11 + h[4] ^= v4 ^ v12 + h[5] ^= v5 ^ v13 + h[6] ^= v6 ^ v14 + h[7] ^= v7 ^ v15 + } + c[0], c[1] = c0, c1 +} diff --git a/vendor/golang.org/x/crypto/blake2s/blake2s_ref.go b/vendor/golang.org/x/crypto/blake2s/blake2s_ref.go new file mode 100644 index 0000000000000000000000000000000000000000..a311273454c38fd7e350bd8565fd680dd3558030 --- /dev/null +++ b/vendor/golang.org/x/crypto/blake2s/blake2s_ref.go @@ -0,0 +1,17 @@ +// Copyright 2016 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,!386 gccgo appengine + +package blake2s + +var ( + useSSE4 = false + useSSSE3 = false + useSSE2 = false +) + +func hashBlocks(h *[8]uint32, c *[2]uint32, flag uint32, blocks []byte) { + hashBlocksGeneric(h, c, flag, blocks) +} diff --git a/vendor/golang.org/x/crypto/blake2s/blake2s_test.go b/vendor/golang.org/x/crypto/blake2s/blake2s_test.go new file mode 100644 index 0000000000000000000000000000000000000000..cfeb18bb433371273973e61b9ad14f0bc5698709 --- /dev/null +++ b/vendor/golang.org/x/crypto/blake2s/blake2s_test.go @@ -0,0 +1,1002 @@ +// Copyright 2016 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 blake2s + +import ( + "encoding/hex" + "fmt" + "testing" +) + +func TestHashes(t *testing.T) { + defer func(sse2, ssse3, sse4 bool) { + useSSE2, useSSSE3, useSSE4 = sse2, ssse3, sse4 + }(useSSE2, useSSSE3, useSSE4) + + if useSSE4 { + t.Log("SSE4 version") + testHashes(t) + testHashes128(t) + useSSE4 = false + } + if useSSSE3 { + t.Log("SSSE3 version") + testHashes(t) + testHashes128(t) + useSSSE3 = false + } + if useSSE2 { + t.Log("SSE2 version") + testHashes(t) + testHashes128(t) + useSSE2 = false + } + + t.Log("generic version") + testHashes(t) + testHashes128(t) +} + +func TestHashes2X(t *testing.T) { + defer func(sse2, ssse3, sse4 bool) { + useSSE2, useSSSE3, useSSE4 = sse2, ssse3, sse4 + }(useSSE2, useSSSE3, useSSE4) + + if useSSE4 { + t.Log("SSE4 version") + testHashes2X(t) + useSSE4 = false + } + if useSSSE3 { + t.Log("SSSE3 version") + testHashes2X(t) + useSSSE3 = false + } + if useSSE2 { + t.Log("SSE2 version") + testHashes2X(t) + useSSE2 = false + } + + t.Log("generic version") + testHashes2X(t) +} + +func testHashes(t *testing.T) { + key, _ := hex.DecodeString("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") + + input := make([]byte, 255) + for i := range input { + input[i] = byte(i) + } + + for i, expectedHex := range hashes { + h, err := New256(key) + if err != nil { + t.Fatalf("#%d: error from New256: %v", i, err) + } + + h.Write(input[:i]) + sum := h.Sum(nil) + + if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex { + t.Fatalf("#%d (single write): got %s, wanted %s", i, gotHex, expectedHex) + } + + h.Reset() + for j := 0; j < i; j++ { + h.Write(input[j : j+1]) + } + + sum = h.Sum(sum[:0]) + if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex { + t.Fatalf("#%d (byte-by-byte): got %s, wanted %s", i, gotHex, expectedHex) + } + } +} + +func testHashes128(t *testing.T) { + key, _ := hex.DecodeString("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") + + input := make([]byte, 255) + for i := range input { + input[i] = byte(i) + } + + for i, expectedHex := range hashes128 { + h, err := New128(key) + if err != nil { + t.Fatalf("#%d: error from New128: %v", i, err) + } + + h.Write(input[:i]) + sum := h.Sum(nil) + + if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex { + t.Fatalf("#%d (single write): got %s, wanted %s", i, gotHex, expectedHex) + } + + h.Reset() + for j := 0; j < i; j++ { + h.Write(input[j : j+1]) + } + + sum = h.Sum(sum[:0]) + if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex { + t.Fatalf("#%d (byte-by-byte): got %s, wanted %s", i, gotHex, expectedHex) + } + } +} + +func testHashes2X(t *testing.T) { + key, _ := hex.DecodeString("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") + + input := make([]byte, 256) + for i := range input { + input[i] = byte(i) + } + + for i, expectedHex := range hashes2X { + length := uint16(len(expectedHex) / 2) + sum := make([]byte, int(length)) + + h, err := NewXOF(length, key) + if err != nil { + t.Fatalf("#%d: error from NewXOF: %v", i, err) + } + + if _, err := h.Write(input); err != nil { + t.Fatalf("#%d (single write): error from Write: %v", i, err) + } + if _, err := h.Read(sum); err != nil { + t.Fatalf("#%d (single write): error from Read: %v", i, err) + } + + if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex { + t.Fatalf("#%d (single write): got %s, wanted %s", i, gotHex, expectedHex) + } + + h.Reset() + for j := 0; j < len(input); j++ { + h.Write(input[j : j+1]) + } + for j := 0; j < len(sum); j++ { + h = h.Clone() + if _, err := h.Read(sum[j : j+1]); err != nil { + t.Fatalf("#%d (byte-by-byte) - Read %d: error from Read: %v", i, j, err) + } + } + if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex { + t.Fatalf("#%d (byte-by-byte): got %s, wanted %s", i, gotHex, expectedHex) + } + } + + h, err := NewXOF(OutputLengthUnknown, key) + if err != nil { + t.Fatalf("#unknown length: error from NewXOF: %v", err) + } + if _, err := h.Write(input); err != nil { + t.Fatalf("#unknown length: error from Write: %v", err) + } + + var result [64]byte + if n, err := h.Read(result[:]); err != nil { + t.Fatalf("#unknown length: error from Read: %v", err) + } else if n != len(result) { + t.Fatalf("#unknown length: Read returned %d bytes, want %d", n, len(result)) + } + + const expected = "2a9a6977d915a2c4dd07dbcafe1918bf1682e56d9c8e567ecd19bfd7cd93528833c764d12b34a5e2a219c9fd463dab45e972c5574d73f45de5b2e23af72530d8" + if fmt.Sprintf("%x", result) != expected { + t.Fatalf("#unknown length: bad result %x, wanted %s", result, expected) + } +} + +// Benchmarks + +func benchmarkSum(b *testing.B, size int) { + data := make([]byte, size) + b.SetBytes(int64(size)) + b.ResetTimer() + for i := 0; i < b.N; i++ { + Sum256(data) + } +} + +func benchmarkWrite(b *testing.B, size int) { + data := make([]byte, size) + h, _ := New256(nil) + b.SetBytes(int64(size)) + b.ResetTimer() + for i := 0; i < b.N; i++ { + h.Write(data) + } +} + +func BenchmarkWrite64(b *testing.B) { benchmarkWrite(b, 64) } +func BenchmarkWrite1K(b *testing.B) { benchmarkWrite(b, 1024) } + +func BenchmarkSum64(b *testing.B) { benchmarkSum(b, 64) } +func BenchmarkSum1K(b *testing.B) { benchmarkSum(b, 1024) } + +// hashes is taken from https://blake2.net/blake2s-test.txt +var hashes = []string{ + "48a8997da407876b3d79c0d92325ad3b89cbb754d86ab71aee047ad345fd2c49", + "40d15fee7c328830166ac3f918650f807e7e01e177258cdc0a39b11f598066f1", + "6bb71300644cd3991b26ccd4d274acd1adeab8b1d7914546c1198bbe9fc9d803", + "1d220dbe2ee134661fdf6d9e74b41704710556f2f6e5a091b227697445dbea6b", + "f6c3fbadb4cc687a0064a5be6e791bec63b868ad62fba61b3757ef9ca52e05b2", + "49c1f21188dfd769aea0e911dd6b41f14dab109d2b85977aa3088b5c707e8598", + "fdd8993dcd43f696d44f3cea0ff35345234ec8ee083eb3cada017c7f78c17143", + "e6c8125637438d0905b749f46560ac89fd471cf8692e28fab982f73f019b83a9", + "19fc8ca6979d60e6edd3b4541e2f967ced740df6ec1eaebbfe813832e96b2974", + "a6ad777ce881b52bb5a4421ab6cdd2dfba13e963652d4d6d122aee46548c14a7", + "f5c4b2ba1a00781b13aba0425242c69cb1552f3f71a9a3bb22b4a6b4277b46dd", + "e33c4c9bd0cc7e45c80e65c77fa5997fec7002738541509e68a9423891e822a3", + "fba16169b2c3ee105be6e1e650e5cbf40746b6753d036ab55179014ad7ef6651", + "f5c4bec6d62fc608bf41cc115f16d61c7efd3ff6c65692bbe0afffb1fede7475", + "a4862e76db847f05ba17ede5da4e7f91b5925cf1ad4ba12732c3995742a5cd6e", + "65f4b860cd15b38ef814a1a804314a55be953caa65fd758ad989ff34a41c1eea", + "19ba234f0a4f38637d1839f9d9f76ad91c8522307143c97d5f93f69274cec9a7", + "1a67186ca4a5cb8e65fca0e2ecbc5ddc14ae381bb8bffeb9e0a103449e3ef03c", + "afbea317b5a2e89c0bd90ccf5d7fd0ed57fe585e4be3271b0a6bf0f5786b0f26", + "f1b01558ce541262f5ec34299d6fb4090009e3434be2f49105cf46af4d2d4124", + "13a0a0c86335635eaa74ca2d5d488c797bbb4f47dc07105015ed6a1f3309efce", + "1580afeebebb346f94d59fe62da0b79237ead7b1491f5667a90e45edf6ca8b03", + "20be1a875b38c573dd7faaa0de489d655c11efb6a552698e07a2d331b5f655c3", + "be1fe3c4c04018c54c4a0f6b9a2ed3c53abe3a9f76b4d26de56fc9ae95059a99", + "e3e3ace537eb3edd8463d9ad3582e13cf86533ffde43d668dd2e93bbdbd7195a", + "110c50c0bf2c6e7aeb7e435d92d132ab6655168e78a2decdec3330777684d9c1", + "e9ba8f505c9c80c08666a701f3367e6cc665f34b22e73c3c0417eb1c2206082f", + "26cd66fca02379c76df12317052bcafd6cd8c3a7b890d805f36c49989782433a", + "213f3596d6e3a5d0e9932cd2159146015e2abc949f4729ee2632fe1edb78d337", + "1015d70108e03be1c702fe97253607d14aee591f2413ea6787427b6459ff219a", + "3ca989de10cfe609909472c8d35610805b2f977734cf652cc64b3bfc882d5d89", + "b6156f72d380ee9ea6acd190464f2307a5c179ef01fd71f99f2d0f7a57360aea", + "c03bc642b20959cbe133a0303e0c1abff3e31ec8e1a328ec8565c36decff5265", + "2c3e08176f760c6264c3a2cd66fec6c3d78de43fc192457b2a4a660a1e0eb22b", + "f738c02f3c1b190c512b1a32deabf353728e0e9ab034490e3c3409946a97aeec", + "8b1880df301cc963418811088964839287ff7fe31c49ea6ebd9e48bdeee497c5", + "1e75cb21c60989020375f1a7a242839f0b0b68973a4c2a05cf7555ed5aaec4c1", + "62bf8a9c32a5bccf290b6c474d75b2a2a4093f1a9e27139433a8f2b3bce7b8d7", + "166c8350d3173b5e702b783dfd33c66ee0432742e9b92b997fd23c60dc6756ca", + "044a14d822a90cacf2f5a101428adc8f4109386ccb158bf905c8618b8ee24ec3", + "387d397ea43a994be84d2d544afbe481a2000f55252696bba2c50c8ebd101347", + "56f8ccf1f86409b46ce36166ae9165138441577589db08cbc5f66ca29743b9fd", + "9706c092b04d91f53dff91fa37b7493d28b576b5d710469df79401662236fc03", + "877968686c068ce2f7e2adcff68bf8748edf3cf862cfb4d3947a3106958054e3", + "8817e5719879acf7024787eccdb271035566cfa333e049407c0178ccc57a5b9f", + "8938249e4b50cadaccdf5b18621326cbb15253e33a20f5636e995d72478de472", + "f164abba4963a44d107257e3232d90aca5e66a1408248c51741e991db5227756", + "d05563e2b1cba0c4a2a1e8bde3a1a0d9f5b40c85a070d6f5fb21066ead5d0601", + "03fbb16384f0a3866f4c3117877666efbf124597564b293d4aab0d269fabddfa", + "5fa8486ac0e52964d1881bbe338eb54be2f719549224892057b4da04ba8b3475", + "cdfabcee46911111236a31708b2539d71fc211d9b09c0d8530a11e1dbf6eed01", + "4f82de03b9504793b82a07a0bdcdff314d759e7b62d26b784946b0d36f916f52", + "259ec7f173bcc76a0994c967b4f5f024c56057fb79c965c4fae41875f06a0e4c", + "193cc8e7c3e08bb30f5437aa27ade1f142369b246a675b2383e6da9b49a9809e", + "5c10896f0e2856b2a2eee0fe4a2c1633565d18f0e93e1fab26c373e8f829654d", + "f16012d93f28851a1eb989f5d0b43f3f39ca73c9a62d5181bff237536bd348c3", + "2966b3cfae1e44ea996dc5d686cf25fa053fb6f67201b9e46eade85d0ad6b806", + "ddb8782485e900bc60bcf4c33a6fd585680cc683d516efa03eb9985fad8715fb", + "4c4d6e71aea05786413148fc7a786b0ecaf582cff1209f5a809fba8504ce662c", + "fb4c5e86d7b2229b99b8ba6d94c247ef964aa3a2bae8edc77569f28dbbff2d4e", + "e94f526de9019633ecd54ac6120f23958d7718f1e7717bf329211a4faeed4e6d", + "cbd6660a10db3f23f7a03d4b9d4044c7932b2801ac89d60bc9eb92d65a46c2a0", + "8818bbd3db4dc123b25cbba5f54c2bc4b3fcf9bf7d7a7709f4ae588b267c4ece", + "c65382513f07460da39833cb666c5ed82e61b9e998f4b0c4287cee56c3cc9bcd", + "8975b0577fd35566d750b362b0897a26c399136df07bababbde6203ff2954ed4", + "21fe0ceb0052be7fb0f004187cacd7de67fa6eb0938d927677f2398c132317a8", + "2ef73f3c26f12d93889f3c78b6a66c1d52b649dc9e856e2c172ea7c58ac2b5e3", + "388a3cd56d73867abb5f8401492b6e2681eb69851e767fd84210a56076fb3dd3", + "af533e022fc9439e4e3cb838ecd18692232adf6fe9839526d3c3dd1b71910b1a", + "751c09d41a9343882a81cd13ee40818d12eb44c6c7f40df16e4aea8fab91972a", + "5b73ddb68d9d2b0aa265a07988d6b88ae9aac582af83032f8a9b21a2e1b7bf18", + "3da29126c7c5d7f43e64242a79feaa4ef3459cdeccc898ed59a97f6ec93b9dab", + "566dc920293da5cb4fe0aa8abda8bbf56f552313bff19046641e3615c1e3ed3f", + "4115bea02f73f97f629e5c5590720c01e7e449ae2a6697d4d2783321303692f9", + "4ce08f4762468a7670012164878d68340c52a35e66c1884d5c864889abc96677", + "81ea0b7804124e0c22ea5fc71104a2afcb52a1fa816f3ecb7dcb5d9dea1786d0", + "fe362733b05f6bedaf9379d7f7936ede209b1f8323c3922549d9e73681b5db7b", + "eff37d30dfd20359be4e73fdf40d27734b3df90a97a55ed745297294ca85d09f", + "172ffc67153d12e0ca76a8b6cd5d4731885b39ce0cac93a8972a18006c8b8baf", + "c47957f1cc88e83ef9445839709a480a036bed5f88ac0fcc8e1e703ffaac132c", + "30f3548370cfdceda5c37b569b6175e799eef1a62aaa943245ae7669c227a7b5", + "c95dcb3cf1f27d0eef2f25d2413870904a877c4a56c2de1e83e2bc2ae2e46821", + "d5d0b5d705434cd46b185749f66bfb5836dcdf6ee549a2b7a4aee7f58007caaf", + "bbc124a712f15d07c300e05b668389a439c91777f721f8320c1c9078066d2c7e", + "a451b48c35a6c7854cfaae60262e76990816382ac0667e5a5c9e1b46c4342ddf", + "b0d150fb55e778d01147f0b5d89d99ecb20ff07e5e6760d6b645eb5b654c622b", + "34f737c0ab219951eee89a9f8dac299c9d4c38f33fa494c5c6eefc92b6db08bc", + "1a62cc3a00800dcbd99891080c1e098458193a8cc9f970ea99fbeff00318c289", + "cfce55ebafc840d7ae48281c7fd57ec8b482d4b704437495495ac414cf4a374b", + "6746facf71146d999dabd05d093ae586648d1ee28e72617b99d0f0086e1e45bf", + "571ced283b3f23b4e750bf12a2caf1781847bd890e43603cdc5976102b7bb11b", + "cfcb765b048e35022c5d089d26e85a36b005a2b80493d03a144e09f409b6afd1", + "4050c7a27705bb27f42089b299f3cbe5054ead68727e8ef9318ce6f25cd6f31d", + "184070bd5d265fbdc142cd1c5cd0d7e414e70369a266d627c8fba84fa5e84c34", + "9edda9a4443902a9588c0d0ccc62b930218479a6841e6fe7d43003f04b1fd643", + "e412feef7908324a6da1841629f35d3d358642019310ec57c614836b63d30763", + "1a2b8edff3f9acc1554fcbae3cf1d6298c6462e22e5eb0259684f835012bd13f", + "288c4ad9b9409762ea07c24a41f04f69a7d74bee2d95435374bde946d7241c7b", + "805691bb286748cfb591d3aebe7e6f4e4dc6e2808c65143cc004e4eb6fd09d43", + "d4ac8d3a0afc6cfa7b460ae3001baeb36dadb37da07d2e8ac91822df348aed3d", + "c376617014d20158bced3d3ba552b6eccf84e62aa3eb650e90029c84d13eea69", + "c41f09f43cecae7293d6007ca0a357087d5ae59be500c1cd5b289ee810c7b082", + "03d1ced1fba5c39155c44b7765cb760c78708dcfc80b0bd8ade3a56da8830b29", + "09bde6f152218dc92c41d7f45387e63e5869d807ec70b821405dbd884b7fcf4b", + "71c9036e18179b90b37d39e9f05eb89cc5fc341fd7c477d0d7493285faca08a4", + "5916833ebb05cd919ca7fe83b692d3205bef72392b2cf6bb0a6d43f994f95f11", + "f63aab3ec641b3b024964c2b437c04f6043c4c7e0279239995401958f86bbe54", + "f172b180bfb09740493120b6326cbdc561e477def9bbcfd28cc8c1c5e3379a31", + "cb9b89cc18381dd9141ade588654d4e6a231d5bf49d4d59ac27d869cbe100cf3", + "7bd8815046fdd810a923e1984aaebdcdf84d87c8992d68b5eeb460f93eb3c8d7", + "607be66862fd08ee5b19facac09dfdbcd40c312101d66e6ebd2b841f1b9a9325", + "9fe03bbe69ab1834f5219b0da88a08b30a66c5913f0151963c360560db0387b3", + "90a83585717b75f0e9b725e055eeeeb9e7a028ea7e6cbc07b20917ec0363e38c", + "336ea0530f4a7469126e0218587ebbde3358a0b31c29d200f7dc7eb15c6aadd8", + "a79e76dc0abca4396f0747cd7b748df913007626b1d659da0c1f78b9303d01a3", + "44e78a773756e0951519504d7038d28d0213a37e0ce375371757bc996311e3b8", + "77ac012a3f754dcfeab5eb996be9cd2d1f96111b6e49f3994df181f28569d825", + "ce5a10db6fccdaf140aaa4ded6250a9c06e9222bc9f9f3658a4aff935f2b9f3a", + "ecc203a7fe2be4abd55bb53e6e673572e0078da8cd375ef430cc97f9f80083af", + "14a5186de9d7a18b0412b8563e51cc5433840b4a129a8ff963b33a3c4afe8ebb", + "13f8ef95cb86e6a638931c8e107673eb76ba10d7c2cd70b9d9920bbeed929409", + "0b338f4ee12f2dfcb78713377941e0b0632152581d1332516e4a2cab1942cca4", + "eaab0ec37b3b8ab796e9f57238de14a264a076f3887d86e29bb5906db5a00e02", + "23cb68b8c0e6dc26dc27766ddc0a13a99438fd55617aa4095d8f969720c872df", + "091d8ee30d6f2968d46b687dd65292665742de0bb83dcc0004c72ce10007a549", + "7f507abc6d19ba00c065a876ec5657868882d18a221bc46c7a6912541f5bc7ba", + "a0607c24e14e8c223db0d70b4d30ee88014d603f437e9e02aa7dafa3cdfbad94", + "ddbfea75cc467882eb3483ce5e2e756a4f4701b76b445519e89f22d60fa86e06", + "0c311f38c35a4fb90d651c289d486856cd1413df9b0677f53ece2cd9e477c60a", + "46a73a8dd3e70f59d3942c01df599def783c9da82fd83222cd662b53dce7dbdf", + "ad038ff9b14de84a801e4e621ce5df029dd93520d0c2fa38bff176a8b1d1698c", + "ab70c5dfbd1ea817fed0cd067293abf319e5d7901c2141d5d99b23f03a38e748", + "1fffda67932b73c8ecaf009a3491a026953babfe1f663b0697c3c4ae8b2e7dcb", + "b0d2cc19472dd57f2b17efc03c8d58c2283dbb19da572f7755855aa9794317a0", + "a0d19a6ee33979c325510e276622df41f71583d07501b87071129a0ad94732a5", + "724642a7032d1062b89e52bea34b75df7d8fe772d9fe3c93ddf3c4545ab5a99b", + "ade5eaa7e61f672d587ea03dae7d7b55229c01d06bc0a5701436cbd18366a626", + "013b31ebd228fcdda51fabb03bb02d60ac20ca215aafa83bdd855e3755a35f0b", + "332ed40bb10dde3c954a75d7b8999d4b26a1c063c1dc6e32c1d91bab7bbb7d16", + "c7a197b3a05b566bcc9facd20e441d6f6c2860ac9651cd51d6b9d2cdeeea0390", + "bd9cf64ea8953c037108e6f654914f3958b68e29c16700dc184d94a21708ff60", + "8835b0ac021151df716474ce27ce4d3c15f0b2dab48003cf3f3efd0945106b9a", + "3bfefa3301aa55c080190cffda8eae51d9af488b4c1f24c3d9a75242fd8ea01d", + "08284d14993cd47d53ebaecf0df0478cc182c89c00e1859c84851686ddf2c1b7", + "1ed7ef9f04c2ac8db6a864db131087f27065098e69c3fe78718d9b947f4a39d0", + "c161f2dcd57e9c1439b31a9dd43d8f3d7dd8f0eb7cfac6fb25a0f28e306f0661", + "c01969ad34c52caf3dc4d80d19735c29731ac6e7a92085ab9250c48dea48a3fc", + "1720b3655619d2a52b3521ae0e49e345cb3389ebd6208acaf9f13fdacca8be49", + "756288361c83e24c617cf95c905b22d017cdc86f0bf1d658f4756c7379873b7f", + "e7d0eda3452693b752abcda1b55e276f82698f5f1605403eff830bea0071a394", + "2c82ecaa6b84803e044af63118afe544687cb6e6c7df49ed762dfd7c8693a1bc", + "6136cbf4b441056fa1e2722498125d6ded45e17b52143959c7f4d4e395218ac2", + "721d3245aafef27f6a624f47954b6c255079526ffa25e9ff77e5dcff473b1597", + "9dd2fbd8cef16c353c0ac21191d509eb28dd9e3e0d8cea5d26ca839393851c3a", + "b2394ceacdebf21bf9df2ced98e58f1c3a4bbbff660dd900f62202d6785cc46e", + "57089f222749ad7871765f062b114f43ba20ec56422a8b1e3f87192c0ea718c6", + "e49a9459961cd33cdf4aae1b1078a5dea7c040e0fea340c93a724872fc4af806", + "ede67f720effd2ca9c88994152d0201dee6b0a2d2c077aca6dae29f73f8b6309", + "e0f434bf22e3088039c21f719ffc67f0f2cb5e98a7a0194c76e96bf4e8e17e61", + "277c04e2853484a4eba910ad336d01b477b67cc200c59f3c8d77eef8494f29cd", + "156d5747d0c99c7f27097d7b7e002b2e185cb72d8dd7eb424a0321528161219f", + "20ddd1ed9b1ca803946d64a83ae4659da67fba7a1a3eddb1e103c0f5e03e3a2c", + "f0af604d3dabbf9a0f2a7d3dda6bd38bba72c6d09be494fcef713ff10189b6e6", + "9802bb87def4cc10c4a5fd49aa58dfe2f3fddb46b4708814ead81d23ba95139b", + "4f8ce1e51d2fe7f24043a904d898ebfc91975418753413aa099b795ecb35cedb", + "bddc6514d7ee6ace0a4ac1d0e068112288cbcf560454642705630177cba608bd", + "d635994f6291517b0281ffdd496afa862712e5b3c4e52e4cd5fdae8c0e72fb08", + "878d9ca600cf87e769cc305c1b35255186615a73a0da613b5f1c98dbf81283ea", + "a64ebe5dc185de9fdde7607b6998702eb23456184957307d2fa72e87a47702d6", + "ce50eab7b5eb52bdc9ad8e5a480ab780ca9320e44360b1fe37e03f2f7ad7de01", + "eeddb7c0db6e30abe66d79e327511e61fcebbc29f159b40a86b046ecf0513823", + "787fc93440c1ec96b5ad01c16cf77916a1405f9426356ec921d8dff3ea63b7e0", + "7f0d5eab47eefda696c0bf0fbf86ab216fce461e9303aba6ac374120e890e8df", + "b68004b42f14ad029f4c2e03b1d5eb76d57160e26476d21131bef20ada7d27f4", + "b0c4eb18ae250b51a41382ead92d0dc7455f9379fc9884428e4770608db0faec", + "f92b7a870c059f4d46464c824ec96355140bdce681322cc3a992ff103e3fea52", + "5364312614813398cc525d4c4e146edeb371265fba19133a2c3d2159298a1742", + "f6620e68d37fb2af5000fc28e23b832297ecd8bce99e8be4d04e85309e3d3374", + "5316a27969d7fe04ff27b283961bffc3bf5dfb32fb6a89d101c6c3b1937c2871", + "81d1664fdf3cb33c24eebac0bd64244b77c4abea90bbe8b5ee0b2aafcf2d6a53", + "345782f295b0880352e924a0467b5fbc3e8f3bfbc3c7e48b67091fb5e80a9442", + "794111ea6cd65e311f74ee41d476cb632ce1e4b051dc1d9e9d061a19e1d0bb49", + "2a85daf6138816b99bf8d08ba2114b7ab07975a78420c1a3b06a777c22dd8bcb", + "89b0d5f289ec16401a069a960d0b093e625da3cf41ee29b59b930c5820145455", + "d0fdcb543943fc27d20864f52181471b942cc77ca675bcb30df31d358ef7b1eb", + "b17ea8d77063c709d4dc6b879413c343e3790e9e62ca85b7900b086f6b75c672", + "e71a3e2c274db842d92114f217e2c0eac8b45093fdfd9df4ca7162394862d501", + "c0476759ab7aa333234f6b44f5fd858390ec23694c622cb986e769c78edd733e", + "9ab8eabb1416434d85391341d56993c55458167d4418b19a0f2ad8b79a83a75b", + "7992d0bbb15e23826f443e00505d68d3ed7372995a5c3e498654102fbcd0964e", + "c021b30085151435df33b007ccecc69df1269f39ba25092bed59d932ac0fdc28", + "91a25ec0ec0d9a567f89c4bfe1a65a0e432d07064b4190e27dfb81901fd3139b", + "5950d39a23e1545f301270aa1a12f2e6c453776e4d6355de425cc153f9818867", + "d79f14720c610af179a3765d4b7c0968f977962dbf655b521272b6f1e194488e", + "e9531bfc8b02995aeaa75ba27031fadbcbf4a0dab8961d9296cd7e84d25d6006", + "34e9c26a01d7f16181b454a9d1623c233cb99d31c694656e9413aca3e918692f", + "d9d7422f437bd439ddd4d883dae2a08350173414be78155133fff1964c3d7972", + "4aee0c7aaf075414ff1793ead7eaca601775c615dbd60b640b0a9f0ce505d435", + "6bfdd15459c83b99f096bfb49ee87b063d69c1974c6928acfcfb4099f8c4ef67", + "9fd1c408fd75c336193a2a14d94f6af5adf050b80387b4b010fb29f4cc72707c", + "13c88480a5d00d6c8c7ad2110d76a82d9b70f4fa6696d4e5dd42a066dcaf9920", + "820e725ee25fe8fd3a8d5abe4c46c3ba889de6fa9191aa22ba67d5705421542b", + "32d93a0eb02f42fbbcaf2bad0085b282e46046a4df7ad10657c9d6476375b93e", + "adc5187905b1669cd8ec9c721e1953786b9d89a9bae30780f1e1eab24a00523c", + "e90756ff7f9ad810b239a10ced2cf9b2284354c1f8c7e0accc2461dc796d6e89", + "1251f76e56978481875359801db589a0b22f86d8d634dc04506f322ed78f17e8", + "3afa899fd980e73ecb7f4d8b8f291dc9af796bc65d27f974c6f193c9191a09fd", + "aa305be26e5deddc3c1010cbc213f95f051c785c5b431e6a7cd048f161787528", + "8ea1884ff32e9d10f039b407d0d44e7e670abd884aeee0fb757ae94eaa97373d", + "d482b2155d4dec6b4736a1f1617b53aaa37310277d3fef0c37ad41768fc235b4", + "4d413971387e7a8898a8dc2a27500778539ea214a2dfe9b3d7e8ebdce5cf3db3", + "696e5d46e6c57e8796e4735d08916e0b7929b3cf298c296d22e9d3019653371c", + "1f5647c1d3b088228885865c8940908bf40d1a8272821973b160008e7a3ce2eb", + "b6e76c330f021a5bda65875010b0edf09126c0f510ea849048192003aef4c61c", + "3cd952a0beada41abb424ce47f94b42be64e1ffb0fd0782276807946d0d0bc55", + "98d92677439b41b7bb513312afb92bcc8ee968b2e3b238cecb9b0f34c9bb63d0", + "ecbca2cf08ae57d517ad16158a32bfa7dc0382eaeda128e91886734c24a0b29d", + "942cc7c0b52e2b16a4b89fa4fc7e0bf609e29a08c1a8543452b77c7bfd11bb28", + "8a065d8b61a0dffb170d5627735a76b0e9506037808cba16c345007c9f79cf8f", + "1b9fa19714659c78ff413871849215361029ac802b1cbcd54e408bd87287f81f", + "8dab071bcd6c7292a9ef727b4ae0d86713301da8618d9a48adce55f303a869a1", + "8253e3e7c7b684b9cb2beb014ce330ff3d99d17abbdbabe4f4d674ded53ffc6b", + "f195f321e9e3d6bd7d074504dd2ab0e6241f92e784b1aa271ff648b1cab6d7f6", + "27e4cc72090f241266476a7c09495f2db153d5bcbd761903ef79275ec56b2ed8", + "899c2405788e25b99a1846355e646d77cf400083415f7dc5afe69d6e17c00023", + "a59b78c4905744076bfee894de707d4f120b5c6893ea0400297d0bb834727632", + "59dc78b105649707a2bb4419c48f005400d3973de3736610230435b10424b24f", + "c0149d1d7e7a6353a6d906efe728f2f329fe14a4149a3ea77609bc42b975ddfa", + "a32f241474a6c16932e9243be0cf09bcdc7e0ca0e7a6a1b9b1a0f01e41502377", + "b239b2e4f81841361c1339f68e2c359f929af9ad9f34e01aab4631ad6d5500b0", + "85fb419c7002a3e0b4b6ea093b4c1ac6936645b65dac5ac15a8528b7b94c1754", + "9619720625f190b93a3fad186ab314189633c0d3a01e6f9bc8c4a8f82f383dbf", + "7d620d90fe69fa469a6538388970a1aa09bb48a2d59b347b97e8ce71f48c7f46", + "294383568596fb37c75bbacd979c5ff6f20a556bf8879cc72924855df9b8240e", + "16b18ab314359c2b833c1c6986d48c55a9fc97cde9a3c1f10a3177140f73f738", + "8cbbdd14bc33f04cf45813e4a153a273d36adad5ce71f499eeb87fb8ac63b729", + "69c9a498db174ecaefcc5a3ac9fdedf0f813a5bec727f1e775babdec7718816e", + "b462c3be40448f1d4f80626254e535b08bc9cdcff599a768578d4b2881a8e3f0", + "553e9d9c5f360ac0b74a7d44e5a391dad4ced03e0c24183b7e8ecabdf1715a64", + "7a7c55a56fa9ae51e655e01975d8a6ff4ae9e4b486fcbe4eac044588f245ebea", + "2afdf3c82abc4867f5de111286c2b3be7d6e48657ba923cfbf101a6dfcf9db9a", + "41037d2edcdce0c49b7fb4a6aa0999ca66976c7483afe631d4eda283144f6dfc", + "c4466f8497ca2eeb4583a0b08e9d9ac74395709fda109d24f2e4462196779c5d", + "75f609338aa67d969a2ae2a2362b2da9d77c695dfd1df7224a6901db932c3364", + "68606ceb989d5488fc7cf649f3d7c272ef055da1a93faecd55fe06f6967098ca", + "44346bdeb7e052f6255048f0d9b42c425bab9c3dd24168212c3ecf1ebf34e6ae", + "8e9cf6e1f366471f2ac7d2ee9b5e6266fda71f8f2e4109f2237ed5f8813fc718", + "84bbeb8406d250951f8c1b3e86a7c010082921833dfd9555a2f909b1086eb4b8", + "ee666f3eef0f7e2a9c222958c97eaf35f51ced393d714485ab09a069340fdf88", + "c153d34a65c47b4a62c5cacf24010975d0356b2f32c8f5da530d338816ad5de6", + "9fc5450109e1b779f6c7ae79d56c27635c8dd426c5a9d54e2578db989b8c3b4e", + "d12bf3732ef4af5c22fa90356af8fc50fcb40f8f2ea5c8594737a3b3d5abdbd7", + "11030b9289bba5af65260672ab6fee88b87420acef4a1789a2073b7ec2f2a09e", + "69cb192b8444005c8c0ceb12c846860768188cda0aec27a9c8a55cdee2123632", + "db444c15597b5f1a03d1f9edd16e4a9f43a667cc275175dfa2b704e3bb1a9b83", + "3fb735061abc519dfe979e54c1ee5bfad0a9d858b3315bad34bde999efd724dd", +} + +var hashes128 = []string{ + "9536f9b267655743dee97b8a670f9f53", + "13bacfb85b48a1223c595f8c1e7e82cb", + "d47a9b1645e2feae501cd5fe44ce6333", + "1e2a79436a7796a3e9826bfedf07659f", + "7640360ed3c4f3054dba79a21dda66b7", + "d1207ac2bf5ac84fc9ef016da5a46a86", + "3123987871e59305ece3125abfc0099a", + "cf9e072ad522f2cda2d825218086731c", + "95d22870392efe2846b12b6e8e84efbb", + "7d63c30e2d51333f245601b038c0b93b", + "ed608b98e13976bdf4bedc63fa35e443", + "ed704b5cd1abf8e0dd67a6ac667a3fa5", + "77dc70109827dc74c70fd26cba379ae5", + "d2bf34508b07825ee934f33958f4560e", + "a340baa7b8a93a6e658adef42e78eeb7", + "b85c5ceaecbe9a251eac76f6932ba395", + "246519722001f6e8e97a2183f5985e53", + "5bce5aa0b7c6cac2ecf6406183cd779a", + "13408f1647c02f6efd0047ad8344f695", + "a63970f196760aa36cb965ab62f0e0fa", + "bc26f48421dd99fd45e15e736d3e7dac", + "4c6f70f9e3237cde918afb52d26f1823", + "45ed610cfbc37db80c4bf0eef14ae8d6", + "87c4c150705ea5078209ec008200539c", + "54de21f5e0e6f2afe04daeb822b6931e", + "9732a04e505064e19de3d542e7e71631", + "d2bd27e95531d6957eef511c4ba64ad4", + "7a36c9f70dcc7c3063b547101a5f6c35", + "322007d1a44c4257bc7903b183305529", + "dbcc9a09f412290ca2e0d53dfd142ddb", + "df12ed43b8e53a56db20e0f83764002c", + "d114cc11e7d5b33a360c45f18d4c7c6e", + "c43b5e836af88620a8a71b1652cb8640", + "9491c653e8867ed73c1b4ac6b5a9bb4d", + "06d0e988df94ada6c6f9f36f588ab7c5", + "561efad2480e93262c8eeaa3677615c4", + "ba8ffc702e5adc93503045eca8702312", + "5782be6ccdc78c8425285e85de8ccdc6", + "aa1c4393e4c07b53ea6e2b5b1e970771", + "42a229dc50e52271c51e8666023ebc1e", + "53706110e919f84de7f8d6c7f0e7b831", + "fc5ac8ee39cc1dd1424391323e2901bd", + "bed27b62ff66cac2fbb68193c727106a", + "cd5e689b96d0b9ea7e08dac36f7b211e", + "0b4c7f604eba058d18e322c6e1baf173", + "eb838227fdfad09a27f0f8413120675d", + "3149cf9d19a7fd529e6154a8b4c3b3ad", + "ca1e20126df930fd5fb7afe4422191e5", + "b23398f910599f3c09b6549fa81bcb46", + "27fb17c11b34fa5d8b5afe5ee3321ead", + "0f665f5f04cf2d46b7fead1a1f328158", + "8f068be73b3681f99f3b282e3c02bba5", + "ba189bbd13808dcf4e002a4dd21660d5", + "2732dcd1b16668ae6ab6a61595d0d62a", + "d410ccdd059f0e02b472ec9ec54bdd3c", + "b2eaa07b055b3a03a399971327f7e8c2", + "2e8a225655e9f99b69c60dc8b4d8e566", + "4eb55416c853f2152e67f8a224133cec", + "49552403790d8de0505a8e317a443687", + "7f2747cd41f56942752e868212c7d5ac", + "02a28f10e193b430df7112d2d98cf759", + "d4213404a9f1cf759017747cf5958270", + "faa34884344f9c65e944882db8476d34", + "ece382a8bd5018f1de5da44b72cea75b", + "f1efa90d2547036841ecd3627fafbc36", + "811ff8686d23a435ecbd0bdafcd27b1b", + "b21beea9c7385f657a76558530438721", + "9cb969da4f1b4fc5b13bf78fe366f0c4", + "8850d16d7b614d3268ccfa009d33c7fc", + "aa98a2b6176ea86415b9aff3268c6f6d", + "ec3e1efa5ed195eff667e16b1af1e39e", + "e40787dca57411d2630db2de699beb08", + "554835890735babd06318de23d31e78a", + "493957feecddc302ee2bb2086b6ebfd3", + "f6069709ad5b0139163717e9ce1114ab", + "ba5ed386098da284484b211555505a01", + "9244c8dfad8cbb68c118fa51465b3ae4", + "51e309a5008eb1f5185e5cc007cfb36f", + "6ce9ff712121b4f6087955f4911eafd4", + "59b51d8dcda031218ccdd7c760828155", + "0012878767a3d4f1c8194458cf1f8832", + "82900708afd5b6582dc16f008c655edd", + "21302c7e39b5a4cdf1d6f86b4f00c9b4", + "e894c7431591eab8d1ce0fe2aa1f01df", + "b67e1c40ee9d988226d605621854d955", + "6237bdafa34137cbbec6be43ea9bd22c", + "4172a8e19b0dcb09b978bb9eff7af52b", + "5714abb55bd4448a5a6ad09fbd872fdf", + "7ce1700bef423e1f958a94a77a94d44a", + "3742ec50cded528527775833453e0b26", + "5d41b135724c7c9c689495324b162f18", + "85c523333c6442c202e9e6e0f1185f93", + "5c71f5222d40ff5d90e7570e71ab2d30", + "6e18912e83d012efb4c66250ced6f0d9", + "4add4448c2e35e0b138a0bac7b4b1775", + "c0376c6bc5e7b8b9d2108ec25d2aab53", + "f72261d5ed156765c977751c8a13fcc1", + "cff4156c48614b6ceed3dd6b9058f17e", + "36bfb513f76c15f514bcb593419835aa", + "166bf48c6bffaf8291e6fdf63854bef4", + "0b67d33f8b859c3157fbabd9e6e47ed0", + "e4da659ca76c88e73a9f9f10f3d51789", + "33c1ae2a86b3f51c0642e6ed5b5aa1f1", + "27469b56aca2334449c1cf4970dcd969", + "b7117b2e363378aa0901b0d6a9f6ddc0", + "a9578233b09e5cd5231943fdb12cd90d", + "486d7d75253598b716a068243c1c3e89", + "66f6b02d682b78ffdc85e9ec86852489", + "38a07b9a4b228fbcc305476e4d2e05d2", + "aedb61c7970e7d05bf9002dae3c6858c", + "c03ef441f7dd30fdb61ad2d4d8e4c7da", + "7f45cc1eea9a00cb6aeb2dd748361190", + "a59538b358459132e55160899e47bd65", + "137010fef72364411820c3fbed15c8df", + "d8362b93fc504500dbd33ac74e1b4d70", + "a7e49f12c8f47e3b29cf8c0889b0a9c8", + "072e94ffbfc684bd8ab2a1b9dade2fd5", + "5ab438584bd2229e452052e002631a5f", + "f233d14221097baef57d3ec205c9e086", + "3a95db000c4a8ff98dc5c89631a7f162", + "0544f18c2994ab4ddf1728f66041ff16", + "0bc02116c60a3cc331928d6c9d3ba37e", + "b189dca6cb5b813c74200834fba97f29", + "ac8aaab075b4a5bc24419da239212650", + "1e9f19323dc71c29ae99c479dc7e8df9", + "12d944c3fa7caa1b3d62adfc492274dd", + "b4c68f1fffe8f0030e9b18aad8c9dc96", + "25887fab1422700d7fa3edc0b20206e2", + "8c09f698d03eaf88abf69f8147865ef6", + "5c363ae42a5bec26fbc5e996428d9bd7", + "7fdfc2e854fbb3928150d5e3abcf56d6", + "f0c944023f714df115f9e4f25bcdb89b", + "6d19534b4c332741c8ddd79a9644de2d", + "32595eb23764fbfc2ee7822649f74a12", + "5a51391aab33c8d575019b6e76ae052a", + "98b861ce2c620f10f913af5d704a5afd", + "b7fe2fc8b77fb1ce434f8465c7ddf793", + "0e8406e0cf8e9cc840668ece2a0fc64e", + "b89922db99c58f6a128ccffe19b6ce60", + "e1be9af665f0932b77d7f5631a511db7", + "74b96f20f58de8dc9ff5e31f91828523", + "36a4cfef5a2a7d8548db6710e50b3009", + "007e95e8d3b91948a1dedb91f75de76b", + "a87a702ce08f5745edf765bfcd5fbe0d", + "847e69a388a749a9c507354d0dddfe09", + "07176eefbc107a78f058f3d424ca6a54", + "ad7e80682333b68296f6cb2b4a8e446d", + "53c4aba43896ae422e5de5b9edbd46bf", + "33bd6c20ca2a7ab916d6e98003c6c5f8", + "060d088ea94aa093f9981a79df1dfcc8", + "5617b214b9df08d4f11e58f5e76d9a56", + "ca3a60ee85bd971e1daf9f7db059d909", + "cd2b7754505d8c884eddf736f1ec613e", + "f496163b252f1439e7e113ba2ecabd8e", + "5719c7dcf9d9f756d6213354acb7d5cf", + "6f7dd40b245c54411e7a9be83ae5701c", + "c8994dd9fdeb077a45ea04a30358b637", + "4b1184f1e35458c1c747817d527a252f", + "fc7df674afeac7a3fd994183f4c67a74", + "4f68e05ce4dcc533acf9c7c01d95711e", + "d4ebc59e918400720035dfc88e0c486a", + "d3105dd6fa123e543b0b3a6e0eeaea9e", + "874196128ed443f5bdb2800ca048fcad", + "01645f134978dc8f9cf0abc93b53780e", + "5b8b64caa257873a0ffd47c981ef6c3f", + "4ee208fc50ba0a6e65c5b58cec44c923", + "53f409a52427b3b7ffabb057ca088428", + "c1d6cd616f5341a93d921e356e5887a9", + "e85c20fea67fa7320dc23379181183c8", + "7912b6409489df001b7372bc94aebde7", + "e559f761ec866a87f1f331767fafc60f", + "20a6f5a36bc37043d977ed7708465ef8", + "6a72f526965ab120826640dd784c6cc4", + "bf486d92ad68e87c613689dd370d001b", + "d339fd0eb35edf3abd6419c8d857acaf", + "9521cd7f32306d969ddabc4e6a617f52", + "a1cd9f3e81520842f3cf6cc301cb0021", + "18e879b6f154492d593edd3f4554e237", + "66e2329c1f5137589e051592587e521e", + "e899566dd6c3e82cbc83958e69feb590", + "8a4b41d7c47e4e80659d77b4e4bfc9ae", + "f1944f6fcfc17803405a1101998c57dd", + "f6bcec07567b4f72851b307139656b18", + "22e7bb256918fe9924dce9093e2d8a27", + "dd25b925815fe7b50b7079f5f65a3970", + "0457f10f299acf0c230dd4007612e58f", + "ecb420c19efd93814fae2964d69b54af", + "14eb47b06dff685d88751c6e32789db4", + "e8f072dbb50d1ab6654aa162604a892d", + "69cff9c62092332f03a166c7b0034469", + "d3619f98970b798ca32c6c14cd25af91", + "2246d423774ee9d51a551e89c0539d9e", + "75e5d1a1e374a04a699247dad827b6cf", + "6d087dd1d4cd15bf47db07c7a96b1db8", + "967e4c055ac51b4b2a3e506cebd5826f", + "7417aa79247e473401bfa92a25b62e2a", + "24f3f4956da34b5c533d9a551ccd7b16", + "0c40382de693a5304e2331eb951cc962", + "9436f949d51b347db5c8e6258dafaaac", + "d2084297fe84c4ba6e04e4fb73d734fe", + "42a6f8ff590af21b512e9e088257aa34", + "c484ad06b1cdb3a54f3f6464a7a2a6fd", + "1b8ac860f5ceb4365400a201ed2917aa", + "c43eadabbe7b7473f3f837fc52650f54", + "0e5d3205406126b1f838875deb150d6a", + "6bf4946f8ec8a9c417f50cd1e67565be", + "42f09a2522314799c95b3fc121a0e3e8", + "06b8f1487f691a3f7c3f74e133d55870", + "1a70a65fb4f314dcf6a31451a9d2704f", + "7d4acdd0823279fd28a1e48b49a04669", + "09545cc8822a5dfc93bbab708fd69174", + "efc063db625013a83c9a426d39a9bddb", + "213bbf89b3f5be0ffdb14854bbcb2588", + "b69624d89fe2774df9a6f43695d755d4", + "c0f9ff9ded82bd73c512e365a894774d", + "d1b68507ed89c17ead6f69012982db71", + "14cf16db04648978e35c44850855d1b0", + "9f254d4eccab74cd91d694df863650a8", + "8f8946e2967baa4a814d36ff01d20813", + "6b9dc4d24ecba166cb2915d7a6cba43b", + "eb35a80418a0042b850e294db7898d4d", + "f55f925d280c637d54055c9df088ef5f", + "f48427a04f67e33f3ba0a17f7c9704a7", + "4a9f5bfcc0321aea2eced896cee65894", + "8723a67d1a1df90f1cef96e6fe81e702", + "c166c343ee25998f80bad4067960d3fd", + "dab67288d16702e676a040fd42344d73", + "c8e9e0d80841eb2c116dd14c180e006c", + "92294f546bacf0dea9042c93ecba8b34", + "013705b1502b37369ad22fe8237d444e", + "9b97f8837d5f2ebab0768fc9a6446b93", + "7e7e5236b05ec35f89edf8bf655498e7", + "7be8f2362c174c776fb9432fe93bf259", + "2422e80420276d2df5702c6470879b01", + "df645795db778bcce23bbe819a76ba48", + "3f97a4ac87dfc58761cda1782d749074", + "50e3f45df21ebfa1b706b9c0a1c245a8", + "7879541c7ff612c7ddf17cb8f7260183", + "67f6542b903b7ba1945eba1a85ee6b1c", + "b34b73d36ab6234b8d3f5494d251138e", + "0aea139641fdba59ab1103479a96e05f", + "02776815a87b8ba878453666d42afe3c", + "5929ab0a90459ebac5a16e2fb37c847e", + "c244def5b20ce0468f2b5012d04ac7fd", + "12116add6fefce36ed8a0aeccce9b6d3", + "3cd743841e9d8b878f34d91b793b4fad", + "45e87510cf5705262185f46905fae35f", + "276047016b0bfb501b2d4fc748165793", + "ddd245df5a799417d350bd7f4e0b0b7e", + "d34d917a54a2983f3fdbc4b14caae382", + "7730fbc09d0c1fb1939a8fc436f6b995", + "eb4899ef257a1711cc9270a19702e5b5", + "8a30932014bce35bba620895d374df7a", + "1924aabf9c50aa00bee5e1f95b5d9e12", + "1758d6f8b982aec9fbe50f20e3082b46", + "cd075928ab7e6883e697fe7fd3ac43ee", +} + +// hashes2X is taken from +// https://github.com/BLAKE2/BLAKE2/blob/master/testvectors/blake2-kat.json +var hashes2X = []string{ + "0e", + "5196", + "ad6bad", + "d8e4b32f", + "8eb89056f3", + "410497c2ed72", + "f0de771b375c90", + "8662db8685033611", + "9ef9f1eed88a3f52ca", + "08225082df0d2b0a815e", + "0f6e84a17439f1bc97c299", + "895ec39c78d3556cefdbfabc", + "2b396b3fa90ab556079a79b44d", + "abae26501c4c1d6123c0f2289111", + "bca098df9099b3f785a37ba40fce5f", + "19b827f054b67a120f11efb0d690be70", + "b88d32a338fd60b58570fda228a121113b", + "3f30143af1cad33f9b794576e078cc79062e", + "ffddb58d9aa8d38086fcdae07e6653e8f31dfc", + "abb99c2e74a74556919040ca0cd857c95ec985e9", + "71f13f89af55ba936f8a7188ee93d2e8fb0cf2a720", + "99734fdf0eef4838a7515426f4c59b800854e2fcdc1c", + "579b1652aa1f5779d2b0e61868af856855020bdd44d7a7", + "1383d4ab4a6d8672b4075d421a159f69380ff47e4bb518d5", + "d3fa1412712dbbab71d4c6265dc1585c8dcc73380cf807f76a", + "1d57868a71e7245667780455d9aaa9e0683baf08fbaf946091c2", + "ef80418fe7049c6251ed7960a6b0e9def0da2749781994b24593a0", + "ef91cb81e4bfb50231e89475e251e2ef2fde59357551cd227588b63f", + "d7f398a5d21c3139cff0562a84f154b6953c7bc18a5f4b60491c196b6d", + "0a2abc6d38f30aef253579a4088c5b9aec64391f37d576eb06a300c193a5", + "02dd758fa23113a14fd94830e50e0f6b86faec4e551e808b0ca8d00fef2a15", + "a4fe2bd0f96a215fa7164ae1a405f4030a586c12b0c29806a099d7d7fdd8dd72", + "7dce710a20f42ab687ec6ea83b53faaa418229ce0d5a2ff2a5e66defb0b65c03c9", + "0320c40b5eea641d0bc25420b7545ac1d796b61563728a4dc451207f1addeedcf860", + "460539415f2baeb626fad748dee0eb3e9f27221661160e13edf39d1b5d476ee0672400", + "02de8ffa5b9c748164f99ed9d678b02e53f4ae88fb26c6d94a8cefc328725a692eae78c2", + "348a61a0136436136910262ad67ef20644b32c15456d5fad6b1679386d0bea87cc1a2e2b5e", + "24c32966c803434d48d2283482ee8f404f598cf7a17961748125d2ed1da987039b1ce00f2ba7", + "bd07cb16121d3b47adf03b96c41c947beadc01e40548e0d0773e61780d48d33a0e2a675ca681a6", + "a35844e34c20b4b9371b6c52fac412afe5d80a4c1e40aa3a0e5a729dc3d41c2c3719d096f616f0ba", + "6df1efbb4567747fe98d218935612f8835852dde2ce3dec767792d7f1d876cdae0056fef085245449d", + "48d6094af78bd38d8f4b39c54279b80ef617bc6ad21def0b2c62113b656c5d6a55aea2e3fde94a254b92", + "cd6e684759d2f19083164712c2aca0038442efb5b646594396b1fccdbd21203290f44cfdecca0373b3801b", + "155dfbf26103c8354362663677fa27d0e1ce3487a821a2a7171014c1bd5dd071f4974df272b1374765b8f2e1", + "15b11067f311efa4ee813dbca48d690dc92780656bc4d4c56510523190a240180867c829a8b8b9844175a8aa23", + "9bc27953a17fb84d5eabe95b4ea6bc03ea450274abccfb6f3938ded8560fb59662459a11a86b0e0f32fbea6bb1f8", + "03b78fb0b34fb8662accdf350a6be75ace9789653ee4375d351e871f6a98ac5e782ca4b4a717665d25e49a5ae25d81", + "687e9a6fda6e2ce0e40e4d30fef38c31e3513d2892bbe85c991fc3715947e42bc49bcd079a40ed061c2c3665efe555ab", + "f3886027d2049a8909e26545bd202d6a6fa2a6f815d31c7d520f705a81fa606dd695369c37aee4fa77dc645e9b05813ceb", + "e4a412ccd20b97797d91ccc286904fcd17c5afe8bed0618f1af333c052c473cd327637d951c32e4af047106036a3bc8c1c45", + "92f4b8c240a28b6238bc2eabadaf2ff3c4bfe0e6c61268ace6aebdeb0691450caea4287db8b329bde96af8cdb8a0fe2f57ef2d", + "e506834b3445e1a9a9b7bae844e91e0834512a06c0dc75fa4604e3b903c4e23616f2e0c78b5cc496660b4a13064bb1138edef4ff", + "27031955a40d8dbd1591f26e3c26e367a3c68f8204a396c6a4ba34b89672896d11276966a42bd516716f35ed63e442e116dbcf35da", + "646b1635c68d2328dddd5ac26eb9877c24c28390a45753a65044c3136ae2fe4fb40d09bf555271646d3dceb1ab1b7c8d8e421f553f94", + "f6171f8d833743bdee7cc8f8b29c38614e1d2d8d6a5fff68bec2c0f4dd463d7941ff5c368e2683d8f1dc97119bde2b73ca412718bc8cb1", + "45db1c478b040aa2e23fb4427017079810775c62abe737e82ec0ef8dcd0fc51f521f29fe6412fff7eac9beb7bcf75f483f3f8b971e42454b", + "500dab14687db3ca3dde9304af5f54194b37bdf475628af46b07bfbf6bc2b64ecef284b17f9d1d9be41794699bc0e76c2878b3a55730f7142d", + "31bba2efc7b3f415c3f031d4c06bb590ae40085ad157370af30238e03e25a359c9e133212ed34b7a006f839173b577e7015a87fdff2270fafddb", + "0600b3fb4b5e1ed0c8b2698ac1d9905e67e027390764821f963ad8d2b33cbc378b9c25c3ee422992d22b760222ed5697be0576d73938ae9d634ed7", + "4c0ca4f177d132594a4c613bad68da24c564efa3b4da0d0a903f26534a2e09f8d799d10e78f48ccdb0203954a36c5cf1bf24c076632c2b022b041200", + "97aacf2e1b013677b2e14084f097cb1e64d7b3fa36f097e189d86dc4a263bcc46817cd1ee6ff0c7ccd9acef63201cdc0e36254e19204a7388643bb571f", + "71fd6846ce7adb0843d6063546a16b79b54ad6c0f018a479a45817624fa221f63525084860559d1a0679c8d89a80701c62743ec2da8419d503f8f0cd7946", + "f73dfb046def3362d6de36077dae2cee2587fe95fe0800548bb7d99737897096ba59052e0dadcc1fb0ccb5535391875328637a0376a43a4d89366758dfe3e2", + "ec470d0aa932c78c5bcf86203ec0014314114765fa679c3daef214f883a17e1b4ca12f44433772a6e4ef685c904b2fc35586c6bd88f325b965968b06d808d73f", + "cf601753ffa09fe48a8a84c37769991e96290e200bbaf1910c57760f989bd0c72e6128e294528ee861ad7eee70d589de3cf4a0c35f7197e1925a64d0133628d87d", + "f15413f7d6fc54bb55829f698da92ee42fcf58dde1aa1bd07d438ecdc32ad6bf2bcdbecc99f18ed43e81b33065af5a4ca29960ae50553e610c0bbf4153d580e73dbb", + "84b1738adb9757fb9402ef7113581291136184d7ae35fe0b6a738da6acb0889d4d5bac7a957024e3709fa80c77d3859871ed1aa25cf488e438a2d24cfadce6008761dd", + "e02814bb81f250c1835a05108396b74c7878e737654bb83155e241774d04e639bbc571b413cd9349092f926c8a149a53cd33e9b63f370b6d460e504199d2e7d849db6cbe", + "aeee4a789956ec0913592c30ce4f9c544894da77ba447c84df3be2c869100e4df8f7e316445d844b31c3209abcc912f647735fd4a7136c2f35c6fda5b2e6708f5ca951b2b0", + "8cfd11ca385de3c843de84c830d59278fe79b70fb5ddbfbfc1ddefeb22c329ef2f607d1d1abbd1cd0d0cc7c5d3ed922add76aadca0d2f57b66cb16c582b6f18f60aee2f7509b", + "852e5ce2047d8d8b42b4c7e4987b95d23e8026a202d4567951bbbd23111e389fe33a736318546a914d2bddedfbf53846036ad9e35f29318b1f96e33eba08f071d6dc665149feb6", + "f225c23164979d0d13874a90ee291627e4f61a672a5578506fd3d65a12cb48a182f78350dc24c637b2f3950dc4882a5c1d5d5bad551c6f3e0093aa87e962bea51566af3791d52d65", + "5f33864d882455f8ef046aed64e2d1691e5c1555e333b0852750592e6f00d3b5ec941d0c00e99629612795d5870cf93c984b45e4464ba072a34903b400a42824ac13da28c7c1cb1959", + "7baaee7c3eb68c18c5ae1d45ba381803de34e36a52e2d7ccc9d48a297273c4d8644b473195bc23005f7a4f5ca790b1fa11f6a96e585e635513f11745dd97a69c1222204ab28d3c7735df", + "d0a2a3fc450ef9af7ae982041feb2842901026467d87839c33b4a9e081ea63d5be60ae99ca6e42393ded45255b8f42886f87ba0310572d9f0d8b5a07ff4b6bae1f30559a844983cc568560", + "3aa4164462b3e7044c35b08b047b924790f6d5c520b1df4305b5d41f4717e81f0cd4bccb9a5a6594773832b8707443adde4047caaed2293f92234df257df54ed275a9658fab483d0576d33a9", + "c8b4239fd7f1b893d978268f77f6505b5775d89090374322d40083b0f4c437423f670ca213f7fe05c61069725da2561646eefaea597ac48e293fbad44c2872046857e56d04a426a84008cefd71", + "f94839a7024c0a16971271b6727c081770110c957b1f2e03be03d2200b565cf8240f2873b0426042aaea996a1784fadb2b27f23bc1a521b4f7320dfbed86cd38d75141365ba9b443defc0a3b4078", + "8af934fdc8b3376ca09bdd89f9057ed38b656bff96a8f8a3038d456a265689ca32036670cb01469cc6e958cc4a46f1e80d700ae56659828a65c0456b8e55f28f255bc86ce48e44377bf1f9970b617d", + "ada572989e42f0e38c1f7c22b46bb52a84df8f7b3b773c9f17a5823e59a9725248d703efb4cb011abc9474e8e711666ed3cfa60db48480a8160615dfabad761bc0eb843d2e46299c59b61a15b4422fdf", + "b11f1ea52a7e4bd2a5cf1e234b7c9eb909fb45860080f0a6bdb5517a37b5b7cd90f3a9e2297f995e96c293189b807a7bf6e7633bebbc36674544db5f18dd33020aeaf50ee832efe4d3d053873fd31ce3b9", + "e54b006cd96c43d19787c1ab1e08ea0f8922bdb7142e748212e7912a1f2c0a4fad1b9f5209c30960b8b83ef4960e929b155a8a48c8fb7ce4326915950cede6b98a96b6f1ecb12715b713985dacd1c1180413", + "ee2c2f31a414ccd8f6a790f55e09155fd50aac2a878f9014f6c6035cae9186f90cdef0b7adf3e207c3d24ddfba8cd321b2e9228b02a1182b6973da6698071fce8cc0a23a7bf0d5aefd21ab1b8dc7818549bba3", + "6d6810793bad6c7efe8fd56cac04a0fb8717a44c09cbfaebce196a80ac318c79ca5c2db54fee8191ee2d305b690a92bd9e2c947a3c29342a93ac05796484638787a184e4525e82aeb9afa2f9480caebb91014c51", + "91e4694366cff84854872667fd168d2d42eca9070cdc92fca9936e8361e7266931f418450d098a42686241d08024dd72f0024d22ba644bd414245e78608942321ff61860ba1245f83c88592dc7995c49c0c53aa8a9", + "608aa620a5cf145f4477694407ccd8faa3182465b29ae98d96a42f7409434c21e4671bcae079f6871a09d8f2965e4926a9b08277d32f9dd6a474e3a9fb232f27fc4235df9c02abf67f7e540ca9ddc270ee91b23a5b57", + "c14f75e92f75f4356ab01c8792af13383e7fef2ffb3064de55e8da0a50511fea364ccd8140134872adccad197228319260a7b77b67a39677a0dcdcadfb750333ac8e032121e278bdcdbed5e452dae0416011186d9ebf29", + "03fcb9f6e1f058091b11351e775184ff2cd1f31ee846c6ea8efd49dd344f4af473f92eb44eba8a019776f77bb24e294aa9f962b39feecf7c59d46f1a606f89b1e81c2715ac9aa252e9ce941d091ffb99bb52404961794cf8", + "11e189b1d90fcfe8111c79c5351d826f5ec15a602af3b71d50bc7ed813f36c9a682520984ae911669d3c3036223a53176794c7e17929efab2b1c5b500f24f8c83d3db5d1029c5714c6fd34eb800a913985c218071677b9885c", + "69f8f5db3ab0321a708ab2f4234645dade6bfda495851dbe7257f2b72e3e8378b9fa8120bc836b737a675271e519b4712d2b56b359e0f2234ba7552dd4828b939e0542e729878ac1f81b6ce14cb573e76af3a6aa227f95b2350e", + "be734d78fae92cacb009cc400e023086bc3a3a10e8ca7cb4d553ea85314f51383660b8508e8477af60baf7e07c04cc9e094690ae12c73e5f089763201b4b48d664b94b4f5820bd1540f4a84100fdf8fce7f6466aa5d5c34fcbab45", + "d61b77032403f9b6ea5ad2b760eb0157545e37f1712ec44d7926ccf130e8fc0fe8e9b15570a6214c3899a074811486182b250dc97ebdd3b61403614d935cd0a61c0899f31b0e49b81c8a9a4fe8409822c470aacfde229d965dd62f51", + "c31bd548e36d5fae95ed8fa6e807642711c897f0fcc3b0d00bd317ed2bca73412064618c6a84a61c71bce3e963333b0266a5656571dcc4ba8a8c9d84af4bdb445c34a7aef445b15d77698e0b13c436c928cc7fa7acd5f68867e8132993", + "9903b8adab803d085b634bfae2e109dd247a7d6249f203403216d9f7410c36142df8fa56fb4d6f78136eef5817bad5ea3608439bb19336628c37d42db16ab2df8018b773baedafb77278a50926370b48bd81710203c7abc7b4043f9a1751", + "4dadaf0d6a96022c8ce40d48f460526d9956da33260e1770315ead420da75b122c762762aa3ddc1aef9070ff2298b2304cf90443318b17183b60778f3859b141053e5827decfff27ff106a48cfdb0371d0ef614fc7400e860b676df3176d1a", + "314dda800f2f494ca9c9678f178940d2284cb29c51cb01ca2019a9bede0cdc50f8ecf2a77e238b884867e78e691461a66100b38f374c4ccac80309641533a3217eca7e6b9a9af01c026201f0afaec5a61629a59eb530c3cb81934b0cb5b45eae", + "4658b7500951f75c84e4509d74047ca621009835c0152f03c9f96ca73beb29608c44390ba4473323e621284be872bdb72175628780113e470036265d11dfcb284ac04604e667f1e4c1d357a411d3100d4d9f84a14a6fabd1e3f4de0ac81af50179", + "491f877592837e7912f16b73ee1fb06f4633d854a5723e156978f48ec48fbd8b5e863c24d838ff95fa865155d07e5513df42c8bb7706f8e3806b705866475c0ac04bbe5aa4b91b7dc373e82153483b1b03304a1a791b058926c1becd069509cbf46e", + "231034720c719ab31f7c146a702a971f5943b70086b80a2a3eb928fa9380b7a1ad8773bfd0739142d2ad6e19819765ca54f92db5f16c1df5fa4b445c266215a92527bd4ef50ed277b9a21aee3fb7a8128c14ce084f53eac878a7a660b7c011eb1a33c5", + "3366860c77804fe0b4f368b02bb5b0d150821d957e3ba37842da9fc8d336e9d702c8446ecafbd19d79b868702f32405853bc17695873a7306e0ce4573cd9ac0b7fc7dd35534d7635198d152a1802f7d8d6a4bb07600fcdaacfaa1c3f40a09bc02e974c99", + "ccbbbe621f910a95835f5f8d74b21e13f8a4b03f72f91f37b5c7e995aa3cd5539508d5e234e77a4668a42c239b2d13ef0e55ecf85142055e3f8a7e46320e21324a6b88e6c823ac04b485125c2aa59b61476481208f92ea4dd330cb18777c1cf0df7cd07893", + "87faf0e49e7e5ab66ee3147921f8817867fe637d4ab694c33ee8009c759e7d707f44c69c1b9754e2b4f8f47b25f51cd01de7273f548f4952e8efc4d9044c6ea72d1d5857e0ffeb3f44b0c88cb67683401cfb2f1d17f0ca5696641bef28d7579f68d9d066d968", + "38c876a007ec727c92e2503990c4d9407cea2271026aee88cd7b16c4396f00cc4b760576adf2d683713a3f6063cc13ecd7e4f3b6148ad914ca89f34d1375aa4c8e2033f1315153189507bfd116b07fc4bc14f751bbbb0e752f621153ae8df4d68491a22430b309", + "87d636a33dbd9ad81ecd6f3569e418bf8a972f97c5644787b99c361195231a72455a121dd7b3254d6ff80101a0a1e2b1eb1ca4866bd23063fe007310c88c4a2ab3b49f14755cd0ee0e5ffa2fd0d2c0ea41d89e67a27a8f6c94b134ba8d361491b3c20bacac3d226b", + "b021af793badbb857f9a353e320450c44c1030fce3885e6b271bcc02e6af65fdc5be4dc483ff44bd5d539ed1e7eb7efe3001252e92a87df8227ace601047e101c871d29302b3cb6c6f4639078afc81c4c0f4c2e04688612ecf3f7be1d58ea92894a5dab49b949f2089", + "c5c1f2fbf2c8504a686b615278fc6221858d401b7fe790b75fb6bca6885cdd128e9142bf925471ee126f9e62d984de1c30c9c677eff5fdbd5eb0fa4ef3bff6a831056cea20fd61cf44d56ffc5bda0e8472ecdc67946d63c40db4ba882bc4dfa16d8ddac600570b9b6bf3", + "88f8cc0daeaeaea7ab0520a311dff91b1fd9a7a3ec778c333422c9f3eb0bc183acc80dfefb17a5ac5f95c490693c45666ec69234919b83244003191bad837aa2a237daeb427e07b9e7aa6ca94b1db03d54ee8f4fe8d0802cb14a6599005eb6326eefe5008d9098d40aa851", + "2eb6b1a58e7fe39ff915ac84c2f21a22432c4f0d260380a3f993310af048b11647f95d23adf8a746500833ee4e467fb52ea9f1039519fa58bcb0f1d0151558147b3c92b83730aba0e20eeeea2b75f3ff3ad79f2f8a46cbbadb114a52e32f018342aeeaf827e03ad6d583bbce", + "3ba7dcd16a98be1df6b904457709b906cbf8d39516ef107006c0bf363db79f91aaae033466624d30858e61c2c368599963e49f22446e4473aa0df06e9c734e183a941510d540536377072334910e9cef56bc66c12df310ecd4b9dc14207439c1da0ac08bdd9be9f2c840df207e", + "a34a7926324ea96867dac6f0dba51d753268e497b1c4f272918c7eb0e34120be65b7b5ba044d583141ec3ea16fcedae6197116b16562fb0706a89dc8efd3ba173ccd0fd7d84d480e0a3dda3b580c326aa1caca623879b0fb91e7d173998889da704eda6495023b5ad4c9ad406298", + "5ef97d80b90d5c716322d9ba645a0e1b7a403968258a7d43d310320f60f96235f50e9f22cac0ad239636521fa0607d2f471051b505b371d88778c46fe6787d47a91a5bec4e3900fe6ed22918226fc9fbb3f70ee733c369420612b76b5f55988d757c891d7005d17ee55783fe506202", + "140d2c08dae0553f6a49585fd5c217796279152b2e100ebde6812d6e5f6b862b2a3a484aed4d6226197e511be2d7f05f55a916e32534ddcb81bdcf499c3f44f526eb515cc3b6fa4c4039ad251253241f541558bba7413ca29318a414179048a054104e433c674ca2d4b3a4c181878727", + "29fdfc1e859b001ee104d107216b5299a792d26b2418e823e0381fa390380d654e4a0a0720ba5ff59b2ff22d8c4e013284f980911dcfec7f0dca2f89867f311ced1ac8a14d669ef1114504a5b7626f67b22ecd86469800f1575543b72ab1d4c5c10ee08f06159a4a3e1ae09937f12aa173", + "52dfb643832a598a10786a430fc484d6370a05356ee61c80a101dbbcfac75847fba78e27e537cc4eb918eb5ab40b968d0fb23506fee2ad37e12fb7534fb55a9e50902b69ceb78d51db449cbe2d1fc0a8c0022d8a82e2182b0a059035e5f6c4f4cc90278518e178becfbea814f317f9e7c051", + "d32f69c6a8ee00ca83b82eaf82e312fbb00d9b2f6202412a1ffc6890b4509bbbeda4c4a90e8f7bca37e7fd82bd23307e2342d27aa10039a83da55e84ce273822740510e4ec239d73c52b0cbc245ad523af961994f19db225212bf4cc160f68a84760233952a8e09f2c963be9bb1d71ca4bb265", + "d1e603a46aa49ee1a9ded63918f80feca5fc22fb45f659fd837ff79be5ad7faf0bbd9c4ba91628ee293b478a7e6a7bd433fa265c20e5941b9ea7edc906055ce9799cbb06d0b33ae7ed7f4b918cc082c3d4a1ac317a4acec175a73cc3eeb7cb97d96d24133a29c19375c57f3a4105519846dd14d4", + "b45ac88fac2e8d8f5a4a90930cd7523730733369af9e39bf1ffb833c01108952198301f4619f04b9c399fef04c214bad3358999967c474b67a7c06457a1d61f9466489ed5c0c64c6cdc83027386d6263491d18e81ae8d68ca4e396a71207adaaa60997d0dca867065e68852e6dba9669b62dc7672b", + "d5f2893edd67f8a4b5245a616039ffe459d50e3d103ad4675102028f2c497ea69bf52fa62cd9e84f30ae2ea40449302932bbb0a5e426a054f166fdbe92c744314cc0a0aa58bbc3a8739f7e099961219ec208a8d01c1ae8a2a2b06534bf822aaa00ca96218e430f0389c69c7f3fd195e128c38d484ff6", + "37279a76e79f33f8b52f29358841db9ec2e03cc86d09a335f5a35c0a31a1db3e9c4eb7b1d1b978332f47f8c3e5409d4e443e1d15342a316f442e3bfa151f6a0d216df2443d80cbcf12c101c51f2946d81161583218584640f4f9c10de3bb3f4772bd3a0f4a365f444777456b913592719818afb26472b6", + "a46d252a0addf504ad2541e7d992cbed58a22ea5679980fb0df072d37540a77dd0a1448bdb7f172da7da19d6e4180a29356ecb2a8b5199b59a24e7028bb4521f3281313d2c00da9e1d284972ab6527066e9d508d68094c6aa03537226ef19c28d47f91dddebfcc796ec4221642ddf9de5b80b3b90c22d9e7", + "060c18d8b57b5e6572dee194c69e265c2743a48d4185a802eaa8d4dbd4c66c9ff725c93667f1fb816418f18c5f9be55e38b7718a9250bc06284bd834c7bd6dfcd11a97c14779ac539629bcd6e15b5fca3466d14fe60d8671af0fb8b080218703bc1c21563b8f640fde0304a3f4aeb9ec0482f880b5be0daa74", + "8f2f42bc01acca20d36054ec81272da60580a9a5414697e0bdb4e44a4ab18b8e690c8056d32f6eaaf9ee08f3448f1f23b9844cf33fb4a93cba5e8157b00b2179d18b6aa7215ae4e9dc9ad52484ad4bfb3688fc80565ddb246dd6db8f0937e01b0d2f2e2a64ad87e03c2a4ad74af5ab97976379445b96404f1d71", + "ccb9e524051cca0578aa1cb437116a01c400338f371f9e57525214ad5143b9c3416897eae8e584ce79347297071f67041f921cbc381c2be0b310b8004d039c7cc08cb8ff30ef83c3db413f3fb9c799e31cd930f64da1592ec980cc19830b2a448594cb12a61fc7a229e9c59fe1d66179772865894afd068f0942e5", + "3eb5dc42172022ab7d0bc465a3c725b2d82ee8d9844b396913ceb8a885323dbbbf9ef4ed549724cc96d451ea1d1d44a8175a75f2a7d44bb8bfc2c2dffed00db0328cfde52bf9171f4025770abbe59b3aefd8151c480bafa09f613955fd571e5d8c0d4936c670d182cf119c068d420ded12af694d63cd5aef2f4f6f71", + "20ea77e58e41337ad63f149ed962a8210b6efa3747fe9bea317c4b48f9641f7145b7906ed020a7ae7d2ee59435392edc32aee7eff978a661375af723fbd440dd84e4a152f2e6ef66f4ab1046b22c77ac52717de721dfe39aa8ba8cd5da27baca00cc1fffe12c52382f0ee83ad1418f4c6a122effaf7471e1e125d7e7ba", + "95c662b835171fa23f948c3c3ed27bab9b3c367bbfe267fe65f8037a35b50cd7fc6030bfce4000425ef646c34793f0762635ae70487a0216ef7428da622be895d1b6040423246511c2370d6876a5c5d2df8bbd48fb14f787b632ad2c1f5a927fdf36bc493c1c8606accfa52de33258669f7d2d73c9c81119591c8ea2b0ef", + "f708a230675d83299cc43167a771602d52fa37cbc068ef9128ef60d186e5d98efb8c98798da619d2011bf4673214f4a4c82e4b11156f6292f6e676d5b84dc1b81e7cc811b0d37310ac58da1bfcb339f6ba689d80dd876b82d131e03f450c6c9f15c3a3b3d4db43c273c94ed1d1bd6d369c4d30256ff80ea626bda56a6b94ea", + "f8417766ce86b275f2b7fec49da832ab9bf9cb6fdfe1b916979ae5b69176d7e0293f8d34cb55cf2b4264a8d671370cb595c419c1a3ce5b8afa642208481333522005fbe48cdc700e47b29254b79f685e1e91e7e34121784f53bd6a7d9fb6369571bba992c54316a54e309bbc2d488e9f4233d51d72a0dd8845772377f2c0feb9", + "3479e04efa2318afc441931a7d0134abc2f04227239fa5a6ae40f25189da1f1f313732026631969d3761aea0c478528b129808955be429136eeff003779dd0b8757e3b802bdff0f5f957e19278eabad72764aa74d469231e935f4c80040462ab56094e4a69a82346b3aeb075e73a8e30318e46fdaec0a42f17ccf5b592fb800613", + "03df0e061fa2ae63b42f94a1ba387661760deaab3ec8ffabcaff20eeed8d0717d8d09a0eafd9bde04e97b9501ac0c6f4255331f787d16054873f0673a3b42ce23b75a3b38c1ebcc04306d086c57a79d6095d8ce78e082a66c9efca7c2650c1046c6e0bbce0b2cba27c3824333e50e046e2a7703d3328ab3b82c9d6a51bc99b9516ff", + "76b488b801932932beefffdd8c19cf5b4632306e69e37e6a837e9a20c8e073bcadd5640549faa4972ebd7ee55cb2425b74cb041a52dd401b1a531beb6dfb23c4cfe74bc84f034156c8f55050ca93236eb73c4e2595d9fbf93dc49e1ec9a31705359732dda73f737ec4274e5c82626dc4ec929e5e2c7a2f5f5fb666181922bd8be575e3", + "ff17f6ef13abc0426b03d309dc6e8eeb822300f7b87eff4f9c44140a424098fd2aef860e5646066d22f5e8ed1e82a459c9b9ad7b9d5978c29718e17bff4eeefd1a80ba48108b551e62cd8be919e29edea8fbd5a96dfc97d01058d226105cfcdec0fba5d70769039c77be10bd182bd67f431e4b48b3345f534f08a4beb49628515d3e0b67", + "95b9d7b5b88431445ec80df511d4d106db2da75a2ba201484f90699157e5954d31a19f34d8f11524c1dabd88b9c3adcdba0520b2bdc8485def670409d1cd3707ff5f3e9dffe1bca56a23f254bf24770e2e636755f215814c8e897a062fd84c9f3f3fd62d16c6672a2578db26f65851b2c9f50e0f42685733a12dd9828cee198eb7c835b066", + "010e2192db21f3d49f96ba542b9977588025d823fc941c1c02d982eae87fb58c200b70b88d41bbe8ab0b0e8d6e0f14f7da03fde25e10148887d698289d2f686fa1408501422e1250af6b63e8bb30aac23dcdec4bba9c517361dff6dff5e6c6d9adcf42e1606e451b0004de10d90f0aed30dd853a7143e9e3f9256a1e638793713013ebee79d5", + "02aaf6b569e8e5b703ff5f28ccb6b89bf879b7311ea7f1a25edd372db62de8e000219afc1ad67e7909cc2f7c714c6fc63ba341062cebf24780980899950afc35cef38086ee88991e3002ae17c07fd8a16a49a8a90fc5540be0956dff95390c3d37629949de99920d93096eb35cf0427f75a6561cf68326e129dbeffb8772bfdce245d320f922ae", + "70752b3f18713e2f533246a2a46e38a83cc36dfccec07c1030b5204cba4432700735a8cee538b078d281a2d0262110381c5815a112bb84404f55af91652bd17502dd75e4910e062943d8a736ae3eecdfdd8e3f83e0a5e2ddeeff0ccbdadaddc95391310fc657a59724f7e6560c37dc1d5bb5db40170190f04a274c864ade9687c0f6a2a48283177a", + "01f3c1333b44077c518cc594d0fb90c37651fb7b2442e71fc0a5611097f1cf7bcfaf11c8e0ac1b1cab54afba15bb9332df6bc64d8032368e3f686c8324b0114e0979dad78a5ccd3fff88bbe89eef89c4be586ca092addef552ed33224e85d8c2f4fba85ac7735f34b6aa5ae5299154f861a9fb83046b0e8fca4db32c1343e02676f283975f43c086cf", + "509283ebc99ff8d87902fa00e2d2a6fa239e335fb840dbd0fdbab6ed2d95e8275402523f7ce9a2fabd4b6c9b533288fbe914bde84365a204711d0977a7d698f4614385984dd4c137e4820035dd6737da364edff1bb62283e87a8c7ae8637314fe9b5777ec4ec21276dafedb2ad5ee1aa0ac99e34a6c01c055c8a239fd28681607f65143082cd4553c529", + "c17e417e876db4e123c631f7136b8a85bfd6ce66a69180d0cd5ecfd6f037bb1c7bd7908d51f2c485bf9e92c0e1799ee5f6ab834ee481f5eb1a8020205adb4d0f90126d4e7c2c859c5a5f644bdfa9c649ff4f168e834de6f9769429732099d46d0af506ab86c6fd92175159bbc05c75db8e1fa867e6030d64250008d64c857c47caec3dc8b2ffb384d0193e", + "950988fbe9d62a66f5f2c492bc8dc944a78eb3796ec37ba94b6a81a9d402ccad03cd8497fff74c5f4a03081c5fecec48574fecb21c1de261332c23108195d3f6a96ff8e433a1a30eda53dd5bb414973334f8cde5510ff759f7c17046cbb5acd8e8c4a6eecf2a9121ec3fc4b22c4daa72678194ce809024cd45c4ebb9ccdb6f854205cdb624f0787480d8034d", + "552a212c403b473741da8e9c7b916d5e5e9bcc9949021ae1ca1ed46b7d4a98addbb604d9fff56175b7e0367db26c9635fa7813653dc8d610befdd09ec41e99b192a716106f4299eec8b940863e5a59cf26cdc2cd0c3017f9b4f215812bed15f69e77edf672178e13c55580982f01fcc2fa131ec3d736a55d56504c545f4be50fee83f1263e4d3f3c877cc6242c", + "b00c4283dd3d9cd26e44bd97cede6c771cb14f2571b51cfdaae4309560ffd165da025a1bbd31096c3aa8286e2d6dcc3e681b8d01f2c5064ea26dfd0b5156b7a7f5d1e046c5bd1628f8fdae24b03bdf7cf7366900cc013a8cbed9d7f5937c914b08f8c27683b956e1279812d04288515333fc6aba3684dde2292951f0610649d90fe61606630fc6a4cd383649252c", + "f6e79457bb6d0884dd223be2cf5ae412a1ed425f1e4012f75951b096aea3b9f3581f9013bcae1aff2d3fc1e5c7e06f24af6d53c2c5c238b71c71cc670b05a7ee5204400026a5c4e5ddec3ad96771e49fae4b0f75ec58049ad9d972e5749a32d90f847f1ed2a1bab83db181e541cf5c8adb6b29ecc64dc25add491d408d3eb3ddcb013de7f5ffb6de9dd7ff300a5fc6", + "fe1d71e1d5efa3f712d23216ee8ee9139e66bd648b83efc02cdb4d45a28cf36759ff190a84d14d9471477abefb5aea4111110336143dd80cf81e02f268120cc07d746538f968e9876bff8358d390f5b8e7eafa61ecd236cedaf276bd61865fdd3424988201dcdeda2e3e0c33c9e3b3670125dd1049106cc6df5695fb2dca443233ff440f265bbff055483bac1e859b83", + "4c80163562872a965dedd8725652906156ada6e9d999027d96f49289edb92f9ef043e9d7c3377e091b27f85275499454af32317535997fb4aaeaf93565ad481ff7d45d2abddd4df4b60f71a6923ec30496c6ae534dc5427107ab4c5e656a322c7ab058d4c13ec0ebafa76576560697ac98f84aa4a554f98ec87134c0d7dca9184cf70412a324aac91823c0aca02537d197", + "fdd58c5ffe88665beb7073c8f4c22472f4bc9390cdd27a42622ca55978b000ab7579f795d4de0dfcaf521b8268980ef1d20277b07567985c0fd5030784ad6c32541ac24e99ab706105a2255fc32935c0fce6fdad9bb224d94ae4eae2a3ff08836618a3adf193630647bce1952b69da4de360f59da303519278bfd39b733cf66820a5e9e971b702f45998b69a0889f4bec8ec", + "ff38b15aba3794e2c81d88003e045ac6cbfc9f4833cdf896cefd8ac0c88674727ad9a9fcb9ef36574deea480e6f6e8691c8390ad73b8ea0eb3665c914b0d886546948e67d7987eea248b5feb52346ffdd965d5c835144c3bc63daf325e74b11267e32e58a914ae4521a668839d9445fececa49c5fba41f9e171698bbc7c6c97fa163a377a96456958d6e1d74f91ada56a30df8", + "f048c19328d60b4e59ed76940415b2c84c23883198bba5699efb0a1774ad5da6d15390c7b55d77d66f37448fe08107f42a5336408d5322f4b630e3275865fc66dccab39f6e13fabc133e5a441fe352d81c7cd9a25f145a6e2e2417d3b0bbc79eafcd7ad688c02011fd268dd44ac3f4f87b37a84a46fd9e9975962fba92c9a3486deb0c45f6a2e044df4bb79f0feeea432c5008b0", + "1b3e5fe6f113cce28a6f8d6f7809d3cec398cabffe9ff2ff10a7fec29a4ee4b54186063fd5307a2be393c9ecd75a37620bdb94c9c18da69b658579676ec90351d10dc33a7cb3b75798b1234f9f684d4a73a0fab2df3d5d6fdb1c1b1514d0935c1f2dd21486f91c2595b2f8f8a500ff443b9305270fb6f3da7961d9316d4ed6a135a31c4a3611d40e6585bbb34f498cd5b9a5d92676", + "740db337baa12b16897f17a85fa5685acc85e48338867f8ac9c0198dd650f5dfa7c17725c1262c72207e365c8aa45ffaab6470a0e5afefbfc3bb702a9766064f28cc8b796878dfdd3ca9d0216c14941438fc541fb5be0a13d29a996c5c985db4f630df067a5626db5dcd8df3a2bff17dc446e46e4079b8815da4318cb228c7722684e2a795a0ca56f500ea51951a6a385385d886f678", + "1465f2d578d167faa017fe8f763ce3cc8dc1e8371d774ed2a8803f12585296ee71a1f2253dd16b717a81f91f0f3641018a0111182b4e65d884b0a3d0292631ad807cdccc88bdeecb476e76f72b5246a630aff6e2401fa9570f85acb73ccb4e19ef04a932a03d7b7985dbe1e5bb410df517fe362321469e6f8b0e0cef6c31d7aa8ec06aa220620d66cc0e133fdee963589b12320fc9678e", + "80c051952fa6f3ef6af0f1759ec3e83c8eb91abee1de360bfa09e74b05af2475a0dbf8f9135aa25892919bbe0515898cfb6f88abc9e1891f2b2180bb97370f578973d55c13c35edb22ed80647c2a7e2884d1ccb2dc2f92d7b6ec5843ade13a608a31190ce965bde97161c4d4af1d91ca9962053f9aa51865bdf04fc23fa35a6fc3c8e888941263a26ed66c2dd0b29b2325dfbd1227c5091c", + "9c1e2a1aed6406052eed12b4495365f2f80e9c9645473f3549b607f20910bcd16dc3a4b173ac8d128129cdb7c76ebbc8e9a2a1ba0d822c66b367e790a69ac71f0a60ed4bff0e979148e3f3ee6607c76dbc572ee5ff17c27e4b52adebb4bedddff517f591a1977299c7cb01106f1453b098d29848ba3751c816215bb0d090c50f9e445b41b2c49d4eec83b92ce6c269ce835fd279e7cbbb5e47", + "466abda8944d0329d2975c0f2e2afc901f117887af301881f63b714f49a2f692fa63a8871fc0b301fe8573dc9b2689880cd8969e5072c57671e0633b041481dab25e65c9de404af033a11a8070c8ab70ca6d465318501afdd9940c7efbe1bb6d49581c222fad251dba4ee0a98efe22a3c4f74da05844523b30bbad6b080ac8df70a02da80bc9d477dfb869adb211e209a316d5dd1fd89a6b8f8e", + "0e89a873e07799ba9372fc95d483193bd91a1ee6cc186374b51c8e4d1f40dd3d30e08f7feecfffbea5395d480ee588a294b96304b04f1ee7bbf6200cc8876395d1db3ac813e1019bb68d27204e514fe4a61ad2cbd1782dca0e38b5538c5390bca626c5895b745cfca5dac636fd4f37fed9014ab46ae1156c7789bbcbb956ff7ee5ce9effa560731d26783dc6ae8bddd53a5d28133614d0ddeddd9c", + "fdde2b80bc7a577ef0a6c03e59512bd5b62c265d860b75416ef0ce374d544cbb4e3a5dbd31e3b43e82975090c28bc77d1bdec907aeceb5d1c8b71375b6d631b84a46153f5f1d195bfcb2af6f597a9cdc83782c5bbbb58c5188a87ebf375eee5212fa52523820a83106e8ecd52bedd60d95cd646159774389c07e1adcaa6b6f649408f33399ec6e507d61659696b3dd249996892d5986b654d94ff337", + "f5d7d66929afcdff04de30e83f248e69e89604daea782e1d82d8032e91a95c1d6fb2f5578f79b51be4397e4cd7cbc608ce143fdddbc6fb6c43ffdd394a7df0124353b919aeeac025f3eb11ff246c3b9657c1a947fc534ce48e18feffada8797037c6bc7e2d9a9e2e019fe65627b3feb28e446473e3bd413047a2587f0be6a103403cb3c33fdc212dca14d8e386aa511c22308e632f5f9528dbabaf2deb", + "332990a8dba55f977bc814436cf386ebbf10cb487a5f6ce83e13741bac670c6810284fbbe4e303547ef411e964fae82854e8c13cf56979b89ecfedd337aad78260060122d13dfbbf8497acb2066ed89e30a1d5c11008bd4d145b5ec353956310536304d8b8bba0793baec6d8f3ff49718a56e6694f8122078265cf5731d9ba61292c1219a1affb3679576d4998290aba3684a205c3469d40761a5c4e96b2", + "efbdff285027610f03182009c89b953f19721cfcdb8accd74bab6ec4bdf3f555ab902cb0dd91284269d140638aaabd211748aa4da3b18cddc653b57e461b9ad8491807c535c08fe97d89eb587c6af19ca152e72479626ab764e8b62da89fefc8354c75a44851f985746d78715a5a92798dac1a4222be27897b3f0aa63d596aa7378545f49b259aa8518c3def8a2ec8f7aa956c43668c8717052035a7c36b47", + "0eea9bb83bdc324fd21b03669aa922fbebc448e7d25e210294c07862cfa6e061731dfb67b4810633f4dbe2130d90fa1c65843af436e74219d213c4458dcac1c48ec4541fc6e3b7918ab2bc621aedda53658050900c3865ca57cd5dfa1d28576827401956d2dd8b861fa90ab11bb0b544ded9bd3d62e3278ed484e17db8f2d5dc5ea4d19a0e15134ba6986714c2b22c59c2f0e517b74eb92ce40d2f5b89e6d79f", + "25da9f90d2d3f81b420ea5b03be69df8ccf05f91cc46d9ace62c7f56ead9de4af576fbeee747b906aad69e59104523fe03e1a0a4d5d902352df18d18dc8225855c46fefeec9bd09c508c916995ed4161ee633f6e6291cb16e8cac7edcce213417d34a2c1edea84a0e613278b1e853e25fb4d66ff4c7ee4584e7f9b681c319c874d43502534e8c16a57b1ae7cc0723783807738a55b661e617ee285bdb8b845607f", + "a76b6f81372df09322098868d469fb3fb9beafc5edb32c674974ca7032966aaca5b5c9bffef87bfe626bd8e33d1c5f054f7d5acd3b91ff95324d1ae39eb905b9f2694fe5cb03486cee86d2f661a751b0e6c716a61d1d405494c2d4e32bf803803dc02dba2c06eecf6f97fb1f6c5fd10cfc4215c06d627c46b6a16da0854e4c7c873d50aa1bd396b35961b5fa31ac962575230c07c369f8fbc1ff2256b47383a3df2a", + "f9db613812f2259972d91b1598ffb166031b339913925ee385f03b3b35dc4b2f1ae78a3c3d99c6ff6a07be129ce1f4b8d994d24988d7fbd31f20535d36ab6bd0592cfb4f8c1ed9244c7fa8a3c46e91272a1a40c6cfcf261c5658476c59793bf1a3775086e41a0492f88a31e2d9d1ce75cf1c6b4b928b3545d838d1de6b61b735d921bcf72e4e0615e9ff969ef76b4b947026cb016e2660ba39b0c4c953369a52c210de", + "e601c7e75f80b10a2d15b06c521618ddc1836fe9b024458385c53cbfcedd79f3b4239598cd7b9f72c42dec0b29dda9d4fa842173558ed16c2c0969f7117157317b57266990855b9acbf510e76310ebe4b96c0de47d7f6b00bb88d06fad2c2f01610b9a686079f3ed84613ba477922502bc2305681cd8dd465e70e357534503b7cbc68070ad16d9c51de96ccf0aae1599299331c5655b801fd1dd48dddf6902d0e9579f0c", + "ee5ff4ca16d1bde59ffaf2d064eac9141c1d8f120ea2bda942b7956ba3effc5f1e725a3b40b0b9223a14d7a50df1681d14ca0e0eda7bb09c428fa3b2701f83a7a3e139485a118f6287d266dbc7fe68c87b35becabc7782537c79cb8165bdc40cc103d7b6d4b627fafa0e4113f92341ab90ceab594bfae20dadbfafd401684584598941f1ffb8e23dc8a04ecd15376cda6d849fe0dfd177538c62413622d172d9d46e05c450", + "1daca80db6ed9cb162ae24aae07c02f4126f07cd09ecee8e798fa1bc25c26c644333b63731b4ebc3f287f2318a820c32a3a55fc976576bc936f7384e2553d2891e3771ff24dd4c7f0256906460a8f12d30ed2b23583a0259cb00a9065a757d654d6e4603e7c7eb4a8426b527ae8a849d9350e9094b890367df3e8b23ad2df4d7dcce416bd8ea3badd037f53f7b07c02e5926515f196d62aeb9b8b14c863f067fc12c5dfc90db", + "27ff4e58a34ff1fcd66855d014ea17889a3cf0021a9fea3fabfd5b270ae770f40b5439e00c0d26bd9766f6fb0b4f23c5fcc195edf6d04bf708e5b0bced4f5c256e5ae47cc5651e51cd9fe9dc5d101439b9bc5cc24f76a8e8847c72686e2af1ce7098ad7bc104dad00c096a6d48b6453322e9cd6773fb91fb1eabd05dc5185a9aea07a2f64c6fea9897681b4428aaffe1fe5fd3e8ceb890b12169ec9d51eaabf0ca3d5ba415770d", + "75e2fb56327983b04f640717be8cba6fef3655b4d8e5539587d6478356ec397efaed818b8425d052778eb30ef0dee656c52c2aeab079ed496ae4441a365f2130432c87ba757e25b4511656ad15e2eff84d342331fd2814d1f1d11af65d98a424c115ba183437c0d0aa55f5c44b8685028a47d89d0d36a0f20aed510c366ab338f074a941b404fb349caaec821e0850a627777cc8f5abce6b509290027a2a28ff1db62a5ed2f95fc6", + "c6ae8b6a060917cd498aa7874ad44baff73efc89a023d9f3e9d12c03d0b7f5bcb5e24e1bc2ab2f2c67b9a9d36ff8beb51b5affd4a3510361001c80642955b22ea4bf28b81a5affe5ecdbabd8d17960a6af3825a4522fe76b3d720b5d06e66bff5379d7a8de1f5cc3e7bb75163a854d77d9b3949bf904b6c4e568682f0dab7f217f80da7303cfdc9a53c17b6b51d8ddff0ce49541e0c7d7b2eed82a9d6be4aec73274c30895f5f0f5fa", + "606c9a15a89cd66a00f26122e33ab0a08c4f73f073d843e0f6a4c1618271cfd64e52a055327deaaea8841bdd5b778ebbbd46fbc5f43362326208fdb0d0f93153c57072e2e84cecfe3b45accae7cf9dd1b3eaf9d8250d8174b3dade2256ecc8c3acc77f79d1bf9795a53c46c0f04196d8b492608a9f2a0f0b80294e2abe012dc01e60af94323c467f44c536bf375cddbb068c78432843703dd00544f4fff3eaa1a5a1467afaae7815f80d", + "88b383cb266937c4259fc65b9005a8c190ee6cc4b7d3575900e6f3f091d0a2cefa26e601259ffb3fd03083270eb63db1ffb8b4515ec454d12f0944f8f9f6869eedc2c5f1689766a748d74e79ad83ff6a1639aefdec6109342dead31e9cead50bcc00c5b2206e8aaa47fdd01397b141880490174141a1e6e19268378c1b54a84aba60ca711fd72f7df88e120dfea2caa140085a0cf73342f3c588b7edfb5b5e5ccabd68a32364746d92d536", + "dc0b293f1ba02a326743509f41efdfeeac1efc45137ac03e397a3273a1f586a0190cfb4ea96d6c13ca692a4de6de905c8338c3e29a04cbae76272f568b9d795cea5d758106b9d9cff6f80ef650d6b7c428ea3946c3acc594907fe4227ed68faf31f2f6775f1be5139dc0b4d73ed6308fa226b9077561c9e4c7a4df68cc6b819b0f463a11b9a09682ba99752c4db7aea9beac1d9279f2c2675d42b551d27aa2c1c34125e32f2f6f45c35bca45", + "5d801a7413311e1d1b19b3c321542b22e2a4ccbe340545d272abede9223741d9835a0fc80cc9da97a13f8bb4110eb4ad71093efba165b1edad0da01da89d86726e0d8e42ae003b4b50297d233c87da08406f0e7fc58ba6da5ee5ba3d2d7142cbe6632734eb2e7b7863c15cc82198ee8f9a0ae0b7f93bdbda1ed269b3824d5d3c8e78513815b17a4c0cc8c9706b9c77423a309ae3fd98e1e05cdbe9e2577834fd71f964301b10b66c316a2d8f2c", + "2fd32a2bc15a9e96a100624404fd0a4e54ba9f8c0543d8ccf7c5c2e35f5e8c3c11dfd497320aa903900a4ca55a2b323b3ac4a7cfcd01bf0b448db8829072bee6b77c3d7bec2e1d8b414d907288d4a804d2379546ef2e2dc628269589164b13fceb32dba6fd5d48a956ce0b5c3eb28d894a95af58bf52f0d6d6cbe51317152744b4ccfc918ed17fa6856478d580b389016b772e1d02e57d2217a204e25361d91d4845a3fa20fefe2c5004f1f89ff7", + "f537b437662759bef8bd64368536b9c64fffbddc5e2cbdad465c3966b7f2c4bc5b96767ef40a1c144a4f1cd49edc4cc5b57e7eb30d9b90108f6fd3c0dc8a8808b9e0bd13aa3d661c4863637c5e4ba286553694a60bef18801299ae349df53a355051dcc46a7d003c4aa613808f430e9db8ca7dfe0b3f0a4c5ab6eb306aeb53e11a01f910064fbe6ca78b2a94fac34a2602f73de3f275953e13ff5c6bb5c39b82321ead17ec0f8ecc479e6afbc926e1", + "1dd9fb7d5b5d5074971e69300720014deba6fbdb942bd29704cdfcd40fa5281d2a1b9f5b776183e03ff99c29587f10e8d325cb49c5c93e94f5132741b92c4086eec1374dea5c1e772cbb230c7b31f3e962eb572be810076bdb926b63732522cdf815c3ab99bbc164a1036aab103cac7b823dd21a911aec9bc794028f07b7f839bae0e68211286441f1c8d3a35b281fd321312577bbda04f643ecb2a74ec4527bb5148dbccbeba749f5ea19b6072366ba", + "5bd63737449de2d20ca63943953338ecf4cdd6cd0a726241adb04376385a809cc6ba0f3482a310746fbc2cd5eb214f03a14cdc548777fb0d048d659cd75a962e490c4fe47affc2430a34b10275e4c76752a115aae3a24d4fb4fad89ce4d79d65de10292f3490bfdaeabfae08ed51bda6ec8230e66cb07ddbeec26e3ef68dd71c852900659fcf0c963f4574ffe4626a33db9abf0873dde68b21138498b81e8cc44d354be4073615889a7ddff633b5447d38", + "a683ec8250506571f9c640fb1837e1ebb06f123e745f95e521e4ea7a0b2b08a514bbe5bdfd316903d1d6a05f5a143d94dab61d8a3a146ab40b2d6b72df2f0e945875a8aa7051ed115975f6f1567cfcbf04c5e11e3a7027b8e179ba00739181ba10b028e3df7259d0712f4a6cef96469ff737865b85fee2c2db02a6423e32505381e18a1e0b4ce3c7998b8d6b1b5e09c3a280b85486d0984c9e193b0ad2043c2bc4ad04f5b00a73956715937eebf6b3e27afc", + "4df9d160b8e81c42930c48956fcb46b20b6656ee30e5a51dd6317876dc33e0160d31280fc185e58479f994991d575a917073b4439919c9ac49b6a7c3f985211d084c82c9d5c5b9a2d29c5699a22e79de3958d7b0e856b9aa97493cd4563aaa04fa3977a9bb89e0bc06a82296bdc76d20c8d393770176d648712454305fdfcf4e117d05acb5a5b006a9f8d0dc66dca708c4e4103ca825d2331750685c44ce3d9b3e753455580f4d6ac4533edeeb02cebec7cc84", + "67bb59c3ef5ee8bc79b89a673e331e581215076cc36b68f517ca0a74f74efafe9dcc240e6d8ca4b21019c27d6c9289f4419b4f218eeb39eb741c5ebebfe0ed2f6faeec5e8c477acf71907990e8e288f4d4049111779b0635c7bbec16b76493f1c22f645745fdac2b383679fee573e4f47af45ee08d84f63a5ace4ee1c06fa41e2e6e14b7bc392e38426813087a3a461efc62ed1941dc8f1728a2bdc04fde72a0b786558783c84abd4bd100e4926979a0a5e707b1", + "d341147169d2937ff2373bd0a9aefa77968ec8f0d993c6f9881eb174a1911e05cdc45993cb86d149a754bbe321ae38363f9518c50dd3faf087ffeeeb6a058b226ccab7858c00ba6de0e8f4d034b1d27508da5cc473f3a413189ee6fd912d7750486912944d4dc34405ce5ccc3885fb0aabcb922bcfa9081d0ab84c288022bd501235a835eb2e1124ed1d48fd4f8682da8e7919321031326502273375625c4e3a7282b9f53452195e53c6b4b57cd5c66f621bed1814", + "27e7872a54dfff359ea7f0fca256983f7600236e716e111be15a1fe72eb66923ea60038ca2953b0286447dfe4fe853ca13c4d1ddc7a578f1fc5fc8598b05809ad0c64a4363c0228f8d15e28280837a16a5c4dadab681e28968ae17934639fbc124bc59212138e494eecad48f6546c38366f1b7b2a0f56f579f41fb3aef75dc5a0958b25deaa50cb7fd1c69816aa9a51874a98e57911a33daf773c6e6166cecfeec7a0cf54df01ab4b931984f54424e92e08cd92d5e43", + "13dcc9c2783b3fbf6711d02505b924e72ec6736131159017b966dda90986b97522bf52fd15fc0560ecb91e2175322334aaaa0097e1f3777c0be6d5d3de18ed6fa3444133486068a777443a8d0fa212ca46994944555c87ad1fb3a367db711c7ebd8f7a7a6dbb3a0207de85851d1b0ad2f4149bdd5a5ba0e1a81ff742df95edee850c0de20e90dd01753137cb8f2c64e5e4638ceb893a3879ae2c049aa5bce44d56bf3f325b6c5029b2b8e1b2da8de7d4e48ca7d8f6fbdc", + "9ca875115b109eab538d4ec7023600ad953cacdb49b5abe263e68b48eafac89a15e803e838d048d9625972f271cc8f36344bed7bab69abf0bf05979a4cfff273b82f9961626509765fcb4b4e7fa48212bcb3ab2b1f2dd5e2af768cba6300a813514dd13e4d269e3d36548af0cacdb18bb2439ec9459f6d847d39f5598304ec46a26d75de1f9f0c2a88db915bd26e45e1f1e68c5b5b50d1890e97a3803c36755f026863d14176b8b57f42e91d3ff37787f9b38e333e9f0433", + "ec006ac11e6d62b6d9b32ebe2e18c002353a9ffd5dfbc5161ab887770ddd9b8c0e19e5321e5bc105add22e473050b71f0399327c7eba1ef809f8667c1f4e2c7172e10e753705e9a083f5bce88d77521225ecd9e89f1e1caed367fb0275dc28f620fbd67e6b176c9ae5d2659e6ec662116c9f2bbca3a93043233a4861e0688db6dc1800f752c5d58aa5033c250c891d9126e534ed921a9026eb333333fa8292059b8b446f336ca6a0cb4c7946b6aea3831653122f154a4ea1d7", + "23deadc94481ce28188f3a0ca3e85431964cb31b60fabf381e6bd45ef0332bd4dde774b0281d317dc2e7d0c298fcf8625fa734126968df8b68ef8a35c325d84ba4fc53936ff3ffdd8838d2a8cabf8a9cac54aa444ed9875944e55994a22f7fa8538b1e983b57d9215fac5c0052029644044e790ce2f5044655608c1d7ad3bb862203ba3aba3b526606f273d342ed5721648e3f600942d3f7546f679161436389d879dd8094e1bd1b1e12cde15cd3cda4c30a40835665e4e5cf94", + "94701e06340114f9cf715a1fb659988d33db59e87bc4844b1500448960af757b5282f6d52967a6ae11aa4ecfc6818c962b084c811a57724f5d401191567f24ce917e4f8c3963474fdc9d2c8613c16f62446448b6da6eeae54d672825ed7606a90e4611d0e318ff00566862c955b636b5e81fec3362e8672ad2a6d222a515cf410482836deba092a51a4d464dfbbab35c50a33437ac16a88256e9e23ddd3c827cc58d3e5000ee90b12e4c5175c5733662d4848ae0d406c2f0a4f498", + "735b0758d5a331b2304f01081172eb95ae4115de651b1a6693c5b9543de33df25d9f421dbaeca033fc8bff57313b482778005aa9fdcbca65c643da2f3320e34197868eec3848ff3c70d7ac7d910fc332e9a359f892ae01641be253013b554a0d3f249b3586b1857e5a0f9482ebd91432a852b221f4287a6e81ed24e8064645d5b28ab9a13b26cc1420ce73dbc47b31acf8a871601022ce23bc443b1222ce9a037a2fe5226295feb4efd4fd671338f459ae146032697cf82fc55c8fbf", + "c48d94f14549352790079fee69e3e72ebaa380510e3581a0824066413e7044a36ad08affbf9b52b21963d2f8e092ff0ac1c973c423ade3ece5d3bca852b894675e8173290529226939c24109f50b8b0d5c9f762ff10388833d99bea99c5ef3ebb2a9d19d2231e67ca6c9056d8834730605897426cd069cbeb6a46b9f5332be73ab45c03fcc35c2d91f22bf3861b2b2549f9ec8798aeff83ceaf707325c77e7389b388de8dab7c7c63a4110ec156c5145e42203c4a8e3d071a7cb83b4cd", + "553e9e0de274167ecdd7b5fc85f9c0e665be7c22c93ddc6ec840ce171cf5d1d1a476743eb7ea0c9492eac5a4c9837c62a91dd1a6ea9e6fff1f1470b22cc62359474a6ba0b0334b2739528454470f4e14b9c4eeb6fd2cdd7e7c6f97668eebd1000bef4388015630a8332de7b17c2004060ecb11e58029b3f9575040a5dd4e294e7c78e4fc99e4390c56534a4e933d9a45460f62ffaaba25da293f7765cd7a4ce78c28a85013b893a0099c1c128b01ee66a76f051dc1409bf4176e5afec90e", + "dea8f97c66a3e375d0a3412105ed4f0784f3973ec8c57b4f553d3da40fd4cfd39761de563ec96a9178804641f7ebbee48caf9dec17a14bc8246618b22e683c0090259e3db19dc5b6175710df80cdc735a92a990a3cfb166461ae713adda7d9fa3c4cf9f409b1467f3cf85d2141ef3f119d1c53f23c0380b1ebd728d7e932c535965bca41a414b6ea5bf0f9a381e098d282a554a25ce41980d7c7be75ff5ce4b1e54cc61e683f1dd817b8e2c1a430d7f895e5e7af13912cc110f0bbb95372fb", + "9dfda2e2f732867e60ed2b5fa99ab88eb82dc7a54334d02031258beef75fa4bd6962a1083b9c29e4eeb3e5ab8065f3e2fc732675b8d7705c16cfb4ef7305eb58120f1af5ddc55872a2cbde3a48661a0598f48f63e2e9aadc603545e2b6001748e3af9e86e1830af7b84ffd3e8f16679213d37cac91f07af0af02b37f5ed946ef5c955b60d488acc6ae736b10459ca7dabeacd7dabcfd656511ac913174f6d99327be59befe3e463a49afbb5235f0ce2840588c6edfbaaba00a4211c0764dd638", + "ddcd23e8b9dc8889b8599c721e7f8ecc2cbdca03e5a8fd5105f7f2941daec4e2906c654210bdd478374ddee43ee749a920ee91872e057a1157d384dcd111266221b3c79774476b4862fe450704ff2c5353e9a936cac87c96515c28ed4c830335a55d084cb5873c5fd2dd907f3266d8eb7bf13b6dd7cd4966982a0949efd8e428dae13daee549e01cc3c226211d6307823f742c5ef2155601a4644c46eddd603d4abd959c6d242e427768df3b1e22d87971df58a1564b38311a897c85b497a72556", + "39016647acfbc63fe55a74598bc1956eaf4e0cb49d532c5d8323fc6a3f15a0231597f06eafd74ad245e672bf6b21e4da503cb5bf9d15e9038ef354b38807564d91f38b4258378ccd9b9420a1562d7136196822a1291c913d83c4cd99fd8d420990c72cdc47607124de21da8d9c7f472fdcc780379f186a04da93cd87628abf323c8dadcd7fb8fbade37d7d2b5c9f9fc524ff77494c98f42f2158a6f68c906105ca9e8bb2df463863cfc1e9008d8344f55c4e3203dde6699b59812d49ce1279fa1c86", + "02cff7567067cbca5911664c6bd7daaf484181edd2a771d0b64566c3ab08d382e83932cdd7b4dbf86c9cdd1a4c353a511e68afb6746a507a9cd385c198246f4543d606c6149a5384e4ff54c1b90d663dc7a4b91aeac3cf716db7ca6f9a1914e3a33efe82e7ccc4215999c0b012782402db4726db1d7d1c73571d45739aa6fcb5a20eeb54a84d5f99902a8d356cbf95f34c9c28c8f2badfbc08c69233514493c0c04963268c88bc54039ab2999c7b06cba405936dfc43b48cb53f62e18e7ff8ff3f6eb9", + "5764812ae6ab9491d8d295a0299228ec7146148ff373241a510faee7db7080706a8dada87938bf726c754e416c8c63c0ac617266a0a4863c2582412bf0f53b827e9a3465949a03dc2db3cb10b8c75e45cb9bf65410a0f6e6410b7f71f3a7e229e647cbbd5a54904bb96f8358adea1aaa0e845ac2838f6dd16936baa15a7c755af8029ef50aed3066d375d3265eaaa38822d11b173f4a1de39461d17d1629c8df7334d8da1b6401daaf7f34b2b48d6556ae99cd29ed1073926bcda867421832a4c36c7095", + "4df3043cf0f90462b37d9106e67366d112e4938c4f06abae97869531af89e9feebce0812dffe71a226de5dc36be652e26ef6a4be47d9b2db5cdd43809a565e4fc0988bfe82037c505dd276b757b785203249fd083fb474a25acccc9f38dc5164ff9097e05989aa6e280739a755231f93670e7226e22046914c155bf33d135b3f736ccca84cc47ae643215a054b54b7e13ffcd7ad73cced9279dc3210b80700fcc757acfb64c68e0bc4da05aac2b6a99d5582e79b303c88a7ac4dd8ed4289516bba0e243527", + "bf041a11622715426c3a755c637d5f478dd7da949e50f05377bf333f1c62c671ebdbf9467d37b780c25f7af9d453fc67fafb2f065a3f9f15d4c3561eeaa73fa6c813bf96dcf02430a2e6b65da8d174d2558110dc1208bdcb7898e2670894c0b9e2c894da3b130f57a90ec8ea1bffd27a37b4da4645c546b2b141db4e2c919154dac00e78dd3eb6e4445974e3bb07905982da35e4069ee8f8c5acd0efcfa5c981b4fd5d42da83c633e3e35ebdc959bd14c8bacb52212b4334f94aa64d2ee183861db35d2d8a94", + "a170ceda0613adc9c3a1e427f07beacf3b16ed69fb42b6bc09a38d803f632ad2929dba215b85683b74e2feb1d18fe17d0ea0db84d1be4e2e73476917a2a4cff51d6eca7c5e82232afde00dd2286a4c20eb09800b4d5d80e7ea35b6965b9792d99e399abda8cf32174ae2b7414b9bdb9d63e148f7357635a7310b130c939593cd3479164724011966c4232142df9966f09422f34f20b30af4b640a2c6d3dd985fe0ba3dfa9083cbb9b8dfe540ff9f6c608d18481213040768ef33300d773f9890c724ead320a1e7", + "929477e9c2d0bbad3429a0e0de776695255013108261dc6404cb09828770e274d8bb650a50e490dfe917fc2047b0f8ee72e105927d9fa70523c727778cbf6ae876d641ad562938c870d12f2e047bb78920739dba0c3f8ce1fb77589623a5f1625f5d6ab81940c7dfc3dc3a641d82b2813629bab8282999317d6b93842334f123fb4693a9c2c9d8ba9bfc746642dfbd045cd2021b272eab7358aa954d453da53fc5392dfa7eb881f6f53809b692d27f3366595ff403289efcc691e118b4744a1147071d8909bef1e8", + "3e98bb14fff5bdf7db38a3960dc55ca7d02333daed8712cca13dd5bffd114636559279db72554cc0a0ee1f7e15557d77cab0f2f1131f94fe698db81be38300a856a5eca85e5cf915fb7b6f38ccd2f27350e62cc30ce10ffe835118be3d435d2342ed3d06199b7e20c8e34d68902f0ab8745bd8b7d5b863d525c1f5906d2dca598db8a0f1e67736182cac15677579c58b8c670cae1be3e3c882153b2aa2988933e579ec2d6dbb00c671da64443dfc027dee6dfc3233c99758304570a982bf9b2eb59ccd70d0b54c4b54", + "aa12c7fa50ffdc2811c1872e4bee15f43e6909212385c872eb489f7e06dc1787043f56126f8373bdfa4b3f61405c73dd4dfd3f40aa5cd207e8520849c26f67716a46c0989a99efff42f24e0736e327af8e607c401a1bac77341e9a78c91e35d55b2457bdd5317a405a1fcf7a2a23de68ef92b65819e8aa3807c545361dfc9fe89125123492da958dc313cb5d03cb4b192c54ac6b27fcbc498652f5ed36b587bb74942b3ad453a8d79e5ddc06ebf806dad5046b73251064582ef5777dc530f8701701761884783fdf197f", + "83e615cf6e17a29e63945710b548a6d9935850eec69830841e26cb6071e908bf72c87cf079ffb34c5eb1a390def72d004a9488224a18e189aa1092a0f1135712834d257a53dc1d0e2c6417d8f472ff13b181910f4c93a307420d44beec8875d5219a3160b8e921434ddf3f71d68db1c1d5c39d68edb7a604792f8b4e31ecda7895c99fc7031a5b98a22009c1da005ac8fd2da0b5d742743f5712d12fd76d11a18e487776ce21ca0d6e5ab9ca6d8c394c321b91c14e291399a642721361811a73b7392e8603a3004e7060bf", + "ae1a8f7bfe4b1a0fa94708921dadb2c20b938239d7b9a2c7c598528f20f49764d322ebe85a5b2ea15563cf2f2304baf55d6607c52e2e1160859dcb7af6d7856899eada0e9128a180d3de6fed9334ba52b80c5c362d5591a0ec30f86d37a399927eb1c53076a12d26775522c511c83eb5b7abc2a00bd2dfd5627a8febba53d85f9b74c4b7f0c862ddb0d9298899b646b774d6cc23e4e23ab47174fccd34499253996d5e0917210e2f6daa1685f89f2f1fdfd5509ebc38191d539ecfb54ff0f5bbe6ef36ea35d425af6462f518", + "1d033e06be253ab800c8176d3a9650ab2a5bcaa03e11ea95fb9ab3834b41eb0d1b2bcecfe219364c3104ef65a8d692bd77c798548b7d9a8faf7f5172db24ec7c93006d6e9839368291b8277a82c034a3731f1b2e298d6e0282ec8a7902e4f844d132f1d261d171375c646065e201849f2df73e3748d853a3122c2206aac92fea448500c5418ecfb3d80e0e6c0d51f85831ce74f6c659cc291f5348a1ef8b949f1b2a753633e382f40c1bd1b2f44748ea61127b6f568255ae25e1da9f52c8c53cd62cd482788ae430388a92694c", + "104bc838b16a641749dcf73c57b207ea3bcc84381170e4ca362065a3d492e892b426a1f4fd82f69461d1ce1f3aaf8fc291ea30d6667e7e1aea4c44f7d52a5fa6d34709e6658483260ff5da76bfb74e7d194ad40dcac00daf0e45e74db4bc2248100a8b256b257278c3c98f1f2e3a80cdb812352aaf4155b3a4033999fb9fe7f506994fcf3a8db31e9e5ca8ef8c2e9c6326ca5b0803724ba641950eca877fe6ed6afc2e014651c56d0e6a61eaff7c5ed0b861d4bebe42904c0a568c26aa8abb2e97da2bfb40f14eafb6bf16cd208f", + "5b92e4a175437d0a53eb10de2c56401720b11715a034459ebf506c3fd6534b5e817a0f09deac4bcfd353301d8d031b1331582ac09189b48e6ccea444655866c4bbd123d45ebabb774f877cf12d33b84cfca4a6a94f3f98869fcf2bbb6cc1b964c2438c2f348bcdf9001dce60a4706d20c169a040baa61cbeb0b8e58d505e6e3739ab03e110ae7efdf91347474033defbd1e86af322ec6456d3394699ca7ca6a29a70d9b10a38fe666eab2858bfe12dacb31568549c826c15af5b6fddf779954351be1872f04e53db7b3b5fbf61fd18", + "401cc7bd9f8227efaed70dad83fc8db3bd38efc166f0f11ab142c565c68ba9db680423a3d698b6f3476ef440051fd20b93f6a2ed045825567df5a65e3f62e4442ec396ad260a16a13a1dee46c7e8d88bdd7edf223ab76a9a787c1f4fe9925c051a4ca0e77a0e78baa29f36d193c862fd3a60653f544ea9e3f75f2f553891be8c1fb882f6a6aad118f576f3c2793efc67221b37a45ab6137434f6228cb002fc137b91fb8572c757f00736879453d64a8a868c131810ffdad9e9d028d132157ecb1da675d54047d19b27d3258c9b1bca0a", + "c20cf0354982ca6a19d9a4dbf78f810934db2373941a12c263adefa61a5f385c859bc47028829c531dc25ccc0004c7510e707175a102ec3c4b4c933e3f52033e67476ff5f864c446c042a21e6037f7798363d20267891b965879fde80af6b59d77862e3a229af01b7ac78b578e94bd9f9b073c38a627c1864df0083aabb17024bdab6c3c0f0f73d31d59480523a2f23b78baa0385c15f290114305d7f98786b7dbc17a8c2aad97448e8ea389e68ef71091a6a9735ac12ca5497b9171da11a93c28d3273f58b74e2e46279d3ce9d0b20d19", + "e2365c2754073b511f16a1881ff8a537541ca7362ae7b84223d3c7d1d49d03a37d6d05dd2b819af9705c015dacc9dda83474eb14b7d5fce6e8a8f8c58e870149338d320e5ae476da6749af45e65ffed550d225a39dc74ffd93ba7da476985d6f44e90fc8e82454496260458431804d802fe804d825f611772f9710667377adfb1a11e4275bcecb42175c515f6a9439a359824f82cc9d480954364e6693099a821ace362e6c7ecbe68be8823bb5b49b4f23ad81b64139e3b63d9d4d298a842f013ef0d91ce7915ee8f816c70ba2aa3994216f", + "9c43944676fe859327096f82049cf69e48b98715878400fdf2805e0d5ee642e6cc9c43739f418b701348a033c5cb96bf8702fcd2fac9be58262a843c1e4155ed8a1724b6ebf7cce659d88a95a0c54deb2d7d9574a45219b6419ee173d1d8fad3ace47c962b349abe1048565df85bbd0eb9b11698258c23598023a00fdd26573e41951452027125c6e894a97736ecd63fd15b29a55d8dd9dab7e2e18f541a2e341890a61b7c896e7dc67aa82f3479dacd4a8ec7558d40c34d9ae4060e13718d676c2450258d83de8a86e012813693098c165b4e", + "1c707c29582d98a0e99639211102f3f041660ca03ad0939fe3855b8c1b22d6a9b8673c93e3eabc0ab231509b2b0d73c76a290a363943d12d2ff0ea30c6dd54eda753767effe04cabb4c3966388fa4c83a1906a0f48519a5fba9aeb585e0f8c45d6123a75ebe98fd1d0272f733a3925119481a321fe7509346c05128302851ba17a137f956f184e057a305e79a148727a5926de6854eb0314d5492fd735fa773d99ea34c95ca7546bd3a3aa8e66bcc6d860cec3d35d0e2165d5fbe8be99b6e7967df6693e5a6243e94c9c4a2528ae6305cbeca209", + "8f1e88103ffa378f062cade0ec509bec99a5c73fb273e79dbef24abf718ac26ac23dfd2b8932038ed3cb9637b71643c161142019f45b25b4fa4c52356737a27027e805ec635154327a66bfe64efc6285cca98c34edc7fb6c0766970a545342cf840aec0a5ba1dd3c6949be4fe97b0f8c8186de07536fd9074db34d09b2f08af9dcf9424d6edbf9cd044102c0e5dc35aff78c36d079dbd2c500e19c8c985ae2abaf6b2a20716bb719754a8840ce97632116c4d0b0e3c83ccca27f11c4204b76b5d6cfe6348a9615d8e4af53500dc4c2cabf12ec8c76", + "b9a0c28f1a6156992c103a84655fc6e654fa6e45e45819513afa797024717c00cc195994512fd53ecd1e12dac4d2448e0c40308382312084d2111f7db147b2e6589ce6d977f6115f629508167df8f45bac98abd49f6b272bcc4fd874dd5e29fb6daceb2d727a2a892194cfb9269eda00626ac89b4e74bd29b21e9f6ef18cb69889a02d4f0a06a2e5718899c1dc3b051c2cfa29653e782f87fefa478e6465bf5ff27f8b6abdb500077aac97100bd955ec535a587d66f23354be51cd8170289344bac9451f74e8aee3639f7c09981f4885e018912324d7", + "456844a34ae1074246f8f71eeef2010ec8733265bed7c1cc60043d770edfa320cbd4284a94be2574337e16d27f125074ebd7e99031f7abb4547b9540a7b0b5148ef501b550dd929f3dfe39ac65519f563e9254424aaafa05b1d37c16c771882e9e25d4906ac58603da749adf686932cd73d81e2658134fe69294c7a521d257eaf2110c667fc9d6f09b52d24b93910e532184eeb96eae9d9c9750ac3c39e79367431ac1af7011172d0a8be46a31010219a0310a733068c589bfc4748f3626aa4ff8d355cc893d05111c287c9992e95ad47481a6c42d6eca", + "c5c4b9900b9727bdc24baa544cad5faf8340be6b3759361f53889f71f5f4b224aa0090d875a00ea7116772117dbefc3a81c6950ca7ceeae71e4ba975c50d61fec82e6d9448d3a0dfd10bb087bdf0673e3e19fa2aaa7e97eebf71f11b86034fcf5a61240c71444ac3da15ef09b27b3523d37d309e8722380f835c1aee4a767bb027ec0674040853e5b53d6a31657f51acff6d2487860becd5ce695696cfe5937f4a0217b69e01cc6facc24dfe5f5230b8692a0b718e3b3c789d682db36101795a9a5f8bbb838c3679be72f7941a1db180135347d0a884ab7c", + "1781df2fedd2c39137854737d054cd3ed16b0ade411e41d97888ac900fdb46d9ae26b3d2dd07e118fd57eabd0dfd03a55793c76420666444865371adffc9b2f35068a0d70f9cfda1ac27ccb4beff4ffa5b8bb8bddac843386675c38a181fd0d935d6d51b25d78e7ff4ecef27a9853c0f0d2879c395ed1c4883987d123890d04f851c3e042e1164c68c0d503de16816f4b0e554236e5f4c339ea11d01ce652f6208f78f457a2417a97c0a6a240f443262def4b6763abf53e597bf1a28f907dc7cbdc751a234ea7d75710ad5ab0c37e8e9805102a375abd44011", + "8963552ad1e729ead07750df599d734157aaa4bcdcac17e8eb19b4f99cdb162686ff433137aa4e8a0cc8df0053999196262115aec326cf37567d9ba4760e0ad21d5763977f1ab9b35c0fc667890fa87fc946ceb776a811b5adc69446bfb8f5d9908029dc5aa38db816e4a4e8f98e5a48cf0a01627031c5bd1ced8bc1940dcafe4ae2f1199b186468eafc07e96a89d95dc18ef0fed3eda5b58ce58f221a47ba5311313cc680367eeb058fafc7bcadce5f520b6371489d9e529278ae6ee2650a85aed82896879038bbd9aa8d685fc9528943ccf2235cdf69a86464", + "23ceae3008085134433f5de4b47bafe0f443d443491e6cd47b216dd2dcc3da65239515a6e6b9beb9a939ae9f1f1f5e11f88326475e0962f319d9bf75ddfb4a46e7cc3f799d7547f3c0b2e089018b75787b82ea1a7295e7411f4852f94c94170e98bb0647923b8eb7d184038e56560da46085540cbfef82b6b577c445d038f6c93fbfdfc96ab3a0191d20a57b8610efb4cc45cd95198198e6f80ac46b0601511885f650eb00992605be903bcb46cd53c360c6f86e476c4c9ca4ad052eb572bbf26eb81dd9c73bcbec137aea6ee27aa97dadf7bef733fa1555019dab", + "c0fd31e82c996d7edef095cccfcf669accb85a483ea9c59f368cc980f73da7202a95c5156c34192ae4ebf773c1a683c079b17ac9d08b4265b4054fcddaf6666ca50f38f1a2ef2497459a68c06837363a526e850ecfbd223f55dba67db017eadb7a9139abb5bf3854834478b838aafa16c5ee90ea52fb2f7b8db2bcefb85b06fc455c2b6c27d0af9a49dbf2f313bf2599370637393e7972b31d8bf6759f3e6115c618e672831f84d76ba1879c754144e1df4d56b1e264b1797dcb8ab165040c8d20b931071081d7f74fbff590bdc8e888e71acc6a720270da8db7c821", + "936fdab91fba396e4a8754a97a04ba333daadc29885c9d0c8fea3387165278f4974e468fea57f2bfd8428c4d0f010833283db73735d39de0c0cb5898d0c06c0ecd05f61098935cb6130a8da60d1a6c2ecfe420f972263fff5a631b09e81c837183c5528bb1c740b36fc39cb082f3383c2b4afb25d04ad1d1f4af63dcf26a0bf5a647cd2e35a51cc119c4dc5031f5715b3bfa1f2b92de06bdac0d670fdd30980f32c51f3936b51e5db6b95a8d36279da5faa4c4e454f2b7e54e9f488071011c7f6f9b63da260a2e46d796d36c9a9dcae88085806a10a77bbb670d475778", + "a55fe162b287bd6eebd6cf7e7aeea8672322d924ae42c7404ff89aedb98943f3755d2889bca488cc7000e6e9b8e7a0ef289273cd29c44cc600e330d1775e3cb767f12150e1615dca8c3f67466463a3ca993a1b788cf67a7a35b95dfff954206eb5ea1e1bf7fb06482a551625b5c9fd9a86e8414c8cf79d3a14104a153cbe04aac5172aa4c4a89349f5856c4262dd1d7317a7544c9afbbed449e7dcc2b58d9df6c9c9ed3883e42e80f5c2433550f30e73c7bce0fccdd880adc19282a392dae26a0108e7faf168cfc15937aeb046d60712603286b8ddfb27916b79242d56f1", + "2bd6976592408cdbc4e41dcd3ecfbb786775ddedef914d9058e6753f839fdfe15b17d549dbc084aa6cdf3befa0158aa84c5d58c5876144fd7e6c41ab7d42419d0dd353732e0e6d3fafc4f5626c07433390a4fd467197e85b5de7e2cf1c26cc575356adedcc0740008523b503df12ff571387726c5ccb280376d19cbacb1d7ce7aab8b13292c6a8b8881e949cbf6d4610d16ebba1d46cdb8d0459596e0aa683d0307bd926e14de19b9bfeaefa29d91b82248604673a455520cbb64eef3f38cfad8e126a3b1cfa1aaba53a784c8ae0c50279c0ecdab54095d36f67ace9b8ebbb", + "71913ae2b1c8729ed6da003c24a1d4f96e28d7faf55ca14ee0b2865282b9b61103ce6ee0b00b00aacf2081adedea5616f9dfd22c6d6d4f5907bcc02eb33edf92de0bd479794f51246d9b612b4543f6ff633c4fc83bfa6144c9d26721cdc690a3d5a8db54d8bc7873bfd32924eeb502810732b5ac2f1852bb021c401d26c39aa3b7eb09083093a9e89bf889b53383b5af61110aca1b9fdf38908c7d5a184fc5f46b3423a66a2749feb8de2c541c563987278dbd0513d99b732411012b5b75e385510de5f6839c3797dc094c9501d5f0504b06b43efb6e746f2129ca189c1da424", + "9d048a83294de08d3063d2ee4b4f3106641d9b340a3785c076233686dd3382d9064a349c9eaa78028d35652078b583e3f708e036eb2ced3f7f0e936c0fd98f5d0f8aa91b8d9badef298bd0c06843831279e7c0c67ca7e572f552cfdd984c12e924c08c13aeec6f7e13d161785546ebfd794b5d6a92a4744e52c4cab1d0df93b9468be6e264e8cfcc488f9c3c1817cbe501f4b9cc5999483b7433aea777226b25273a6ef2331b5f3b6db8091591e8e276015da3ef78bb2ee0526ffe23def2d8d193cbe594e8ced1f3d216fcedae2a1eb288da82e34cf98aebc28def658ee0849ae7", + "3251c96cbf82ee2e5264528c0b6cdfc23d20e1eb2d6441b5d62f0fd24c692a0d45a8bc8aac32884b7141ac0f4f113ec9fc7f6b4db3d696374177f9a42d602ca471275b928f639105a55b846da9ac7274cc37de8c38541f6895f94d72a81e117844b46601c201f7189b935a96e42505f2098ac985d92dfe86349a706ef6325b3c2e4060ced3c453e68ed09e043bcc75846b80118dc53530248da250fb57922d0afa53a7b2c89161aa4fa372a46b2a8e1307741cecedf585d2f998a9d496763800b6965c38a5d8aa566c709f13699c8185ab4fd8fdc8b824f4dd6d1c255b4788f50574", + "2de31dbc8a012254586f3229d3524fc529554e98850d30acdfc11406bba6a142029126ac165ee90b2de7509fc3571a8ee12e16b05054eb8baea879d135b39627f0d8331be3e66bc720c2096ce74e437daebf3bc53d8f2ccc228c3256d3edb6e9ae7c354a0c9350e6d663a9a30630bf9da3d96b96608a2a171ae28105714058b6c4b38a36c56561c4612c32aad25c65b7fb6faa4e4ecd44ebf9b2fad42ff9a807cda2581614fd30d41a7436069399b8d4f062a37a5bd4066a93d541fa5797a7d3e7dc9c4c40f0bbf5256f71613240f9ef128b3423eacaf428ada06b6a531f835281e4f3", + "07dadee629a08223dcd7ec441287b4c5e26347451d9c003e3a8496b4ea313b51126283a6720d7851e24423d9c9c818b4601247178f38a61f45fd4c8596d79529d416834226666a2c8552bbc901cc5cc3406a18fc88077fea52e1b620748553052ab7788c0d025b095b736fbe714cb3a968ec16b5917652eba2d7cf32ef3140d6c27b25d053e9786d24cd09a5306a0ef55e46201faa6196a91084267d7a7b5ca57c2efdeb2cb97d682d2a191b915553c8933f1d1b7faf0b4a1d83ef611f1e44438bc1c3d860fbfd12b5f26e5a6889a31ce26ae6a55c7a563b5816d113423ef3f25fa9befc", + "1d94166bb387526d519c4ce150221954da8930f66765fe6a5504e30a69962d595cfdd07a82c003843598864261f053bdb6f5086d516c261e089caa89990f0967605768ae9200bdfe4dcd7b77a93265cb33d9851a2a1036113c732bf3f37534530641300f0620de5c16101e16f4baf39d9fcbfcb01c52afce0992c329d8dbb438c314eee995c5020611d6f889e06b8a032785cba9a415580dbf752b5e510523c89f478cc6f047bd926f51e4a965c9749d1e76379c0e7e5b56803893bafaa4d2892b4c52f143b2fa777cd1035ea418684b8019df084f9a3f1f768753096621f342895c510d01", + "fc0073f199ed8a1d6edc8e7bdf182670003108d82b283aba82326e856f8de378987a03d0fe8d2041440fd29d51c63796aab44090d2b14ee00859b3a08cbe88f724badcd3c401226c5db8b307b8deea5be305412b080e9f99cf79d6d08d3646f347a7afebb62912e3e246e2e726f9aec5c101d916e47f984507b1d65d313697256c77da7eca3bc5811c87bee02a2826cefff0d92bae989609aaf95d70561b40d98474c37277c884aed887a1606d206b11e8a8a71d1f1d19319557b57351228ff0404be700a6cc56c0a30f3d4b7a0a046463fdaf19e7d5f59e155f378e35baa33db1e881f2207f", + "f42a6a91278d6a076feba985b1cf4ce0af1fa9d6d039c136e8971e665ff088a10b6b9a379a6f5526fc5957773a0ccb8972a4a19be0745ac13937030a54b18dee4f4c5df47a58a33a7516b90e646e5da999166ab0e52f457f7c9b7e391836a687eaae37b377e59a4c995ab0c57162c307ab951a9ba6590f429cd27250e7010eb794ec1b1ec35f8aad189b2fd3e8aff24d93601d91a4884e6f84b02757ce7620a02901519fccfda52f68ad6df709d112a9c25d66bcbb9622806427ca8b8d346b6db05874bde800cde9cf17df4b05baab0f133febd1ebbb053b49c109a7f5b1f864a304d10288e2f0", + "bbcefaf4a0739509f8a2f831c954071aac52e60cfa882a867b8b910dcf7edf92e1c0692bb027bc378c460a01cb6ecc8f2a012dd84ee5a678cd497b1457b6d393421fbee98ff544fc7eba24cbc3aae506254d9a2d74dde74437ce4c8a69010718506bf4c5943342a942e5e2d3406a3016280b6e37954c5d5e763346251afb0b746cad68cac757f9df765e092518729cfb9a5e76300c124e708ca33591a369767ffb63933cb72fba67beb2223d98984d0b75eb5d1a38615913747b520b3d613c715c0c77d2987bb88f3c419bcc5d38573cf4a8a4f550b2d876f05ca252d88c70a561d869a5018b32f7", + "dc2437010cb05d9cab2af5c275e1d2acd627ce19fb86355df91fb8d059e60d591663c8eb077d48388c9a321057a98136f49f0098348d9f29d808936f98bb1787c7ac75fb14f6076dfd2de5b59b1fa4848cabaa9a99a091dc24b561911c392ecdbe53f4adae82b852d830adea3a10490c908e337ce0a6d12354ce05a37ad3a06696b66820af8a1f67e6287533fd6f38a5f6ad1c6b078c08baf2c37d2683af01e6a5b33796c8ae48935a888f9bd265f4f11a4e27c433b8b1c9afd140bcd21a07e24378ad6badde8e47c57e3340f49e2406e8d49afadd65eaaa4c3d078c27d7e42118cb86cd248100a356", + "6c290db326dd3152e6fa9b9c0cd7d49e50a0221b96e32f5f34a8cb7d0c2edd3e937a7d025d6999b7b468add4d6894d8f7aceaabc18f4d9c171f1fe95ea1ae8570382a8450fbc595d95b1f51d24e1abc2970b0e1d20ca40aa21bdfb3656adf2f19882eda606f5ef1c03174e1d94c8d12f0fee8dce6852f42a364eeafa27a7971d4379405db8e46baac4d685b969238e5df06292a6c790bf1994a051b038e1d8db91e1bc4804f32443781c34a552ed2e8100cea374e77af56ba0e11c45990d3ba68df9087b1f4968cbcbb1c42f99b7267c76af926ff3134e093df28fab039cad420c6b70f2d9b5e678c155", + "ac724a22ebabaedbbb052953e3c264a4b6440f313bad501cdc1484b64f33402a2230898776db5c818c28035ffae6ea24abd04b7159e42159833903a0c23a7c564f7645e49ddedb748fd9e51bd6cbf2eced98caaa35226970f003ce1fd260ac5795e096f1c04aebf8fd36e5e2adeea929b5e963a3cb71d6b55c85bb7d3a2b03a7e74b4416de8fa68950168d7c3ae8ed2e29bad1e8a182a7c5418e5d564373163778cd3c34e9d320eb1a60480a8f98b12e0026cbd7752e6079812e3767d9f55f3f10b8c214a6eceb2a58954091a06b33862af171a9b60bf2c6a44e8766e6c56e98092c56f2a8510f6d05c103", + "8c70114f7cffb375c2b9a06e27297a5c32418b2daf68af5bbedcc7106edbc070e764bf40c1f8eb15079e2ab77f898afff3490108ed9afb7ea9cb05df41d263be0e42d2321d3d2656622d7bd232bf68d37375fe7314b09cba66f19c8b59424198ee69e7a9f3de0ecce0685127807ce336fa479ccaf7aa1ebc4e406271ce6c4923ec36093516498cc227f9218869346c80ba5ae83e023aca0ae2bc86b5bf5d115a4616b6587cb869d92f8c780ab70d5766de07a204af5e1c8dbba622516d2e911b36c82e4687e4d258ea616c07f76ff0baa376c8d5975cffac0b25817f779ae3ce88b72eb47e378484ce999bf0", + "0733d59f041036398233fd47a84b93f6778ae5259ef5d62aa3b9faedec34c7edb570c18b2a5d2c4c55cf656d98a1ae396d45a3b746b7ad6f07312c3d05d1a50ffa90bcdcdba105e25b7b0c52664223f8c2476925d46dc6ea2406ded7d0b0b292f6656cebcc7616cfa4b82aec68b35d1da67f6ed2bf0171849d6bb65128d8a140ea5cf97f1003f8d7093bee077be78def4f7bd2caccbf0644f26b26285225142c40038484c3bb9ba9597744f4389e76dca3eb695c33ccc621cab1fb603cb3535a0ad318d220385d5e94f8674f3d55e97e097f8d5c049e911946afbfce783819951d65d6bff4567dc951390d1aaa", + "398ddbba3dcb5642c102efa841c1fcdaf067062e7eef8e2ee0cd73d7f77e57372d6ee1a9b7b6f86ad12d575001ae71f593449cb5a476c6bfeddaa2af0f9239c1d7effdedf66ceaf413707b5ab9661a7cc0ef8cfe4d1651579c4f0f64e2d12a52653c54f2dd60864e769eab8a627c89c56ee93365d031f0d2523cb95664b1575d51b122f33c9e94de75432a690658c977b68aa5b721a393f9b9b3b612c10e920a7d510c6d8460b35f8614c42f5d2c241a01b28105aa7c1b521ac63ebbedafac6d5a38c898e8590f918a1927bc53aecc2b1c8b18d7df9107c6997d9b3fa4b0bdb1c603da619d9e75670b97a5b40f06", + "ef07bbc7c4150dd47f8c69a7989948fe831dc798b0424dcd6551bfa8e88216095a7e5d720909bf3d23526b9ba464b66ff6b63a7337c31451ab9a15f04ead809a62bb52206237de77597a730106d02d227dd6099ea9ee2a92cdc446ac3b9d024e32255adb3e9b56b561c431e0b5a721f0336f19568a5335d0ebc6c73ed8ff2c15e219477d9e4b67f2928e251f8a61a2848857e037d010806c718ab062967fd8e85f3722252957923f5f9005aae47b4b1b3fa464e3ba9df573a56055f17e903126fbbcb6cb96de92fe617c97f84ef3ba0d8f2651dc4aa80c157f372ae1bc02e5067ad076f3fe48bb72c0f3c99273f82b", + "c7076986d2333f3a6752adf11f1a9e5c6bc4755f341073cc86a9c7519c8db029d5ae833fdf3fee826ff4692c57880c5074620ea97c00f1dde1e8a0f18501627984ded4d1b5c4af35be5cc1bcc868060a49a968dc0547acde490b4c68d79924a93a986aa0ad060c7de706e8a99ce8f84a4f8707b52a8ee122b763ba580d6b1f35f6af25094c69f49247da96c836991851ad36f60bf577863d7471608a012afa7a56656abeee7cd9b4f1f4d9d13a8526c0f33cd251caf7486639e787250390e7e488e9ec311fc3d847a7266cc59bcc2bc34192554aa57cf25db10ce04bdabef3fde6db85f55195ecc2ff892b2e268ebea6", + "01789f40d42d8d3e4a416fd9ae7de78c3a30507809eda200e1afaaf8d7020cd1fad18eba62d821946f220506cf105ff0e2069a771a2c233714afa6b2f695497e4b95c9693dbb93ec4c9a14720676aa87ee31dd34e4e081756477032b4a57b328285f2cdec1b269754c474936927e93acc26012aff1bb36f30c2402aca0a9b9ce9568f5000e2c934263933b436c94f8d6589c89db7edabc5d03a8fe795fe50c5166beab64ed7c22662b984ae2c66dbe4c090b0df603b27c759278f8d66859afea3f6a8f02c2c2a2202b9fc29132256f164b5050a803b43688dc4c9ba86374a3522afba5d1a19bb3820b883aebc267627095", + "2c61944bd6a50da00ebb951d2b67d79fc6b6fb5aca83b1de3dbd7690ab756bb1e1a21051ccf1e24136ac8ccb42a2ee10be94d2cb9289d5f52b6f90e9d07a3478f36a1eb7d08c3dec52ca154fd1427ba92a4ecbe73a71bceafbd26e9a39d50821e2876d3a0c0e6e373b9795dbf72ea29cc439ff42706be798c90d4617b39c90ec84bf9fb699dc8a9a34e25d81759d6c57df45efb1d0d68aa51278564b99633ed5dc464bb7d53c5c21f798f33bcd868657ecfe75a1ed8149d394b398969ef624831b30f1458465bfd2fdf3f284f2ffc54bf2817b5fab2e02056e864f78bb6fd870c64f3609dab218f25da8060f756e45121e79", + "942fa0c68cc72f69518a3a7aac0cde45bab0e928b5cb2bd24d049fc313f74b6afa87c4e34150484f3b5200163f8a6472d04777928ecc49319539fc17d71a38090f55a74f757fe45781a3c09f08dcd3dd4c73c8533a5e00cf8a86ebe77fe45be2848574f7c5d25e9a0632a60d2dd41febdbf987d2a0487e4a4ce6ed5f49f2d741a88ecac232b1498253fa4ee8147bbd0f600abdf295e81f7570015aac5fe6ca7bb4a99bb3fc54287106d7fc1132a574af49db82a7b9a5f33e193cde527ca2176c52cdab672165e0fe5720f71ada57ee90060aa069ae2a0bfe67c1b71b17c601c3c2224bf9891bc11ba216e3ebcb51fd95b8d7cb", + "0d68cfe9c087ec116fe7572042385159cc705960f842aabad1ed1387ec1697f4413a23c6090041328fedd4b626c6eeaac5b5a71acc1fd1bb8fbd228857ac5bd045c364be7a5a26338ff04c99c4c473cf445a891db6422d1bdef4533442df171643fc36a092fabb464298e4194c9e2950884de13d113ee24160a416404c16ddc5d2476cb3fb80da543e6ed9105f6003977acb34e1fdd2cbdf7a00d5ff84350b74ac231418c0d88269d02d824802791ff42a51cc835deb9869a6023f867f82ef6dc0bfb03e6dfa835646bb18a4074773486e308aa39e532aaea4e6fb35dcada7e060f8282c371ed26d22302323d4fd142a85534671", + "45e24b167a0bbef1bd8f79dd047763d0754f36a7b623f298059d177e8ac994945c37d2c4af06f01318960301595941124592f2995af1459d854339998d3ae17534df2d9793d6e203857d02c98a0cd88991e641b3e640090ba303f87b907dca8ca462fac19ad079b2c82ea5b521ab891b10138b083b3d9fa214a8fe60d1cb3599c5d199c61a2cfb7ee2f39e5a5abad5ac4998b707545f73e92128d21803420526d2598a53bb314adf29a0ef56b94bd2221601eb53ecb8540e8fffd38fba7bd827ef255e4ef55491475c0f383a241f81c72af4e1dbf2a65cd4d18a497615aa0de2791a3511a7977a8d4d41492bfa4085f2fd4e8f751d", + "1c1bb695ae90e6e33fc1e8b2a62ab98bf835ac7193440f2351c8cdd830472b637d2fd9c9013cb83caef506abc1c4f7567706db6046b1d184579c7a9223ab1b35e32898c70a3c27628123ffcfa518612f080a2c4a9f8e0a927a47dc98307d2b48de9d5dddcb5c82f0b0e4e610d44f1baa9bbbf7f5a727134680bb7d1327b73b52d8e5e36dbb53971e99e699d79f75a3fc01316bd7012947d119d6aeb7f75b8fbf0479c03002148553fa0da450fd59d4f1bebc252caa11ed9bec5b6ef54279b5f8382b61cffc67ec03f4baa7ea476c31364b86aa8ccad9fd0818717f0ced2dd49477874b4341c602d7a1beab860eb476c7e3ce597e6926", + "7a3cd9bb2277e2c7f1134fe7233f0f7883c2db9fba80aa5742b03041de0fe589d9e5ea84470dabf41bb66816f3e33ebf19a0ca5aba1004cf971249b258ff26a98dbd0c37ec6cd574854109433357720040bafed4531e0079186b1e853e0ced35d08d27f6d732ed6e2c6651b51cc15c420a24f2dc36c16ef4b3896df1bb03b3963f9aaeb02a48eac5772abd5948c2fd0db2bb74e3351e5eabd681c4f413655bd94dec96b1544c1d5d2d1df4bdc26020d25fe81d5238de824687a5505e1fbe08d11b3924b3ccc070fd225bf01eb79e3d21f7b62a836cd3bcc11c931669c37613470e356143df87c48848a829f5e018973a5db88eb6c60203", + "3f158afd0733fcc5dfe1efc2dd4eada732f942af734ee664955bb1ba613eafd0f349e7554a14d68200c62d8f2dca2ec8b81c8350735eaf437041f78b452598825b6899560963ade66a0fc74ad01f8343d1d19c7bb327a8dc14ffdb1c42fa72b2970d9155e2da6a2e6419d4117842d826ff38ffab9617307a0283d3ea28c8104ad9a6e087bb750ed1d10fd8f7100b1663682e979d80e43968c33d9eff66f4d1344e583ee521e78d0a2193c0577516b978339c143bfc689bc744bbc4a9163063de82c9706384b6b385e54666c86b34f23c1e25be293af06092ca31d857e11e5b2caf0d19dd3afbe85380878eda76d718b4bb869c67e044e242", + "a177af4387b9bfa3d59e97ee7b0ff5f4ae4a326fd9204c8d28831a67fcc385ee6c4828247b16d11aea9bb8cd9e6c4d2876c6b2fa6d5041ad39e1b04039071e29c4d86417e7eac4fc7d3823958a021823e2c880a757dfbcd0c8196371db5bbfac15e4d1a0596508b6d26f8c4a664924c95082d173f817995b44c4285d625d9b2f56c86632fe1295c5a8a7a3760028072bcb07bc245a705e7174d06b9d5c0c8ca495b9ac218f1921fa63f2db3fd148f07545366d008fb5aead7497d902b91fbaa39669929d4ae9d07df8557f1f0aed7b51252f10c6606e5ff3ede1327530ca356b4896ecf14bf7322d77fddfbe28d52f6de7f66eeb81704c87e2", + "01a15b9018e35cc342c926b01d03ad9db4993a6bf92e0555969fee90033f28f3ec234c1268b11b040dfa0770d4ceb39edfeb8ee6a589f4eebcc08d2d1b0a1a52953aa26eb44fdf4a2743c3dacb212a0c0f325572f645f53027b6f3c0c55abaeb1b0918c89bedcb5028f094d743ea354f8ff553c45f111a8fd5a14a4e5c835164747d302472e19a67da04b4c8e39756a9d248ce14d1ed43de75aca86850f2455eccd4639b2af035bb3f504cc9065d091c1c47e036083cb3fc50bf39292b11737c7ce0b49673ba93981de304dc65a671775b6ff927e3ff93850b214fffb5792105a4bdc81354d5b09e84afbdd1792b8fb4e9d0ae3dad2492b03282", + "24f07ae31279ceed18ec6d35990f21200934ad6b132c6c62e82fe92a40a0e60a5bed10720eff5a1f728971888682772b2d9060d4fee88f37d0824e7384dddcc549475f0e1a44eda4804778b62febe46e04657a20577ee70acb3425e334881eebd8ddf714ae8c527ea747e3367de384e595a43b299b6bb3f6b0a4716cf90038e0f75a47d5057d7fcc3c8a8f9224992c67f8ae0d3251ea09a24aed9ce57ab637f6b3cbb7083df62b6287f64d0877984c4249d113bdb2b07865082aa24cd7ec07061b17de320f51f29f25b82d7073d369cf2dbf96310c0c311997911b2cc02f606f9cd99663c57e78499192a2a78f9c9fa67013e0f9817287faa69b22", + "4aeb32bf9d050f10bea18d9f71b4afea7bd08550e574e7d50df234c7413668b297b6721d7a0f0bdcdcceb2f55adddea28cd59bd44be0c5ec067039e428706caae11f565d961ad6e7f4c51b0aed6d05cc5b8d826c4b9c39daefb6c7da46dce619a359dc9ce215a215218fa8d54ee0b4f301b6c201c7c2c5f7cb1c6e0cb76ba6c6e8f63ef7a5213d550b0d0857fa0ff9e3e38e497161617413ac066e2fa539520233193a5cb7baa0c2cb20b45e56bfed2c40a9544d1f230dd0cd6d4976e7cf51da8a13200c3957c0154c8237b2931ce19b824963ac576ea49b548cc6aa85c47796b470fb2c6308d88f390bb13607e294c84a838b2713b14ca6a5e8bcee", + "77e607478be5502432230c913d9ec82f967d87c0ee169a74076f989648853eca693277287f8a5b306bc94dfdbf64ca5cb5dfc0bc498589d51a691b8d57d4b0a9ee247d038fe1b5571183be3e75c37045bf1235863ff1b84b208c10e7f1a5ba54ff36af5b2870129867164d013e0a6d2cc067a3509bba2f46390302c80b651cf590ef69aad8effd94cab28a9b44be6a38b58cfc47c9c725d6fa467894163383b6873d10d263b1cbbad932ded59ab503920267ac026726f794a335a88f6ef564f8968c6fa6f5d3ea161eb6062ca349b9a0e4038273399cfa297a6b07ceda1ebaa99c9de2d935ee230a08c5a488ad46f3393243371d40916b8063cac9da63", + "50957c407519951bd32e45d21129d6b83436e520b0801ec8292d79a828106a41583a0d607f853dc4410e0a1427f7e873455a75df065cfc6eef970f7e49d123b346976460aadd91cf513c140c356442a84656904a8b1d708dc6089db371c36f4fe059c62302eaab3c06c0cb3b429961f899dcf99798464b8571a440cac7a52b495f32417af6bc8f58adc63647531f804b4e96273b29b42434c1236bde80ba3744fef7b1d11c2f9db332b35bc25123338ac9a0796aac213c9709b3c514ea7ecd80e22d3d8a74f28c8194418a6e1ff30714d0f5a61c068b73b2ba6cad14e05569b4a5a100da3f91429d6e3ffee10ceea057845ec6fc47a6c5125b22e598b2dc", + "f2273ec31e03cf42d9ca953f8b87e78c291cb538098e0f2436194b308ce30583f553fccb21ae6c2d58f3a5a2ca6037c1b8b7afb291009e4310a0c518e75314c5bb1e813bf521f56d0a4891d0772ad84f09a00634815029a3f9ad4e41eafb4a745e409ef3d4f0b1cf6232b70a5ce262b9432f096e834201a0992db5d09ffa5cbc5471460519a4bc7cdc33ae6dfe6ffc1e80ea5d29813136406499c3514186ced71854a340701519ef33b6c82ca67049ab58578ff49c4c4fbf7d97bfec2ecd8fbefec1b6d6467503fea9d26e134e8c35739a422647aaf4db29c9a32e3df36e5845791fdd75a70903e0ce808313a3327431b7772567f779bbaee2e134c109a387", + "5784e614d538f7f26c803191deb464a884817002988c36448dcbecfad1997fe51ab0b3853c51ed49ce9f4e477522fb3f32cc50515b753c18fb89a8d965afcf1ed5e099b22c4225732baeb986f5c5bc88e4582d27915e2a19126d3d4555fab4f6516a6a156dbfeed9e982fc589e33ce2b9e1ba2b416e11852ddeab93025974267ac82c84f071c3d07f215f47e3565fd1d962c76e0d635892ea71488273765887d31f250a26c4ddc377ed89b17326e259f6cc1de0e63158e83aebb7f5a7c08c63c767876c8203639958a407acca096d1f606c04b4f4b3fd771781a5901b1c3cee7c04c3b6870226eee309b74f51edbf70a3817cc8da87875301e04d0416a65dc5d", +} diff --git a/vendor/golang.org/x/crypto/blake2s/blake2x.go b/vendor/golang.org/x/crypto/blake2s/blake2x.go new file mode 100644 index 0000000000000000000000000000000000000000..eaff2a7f8df4fb477804812efea1a078a69d5a58 --- /dev/null +++ b/vendor/golang.org/x/crypto/blake2s/blake2x.go @@ -0,0 +1,178 @@ +// Copyright 2017 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 blake2s + +import ( + "encoding/binary" + "errors" + "io" +) + +// XOF defines the interface to hash functions that +// support arbitrary-length output. +type XOF interface { + // Write absorbs more data into the hash's state. It panics if called + // after Read. + io.Writer + + // Read reads more output from the hash. It returns io.EOF if the limit + // has been reached. + io.Reader + + // Clone returns a copy of the XOF in its current state. + Clone() XOF + + // Reset resets the XOF to its initial state. + Reset() +} + +// OutputLengthUnknown can be used as the size argument to NewXOF to indicate +// the the length of the output is not known in advance. +const OutputLengthUnknown = 0 + +// magicUnknownOutputLength is a magic value for the output size that indicates +// an unknown number of output bytes. +const magicUnknownOutputLength = 65535 + +// maxOutputLength is the absolute maximum number of bytes to produce when the +// number of output bytes is unknown. +const maxOutputLength = (1 << 32) * 32 + +// NewXOF creates a new variable-output-length hash. The hash either produce a +// known number of bytes (1 <= size < 65535), or an unknown number of bytes +// (size == OutputLengthUnknown). In the latter case, an absolute limit of +// 128GiB applies. +// +// A non-nil key turns the hash into a MAC. The key must between +// zero and 32 bytes long. +func NewXOF(size uint16, key []byte) (XOF, error) { + if len(key) > Size { + return nil, errKeySize + } + if size == magicUnknownOutputLength { + // 2^16-1 indicates an unknown number of bytes and thus isn't a + // valid length. + return nil, errors.New("blake2s: XOF length too large") + } + if size == OutputLengthUnknown { + size = magicUnknownOutputLength + } + x := &xof{ + d: digest{ + size: Size, + keyLen: len(key), + }, + length: size, + } + copy(x.d.key[:], key) + x.Reset() + return x, nil +} + +type xof struct { + d digest + length uint16 + remaining uint64 + cfg, root, block [Size]byte + offset int + nodeOffset uint32 + readMode bool +} + +func (x *xof) Write(p []byte) (n int, err error) { + if x.readMode { + panic("blake2s: write to XOF after read") + } + return x.d.Write(p) +} + +func (x *xof) Clone() XOF { + clone := *x + return &clone +} + +func (x *xof) Reset() { + x.cfg[0] = byte(Size) + binary.LittleEndian.PutUint32(x.cfg[4:], uint32(Size)) // leaf length + binary.LittleEndian.PutUint16(x.cfg[12:], x.length) // XOF length + x.cfg[15] = byte(Size) // inner hash size + + x.d.Reset() + x.d.h[3] ^= uint32(x.length) + + x.remaining = uint64(x.length) + if x.remaining == magicUnknownOutputLength { + x.remaining = maxOutputLength + } + x.offset, x.nodeOffset = 0, 0 + x.readMode = false +} + +func (x *xof) Read(p []byte) (n int, err error) { + if !x.readMode { + x.d.finalize(&x.root) + x.readMode = true + } + + if x.remaining == 0 { + return 0, io.EOF + } + + n = len(p) + if uint64(n) > x.remaining { + n = int(x.remaining) + p = p[:n] + } + + if x.offset > 0 { + blockRemaining := Size - x.offset + if n < blockRemaining { + x.offset += copy(p, x.block[x.offset:]) + x.remaining -= uint64(n) + return + } + copy(p, x.block[x.offset:]) + p = p[blockRemaining:] + x.offset = 0 + x.remaining -= uint64(blockRemaining) + } + + for len(p) >= Size { + binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset) + x.nodeOffset++ + + x.d.initConfig(&x.cfg) + x.d.Write(x.root[:]) + x.d.finalize(&x.block) + + copy(p, x.block[:]) + p = p[Size:] + x.remaining -= uint64(Size) + } + + if todo := len(p); todo > 0 { + if x.remaining < uint64(Size) { + x.cfg[0] = byte(x.remaining) + } + binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset) + x.nodeOffset++ + + x.d.initConfig(&x.cfg) + x.d.Write(x.root[:]) + x.d.finalize(&x.block) + + x.offset = copy(p, x.block[:todo]) + x.remaining -= uint64(todo) + } + + return +} + +func (d *digest) initConfig(cfg *[Size]byte) { + d.offset, d.c[0], d.c[1] = 0, 0, 0 + for i := range d.h { + d.h[i] = iv[i] ^ binary.LittleEndian.Uint32(cfg[i*4:]) + } +} diff --git a/vendor/golang.org/x/crypto/blake2s/register.go b/vendor/golang.org/x/crypto/blake2s/register.go new file mode 100644 index 0000000000000000000000000000000000000000..d277459a1c2ab1c7e0830b77b53c12f91f402e9d --- /dev/null +++ b/vendor/golang.org/x/crypto/blake2s/register.go @@ -0,0 +1,21 @@ +// Copyright 2017 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 go1.9 + +package blake2s + +import ( + "crypto" + "hash" +) + +func init() { + newHash256 := func() hash.Hash { + h, _ := New256(nil) + return h + } + + crypto.RegisterHash(crypto.BLAKE2s_256, newHash256) +} diff --git a/vendor/golang.org/x/crypto/blowfish/block.go b/vendor/golang.org/x/crypto/blowfish/block.go new file mode 100644 index 0000000000000000000000000000000000000000..9d80f19521b461af2a77b10e8eaf64936d8e223d --- /dev/null +++ b/vendor/golang.org/x/crypto/blowfish/block.go @@ -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 +} diff --git a/vendor/golang.org/x/crypto/blowfish/blowfish_test.go b/vendor/golang.org/x/crypto/blowfish/blowfish_test.go new file mode 100644 index 0000000000000000000000000000000000000000..368ba872bfd5ef10ebfa20fdc7e0f308f92a058e --- /dev/null +++ b/vendor/golang.org/x/crypto/blowfish/blowfish_test.go @@ -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 https://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) + } +} diff --git a/vendor/golang.org/x/crypto/blowfish/cipher.go b/vendor/golang.org/x/crypto/blowfish/cipher.go new file mode 100644 index 0000000000000000000000000000000000000000..2641dadd6494e8ff5295e1d53842191ce5dadbe1 --- /dev/null +++ b/vendor/golang.org/x/crypto/blowfish/cipher.go @@ -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 https://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 compatibility, 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:]) +} diff --git a/vendor/golang.org/x/crypto/blowfish/const.go b/vendor/golang.org/x/crypto/blowfish/const.go new file mode 100644 index 0000000000000000000000000000000000000000..d04077595abc44b8db297e4945c4fd546e3eb073 --- /dev/null +++ b/vendor/golang.org/x/crypto/blowfish/const.go @@ -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: +// https://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, +} diff --git a/vendor/golang.org/x/crypto/bn256/bn256.go b/vendor/golang.org/x/crypto/bn256/bn256.go new file mode 100644 index 0000000000000000000000000000000000000000..f88f3fc3b16631dbaf43f85a4afe0f596ee0729a --- /dev/null +++ b/vendor/golang.org/x/crypto/bn256/bn256.go @@ -0,0 +1,408 @@ +// 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. +// +// 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. +// +// (This package previously claimed to operate at a 128-bit security level. +// However, recent improvements in attacks mean that is no longer true. See +// https://moderncrypto.org/mail-archive/curves/2016/000740.html.) +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 (e *G1) String() string { + return "bn256.G1" + e.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 (e *G1) Marshal() []byte { + e.p.MakeAffine(nil) + + xBytes := new(big.Int).Mod(e.p.x, p).Bytes() + yBytes := new(big.Int).Mod(e.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 (e *G2) String() string { + return "bn256.G2" + e.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 +} diff --git a/vendor/golang.org/x/crypto/bn256/bn256_test.go b/vendor/golang.org/x/crypto/bn256/bn256_test.go new file mode 100644 index 0000000000000000000000000000000000000000..1cec3884ecd4c95348d693e435dbb30d976fc0a9 --- /dev/null +++ b/vendor/golang.org/x/crypto/bn256/bn256_test.go @@ -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}) + } +} diff --git a/vendor/golang.org/x/crypto/bn256/constants.go b/vendor/golang.org/x/crypto/bn256/constants.go new file mode 100644 index 0000000000000000000000000000000000000000..1ccefc4982aa2a6eb06426e2a72d212199e9d4ca --- /dev/null +++ b/vendor/golang.org/x/crypto/bn256/constants.go @@ -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")} diff --git a/vendor/golang.org/x/crypto/bn256/curve.go b/vendor/golang.org/x/crypto/bn256/curve.go new file mode 100644 index 0000000000000000000000000000000000000000..55b7063f1635865e68412d74dcea9707f80fc183 --- /dev/null +++ b/vendor/golang.org/x/crypto/bn256/curve.go @@ -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) +} diff --git a/vendor/golang.org/x/crypto/bn256/example_test.go b/vendor/golang.org/x/crypto/bn256/example_test.go new file mode 100644 index 0000000000000000000000000000000000000000..b2d19807a25e6dd97380ee18457abe2fd9cafbd5 --- /dev/null +++ b/vendor/golang.org/x/crypto/bn256/example_test.go @@ -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. +} diff --git a/vendor/golang.org/x/crypto/bn256/gfp12.go b/vendor/golang.org/x/crypto/bn256/gfp12.go new file mode 100644 index 0000000000000000000000000000000000000000..f084eddf21267cf8322e55d1fbb87eb1666184e4 --- /dev/null +++ b/vendor/golang.org/x/crypto/bn256/gfp12.go @@ -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 +} diff --git a/vendor/golang.org/x/crypto/bn256/gfp2.go b/vendor/golang.org/x/crypto/bn256/gfp2.go new file mode 100644 index 0000000000000000000000000000000000000000..97f3f1f3fa1a0e1d051024c4980d0126ccd7913a --- /dev/null +++ b/vendor/golang.org/x/crypto/bn256/gfp2.go @@ -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 +} diff --git a/vendor/golang.org/x/crypto/bn256/gfp6.go b/vendor/golang.org/x/crypto/bn256/gfp6.go new file mode 100644 index 0000000000000000000000000000000000000000..f98ae782cc154af31b02358bd038874d93c731ab --- /dev/null +++ b/vendor/golang.org/x/crypto/bn256/gfp6.go @@ -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 +} diff --git a/vendor/golang.org/x/crypto/bn256/optate.go b/vendor/golang.org/x/crypto/bn256/optate.go new file mode 100644 index 0000000000000000000000000000000000000000..7ae0746eb10b892841301a5b7c0aa319aa6d700b --- /dev/null +++ b/vendor/golang.org/x/crypto/bn256/optate.go @@ -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 +} diff --git a/vendor/golang.org/x/crypto/bn256/twist.go b/vendor/golang.org/x/crypto/bn256/twist.go new file mode 100644 index 0000000000000000000000000000000000000000..4f8b3fede4242e09ae9e3e4a82b91ee3a392ee5a --- /dev/null +++ b/vendor/golang.org/x/crypto/bn256/twist.go @@ -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() +} diff --git a/vendor/golang.org/x/crypto/cast5/cast5.go b/vendor/golang.org/x/crypto/cast5/cast5.go new file mode 100644 index 0000000000000000000000000000000000000000..0b4af37bdc294c35c754df9c06d9f5b707a3fa59 --- /dev/null +++ b/vendor/golang.org/x/crypto/cast5/cast5.go @@ -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, + }, +} diff --git a/vendor/golang.org/x/crypto/cast5/cast5_test.go b/vendor/golang.org/x/crypto/cast5/cast5_test.go new file mode 100644 index 0000000000000000000000000000000000000000..778b272a638885dacae0f362000142b6d5af57fd --- /dev/null +++ b/vendor/golang.org/x/crypto/cast5/cast5_test.go @@ -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) + } +} diff --git a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go new file mode 100644 index 0000000000000000000000000000000000000000..3f0dcb9d8cfac541a6bbea2f7258b3471557759a --- /dev/null +++ b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go @@ -0,0 +1,83 @@ +// Copyright 2016 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 chacha20poly1305 implements the ChaCha20-Poly1305 AEAD as specified in RFC 7539. +package chacha20poly1305 // import "golang.org/x/crypto/chacha20poly1305" + +import ( + "crypto/cipher" + "errors" +) + +const ( + // KeySize is the size of the key used by this AEAD, in bytes. + KeySize = 32 + // NonceSize is the size of the nonce used with this AEAD, in bytes. + NonceSize = 12 +) + +type chacha20poly1305 struct { + key [32]byte +} + +// New returns a ChaCha20-Poly1305 AEAD that uses the given, 256-bit key. +func New(key []byte) (cipher.AEAD, error) { + if len(key) != KeySize { + return nil, errors.New("chacha20poly1305: bad key length") + } + ret := new(chacha20poly1305) + copy(ret.key[:], key) + return ret, nil +} + +func (c *chacha20poly1305) NonceSize() int { + return NonceSize +} + +func (c *chacha20poly1305) Overhead() int { + return 16 +} + +func (c *chacha20poly1305) Seal(dst, nonce, plaintext, additionalData []byte) []byte { + if len(nonce) != NonceSize { + panic("chacha20poly1305: bad nonce length passed to Seal") + } + + if uint64(len(plaintext)) > (1<<38)-64 { + panic("chacha20poly1305: plaintext too large") + } + + return c.seal(dst, nonce, plaintext, additionalData) +} + +var errOpen = errors.New("chacha20poly1305: message authentication failed") + +func (c *chacha20poly1305) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { + if len(nonce) != NonceSize { + panic("chacha20poly1305: bad nonce length passed to Open") + } + if len(ciphertext) < 16 { + return nil, errOpen + } + if uint64(len(ciphertext)) > (1<<38)-48 { + panic("chacha20poly1305: ciphertext too large") + } + + return c.open(dst, nonce, ciphertext, additionalData) +} + +// sliceForAppend takes a slice and a requested number of bytes. It returns a +// slice with the contents of the given slice followed by that many bytes and a +// second slice that aliases into it and contains only the extra bytes. If the +// original slice has sufficient capacity then no allocation is performed. +func sliceForAppend(in []byte, n int) (head, tail []byte) { + if total := len(in) + n; cap(in) >= total { + head = in[:total] + } else { + head = make([]byte, total) + copy(head, in) + } + tail = head[len(in):] + return +} diff --git a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go new file mode 100644 index 0000000000000000000000000000000000000000..7cd7ad834f0be880ac399dca0fffcce6065ab5fb --- /dev/null +++ b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go @@ -0,0 +1,127 @@ +// Copyright 2016 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 go1.7,amd64,!gccgo,!appengine + +package chacha20poly1305 + +import "encoding/binary" + +//go:noescape +func chacha20Poly1305Open(dst []byte, key []uint32, src, ad []byte) bool + +//go:noescape +func chacha20Poly1305Seal(dst []byte, key []uint32, src, ad []byte) + +// cpuid is implemented in chacha20poly1305_amd64.s. +func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32) + +// xgetbv with ecx = 0 is implemented in chacha20poly1305_amd64.s. +func xgetbv() (eax, edx uint32) + +var ( + useASM bool + useAVX2 bool +) + +func init() { + detectCPUFeatures() +} + +// detectCPUFeatures is used to detect if cpu instructions +// used by the functions implemented in assembler in +// chacha20poly1305_amd64.s are supported. +func detectCPUFeatures() { + maxID, _, _, _ := cpuid(0, 0) + if maxID < 1 { + return + } + + _, _, ecx1, _ := cpuid(1, 0) + + haveSSSE3 := isSet(9, ecx1) + useASM = haveSSSE3 + + haveOSXSAVE := isSet(27, ecx1) + + osSupportsAVX := false + // For XGETBV, OSXSAVE bit is required and sufficient. + if haveOSXSAVE { + eax, _ := xgetbv() + // Check if XMM and YMM registers have OS support. + osSupportsAVX = isSet(1, eax) && isSet(2, eax) + } + haveAVX := isSet(28, ecx1) && osSupportsAVX + + if maxID < 7 { + return + } + + _, ebx7, _, _ := cpuid(7, 0) + haveAVX2 := isSet(5, ebx7) && haveAVX + haveBMI2 := isSet(8, ebx7) + + useAVX2 = haveAVX2 && haveBMI2 +} + +// isSet checks if bit at bitpos is set in value. +func isSet(bitpos uint, value uint32) bool { + return value&(1<+0x00(SB)/4, $0x61707865 +DATA ·chacha20Constants<>+0x04(SB)/4, $0x3320646e +DATA ·chacha20Constants<>+0x08(SB)/4, $0x79622d32 +DATA ·chacha20Constants<>+0x0c(SB)/4, $0x6b206574 +DATA ·chacha20Constants<>+0x10(SB)/4, $0x61707865 +DATA ·chacha20Constants<>+0x14(SB)/4, $0x3320646e +DATA ·chacha20Constants<>+0x18(SB)/4, $0x79622d32 +DATA ·chacha20Constants<>+0x1c(SB)/4, $0x6b206574 +// <<< 16 with PSHUFB +DATA ·rol16<>+0x00(SB)/8, $0x0504070601000302 +DATA ·rol16<>+0x08(SB)/8, $0x0D0C0F0E09080B0A +DATA ·rol16<>+0x10(SB)/8, $0x0504070601000302 +DATA ·rol16<>+0x18(SB)/8, $0x0D0C0F0E09080B0A +// <<< 8 with PSHUFB +DATA ·rol8<>+0x00(SB)/8, $0x0605040702010003 +DATA ·rol8<>+0x08(SB)/8, $0x0E0D0C0F0A09080B +DATA ·rol8<>+0x10(SB)/8, $0x0605040702010003 +DATA ·rol8<>+0x18(SB)/8, $0x0E0D0C0F0A09080B + +DATA ·avx2InitMask<>+0x00(SB)/8, $0x0 +DATA ·avx2InitMask<>+0x08(SB)/8, $0x0 +DATA ·avx2InitMask<>+0x10(SB)/8, $0x1 +DATA ·avx2InitMask<>+0x18(SB)/8, $0x0 + +DATA ·avx2IncMask<>+0x00(SB)/8, $0x2 +DATA ·avx2IncMask<>+0x08(SB)/8, $0x0 +DATA ·avx2IncMask<>+0x10(SB)/8, $0x2 +DATA ·avx2IncMask<>+0x18(SB)/8, $0x0 +// Poly1305 key clamp +DATA ·polyClampMask<>+0x00(SB)/8, $0x0FFFFFFC0FFFFFFF +DATA ·polyClampMask<>+0x08(SB)/8, $0x0FFFFFFC0FFFFFFC +DATA ·polyClampMask<>+0x10(SB)/8, $0xFFFFFFFFFFFFFFFF +DATA ·polyClampMask<>+0x18(SB)/8, $0xFFFFFFFFFFFFFFFF + +DATA ·sseIncMask<>+0x00(SB)/8, $0x1 +DATA ·sseIncMask<>+0x08(SB)/8, $0x0 +// To load/store the last < 16 bytes in a buffer +DATA ·andMask<>+0x00(SB)/8, $0x00000000000000ff +DATA ·andMask<>+0x08(SB)/8, $0x0000000000000000 +DATA ·andMask<>+0x10(SB)/8, $0x000000000000ffff +DATA ·andMask<>+0x18(SB)/8, $0x0000000000000000 +DATA ·andMask<>+0x20(SB)/8, $0x0000000000ffffff +DATA ·andMask<>+0x28(SB)/8, $0x0000000000000000 +DATA ·andMask<>+0x30(SB)/8, $0x00000000ffffffff +DATA ·andMask<>+0x38(SB)/8, $0x0000000000000000 +DATA ·andMask<>+0x40(SB)/8, $0x000000ffffffffff +DATA ·andMask<>+0x48(SB)/8, $0x0000000000000000 +DATA ·andMask<>+0x50(SB)/8, $0x0000ffffffffffff +DATA ·andMask<>+0x58(SB)/8, $0x0000000000000000 +DATA ·andMask<>+0x60(SB)/8, $0x00ffffffffffffff +DATA ·andMask<>+0x68(SB)/8, $0x0000000000000000 +DATA ·andMask<>+0x70(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+0x78(SB)/8, $0x0000000000000000 +DATA ·andMask<>+0x80(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+0x88(SB)/8, $0x00000000000000ff +DATA ·andMask<>+0x90(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+0x98(SB)/8, $0x000000000000ffff +DATA ·andMask<>+0xa0(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+0xa8(SB)/8, $0x0000000000ffffff +DATA ·andMask<>+0xb0(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+0xb8(SB)/8, $0x00000000ffffffff +DATA ·andMask<>+0xc0(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+0xc8(SB)/8, $0x000000ffffffffff +DATA ·andMask<>+0xd0(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+0xd8(SB)/8, $0x0000ffffffffffff +DATA ·andMask<>+0xe0(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+0xe8(SB)/8, $0x00ffffffffffffff + +GLOBL ·chacha20Constants<>(SB), (NOPTR+RODATA), $32 +GLOBL ·rol16<>(SB), (NOPTR+RODATA), $32 +GLOBL ·rol8<>(SB), (NOPTR+RODATA), $32 +GLOBL ·sseIncMask<>(SB), (NOPTR+RODATA), $16 +GLOBL ·avx2IncMask<>(SB), (NOPTR+RODATA), $32 +GLOBL ·avx2InitMask<>(SB), (NOPTR+RODATA), $32 +GLOBL ·polyClampMask<>(SB), (NOPTR+RODATA), $32 +GLOBL ·andMask<>(SB), (NOPTR+RODATA), $240 +// No PALIGNR in Go ASM yet (but VPALIGNR is present). +#define shiftB0Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xdb; BYTE $0x04 // PALIGNR $4, X3, X3 +#define shiftB1Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xe4; BYTE $0x04 // PALIGNR $4, X4, X4 +#define shiftB2Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xed; BYTE $0x04 // PALIGNR $4, X5, X5 +#define shiftB3Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xed; BYTE $0x04 // PALIGNR $4, X13, X13 +#define shiftC0Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xf6; BYTE $0x08 // PALIGNR $8, X6, X6 +#define shiftC1Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xff; BYTE $0x08 // PALIGNR $8, X7, X7 +#define shiftC2Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xc0; BYTE $0x08 // PALIGNR $8, X8, X8 +#define shiftC3Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xf6; BYTE $0x08 // PALIGNR $8, X14, X14 +#define shiftD0Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xc9; BYTE $0x0c // PALIGNR $12, X9, X9 +#define shiftD1Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xd2; BYTE $0x0c // PALIGNR $12, X10, X10 +#define shiftD2Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xdb; BYTE $0x0c // PALIGNR $12, X11, X11 +#define shiftD3Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xff; BYTE $0x0c // PALIGNR $12, X15, X15 +#define shiftB0Right BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xdb; BYTE $0x0c // PALIGNR $12, X3, X3 +#define shiftB1Right BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xe4; BYTE $0x0c // PALIGNR $12, X4, X4 +#define shiftB2Right BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xed; BYTE $0x0c // PALIGNR $12, X5, X5 +#define shiftB3Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xed; BYTE $0x0c // PALIGNR $12, X13, X13 +#define shiftC0Right shiftC0Left +#define shiftC1Right shiftC1Left +#define shiftC2Right shiftC2Left +#define shiftC3Right shiftC3Left +#define shiftD0Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xc9; BYTE $0x04 // PALIGNR $4, X9, X9 +#define shiftD1Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xd2; BYTE $0x04 // PALIGNR $4, X10, X10 +#define shiftD2Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xdb; BYTE $0x04 // PALIGNR $4, X11, X11 +#define shiftD3Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xff; BYTE $0x04 // PALIGNR $4, X15, X15 +// Some macros +#define chachaQR(A, B, C, D, T) \ + PADDD B, A; PXOR A, D; PSHUFB ·rol16<>(SB), D \ + PADDD D, C; PXOR C, B; MOVO B, T; PSLLL $12, T; PSRLL $20, B; PXOR T, B \ + PADDD B, A; PXOR A, D; PSHUFB ·rol8<>(SB), D \ + PADDD D, C; PXOR C, B; MOVO B, T; PSLLL $7, T; PSRLL $25, B; PXOR T, B + +#define chachaQR_AVX2(A, B, C, D, T) \ + VPADDD B, A, A; VPXOR A, D, D; VPSHUFB ·rol16<>(SB), D, D \ + VPADDD D, C, C; VPXOR C, B, B; VPSLLD $12, B, T; VPSRLD $20, B, B; VPXOR T, B, B \ + VPADDD B, A, A; VPXOR A, D, D; VPSHUFB ·rol8<>(SB), D, D \ + VPADDD D, C, C; VPXOR C, B, B; VPSLLD $7, B, T; VPSRLD $25, B, B; VPXOR T, B, B + +#define polyAdd(S) ADDQ S, acc0; ADCQ 8+S, acc1; ADCQ $1, acc2 +#define polyMulStage1 MOVQ (0*8)(BP), AX; MOVQ AX, t2; MULQ acc0; MOVQ AX, t0; MOVQ DX, t1; MOVQ (0*8)(BP), AX; MULQ acc1; IMULQ acc2, t2; ADDQ AX, t1; ADCQ DX, t2 +#define polyMulStage2 MOVQ (1*8)(BP), AX; MOVQ AX, t3; MULQ acc0; ADDQ AX, t1; ADCQ $0, DX; MOVQ DX, acc0; MOVQ (1*8)(BP), AX; MULQ acc1; ADDQ AX, t2; ADCQ $0, DX +#define polyMulStage3 IMULQ acc2, t3; ADDQ acc0, t2; ADCQ DX, t3 +#define polyMulReduceStage MOVQ t0, acc0; MOVQ t1, acc1; MOVQ t2, acc2; ANDQ $3, acc2; MOVQ t2, t0; ANDQ $-4, t0; MOVQ t3, t1; SHRQ $2, t2:t3; SHRQ $2, t3; ADDQ t0, acc0; ADCQ t1, acc1; ADCQ $0, acc2; ADDQ t2, acc0; ADCQ t3, acc1; ADCQ $0, acc2 + +#define polyMulStage1_AVX2 MOVQ (0*8)(BP), DX; MOVQ DX, t2; MULXQ acc0, t0, t1; IMULQ acc2, t2; MULXQ acc1, AX, DX; ADDQ AX, t1; ADCQ DX, t2 +#define polyMulStage2_AVX2 MOVQ (1*8)(BP), DX; MULXQ acc0, acc0, AX; ADDQ acc0, t1; MULXQ acc1, acc1, t3; ADCQ acc1, t2; ADCQ $0, t3 +#define polyMulStage3_AVX2 IMULQ acc2, DX; ADDQ AX, t2; ADCQ DX, t3 + +#define polyMul polyMulStage1; polyMulStage2; polyMulStage3; polyMulReduceStage +#define polyMulAVX2 polyMulStage1_AVX2; polyMulStage2_AVX2; polyMulStage3_AVX2; polyMulReduceStage +// ---------------------------------------------------------------------------- +TEXT polyHashADInternal<>(SB), NOSPLIT, $0 + // adp points to beginning of additional data + // itr2 holds ad length + XORQ acc0, acc0 + XORQ acc1, acc1 + XORQ acc2, acc2 + CMPQ itr2, $13 + JNE hashADLoop + +openFastTLSAD: + // Special treatment for the TLS case of 13 bytes + MOVQ (adp), acc0 + MOVQ 5(adp), acc1 + SHRQ $24, acc1 + MOVQ $1, acc2 + polyMul + RET + +hashADLoop: + // Hash in 16 byte chunks + CMPQ itr2, $16 + JB hashADTail + polyAdd(0(adp)) + LEAQ (1*16)(adp), adp + SUBQ $16, itr2 + polyMul + JMP hashADLoop + +hashADTail: + CMPQ itr2, $0 + JE hashADDone + + // Hash last < 16 byte tail + XORQ t0, t0 + XORQ t1, t1 + XORQ t2, t2 + ADDQ itr2, adp + +hashADTailLoop: + SHLQ $8, t1:t0 + SHLQ $8, t0 + MOVB -1(adp), t2 + XORQ t2, t0 + DECQ adp + DECQ itr2 + JNE hashADTailLoop + +hashADTailFinish: + ADDQ t0, acc0; ADCQ t1, acc1; ADCQ $1, acc2 + polyMul + + // Finished AD +hashADDone: + RET + +// ---------------------------------------------------------------------------- +// func chacha20Poly1305Open(dst, key, src, ad []byte) bool +TEXT ·chacha20Poly1305Open(SB), 0, $288-97 + // For aligned stack access + MOVQ SP, BP + ADDQ $32, BP + ANDQ $-32, BP + MOVQ dst+0(FP), oup + MOVQ key+24(FP), keyp + MOVQ src+48(FP), inp + MOVQ src_len+56(FP), inl + MOVQ ad+72(FP), adp + + // Check for AVX2 support + CMPB ·useAVX2(SB), $1 + JE chacha20Poly1305Open_AVX2 + + // Special optimization, for very short buffers + CMPQ inl, $128 + JBE openSSE128 // About 16% faster + + // For long buffers, prepare the poly key first + MOVOU ·chacha20Constants<>(SB), A0 + MOVOU (1*16)(keyp), B0 + MOVOU (2*16)(keyp), C0 + MOVOU (3*16)(keyp), D0 + MOVO D0, T1 + + // Store state on stack for future use + MOVO B0, state1Store + MOVO C0, state2Store + MOVO D0, ctr3Store + MOVQ $10, itr2 + +openSSEPreparePolyKey: + chachaQR(A0, B0, C0, D0, T0) + shiftB0Left; shiftC0Left; shiftD0Left + chachaQR(A0, B0, C0, D0, T0) + shiftB0Right; shiftC0Right; shiftD0Right + DECQ itr2 + JNE openSSEPreparePolyKey + + // A0|B0 hold the Poly1305 32-byte key, C0,D0 can be discarded + PADDL ·chacha20Constants<>(SB), A0; PADDL state1Store, B0 + + // Clamp and store the key + PAND ·polyClampMask<>(SB), A0 + MOVO A0, rStore; MOVO B0, sStore + + // Hash AAD + MOVQ ad_len+80(FP), itr2 + CALL polyHashADInternal<>(SB) + +openSSEMainLoop: + CMPQ inl, $256 + JB openSSEMainLoopDone + + // Load state, increment counter blocks + MOVO ·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL ·sseIncMask<>(SB), D0 + MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1 + MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2 + MOVO A2, A3; MOVO B2, B3; MOVO C2, C3; MOVO D2, D3; PADDL ·sseIncMask<>(SB), D3 + + // Store counters + MOVO D0, ctr0Store; MOVO D1, ctr1Store; MOVO D2, ctr2Store; MOVO D3, ctr3Store + + // There are 10 ChaCha20 iterations of 2QR each, so for 6 iterations we hash 2 blocks, and for the remaining 4 only 1 block - for a total of 16 + MOVQ $4, itr1 + MOVQ inp, itr2 + +openSSEInternalLoop: + MOVO C3, tmpStore + chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) + MOVO tmpStore, C3 + MOVO C1, tmpStore + chachaQR(A3, B3, C3, D3, C1) + MOVO tmpStore, C1 + polyAdd(0(itr2)) + shiftB0Left; shiftB1Left; shiftB2Left; shiftB3Left + shiftC0Left; shiftC1Left; shiftC2Left; shiftC3Left + shiftD0Left; shiftD1Left; shiftD2Left; shiftD3Left + polyMulStage1 + polyMulStage2 + LEAQ (2*8)(itr2), itr2 + MOVO C3, tmpStore + chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) + MOVO tmpStore, C3 + MOVO C1, tmpStore + polyMulStage3 + chachaQR(A3, B3, C3, D3, C1) + MOVO tmpStore, C1 + polyMulReduceStage + shiftB0Right; shiftB1Right; shiftB2Right; shiftB3Right + shiftC0Right; shiftC1Right; shiftC2Right; shiftC3Right + shiftD0Right; shiftD1Right; shiftD2Right; shiftD3Right + DECQ itr1 + JGE openSSEInternalLoop + + polyAdd(0(itr2)) + polyMul + LEAQ (2*8)(itr2), itr2 + + CMPQ itr1, $-6 + JG openSSEInternalLoop + + // Add in the state + PADDD ·chacha20Constants<>(SB), A0; PADDD ·chacha20Constants<>(SB), A1; PADDD ·chacha20Constants<>(SB), A2; PADDD ·chacha20Constants<>(SB), A3 + PADDD state1Store, B0; PADDD state1Store, B1; PADDD state1Store, B2; PADDD state1Store, B3 + PADDD state2Store, C0; PADDD state2Store, C1; PADDD state2Store, C2; PADDD state2Store, C3 + PADDD ctr0Store, D0; PADDD ctr1Store, D1; PADDD ctr2Store, D2; PADDD ctr3Store, D3 + + // Load - xor - store + MOVO D3, tmpStore + MOVOU (0*16)(inp), D3; PXOR D3, A0; MOVOU A0, (0*16)(oup) + MOVOU (1*16)(inp), D3; PXOR D3, B0; MOVOU B0, (1*16)(oup) + MOVOU (2*16)(inp), D3; PXOR D3, C0; MOVOU C0, (2*16)(oup) + MOVOU (3*16)(inp), D3; PXOR D3, D0; MOVOU D0, (3*16)(oup) + MOVOU (4*16)(inp), D0; PXOR D0, A1; MOVOU A1, (4*16)(oup) + MOVOU (5*16)(inp), D0; PXOR D0, B1; MOVOU B1, (5*16)(oup) + MOVOU (6*16)(inp), D0; PXOR D0, C1; MOVOU C1, (6*16)(oup) + MOVOU (7*16)(inp), D0; PXOR D0, D1; MOVOU D1, (7*16)(oup) + MOVOU (8*16)(inp), D0; PXOR D0, A2; MOVOU A2, (8*16)(oup) + MOVOU (9*16)(inp), D0; PXOR D0, B2; MOVOU B2, (9*16)(oup) + MOVOU (10*16)(inp), D0; PXOR D0, C2; MOVOU C2, (10*16)(oup) + MOVOU (11*16)(inp), D0; PXOR D0, D2; MOVOU D2, (11*16)(oup) + MOVOU (12*16)(inp), D0; PXOR D0, A3; MOVOU A3, (12*16)(oup) + MOVOU (13*16)(inp), D0; PXOR D0, B3; MOVOU B3, (13*16)(oup) + MOVOU (14*16)(inp), D0; PXOR D0, C3; MOVOU C3, (14*16)(oup) + MOVOU (15*16)(inp), D0; PXOR tmpStore, D0; MOVOU D0, (15*16)(oup) + LEAQ 256(inp), inp + LEAQ 256(oup), oup + SUBQ $256, inl + JMP openSSEMainLoop + +openSSEMainLoopDone: + // Handle the various tail sizes efficiently + TESTQ inl, inl + JE openSSEFinalize + CMPQ inl, $64 + JBE openSSETail64 + CMPQ inl, $128 + JBE openSSETail128 + CMPQ inl, $192 + JBE openSSETail192 + JMP openSSETail256 + +openSSEFinalize: + // Hash in the PT, AAD lengths + ADDQ ad_len+80(FP), acc0; ADCQ src_len+56(FP), acc1; ADCQ $1, acc2 + polyMul + + // Final reduce + MOVQ acc0, t0 + MOVQ acc1, t1 + MOVQ acc2, t2 + SUBQ $-5, acc0 + SBBQ $-1, acc1 + SBBQ $3, acc2 + CMOVQCS t0, acc0 + CMOVQCS t1, acc1 + CMOVQCS t2, acc2 + + // Add in the "s" part of the key + ADDQ 0+sStore, acc0 + ADCQ 8+sStore, acc1 + + // Finally, constant time compare to the tag at the end of the message + XORQ AX, AX + MOVQ $1, DX + XORQ (0*8)(inp), acc0 + XORQ (1*8)(inp), acc1 + ORQ acc1, acc0 + CMOVQEQ DX, AX + + // Return true iff tags are equal + MOVB AX, ret+96(FP) + RET + +// ---------------------------------------------------------------------------- +// Special optimization for buffers smaller than 129 bytes +openSSE128: + // For up to 128 bytes of ciphertext and 64 bytes for the poly key, we require to process three blocks + MOVOU ·chacha20Constants<>(SB), A0; MOVOU (1*16)(keyp), B0; MOVOU (2*16)(keyp), C0; MOVOU (3*16)(keyp), D0 + MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1 + MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2 + MOVO B0, T1; MOVO C0, T2; MOVO D1, T3 + MOVQ $10, itr2 + +openSSE128InnerCipherLoop: + chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) + shiftB0Left; shiftB1Left; shiftB2Left + shiftC0Left; shiftC1Left; shiftC2Left + shiftD0Left; shiftD1Left; shiftD2Left + chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) + shiftB0Right; shiftB1Right; shiftB2Right + shiftC0Right; shiftC1Right; shiftC2Right + shiftD0Right; shiftD1Right; shiftD2Right + DECQ itr2 + JNE openSSE128InnerCipherLoop + + // A0|B0 hold the Poly1305 32-byte key, C0,D0 can be discarded + PADDL ·chacha20Constants<>(SB), A0; PADDL ·chacha20Constants<>(SB), A1; PADDL ·chacha20Constants<>(SB), A2 + PADDL T1, B0; PADDL T1, B1; PADDL T1, B2 + PADDL T2, C1; PADDL T2, C2 + PADDL T3, D1; PADDL ·sseIncMask<>(SB), T3; PADDL T3, D2 + + // Clamp and store the key + PAND ·polyClampMask<>(SB), A0 + MOVOU A0, rStore; MOVOU B0, sStore + + // Hash + MOVQ ad_len+80(FP), itr2 + CALL polyHashADInternal<>(SB) + +openSSE128Open: + CMPQ inl, $16 + JB openSSETail16 + SUBQ $16, inl + + // Load for hashing + polyAdd(0(inp)) + + // Load for decryption + MOVOU (inp), T0; PXOR T0, A1; MOVOU A1, (oup) + LEAQ (1*16)(inp), inp + LEAQ (1*16)(oup), oup + polyMul + + // Shift the stream "left" + MOVO B1, A1 + MOVO C1, B1 + MOVO D1, C1 + MOVO A2, D1 + MOVO B2, A2 + MOVO C2, B2 + MOVO D2, C2 + JMP openSSE128Open + +openSSETail16: + TESTQ inl, inl + JE openSSEFinalize + + // We can safely load the CT from the end, because it is padded with the MAC + MOVQ inl, itr2 + SHLQ $4, itr2 + LEAQ ·andMask<>(SB), t0 + MOVOU (inp), T0 + ADDQ inl, inp + PAND -16(t0)(itr2*1), T0 + MOVO T0, 0+tmpStore + MOVQ T0, t0 + MOVQ 8+tmpStore, t1 + PXOR A1, T0 + + // We can only store one byte at a time, since plaintext can be shorter than 16 bytes +openSSETail16Store: + MOVQ T0, t3 + MOVB t3, (oup) + PSRLDQ $1, T0 + INCQ oup + DECQ inl + JNE openSSETail16Store + ADDQ t0, acc0; ADCQ t1, acc1; ADCQ $1, acc2 + polyMul + JMP openSSEFinalize + +// ---------------------------------------------------------------------------- +// Special optimization for the last 64 bytes of ciphertext +openSSETail64: + // Need to decrypt up to 64 bytes - prepare single block + MOVO ·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL ·sseIncMask<>(SB), D0; MOVO D0, ctr0Store + XORQ itr2, itr2 + MOVQ inl, itr1 + CMPQ itr1, $16 + JB openSSETail64LoopB + +openSSETail64LoopA: + // Perform ChaCha rounds, while hashing the remaining input + polyAdd(0(inp)(itr2*1)) + polyMul + SUBQ $16, itr1 + +openSSETail64LoopB: + ADDQ $16, itr2 + chachaQR(A0, B0, C0, D0, T0) + shiftB0Left; shiftC0Left; shiftD0Left + chachaQR(A0, B0, C0, D0, T0) + shiftB0Right; shiftC0Right; shiftD0Right + + CMPQ itr1, $16 + JAE openSSETail64LoopA + + CMPQ itr2, $160 + JNE openSSETail64LoopB + + PADDL ·chacha20Constants<>(SB), A0; PADDL state1Store, B0; PADDL state2Store, C0; PADDL ctr0Store, D0 + +openSSETail64DecLoop: + CMPQ inl, $16 + JB openSSETail64DecLoopDone + SUBQ $16, inl + MOVOU (inp), T0 + PXOR T0, A0 + MOVOU A0, (oup) + LEAQ 16(inp), inp + LEAQ 16(oup), oup + MOVO B0, A0 + MOVO C0, B0 + MOVO D0, C0 + JMP openSSETail64DecLoop + +openSSETail64DecLoopDone: + MOVO A0, A1 + JMP openSSETail16 + +// ---------------------------------------------------------------------------- +// Special optimization for the last 128 bytes of ciphertext +openSSETail128: + // Need to decrypt up to 128 bytes - prepare two blocks + MOVO ·chacha20Constants<>(SB), A1; MOVO state1Store, B1; MOVO state2Store, C1; MOVO ctr3Store, D1; PADDL ·sseIncMask<>(SB), D1; MOVO D1, ctr0Store + MOVO A1, A0; MOVO B1, B0; MOVO C1, C0; MOVO D1, D0; PADDL ·sseIncMask<>(SB), D0; MOVO D0, ctr1Store + XORQ itr2, itr2 + MOVQ inl, itr1 + ANDQ $-16, itr1 + +openSSETail128LoopA: + // Perform ChaCha rounds, while hashing the remaining input + polyAdd(0(inp)(itr2*1)) + polyMul + +openSSETail128LoopB: + ADDQ $16, itr2 + chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0) + shiftB0Left; shiftC0Left; shiftD0Left + shiftB1Left; shiftC1Left; shiftD1Left + chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0) + shiftB0Right; shiftC0Right; shiftD0Right + shiftB1Right; shiftC1Right; shiftD1Right + + CMPQ itr2, itr1 + JB openSSETail128LoopA + + CMPQ itr2, $160 + JNE openSSETail128LoopB + + PADDL ·chacha20Constants<>(SB), A0; PADDL ·chacha20Constants<>(SB), A1 + PADDL state1Store, B0; PADDL state1Store, B1 + PADDL state2Store, C0; PADDL state2Store, C1 + PADDL ctr1Store, D0; PADDL ctr0Store, D1 + + MOVOU (0*16)(inp), T0; MOVOU (1*16)(inp), T1; MOVOU (2*16)(inp), T2; MOVOU (3*16)(inp), T3 + PXOR T0, A1; PXOR T1, B1; PXOR T2, C1; PXOR T3, D1 + MOVOU A1, (0*16)(oup); MOVOU B1, (1*16)(oup); MOVOU C1, (2*16)(oup); MOVOU D1, (3*16)(oup) + + SUBQ $64, inl + LEAQ 64(inp), inp + LEAQ 64(oup), oup + JMP openSSETail64DecLoop + +// ---------------------------------------------------------------------------- +// Special optimization for the last 192 bytes of ciphertext +openSSETail192: + // Need to decrypt up to 192 bytes - prepare three blocks + MOVO ·chacha20Constants<>(SB), A2; MOVO state1Store, B2; MOVO state2Store, C2; MOVO ctr3Store, D2; PADDL ·sseIncMask<>(SB), D2; MOVO D2, ctr0Store + MOVO A2, A1; MOVO B2, B1; MOVO C2, C1; MOVO D2, D1; PADDL ·sseIncMask<>(SB), D1; MOVO D1, ctr1Store + MOVO A1, A0; MOVO B1, B0; MOVO C1, C0; MOVO D1, D0; PADDL ·sseIncMask<>(SB), D0; MOVO D0, ctr2Store + + MOVQ inl, itr1 + MOVQ $160, itr2 + CMPQ itr1, $160 + CMOVQGT itr2, itr1 + ANDQ $-16, itr1 + XORQ itr2, itr2 + +openSSLTail192LoopA: + // Perform ChaCha rounds, while hashing the remaining input + polyAdd(0(inp)(itr2*1)) + polyMul + +openSSLTail192LoopB: + ADDQ $16, itr2 + chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) + shiftB0Left; shiftC0Left; shiftD0Left + shiftB1Left; shiftC1Left; shiftD1Left + shiftB2Left; shiftC2Left; shiftD2Left + + chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) + shiftB0Right; shiftC0Right; shiftD0Right + shiftB1Right; shiftC1Right; shiftD1Right + shiftB2Right; shiftC2Right; shiftD2Right + + CMPQ itr2, itr1 + JB openSSLTail192LoopA + + CMPQ itr2, $160 + JNE openSSLTail192LoopB + + CMPQ inl, $176 + JB openSSLTail192Store + + polyAdd(160(inp)) + polyMul + + CMPQ inl, $192 + JB openSSLTail192Store + + polyAdd(176(inp)) + polyMul + +openSSLTail192Store: + PADDL ·chacha20Constants<>(SB), A0; PADDL ·chacha20Constants<>(SB), A1; PADDL ·chacha20Constants<>(SB), A2 + PADDL state1Store, B0; PADDL state1Store, B1; PADDL state1Store, B2 + PADDL state2Store, C0; PADDL state2Store, C1; PADDL state2Store, C2 + PADDL ctr2Store, D0; PADDL ctr1Store, D1; PADDL ctr0Store, D2 + + MOVOU (0*16)(inp), T0; MOVOU (1*16)(inp), T1; MOVOU (2*16)(inp), T2; MOVOU (3*16)(inp), T3 + PXOR T0, A2; PXOR T1, B2; PXOR T2, C2; PXOR T3, D2 + MOVOU A2, (0*16)(oup); MOVOU B2, (1*16)(oup); MOVOU C2, (2*16)(oup); MOVOU D2, (3*16)(oup) + + MOVOU (4*16)(inp), T0; MOVOU (5*16)(inp), T1; MOVOU (6*16)(inp), T2; MOVOU (7*16)(inp), T3 + PXOR T0, A1; PXOR T1, B1; PXOR T2, C1; PXOR T3, D1 + MOVOU A1, (4*16)(oup); MOVOU B1, (5*16)(oup); MOVOU C1, (6*16)(oup); MOVOU D1, (7*16)(oup) + + SUBQ $128, inl + LEAQ 128(inp), inp + LEAQ 128(oup), oup + JMP openSSETail64DecLoop + +// ---------------------------------------------------------------------------- +// Special optimization for the last 256 bytes of ciphertext +openSSETail256: + // Need to decrypt up to 256 bytes - prepare four blocks + MOVO ·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL ·sseIncMask<>(SB), D0 + MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1 + MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2 + MOVO A2, A3; MOVO B2, B3; MOVO C2, C3; MOVO D2, D3; PADDL ·sseIncMask<>(SB), D3 + + // Store counters + MOVO D0, ctr0Store; MOVO D1, ctr1Store; MOVO D2, ctr2Store; MOVO D3, ctr3Store + XORQ itr2, itr2 + +openSSETail256Loop: + // This loop inteleaves 8 ChaCha quarter rounds with 1 poly multiplication + polyAdd(0(inp)(itr2*1)) + MOVO C3, tmpStore + chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) + MOVO tmpStore, C3 + MOVO C1, tmpStore + chachaQR(A3, B3, C3, D3, C1) + MOVO tmpStore, C1 + shiftB0Left; shiftB1Left; shiftB2Left; shiftB3Left + shiftC0Left; shiftC1Left; shiftC2Left; shiftC3Left + shiftD0Left; shiftD1Left; shiftD2Left; shiftD3Left + polyMulStage1 + polyMulStage2 + MOVO C3, tmpStore + chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) + MOVO tmpStore, C3 + MOVO C1, tmpStore + chachaQR(A3, B3, C3, D3, C1) + MOVO tmpStore, C1 + polyMulStage3 + polyMulReduceStage + shiftB0Right; shiftB1Right; shiftB2Right; shiftB3Right + shiftC0Right; shiftC1Right; shiftC2Right; shiftC3Right + shiftD0Right; shiftD1Right; shiftD2Right; shiftD3Right + ADDQ $2*8, itr2 + CMPQ itr2, $160 + JB openSSETail256Loop + MOVQ inl, itr1 + ANDQ $-16, itr1 + +openSSETail256HashLoop: + polyAdd(0(inp)(itr2*1)) + polyMul + ADDQ $2*8, itr2 + CMPQ itr2, itr1 + JB openSSETail256HashLoop + + // Add in the state + PADDD ·chacha20Constants<>(SB), A0; PADDD ·chacha20Constants<>(SB), A1; PADDD ·chacha20Constants<>(SB), A2; PADDD ·chacha20Constants<>(SB), A3 + PADDD state1Store, B0; PADDD state1Store, B1; PADDD state1Store, B2; PADDD state1Store, B3 + PADDD state2Store, C0; PADDD state2Store, C1; PADDD state2Store, C2; PADDD state2Store, C3 + PADDD ctr0Store, D0; PADDD ctr1Store, D1; PADDD ctr2Store, D2; PADDD ctr3Store, D3 + MOVO D3, tmpStore + + // Load - xor - store + MOVOU (0*16)(inp), D3; PXOR D3, A0 + MOVOU (1*16)(inp), D3; PXOR D3, B0 + MOVOU (2*16)(inp), D3; PXOR D3, C0 + MOVOU (3*16)(inp), D3; PXOR D3, D0 + MOVOU A0, (0*16)(oup) + MOVOU B0, (1*16)(oup) + MOVOU C0, (2*16)(oup) + MOVOU D0, (3*16)(oup) + MOVOU (4*16)(inp), A0; MOVOU (5*16)(inp), B0; MOVOU (6*16)(inp), C0; MOVOU (7*16)(inp), D0 + PXOR A0, A1; PXOR B0, B1; PXOR C0, C1; PXOR D0, D1 + MOVOU A1, (4*16)(oup); MOVOU B1, (5*16)(oup); MOVOU C1, (6*16)(oup); MOVOU D1, (7*16)(oup) + MOVOU (8*16)(inp), A0; MOVOU (9*16)(inp), B0; MOVOU (10*16)(inp), C0; MOVOU (11*16)(inp), D0 + PXOR A0, A2; PXOR B0, B2; PXOR C0, C2; PXOR D0, D2 + MOVOU A2, (8*16)(oup); MOVOU B2, (9*16)(oup); MOVOU C2, (10*16)(oup); MOVOU D2, (11*16)(oup) + LEAQ 192(inp), inp + LEAQ 192(oup), oup + SUBQ $192, inl + MOVO A3, A0 + MOVO B3, B0 + MOVO C3, C0 + MOVO tmpStore, D0 + + JMP openSSETail64DecLoop + +// ---------------------------------------------------------------------------- +// ------------------------- AVX2 Code ---------------------------------------- +chacha20Poly1305Open_AVX2: + VZEROUPPER + VMOVDQU ·chacha20Constants<>(SB), AA0 + BYTE $0xc4; BYTE $0x42; BYTE $0x7d; BYTE $0x5a; BYTE $0x70; BYTE $0x10 // broadcasti128 16(r8), ymm14 + BYTE $0xc4; BYTE $0x42; BYTE $0x7d; BYTE $0x5a; BYTE $0x60; BYTE $0x20 // broadcasti128 32(r8), ymm12 + BYTE $0xc4; BYTE $0xc2; BYTE $0x7d; BYTE $0x5a; BYTE $0x60; BYTE $0x30 // broadcasti128 48(r8), ymm4 + VPADDD ·avx2InitMask<>(SB), DD0, DD0 + + // Special optimization, for very short buffers + CMPQ inl, $192 + JBE openAVX2192 + CMPQ inl, $320 + JBE openAVX2320 + + // For the general key prepare the key first - as a byproduct we have 64 bytes of cipher stream + VMOVDQA BB0, state1StoreAVX2 + VMOVDQA CC0, state2StoreAVX2 + VMOVDQA DD0, ctr3StoreAVX2 + MOVQ $10, itr2 + +openAVX2PreparePolyKey: + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) + VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $12, DD0, DD0, DD0 + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) + VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $4, DD0, DD0, DD0 + DECQ itr2 + JNE openAVX2PreparePolyKey + + VPADDD ·chacha20Constants<>(SB), AA0, AA0 + VPADDD state1StoreAVX2, BB0, BB0 + VPADDD state2StoreAVX2, CC0, CC0 + VPADDD ctr3StoreAVX2, DD0, DD0 + + VPERM2I128 $0x02, AA0, BB0, TT0 + + // Clamp and store poly key + VPAND ·polyClampMask<>(SB), TT0, TT0 + VMOVDQA TT0, rsStoreAVX2 + + // Stream for the first 64 bytes + VPERM2I128 $0x13, AA0, BB0, AA0 + VPERM2I128 $0x13, CC0, DD0, BB0 + + // Hash AD + first 64 bytes + MOVQ ad_len+80(FP), itr2 + CALL polyHashADInternal<>(SB) + XORQ itr1, itr1 + +openAVX2InitialHash64: + polyAdd(0(inp)(itr1*1)) + polyMulAVX2 + ADDQ $16, itr1 + CMPQ itr1, $64 + JNE openAVX2InitialHash64 + + // Decrypt the first 64 bytes + VPXOR (0*32)(inp), AA0, AA0 + VPXOR (1*32)(inp), BB0, BB0 + VMOVDQU AA0, (0*32)(oup) + VMOVDQU BB0, (1*32)(oup) + LEAQ (2*32)(inp), inp + LEAQ (2*32)(oup), oup + SUBQ $64, inl + +openAVX2MainLoop: + CMPQ inl, $512 + JB openAVX2MainLoopDone + + // Load state, increment counter blocks, store the incremented counters + VMOVDQU ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3 + VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3 + VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3 + VMOVDQA ctr3StoreAVX2, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD1; VPADDD ·avx2IncMask<>(SB), DD1, DD2; VPADDD ·avx2IncMask<>(SB), DD2, DD3 + VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2 + XORQ itr1, itr1 + +openAVX2InternalLoop: + // Lets just say this spaghetti loop interleaves 2 quarter rounds with 3 poly multiplications + // Effectively per 512 bytes of stream we hash 480 bytes of ciphertext + polyAdd(0*8(inp)(itr1*1)) + VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 + polyMulStage1_AVX2 + VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 + VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3 + polyMulStage2_AVX2 + VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 + VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 + polyMulStage3_AVX2 + VMOVDQA CC3, tmpStoreAVX2 + VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 + VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 + VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 + VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 + VMOVDQA tmpStoreAVX2, CC3 + polyMulReduceStage + VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 + VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 + VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3 + polyAdd(2*8(inp)(itr1*1)) + VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 + polyMulStage1_AVX2 + VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 + VMOVDQA CC3, tmpStoreAVX2 + VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 + VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 + VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 + VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 + VMOVDQA tmpStoreAVX2, CC3 + polyMulStage2_AVX2 + VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $4, BB3, BB3, BB3 + VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 + VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2; VPALIGNR $12, DD3, DD3, DD3 + VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 + polyMulStage3_AVX2 + VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 + VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3 + polyMulReduceStage + VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 + VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 + polyAdd(4*8(inp)(itr1*1)) + LEAQ (6*8)(itr1), itr1 + VMOVDQA CC3, tmpStoreAVX2 + VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 + VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 + VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 + VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 + VMOVDQA tmpStoreAVX2, CC3 + polyMulStage1_AVX2 + VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 + VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 + polyMulStage2_AVX2 + VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3 + VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 + polyMulStage3_AVX2 + VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 + VMOVDQA CC3, tmpStoreAVX2 + VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 + VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 + VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 + VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 + VMOVDQA tmpStoreAVX2, CC3 + polyMulReduceStage + VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $12, BB3, BB3, BB3 + VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 + VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2; VPALIGNR $4, DD3, DD3, DD3 + CMPQ itr1, $480 + JNE openAVX2InternalLoop + + VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2; VPADDD ·chacha20Constants<>(SB), AA3, AA3 + VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3 + VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3 + VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3 + VMOVDQA CC3, tmpStoreAVX2 + + // We only hashed 480 of the 512 bytes available - hash the remaining 32 here + polyAdd(480(inp)) + polyMulAVX2 + VPERM2I128 $0x02, AA0, BB0, CC3; VPERM2I128 $0x13, AA0, BB0, BB0; VPERM2I128 $0x02, CC0, DD0, AA0; VPERM2I128 $0x13, CC0, DD0, CC0 + VPXOR (0*32)(inp), CC3, CC3; VPXOR (1*32)(inp), AA0, AA0; VPXOR (2*32)(inp), BB0, BB0; VPXOR (3*32)(inp), CC0, CC0 + VMOVDQU CC3, (0*32)(oup); VMOVDQU AA0, (1*32)(oup); VMOVDQU BB0, (2*32)(oup); VMOVDQU CC0, (3*32)(oup) + VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0 + VPXOR (4*32)(inp), AA0, AA0; VPXOR (5*32)(inp), BB0, BB0; VPXOR (6*32)(inp), CC0, CC0; VPXOR (7*32)(inp), DD0, DD0 + VMOVDQU AA0, (4*32)(oup); VMOVDQU BB0, (5*32)(oup); VMOVDQU CC0, (6*32)(oup); VMOVDQU DD0, (7*32)(oup) + + // and here + polyAdd(496(inp)) + polyMulAVX2 + VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0 + VPXOR (8*32)(inp), AA0, AA0; VPXOR (9*32)(inp), BB0, BB0; VPXOR (10*32)(inp), CC0, CC0; VPXOR (11*32)(inp), DD0, DD0 + VMOVDQU AA0, (8*32)(oup); VMOVDQU BB0, (9*32)(oup); VMOVDQU CC0, (10*32)(oup); VMOVDQU DD0, (11*32)(oup) + VPERM2I128 $0x02, AA3, BB3, AA0; VPERM2I128 $0x02, tmpStoreAVX2, DD3, BB0; VPERM2I128 $0x13, AA3, BB3, CC0; VPERM2I128 $0x13, tmpStoreAVX2, DD3, DD0 + VPXOR (12*32)(inp), AA0, AA0; VPXOR (13*32)(inp), BB0, BB0; VPXOR (14*32)(inp), CC0, CC0; VPXOR (15*32)(inp), DD0, DD0 + VMOVDQU AA0, (12*32)(oup); VMOVDQU BB0, (13*32)(oup); VMOVDQU CC0, (14*32)(oup); VMOVDQU DD0, (15*32)(oup) + LEAQ (32*16)(inp), inp + LEAQ (32*16)(oup), oup + SUBQ $(32*16), inl + JMP openAVX2MainLoop + +openAVX2MainLoopDone: + // Handle the various tail sizes efficiently + TESTQ inl, inl + JE openSSEFinalize + CMPQ inl, $128 + JBE openAVX2Tail128 + CMPQ inl, $256 + JBE openAVX2Tail256 + CMPQ inl, $384 + JBE openAVX2Tail384 + JMP openAVX2Tail512 + +// ---------------------------------------------------------------------------- +// Special optimization for buffers smaller than 193 bytes +openAVX2192: + // For up to 192 bytes of ciphertext and 64 bytes for the poly key, we process four blocks + VMOVDQA AA0, AA1 + VMOVDQA BB0, BB1 + VMOVDQA CC0, CC1 + VPADDD ·avx2IncMask<>(SB), DD0, DD1 + VMOVDQA AA0, AA2 + VMOVDQA BB0, BB2 + VMOVDQA CC0, CC2 + VMOVDQA DD0, DD2 + VMOVDQA DD1, TT3 + MOVQ $10, itr2 + +openAVX2192InnerCipherLoop: + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) + VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1 + VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 + VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1 + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) + VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1 + VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 + VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1 + DECQ itr2 + JNE openAVX2192InnerCipherLoop + VPADDD AA2, AA0, AA0; VPADDD AA2, AA1, AA1 + VPADDD BB2, BB0, BB0; VPADDD BB2, BB1, BB1 + VPADDD CC2, CC0, CC0; VPADDD CC2, CC1, CC1 + VPADDD DD2, DD0, DD0; VPADDD TT3, DD1, DD1 + VPERM2I128 $0x02, AA0, BB0, TT0 + + // Clamp and store poly key + VPAND ·polyClampMask<>(SB), TT0, TT0 + VMOVDQA TT0, rsStoreAVX2 + + // Stream for up to 192 bytes + VPERM2I128 $0x13, AA0, BB0, AA0 + VPERM2I128 $0x13, CC0, DD0, BB0 + VPERM2I128 $0x02, AA1, BB1, CC0 + VPERM2I128 $0x02, CC1, DD1, DD0 + VPERM2I128 $0x13, AA1, BB1, AA1 + VPERM2I128 $0x13, CC1, DD1, BB1 + +openAVX2ShortOpen: + // Hash + MOVQ ad_len+80(FP), itr2 + CALL polyHashADInternal<>(SB) + +openAVX2ShortOpenLoop: + CMPQ inl, $32 + JB openAVX2ShortTail32 + SUBQ $32, inl + + // Load for hashing + polyAdd(0*8(inp)) + polyMulAVX2 + polyAdd(2*8(inp)) + polyMulAVX2 + + // Load for decryption + VPXOR (inp), AA0, AA0 + VMOVDQU AA0, (oup) + LEAQ (1*32)(inp), inp + LEAQ (1*32)(oup), oup + + // Shift stream left + VMOVDQA BB0, AA0 + VMOVDQA CC0, BB0 + VMOVDQA DD0, CC0 + VMOVDQA AA1, DD0 + VMOVDQA BB1, AA1 + VMOVDQA CC1, BB1 + VMOVDQA DD1, CC1 + VMOVDQA AA2, DD1 + VMOVDQA BB2, AA2 + JMP openAVX2ShortOpenLoop + +openAVX2ShortTail32: + CMPQ inl, $16 + VMOVDQA A0, A1 + JB openAVX2ShortDone + + SUBQ $16, inl + + // Load for hashing + polyAdd(0*8(inp)) + polyMulAVX2 + + // Load for decryption + VPXOR (inp), A0, T0 + VMOVDQU T0, (oup) + LEAQ (1*16)(inp), inp + LEAQ (1*16)(oup), oup + VPERM2I128 $0x11, AA0, AA0, AA0 + VMOVDQA A0, A1 + +openAVX2ShortDone: + VZEROUPPER + JMP openSSETail16 + +// ---------------------------------------------------------------------------- +// Special optimization for buffers smaller than 321 bytes +openAVX2320: + // For up to 320 bytes of ciphertext and 64 bytes for the poly key, we process six blocks + VMOVDQA AA0, AA1; VMOVDQA BB0, BB1; VMOVDQA CC0, CC1; VPADDD ·avx2IncMask<>(SB), DD0, DD1 + VMOVDQA AA0, AA2; VMOVDQA BB0, BB2; VMOVDQA CC0, CC2; VPADDD ·avx2IncMask<>(SB), DD1, DD2 + VMOVDQA BB0, TT1; VMOVDQA CC0, TT2; VMOVDQA DD0, TT3 + MOVQ $10, itr2 + +openAVX2320InnerCipherLoop: + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) + VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2 + VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 + VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2 + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) + VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2 + VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 + VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2 + DECQ itr2 + JNE openAVX2320InnerCipherLoop + + VMOVDQA ·chacha20Constants<>(SB), TT0 + VPADDD TT0, AA0, AA0; VPADDD TT0, AA1, AA1; VPADDD TT0, AA2, AA2 + VPADDD TT1, BB0, BB0; VPADDD TT1, BB1, BB1; VPADDD TT1, BB2, BB2 + VPADDD TT2, CC0, CC0; VPADDD TT2, CC1, CC1; VPADDD TT2, CC2, CC2 + VMOVDQA ·avx2IncMask<>(SB), TT0 + VPADDD TT3, DD0, DD0; VPADDD TT0, TT3, TT3 + VPADDD TT3, DD1, DD1; VPADDD TT0, TT3, TT3 + VPADDD TT3, DD2, DD2 + + // Clamp and store poly key + VPERM2I128 $0x02, AA0, BB0, TT0 + VPAND ·polyClampMask<>(SB), TT0, TT0 + VMOVDQA TT0, rsStoreAVX2 + + // Stream for up to 320 bytes + VPERM2I128 $0x13, AA0, BB0, AA0 + VPERM2I128 $0x13, CC0, DD0, BB0 + VPERM2I128 $0x02, AA1, BB1, CC0 + VPERM2I128 $0x02, CC1, DD1, DD0 + VPERM2I128 $0x13, AA1, BB1, AA1 + VPERM2I128 $0x13, CC1, DD1, BB1 + VPERM2I128 $0x02, AA2, BB2, CC1 + VPERM2I128 $0x02, CC2, DD2, DD1 + VPERM2I128 $0x13, AA2, BB2, AA2 + VPERM2I128 $0x13, CC2, DD2, BB2 + JMP openAVX2ShortOpen + +// ---------------------------------------------------------------------------- +// Special optimization for the last 128 bytes of ciphertext +openAVX2Tail128: + // Need to decrypt up to 128 bytes - prepare two blocks + VMOVDQA ·chacha20Constants<>(SB), AA1 + VMOVDQA state1StoreAVX2, BB1 + VMOVDQA state2StoreAVX2, CC1 + VMOVDQA ctr3StoreAVX2, DD1 + VPADDD ·avx2IncMask<>(SB), DD1, DD1 + VMOVDQA DD1, DD0 + + XORQ itr2, itr2 + MOVQ inl, itr1 + ANDQ $-16, itr1 + TESTQ itr1, itr1 + JE openAVX2Tail128LoopB + +openAVX2Tail128LoopA: + // Perform ChaCha rounds, while hashing the remaining input + polyAdd(0(inp)(itr2*1)) + polyMulAVX2 + +openAVX2Tail128LoopB: + ADDQ $16, itr2 + chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) + VPALIGNR $4, BB1, BB1, BB1 + VPALIGNR $8, CC1, CC1, CC1 + VPALIGNR $12, DD1, DD1, DD1 + chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) + VPALIGNR $12, BB1, BB1, BB1 + VPALIGNR $8, CC1, CC1, CC1 + VPALIGNR $4, DD1, DD1, DD1 + CMPQ itr2, itr1 + JB openAVX2Tail128LoopA + CMPQ itr2, $160 + JNE openAVX2Tail128LoopB + + VPADDD ·chacha20Constants<>(SB), AA1, AA1 + VPADDD state1StoreAVX2, BB1, BB1 + VPADDD state2StoreAVX2, CC1, CC1 + VPADDD DD0, DD1, DD1 + VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0 + +openAVX2TailLoop: + CMPQ inl, $32 + JB openAVX2Tail + SUBQ $32, inl + + // Load for decryption + VPXOR (inp), AA0, AA0 + VMOVDQU AA0, (oup) + LEAQ (1*32)(inp), inp + LEAQ (1*32)(oup), oup + VMOVDQA BB0, AA0 + VMOVDQA CC0, BB0 + VMOVDQA DD0, CC0 + JMP openAVX2TailLoop + +openAVX2Tail: + CMPQ inl, $16 + VMOVDQA A0, A1 + JB openAVX2TailDone + SUBQ $16, inl + + // Load for decryption + VPXOR (inp), A0, T0 + VMOVDQU T0, (oup) + LEAQ (1*16)(inp), inp + LEAQ (1*16)(oup), oup + VPERM2I128 $0x11, AA0, AA0, AA0 + VMOVDQA A0, A1 + +openAVX2TailDone: + VZEROUPPER + JMP openSSETail16 + +// ---------------------------------------------------------------------------- +// Special optimization for the last 256 bytes of ciphertext +openAVX2Tail256: + // Need to decrypt up to 256 bytes - prepare four blocks + VMOVDQA ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1 + VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1 + VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1 + VMOVDQA ctr3StoreAVX2, DD0 + VPADDD ·avx2IncMask<>(SB), DD0, DD0 + VPADDD ·avx2IncMask<>(SB), DD0, DD1 + VMOVDQA DD0, TT1 + VMOVDQA DD1, TT2 + + // Compute the number of iterations that will hash data + MOVQ inl, tmpStoreAVX2 + MOVQ inl, itr1 + SUBQ $128, itr1 + SHRQ $4, itr1 + MOVQ $10, itr2 + CMPQ itr1, $10 + CMOVQGT itr2, itr1 + MOVQ inp, inl + XORQ itr2, itr2 + +openAVX2Tail256LoopA: + polyAdd(0(inl)) + polyMulAVX2 + LEAQ 16(inl), inl + + // Perform ChaCha rounds, while hashing the remaining input +openAVX2Tail256LoopB: + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) + VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1 + VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 + VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1 + INCQ itr2 + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) + VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1 + VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 + VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1 + CMPQ itr2, itr1 + JB openAVX2Tail256LoopA + + CMPQ itr2, $10 + JNE openAVX2Tail256LoopB + + MOVQ inl, itr2 + SUBQ inp, inl + MOVQ inl, itr1 + MOVQ tmpStoreAVX2, inl + + // Hash the remainder of data (if any) +openAVX2Tail256Hash: + ADDQ $16, itr1 + CMPQ itr1, inl + JGT openAVX2Tail256HashEnd + polyAdd (0(itr2)) + polyMulAVX2 + LEAQ 16(itr2), itr2 + JMP openAVX2Tail256Hash + +// Store 128 bytes safely, then go to store loop +openAVX2Tail256HashEnd: + VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1 + VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1 + VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1 + VPADDD TT1, DD0, DD0; VPADDD TT2, DD1, DD1 + VPERM2I128 $0x02, AA0, BB0, AA2; VPERM2I128 $0x02, CC0, DD0, BB2; VPERM2I128 $0x13, AA0, BB0, CC2; VPERM2I128 $0x13, CC0, DD0, DD2 + VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0 + + VPXOR (0*32)(inp), AA2, AA2; VPXOR (1*32)(inp), BB2, BB2; VPXOR (2*32)(inp), CC2, CC2; VPXOR (3*32)(inp), DD2, DD2 + VMOVDQU AA2, (0*32)(oup); VMOVDQU BB2, (1*32)(oup); VMOVDQU CC2, (2*32)(oup); VMOVDQU DD2, (3*32)(oup) + LEAQ (4*32)(inp), inp + LEAQ (4*32)(oup), oup + SUBQ $4*32, inl + + JMP openAVX2TailLoop + +// ---------------------------------------------------------------------------- +// Special optimization for the last 384 bytes of ciphertext +openAVX2Tail384: + // Need to decrypt up to 384 bytes - prepare six blocks + VMOVDQA ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2 + VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2 + VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2 + VMOVDQA ctr3StoreAVX2, DD0 + VPADDD ·avx2IncMask<>(SB), DD0, DD0 + VPADDD ·avx2IncMask<>(SB), DD0, DD1 + VPADDD ·avx2IncMask<>(SB), DD1, DD2 + VMOVDQA DD0, ctr0StoreAVX2 + VMOVDQA DD1, ctr1StoreAVX2 + VMOVDQA DD2, ctr2StoreAVX2 + + // Compute the number of iterations that will hash two blocks of data + MOVQ inl, tmpStoreAVX2 + MOVQ inl, itr1 + SUBQ $256, itr1 + SHRQ $4, itr1 + ADDQ $6, itr1 + MOVQ $10, itr2 + CMPQ itr1, $10 + CMOVQGT itr2, itr1 + MOVQ inp, inl + XORQ itr2, itr2 + + // Perform ChaCha rounds, while hashing the remaining input +openAVX2Tail384LoopB: + polyAdd(0(inl)) + polyMulAVX2 + LEAQ 16(inl), inl + +openAVX2Tail384LoopA: + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) + VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2 + VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 + VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2 + polyAdd(0(inl)) + polyMulAVX2 + LEAQ 16(inl), inl + INCQ itr2 + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) + VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2 + VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 + VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2 + + CMPQ itr2, itr1 + JB openAVX2Tail384LoopB + + CMPQ itr2, $10 + JNE openAVX2Tail384LoopA + + MOVQ inl, itr2 + SUBQ inp, inl + MOVQ inl, itr1 + MOVQ tmpStoreAVX2, inl + +openAVX2Tail384Hash: + ADDQ $16, itr1 + CMPQ itr1, inl + JGT openAVX2Tail384HashEnd + polyAdd(0(itr2)) + polyMulAVX2 + LEAQ 16(itr2), itr2 + JMP openAVX2Tail384Hash + +// Store 256 bytes safely, then go to store loop +openAVX2Tail384HashEnd: + VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2 + VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2 + VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2 + VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2 + VPERM2I128 $0x02, AA0, BB0, TT0; VPERM2I128 $0x02, CC0, DD0, TT1; VPERM2I128 $0x13, AA0, BB0, TT2; VPERM2I128 $0x13, CC0, DD0, TT3 + VPXOR (0*32)(inp), TT0, TT0; VPXOR (1*32)(inp), TT1, TT1; VPXOR (2*32)(inp), TT2, TT2; VPXOR (3*32)(inp), TT3, TT3 + VMOVDQU TT0, (0*32)(oup); VMOVDQU TT1, (1*32)(oup); VMOVDQU TT2, (2*32)(oup); VMOVDQU TT3, (3*32)(oup) + VPERM2I128 $0x02, AA1, BB1, TT0; VPERM2I128 $0x02, CC1, DD1, TT1; VPERM2I128 $0x13, AA1, BB1, TT2; VPERM2I128 $0x13, CC1, DD1, TT3 + VPXOR (4*32)(inp), TT0, TT0; VPXOR (5*32)(inp), TT1, TT1; VPXOR (6*32)(inp), TT2, TT2; VPXOR (7*32)(inp), TT3, TT3 + VMOVDQU TT0, (4*32)(oup); VMOVDQU TT1, (5*32)(oup); VMOVDQU TT2, (6*32)(oup); VMOVDQU TT3, (7*32)(oup) + VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0 + LEAQ (8*32)(inp), inp + LEAQ (8*32)(oup), oup + SUBQ $8*32, inl + JMP openAVX2TailLoop + +// ---------------------------------------------------------------------------- +// Special optimization for the last 512 bytes of ciphertext +openAVX2Tail512: + VMOVDQU ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3 + VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3 + VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3 + VMOVDQA ctr3StoreAVX2, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD1; VPADDD ·avx2IncMask<>(SB), DD1, DD2; VPADDD ·avx2IncMask<>(SB), DD2, DD3 + VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2 + XORQ itr1, itr1 + MOVQ inp, itr2 + +openAVX2Tail512LoopB: + polyAdd(0(itr2)) + polyMulAVX2 + LEAQ (2*8)(itr2), itr2 + +openAVX2Tail512LoopA: + VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 + VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 + VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3 + VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 + VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 + VMOVDQA CC3, tmpStoreAVX2 + VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 + VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 + VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 + VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 + VMOVDQA tmpStoreAVX2, CC3 + polyAdd(0*8(itr2)) + polyMulAVX2 + VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 + VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 + VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3 + VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 + VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 + VMOVDQA CC3, tmpStoreAVX2 + VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 + VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 + VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 + VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 + VMOVDQA tmpStoreAVX2, CC3 + VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $4, BB3, BB3, BB3 + VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 + VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2; VPALIGNR $12, DD3, DD3, DD3 + VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 + VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 + VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3 + VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 + VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 + polyAdd(2*8(itr2)) + polyMulAVX2 + LEAQ (4*8)(itr2), itr2 + VMOVDQA CC3, tmpStoreAVX2 + VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 + VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 + VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 + VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 + VMOVDQA tmpStoreAVX2, CC3 + VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 + VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 + VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3 + VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 + VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 + VMOVDQA CC3, tmpStoreAVX2 + VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 + VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 + VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 + VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 + VMOVDQA tmpStoreAVX2, CC3 + VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $12, BB3, BB3, BB3 + VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 + VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2; VPALIGNR $4, DD3, DD3, DD3 + INCQ itr1 + CMPQ itr1, $4 + JLT openAVX2Tail512LoopB + + CMPQ itr1, $10 + JNE openAVX2Tail512LoopA + + MOVQ inl, itr1 + SUBQ $384, itr1 + ANDQ $-16, itr1 + +openAVX2Tail512HashLoop: + TESTQ itr1, itr1 + JE openAVX2Tail512HashEnd + polyAdd(0(itr2)) + polyMulAVX2 + LEAQ 16(itr2), itr2 + SUBQ $16, itr1 + JMP openAVX2Tail512HashLoop + +openAVX2Tail512HashEnd: + VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2; VPADDD ·chacha20Constants<>(SB), AA3, AA3 + VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3 + VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3 + VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3 + VMOVDQA CC3, tmpStoreAVX2 + VPERM2I128 $0x02, AA0, BB0, CC3; VPERM2I128 $0x13, AA0, BB0, BB0; VPERM2I128 $0x02, CC0, DD0, AA0; VPERM2I128 $0x13, CC0, DD0, CC0 + VPXOR (0*32)(inp), CC3, CC3; VPXOR (1*32)(inp), AA0, AA0; VPXOR (2*32)(inp), BB0, BB0; VPXOR (3*32)(inp), CC0, CC0 + VMOVDQU CC3, (0*32)(oup); VMOVDQU AA0, (1*32)(oup); VMOVDQU BB0, (2*32)(oup); VMOVDQU CC0, (3*32)(oup) + VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0 + VPXOR (4*32)(inp), AA0, AA0; VPXOR (5*32)(inp), BB0, BB0; VPXOR (6*32)(inp), CC0, CC0; VPXOR (7*32)(inp), DD0, DD0 + VMOVDQU AA0, (4*32)(oup); VMOVDQU BB0, (5*32)(oup); VMOVDQU CC0, (6*32)(oup); VMOVDQU DD0, (7*32)(oup) + VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0 + VPXOR (8*32)(inp), AA0, AA0; VPXOR (9*32)(inp), BB0, BB0; VPXOR (10*32)(inp), CC0, CC0; VPXOR (11*32)(inp), DD0, DD0 + VMOVDQU AA0, (8*32)(oup); VMOVDQU BB0, (9*32)(oup); VMOVDQU CC0, (10*32)(oup); VMOVDQU DD0, (11*32)(oup) + VPERM2I128 $0x02, AA3, BB3, AA0; VPERM2I128 $0x02, tmpStoreAVX2, DD3, BB0; VPERM2I128 $0x13, AA3, BB3, CC0; VPERM2I128 $0x13, tmpStoreAVX2, DD3, DD0 + + LEAQ (12*32)(inp), inp + LEAQ (12*32)(oup), oup + SUBQ $12*32, inl + + JMP openAVX2TailLoop + +// ---------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- +// func chacha20Poly1305Seal(dst, key, src, ad []byte) +TEXT ·chacha20Poly1305Seal(SB), 0, $288-96 + // For aligned stack access + MOVQ SP, BP + ADDQ $32, BP + ANDQ $-32, BP + MOVQ dst+0(FP), oup + MOVQ key+24(FP), keyp + MOVQ src+48(FP), inp + MOVQ src_len+56(FP), inl + MOVQ ad+72(FP), adp + + CMPB ·useAVX2(SB), $1 + JE chacha20Poly1305Seal_AVX2 + + // Special optimization, for very short buffers + CMPQ inl, $128 + JBE sealSSE128 // About 15% faster + + // In the seal case - prepare the poly key + 3 blocks of stream in the first iteration + MOVOU ·chacha20Constants<>(SB), A0 + MOVOU (1*16)(keyp), B0 + MOVOU (2*16)(keyp), C0 + MOVOU (3*16)(keyp), D0 + + // Store state on stack for future use + MOVO B0, state1Store + MOVO C0, state2Store + + // Load state, increment counter blocks + MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1 + MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2 + MOVO A2, A3; MOVO B2, B3; MOVO C2, C3; MOVO D2, D3; PADDL ·sseIncMask<>(SB), D3 + + // Store counters + MOVO D0, ctr0Store; MOVO D1, ctr1Store; MOVO D2, ctr2Store; MOVO D3, ctr3Store + MOVQ $10, itr2 + +sealSSEIntroLoop: + MOVO C3, tmpStore + chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) + MOVO tmpStore, C3 + MOVO C1, tmpStore + chachaQR(A3, B3, C3, D3, C1) + MOVO tmpStore, C1 + shiftB0Left; shiftB1Left; shiftB2Left; shiftB3Left + shiftC0Left; shiftC1Left; shiftC2Left; shiftC3Left + shiftD0Left; shiftD1Left; shiftD2Left; shiftD3Left + + MOVO C3, tmpStore + chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) + MOVO tmpStore, C3 + MOVO C1, tmpStore + chachaQR(A3, B3, C3, D3, C1) + MOVO tmpStore, C1 + shiftB0Right; shiftB1Right; shiftB2Right; shiftB3Right + shiftC0Right; shiftC1Right; shiftC2Right; shiftC3Right + shiftD0Right; shiftD1Right; shiftD2Right; shiftD3Right + DECQ itr2 + JNE sealSSEIntroLoop + + // Add in the state + PADDD ·chacha20Constants<>(SB), A0; PADDD ·chacha20Constants<>(SB), A1; PADDD ·chacha20Constants<>(SB), A2; PADDD ·chacha20Constants<>(SB), A3 + PADDD state1Store, B0; PADDD state1Store, B1; PADDD state1Store, B2; PADDD state1Store, B3 + PADDD state2Store, C1; PADDD state2Store, C2; PADDD state2Store, C3 + PADDD ctr1Store, D1; PADDD ctr2Store, D2; PADDD ctr3Store, D3 + + // Clamp and store the key + PAND ·polyClampMask<>(SB), A0 + MOVO A0, rStore + MOVO B0, sStore + + // Hash AAD + MOVQ ad_len+80(FP), itr2 + CALL polyHashADInternal<>(SB) + + MOVOU (0*16)(inp), A0; MOVOU (1*16)(inp), B0; MOVOU (2*16)(inp), C0; MOVOU (3*16)(inp), D0 + PXOR A0, A1; PXOR B0, B1; PXOR C0, C1; PXOR D0, D1 + MOVOU A1, (0*16)(oup); MOVOU B1, (1*16)(oup); MOVOU C1, (2*16)(oup); MOVOU D1, (3*16)(oup) + MOVOU (4*16)(inp), A0; MOVOU (5*16)(inp), B0; MOVOU (6*16)(inp), C0; MOVOU (7*16)(inp), D0 + PXOR A0, A2; PXOR B0, B2; PXOR C0, C2; PXOR D0, D2 + MOVOU A2, (4*16)(oup); MOVOU B2, (5*16)(oup); MOVOU C2, (6*16)(oup); MOVOU D2, (7*16)(oup) + + MOVQ $128, itr1 + SUBQ $128, inl + LEAQ 128(inp), inp + + MOVO A3, A1; MOVO B3, B1; MOVO C3, C1; MOVO D3, D1 + + CMPQ inl, $64 + JBE sealSSE128SealHash + + MOVOU (0*16)(inp), A0; MOVOU (1*16)(inp), B0; MOVOU (2*16)(inp), C0; MOVOU (3*16)(inp), D0 + PXOR A0, A3; PXOR B0, B3; PXOR C0, C3; PXOR D0, D3 + MOVOU A3, (8*16)(oup); MOVOU B3, (9*16)(oup); MOVOU C3, (10*16)(oup); MOVOU D3, (11*16)(oup) + + ADDQ $64, itr1 + SUBQ $64, inl + LEAQ 64(inp), inp + + MOVQ $2, itr1 + MOVQ $8, itr2 + + CMPQ inl, $64 + JBE sealSSETail64 + CMPQ inl, $128 + JBE sealSSETail128 + CMPQ inl, $192 + JBE sealSSETail192 + +sealSSEMainLoop: + // Load state, increment counter blocks + MOVO ·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL ·sseIncMask<>(SB), D0 + MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1 + MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2 + MOVO A2, A3; MOVO B2, B3; MOVO C2, C3; MOVO D2, D3; PADDL ·sseIncMask<>(SB), D3 + + // Store counters + MOVO D0, ctr0Store; MOVO D1, ctr1Store; MOVO D2, ctr2Store; MOVO D3, ctr3Store + +sealSSEInnerLoop: + MOVO C3, tmpStore + chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) + MOVO tmpStore, C3 + MOVO C1, tmpStore + chachaQR(A3, B3, C3, D3, C1) + MOVO tmpStore, C1 + polyAdd(0(oup)) + shiftB0Left; shiftB1Left; shiftB2Left; shiftB3Left + shiftC0Left; shiftC1Left; shiftC2Left; shiftC3Left + shiftD0Left; shiftD1Left; shiftD2Left; shiftD3Left + polyMulStage1 + polyMulStage2 + LEAQ (2*8)(oup), oup + MOVO C3, tmpStore + chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) + MOVO tmpStore, C3 + MOVO C1, tmpStore + polyMulStage3 + chachaQR(A3, B3, C3, D3, C1) + MOVO tmpStore, C1 + polyMulReduceStage + shiftB0Right; shiftB1Right; shiftB2Right; shiftB3Right + shiftC0Right; shiftC1Right; shiftC2Right; shiftC3Right + shiftD0Right; shiftD1Right; shiftD2Right; shiftD3Right + DECQ itr2 + JGE sealSSEInnerLoop + polyAdd(0(oup)) + polyMul + LEAQ (2*8)(oup), oup + DECQ itr1 + JG sealSSEInnerLoop + + // Add in the state + PADDD ·chacha20Constants<>(SB), A0; PADDD ·chacha20Constants<>(SB), A1; PADDD ·chacha20Constants<>(SB), A2; PADDD ·chacha20Constants<>(SB), A3 + PADDD state1Store, B0; PADDD state1Store, B1; PADDD state1Store, B2; PADDD state1Store, B3 + PADDD state2Store, C0; PADDD state2Store, C1; PADDD state2Store, C2; PADDD state2Store, C3 + PADDD ctr0Store, D0; PADDD ctr1Store, D1; PADDD ctr2Store, D2; PADDD ctr3Store, D3 + MOVO D3, tmpStore + + // Load - xor - store + MOVOU (0*16)(inp), D3; PXOR D3, A0 + MOVOU (1*16)(inp), D3; PXOR D3, B0 + MOVOU (2*16)(inp), D3; PXOR D3, C0 + MOVOU (3*16)(inp), D3; PXOR D3, D0 + MOVOU A0, (0*16)(oup) + MOVOU B0, (1*16)(oup) + MOVOU C0, (2*16)(oup) + MOVOU D0, (3*16)(oup) + MOVO tmpStore, D3 + + MOVOU (4*16)(inp), A0; MOVOU (5*16)(inp), B0; MOVOU (6*16)(inp), C0; MOVOU (7*16)(inp), D0 + PXOR A0, A1; PXOR B0, B1; PXOR C0, C1; PXOR D0, D1 + MOVOU A1, (4*16)(oup); MOVOU B1, (5*16)(oup); MOVOU C1, (6*16)(oup); MOVOU D1, (7*16)(oup) + MOVOU (8*16)(inp), A0; MOVOU (9*16)(inp), B0; MOVOU (10*16)(inp), C0; MOVOU (11*16)(inp), D0 + PXOR A0, A2; PXOR B0, B2; PXOR C0, C2; PXOR D0, D2 + MOVOU A2, (8*16)(oup); MOVOU B2, (9*16)(oup); MOVOU C2, (10*16)(oup); MOVOU D2, (11*16)(oup) + ADDQ $192, inp + MOVQ $192, itr1 + SUBQ $192, inl + MOVO A3, A1 + MOVO B3, B1 + MOVO C3, C1 + MOVO D3, D1 + CMPQ inl, $64 + JBE sealSSE128SealHash + MOVOU (0*16)(inp), A0; MOVOU (1*16)(inp), B0; MOVOU (2*16)(inp), C0; MOVOU (3*16)(inp), D0 + PXOR A0, A3; PXOR B0, B3; PXOR C0, C3; PXOR D0, D3 + MOVOU A3, (12*16)(oup); MOVOU B3, (13*16)(oup); MOVOU C3, (14*16)(oup); MOVOU D3, (15*16)(oup) + LEAQ 64(inp), inp + SUBQ $64, inl + MOVQ $6, itr1 + MOVQ $4, itr2 + CMPQ inl, $192 + JG sealSSEMainLoop + + MOVQ inl, itr1 + TESTQ inl, inl + JE sealSSE128SealHash + MOVQ $6, itr1 + CMPQ inl, $64 + JBE sealSSETail64 + CMPQ inl, $128 + JBE sealSSETail128 + JMP sealSSETail192 + +// ---------------------------------------------------------------------------- +// Special optimization for the last 64 bytes of plaintext +sealSSETail64: + // Need to encrypt up to 64 bytes - prepare single block, hash 192 or 256 bytes + MOVO ·chacha20Constants<>(SB), A1 + MOVO state1Store, B1 + MOVO state2Store, C1 + MOVO ctr3Store, D1 + PADDL ·sseIncMask<>(SB), D1 + MOVO D1, ctr0Store + +sealSSETail64LoopA: + // Perform ChaCha rounds, while hashing the previously encrypted ciphertext + polyAdd(0(oup)) + polyMul + LEAQ 16(oup), oup + +sealSSETail64LoopB: + chachaQR(A1, B1, C1, D1, T1) + shiftB1Left; shiftC1Left; shiftD1Left + chachaQR(A1, B1, C1, D1, T1) + shiftB1Right; shiftC1Right; shiftD1Right + polyAdd(0(oup)) + polyMul + LEAQ 16(oup), oup + + DECQ itr1 + JG sealSSETail64LoopA + + DECQ itr2 + JGE sealSSETail64LoopB + PADDL ·chacha20Constants<>(SB), A1 + PADDL state1Store, B1 + PADDL state2Store, C1 + PADDL ctr0Store, D1 + + JMP sealSSE128Seal + +// ---------------------------------------------------------------------------- +// Special optimization for the last 128 bytes of plaintext +sealSSETail128: + // Need to encrypt up to 128 bytes - prepare two blocks, hash 192 or 256 bytes + MOVO ·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL ·sseIncMask<>(SB), D0; MOVO D0, ctr0Store + MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1; MOVO D1, ctr1Store + +sealSSETail128LoopA: + // Perform ChaCha rounds, while hashing the previously encrypted ciphertext + polyAdd(0(oup)) + polyMul + LEAQ 16(oup), oup + +sealSSETail128LoopB: + chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0) + shiftB0Left; shiftC0Left; shiftD0Left + shiftB1Left; shiftC1Left; shiftD1Left + polyAdd(0(oup)) + polyMul + LEAQ 16(oup), oup + chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0) + shiftB0Right; shiftC0Right; shiftD0Right + shiftB1Right; shiftC1Right; shiftD1Right + + DECQ itr1 + JG sealSSETail128LoopA + + DECQ itr2 + JGE sealSSETail128LoopB + + PADDL ·chacha20Constants<>(SB), A0; PADDL ·chacha20Constants<>(SB), A1 + PADDL state1Store, B0; PADDL state1Store, B1 + PADDL state2Store, C0; PADDL state2Store, C1 + PADDL ctr0Store, D0; PADDL ctr1Store, D1 + + MOVOU (0*16)(inp), T0; MOVOU (1*16)(inp), T1; MOVOU (2*16)(inp), T2; MOVOU (3*16)(inp), T3 + PXOR T0, A0; PXOR T1, B0; PXOR T2, C0; PXOR T3, D0 + MOVOU A0, (0*16)(oup); MOVOU B0, (1*16)(oup); MOVOU C0, (2*16)(oup); MOVOU D0, (3*16)(oup) + + MOVQ $64, itr1 + LEAQ 64(inp), inp + SUBQ $64, inl + + JMP sealSSE128SealHash + +// ---------------------------------------------------------------------------- +// Special optimization for the last 192 bytes of plaintext +sealSSETail192: + // Need to encrypt up to 192 bytes - prepare three blocks, hash 192 or 256 bytes + MOVO ·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL ·sseIncMask<>(SB), D0; MOVO D0, ctr0Store + MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1; MOVO D1, ctr1Store + MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2; MOVO D2, ctr2Store + +sealSSETail192LoopA: + // Perform ChaCha rounds, while hashing the previously encrypted ciphertext + polyAdd(0(oup)) + polyMul + LEAQ 16(oup), oup + +sealSSETail192LoopB: + chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) + shiftB0Left; shiftC0Left; shiftD0Left + shiftB1Left; shiftC1Left; shiftD1Left + shiftB2Left; shiftC2Left; shiftD2Left + + polyAdd(0(oup)) + polyMul + LEAQ 16(oup), oup + + chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) + shiftB0Right; shiftC0Right; shiftD0Right + shiftB1Right; shiftC1Right; shiftD1Right + shiftB2Right; shiftC2Right; shiftD2Right + + DECQ itr1 + JG sealSSETail192LoopA + + DECQ itr2 + JGE sealSSETail192LoopB + + PADDL ·chacha20Constants<>(SB), A0; PADDL ·chacha20Constants<>(SB), A1; PADDL ·chacha20Constants<>(SB), A2 + PADDL state1Store, B0; PADDL state1Store, B1; PADDL state1Store, B2 + PADDL state2Store, C0; PADDL state2Store, C1; PADDL state2Store, C2 + PADDL ctr0Store, D0; PADDL ctr1Store, D1; PADDL ctr2Store, D2 + + MOVOU (0*16)(inp), T0; MOVOU (1*16)(inp), T1; MOVOU (2*16)(inp), T2; MOVOU (3*16)(inp), T3 + PXOR T0, A0; PXOR T1, B0; PXOR T2, C0; PXOR T3, D0 + MOVOU A0, (0*16)(oup); MOVOU B0, (1*16)(oup); MOVOU C0, (2*16)(oup); MOVOU D0, (3*16)(oup) + MOVOU (4*16)(inp), T0; MOVOU (5*16)(inp), T1; MOVOU (6*16)(inp), T2; MOVOU (7*16)(inp), T3 + PXOR T0, A1; PXOR T1, B1; PXOR T2, C1; PXOR T3, D1 + MOVOU A1, (4*16)(oup); MOVOU B1, (5*16)(oup); MOVOU C1, (6*16)(oup); MOVOU D1, (7*16)(oup) + + MOVO A2, A1 + MOVO B2, B1 + MOVO C2, C1 + MOVO D2, D1 + MOVQ $128, itr1 + LEAQ 128(inp), inp + SUBQ $128, inl + + JMP sealSSE128SealHash + +// ---------------------------------------------------------------------------- +// Special seal optimization for buffers smaller than 129 bytes +sealSSE128: + // For up to 128 bytes of ciphertext and 64 bytes for the poly key, we require to process three blocks + MOVOU ·chacha20Constants<>(SB), A0; MOVOU (1*16)(keyp), B0; MOVOU (2*16)(keyp), C0; MOVOU (3*16)(keyp), D0 + MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1 + MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2 + MOVO B0, T1; MOVO C0, T2; MOVO D1, T3 + MOVQ $10, itr2 + +sealSSE128InnerCipherLoop: + chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) + shiftB0Left; shiftB1Left; shiftB2Left + shiftC0Left; shiftC1Left; shiftC2Left + shiftD0Left; shiftD1Left; shiftD2Left + chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) + shiftB0Right; shiftB1Right; shiftB2Right + shiftC0Right; shiftC1Right; shiftC2Right + shiftD0Right; shiftD1Right; shiftD2Right + DECQ itr2 + JNE sealSSE128InnerCipherLoop + + // A0|B0 hold the Poly1305 32-byte key, C0,D0 can be discarded + PADDL ·chacha20Constants<>(SB), A0; PADDL ·chacha20Constants<>(SB), A1; PADDL ·chacha20Constants<>(SB), A2 + PADDL T1, B0; PADDL T1, B1; PADDL T1, B2 + PADDL T2, C1; PADDL T2, C2 + PADDL T3, D1; PADDL ·sseIncMask<>(SB), T3; PADDL T3, D2 + PAND ·polyClampMask<>(SB), A0 + MOVOU A0, rStore + MOVOU B0, sStore + + // Hash + MOVQ ad_len+80(FP), itr2 + CALL polyHashADInternal<>(SB) + XORQ itr1, itr1 + +sealSSE128SealHash: + // itr1 holds the number of bytes encrypted but not yet hashed + CMPQ itr1, $16 + JB sealSSE128Seal + polyAdd(0(oup)) + polyMul + + SUBQ $16, itr1 + ADDQ $16, oup + + JMP sealSSE128SealHash + +sealSSE128Seal: + CMPQ inl, $16 + JB sealSSETail + SUBQ $16, inl + + // Load for decryption + MOVOU (inp), T0 + PXOR T0, A1 + MOVOU A1, (oup) + LEAQ (1*16)(inp), inp + LEAQ (1*16)(oup), oup + + // Extract for hashing + MOVQ A1, t0 + PSRLDQ $8, A1 + MOVQ A1, t1 + ADDQ t0, acc0; ADCQ t1, acc1; ADCQ $1, acc2 + polyMul + + // Shift the stream "left" + MOVO B1, A1 + MOVO C1, B1 + MOVO D1, C1 + MOVO A2, D1 + MOVO B2, A2 + MOVO C2, B2 + MOVO D2, C2 + JMP sealSSE128Seal + +sealSSETail: + TESTQ inl, inl + JE sealSSEFinalize + + // We can only load the PT one byte at a time to avoid read after end of buffer + MOVQ inl, itr2 + SHLQ $4, itr2 + LEAQ ·andMask<>(SB), t0 + MOVQ inl, itr1 + LEAQ -1(inp)(inl*1), inp + XORQ t2, t2 + XORQ t3, t3 + XORQ AX, AX + +sealSSETailLoadLoop: + SHLQ $8, t2, t3 + SHLQ $8, t2 + MOVB (inp), AX + XORQ AX, t2 + LEAQ -1(inp), inp + DECQ itr1 + JNE sealSSETailLoadLoop + MOVQ t2, 0+tmpStore + MOVQ t3, 8+tmpStore + PXOR 0+tmpStore, A1 + MOVOU A1, (oup) + MOVOU -16(t0)(itr2*1), T0 + PAND T0, A1 + MOVQ A1, t0 + PSRLDQ $8, A1 + MOVQ A1, t1 + ADDQ t0, acc0; ADCQ t1, acc1; ADCQ $1, acc2 + polyMul + + ADDQ inl, oup + +sealSSEFinalize: + // Hash in the buffer lengths + ADDQ ad_len+80(FP), acc0 + ADCQ src_len+56(FP), acc1 + ADCQ $1, acc2 + polyMul + + // Final reduce + MOVQ acc0, t0 + MOVQ acc1, t1 + MOVQ acc2, t2 + SUBQ $-5, acc0 + SBBQ $-1, acc1 + SBBQ $3, acc2 + CMOVQCS t0, acc0 + CMOVQCS t1, acc1 + CMOVQCS t2, acc2 + + // Add in the "s" part of the key + ADDQ 0+sStore, acc0 + ADCQ 8+sStore, acc1 + + // Finally store the tag at the end of the message + MOVQ acc0, (0*8)(oup) + MOVQ acc1, (1*8)(oup) + RET + +// ---------------------------------------------------------------------------- +// ------------------------- AVX2 Code ---------------------------------------- +chacha20Poly1305Seal_AVX2: + VZEROUPPER + VMOVDQU ·chacha20Constants<>(SB), AA0 + BYTE $0xc4; BYTE $0x42; BYTE $0x7d; BYTE $0x5a; BYTE $0x70; BYTE $0x10 // broadcasti128 16(r8), ymm14 + BYTE $0xc4; BYTE $0x42; BYTE $0x7d; BYTE $0x5a; BYTE $0x60; BYTE $0x20 // broadcasti128 32(r8), ymm12 + BYTE $0xc4; BYTE $0xc2; BYTE $0x7d; BYTE $0x5a; BYTE $0x60; BYTE $0x30 // broadcasti128 48(r8), ymm4 + VPADDD ·avx2InitMask<>(SB), DD0, DD0 + + // Special optimizations, for very short buffers + CMPQ inl, $192 + JBE seal192AVX2 // 33% faster + CMPQ inl, $320 + JBE seal320AVX2 // 17% faster + + // For the general key prepare the key first - as a byproduct we have 64 bytes of cipher stream + VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3 + VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3; VMOVDQA BB0, state1StoreAVX2 + VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3; VMOVDQA CC0, state2StoreAVX2 + VPADDD ·avx2IncMask<>(SB), DD0, DD1; VMOVDQA DD0, ctr0StoreAVX2 + VPADDD ·avx2IncMask<>(SB), DD1, DD2; VMOVDQA DD1, ctr1StoreAVX2 + VPADDD ·avx2IncMask<>(SB), DD2, DD3; VMOVDQA DD2, ctr2StoreAVX2 + VMOVDQA DD3, ctr3StoreAVX2 + MOVQ $10, itr2 + +sealAVX2IntroLoop: + VMOVDQA CC3, tmpStoreAVX2 + chachaQR_AVX2(AA0, BB0, CC0, DD0, CC3); chachaQR_AVX2(AA1, BB1, CC1, DD1, CC3); chachaQR_AVX2(AA2, BB2, CC2, DD2, CC3) + VMOVDQA tmpStoreAVX2, CC3 + VMOVDQA CC1, tmpStoreAVX2 + chachaQR_AVX2(AA3, BB3, CC3, DD3, CC1) + VMOVDQA tmpStoreAVX2, CC1 + + VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $12, DD0, DD0, DD0 + VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $12, DD1, DD1, DD1 + VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $12, DD2, DD2, DD2 + VPALIGNR $4, BB3, BB3, BB3; VPALIGNR $8, CC3, CC3, CC3; VPALIGNR $12, DD3, DD3, DD3 + + VMOVDQA CC3, tmpStoreAVX2 + chachaQR_AVX2(AA0, BB0, CC0, DD0, CC3); chachaQR_AVX2(AA1, BB1, CC1, DD1, CC3); chachaQR_AVX2(AA2, BB2, CC2, DD2, CC3) + VMOVDQA tmpStoreAVX2, CC3 + VMOVDQA CC1, tmpStoreAVX2 + chachaQR_AVX2(AA3, BB3, CC3, DD3, CC1) + VMOVDQA tmpStoreAVX2, CC1 + + VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $4, DD0, DD0, DD0 + VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $4, DD1, DD1, DD1 + VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $4, DD2, DD2, DD2 + VPALIGNR $12, BB3, BB3, BB3; VPALIGNR $8, CC3, CC3, CC3; VPALIGNR $4, DD3, DD3, DD3 + DECQ itr2 + JNE sealAVX2IntroLoop + + VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2; VPADDD ·chacha20Constants<>(SB), AA3, AA3 + VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3 + VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3 + VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3 + + VPERM2I128 $0x13, CC0, DD0, CC0 // Stream bytes 96 - 127 + VPERM2I128 $0x02, AA0, BB0, DD0 // The Poly1305 key + VPERM2I128 $0x13, AA0, BB0, AA0 // Stream bytes 64 - 95 + + // Clamp and store poly key + VPAND ·polyClampMask<>(SB), DD0, DD0 + VMOVDQA DD0, rsStoreAVX2 + + // Hash AD + MOVQ ad_len+80(FP), itr2 + CALL polyHashADInternal<>(SB) + + // Can store at least 320 bytes + VPXOR (0*32)(inp), AA0, AA0 + VPXOR (1*32)(inp), CC0, CC0 + VMOVDQU AA0, (0*32)(oup) + VMOVDQU CC0, (1*32)(oup) + + VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0 + VPXOR (2*32)(inp), AA0, AA0; VPXOR (3*32)(inp), BB0, BB0; VPXOR (4*32)(inp), CC0, CC0; VPXOR (5*32)(inp), DD0, DD0 + VMOVDQU AA0, (2*32)(oup); VMOVDQU BB0, (3*32)(oup); VMOVDQU CC0, (4*32)(oup); VMOVDQU DD0, (5*32)(oup) + VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0 + VPXOR (6*32)(inp), AA0, AA0; VPXOR (7*32)(inp), BB0, BB0; VPXOR (8*32)(inp), CC0, CC0; VPXOR (9*32)(inp), DD0, DD0 + VMOVDQU AA0, (6*32)(oup); VMOVDQU BB0, (7*32)(oup); VMOVDQU CC0, (8*32)(oup); VMOVDQU DD0, (9*32)(oup) + + MOVQ $320, itr1 + SUBQ $320, inl + LEAQ 320(inp), inp + + VPERM2I128 $0x02, AA3, BB3, AA0; VPERM2I128 $0x02, CC3, DD3, BB0; VPERM2I128 $0x13, AA3, BB3, CC0; VPERM2I128 $0x13, CC3, DD3, DD0 + CMPQ inl, $128 + JBE sealAVX2SealHash + + VPXOR (0*32)(inp), AA0, AA0; VPXOR (1*32)(inp), BB0, BB0; VPXOR (2*32)(inp), CC0, CC0; VPXOR (3*32)(inp), DD0, DD0 + VMOVDQU AA0, (10*32)(oup); VMOVDQU BB0, (11*32)(oup); VMOVDQU CC0, (12*32)(oup); VMOVDQU DD0, (13*32)(oup) + SUBQ $128, inl + LEAQ 128(inp), inp + + MOVQ $8, itr1 + MOVQ $2, itr2 + + CMPQ inl, $128 + JBE sealAVX2Tail128 + CMPQ inl, $256 + JBE sealAVX2Tail256 + CMPQ inl, $384 + JBE sealAVX2Tail384 + CMPQ inl, $512 + JBE sealAVX2Tail512 + + // We have 448 bytes to hash, but main loop hashes 512 bytes at a time - perform some rounds, before the main loop + VMOVDQA ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3 + VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3 + VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3 + VMOVDQA ctr3StoreAVX2, DD0 + VPADDD ·avx2IncMask<>(SB), DD0, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD1; VPADDD ·avx2IncMask<>(SB), DD1, DD2; VPADDD ·avx2IncMask<>(SB), DD2, DD3 + VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2 + + VMOVDQA CC3, tmpStoreAVX2 + chachaQR_AVX2(AA0, BB0, CC0, DD0, CC3); chachaQR_AVX2(AA1, BB1, CC1, DD1, CC3); chachaQR_AVX2(AA2, BB2, CC2, DD2, CC3) + VMOVDQA tmpStoreAVX2, CC3 + VMOVDQA CC1, tmpStoreAVX2 + chachaQR_AVX2(AA3, BB3, CC3, DD3, CC1) + VMOVDQA tmpStoreAVX2, CC1 + + VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $12, DD0, DD0, DD0 + VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $12, DD1, DD1, DD1 + VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $12, DD2, DD2, DD2 + VPALIGNR $4, BB3, BB3, BB3; VPALIGNR $8, CC3, CC3, CC3; VPALIGNR $12, DD3, DD3, DD3 + + VMOVDQA CC3, tmpStoreAVX2 + chachaQR_AVX2(AA0, BB0, CC0, DD0, CC3); chachaQR_AVX2(AA1, BB1, CC1, DD1, CC3); chachaQR_AVX2(AA2, BB2, CC2, DD2, CC3) + VMOVDQA tmpStoreAVX2, CC3 + VMOVDQA CC1, tmpStoreAVX2 + chachaQR_AVX2(AA3, BB3, CC3, DD3, CC1) + VMOVDQA tmpStoreAVX2, CC1 + + VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $4, DD0, DD0, DD0 + VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $4, DD1, DD1, DD1 + VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $4, DD2, DD2, DD2 + VPALIGNR $12, BB3, BB3, BB3; VPALIGNR $8, CC3, CC3, CC3; VPALIGNR $4, DD3, DD3, DD3 + VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 + VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 + VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3 + VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 + VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 + VMOVDQA CC3, tmpStoreAVX2 + VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 + VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 + VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 + VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 + VMOVDQA tmpStoreAVX2, CC3 + + SUBQ $16, oup // Adjust the pointer + MOVQ $9, itr1 + JMP sealAVX2InternalLoopStart + +sealAVX2MainLoop: + // Load state, increment counter blocks, store the incremented counters + VMOVDQU ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3 + VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3 + VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3 + VMOVDQA ctr3StoreAVX2, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD1; VPADDD ·avx2IncMask<>(SB), DD1, DD2; VPADDD ·avx2IncMask<>(SB), DD2, DD3 + VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2 + MOVQ $10, itr1 + +sealAVX2InternalLoop: + polyAdd(0*8(oup)) + VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 + polyMulStage1_AVX2 + VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 + VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3 + polyMulStage2_AVX2 + VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 + VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 + polyMulStage3_AVX2 + VMOVDQA CC3, tmpStoreAVX2 + VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 + VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 + VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 + VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 + VMOVDQA tmpStoreAVX2, CC3 + polyMulReduceStage + +sealAVX2InternalLoopStart: + VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 + VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 + VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3 + polyAdd(2*8(oup)) + VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 + polyMulStage1_AVX2 + VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 + VMOVDQA CC3, tmpStoreAVX2 + VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 + VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 + VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 + VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 + VMOVDQA tmpStoreAVX2, CC3 + polyMulStage2_AVX2 + VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $4, BB3, BB3, BB3 + VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 + VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2; VPALIGNR $12, DD3, DD3, DD3 + VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 + polyMulStage3_AVX2 + VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 + VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3 + polyMulReduceStage + VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 + VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 + polyAdd(4*8(oup)) + LEAQ (6*8)(oup), oup + VMOVDQA CC3, tmpStoreAVX2 + VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 + VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 + VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 + VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 + VMOVDQA tmpStoreAVX2, CC3 + polyMulStage1_AVX2 + VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 + VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 + polyMulStage2_AVX2 + VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3 + VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 + polyMulStage3_AVX2 + VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 + VMOVDQA CC3, tmpStoreAVX2 + VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 + VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 + VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 + VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 + VMOVDQA tmpStoreAVX2, CC3 + polyMulReduceStage + VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $12, BB3, BB3, BB3 + VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 + VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2; VPALIGNR $4, DD3, DD3, DD3 + DECQ itr1 + JNE sealAVX2InternalLoop + + VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2; VPADDD ·chacha20Constants<>(SB), AA3, AA3 + VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3 + VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3 + VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3 + VMOVDQA CC3, tmpStoreAVX2 + + // We only hashed 480 of the 512 bytes available - hash the remaining 32 here + polyAdd(0*8(oup)) + polyMulAVX2 + LEAQ (4*8)(oup), oup + VPERM2I128 $0x02, AA0, BB0, CC3; VPERM2I128 $0x13, AA0, BB0, BB0; VPERM2I128 $0x02, CC0, DD0, AA0; VPERM2I128 $0x13, CC0, DD0, CC0 + VPXOR (0*32)(inp), CC3, CC3; VPXOR (1*32)(inp), AA0, AA0; VPXOR (2*32)(inp), BB0, BB0; VPXOR (3*32)(inp), CC0, CC0 + VMOVDQU CC3, (0*32)(oup); VMOVDQU AA0, (1*32)(oup); VMOVDQU BB0, (2*32)(oup); VMOVDQU CC0, (3*32)(oup) + VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0 + VPXOR (4*32)(inp), AA0, AA0; VPXOR (5*32)(inp), BB0, BB0; VPXOR (6*32)(inp), CC0, CC0; VPXOR (7*32)(inp), DD0, DD0 + VMOVDQU AA0, (4*32)(oup); VMOVDQU BB0, (5*32)(oup); VMOVDQU CC0, (6*32)(oup); VMOVDQU DD0, (7*32)(oup) + + // and here + polyAdd(-2*8(oup)) + polyMulAVX2 + VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0 + VPXOR (8*32)(inp), AA0, AA0; VPXOR (9*32)(inp), BB0, BB0; VPXOR (10*32)(inp), CC0, CC0; VPXOR (11*32)(inp), DD0, DD0 + VMOVDQU AA0, (8*32)(oup); VMOVDQU BB0, (9*32)(oup); VMOVDQU CC0, (10*32)(oup); VMOVDQU DD0, (11*32)(oup) + VPERM2I128 $0x02, AA3, BB3, AA0; VPERM2I128 $0x02, tmpStoreAVX2, DD3, BB0; VPERM2I128 $0x13, AA3, BB3, CC0; VPERM2I128 $0x13, tmpStoreAVX2, DD3, DD0 + VPXOR (12*32)(inp), AA0, AA0; VPXOR (13*32)(inp), BB0, BB0; VPXOR (14*32)(inp), CC0, CC0; VPXOR (15*32)(inp), DD0, DD0 + VMOVDQU AA0, (12*32)(oup); VMOVDQU BB0, (13*32)(oup); VMOVDQU CC0, (14*32)(oup); VMOVDQU DD0, (15*32)(oup) + LEAQ (32*16)(inp), inp + SUBQ $(32*16), inl + CMPQ inl, $512 + JG sealAVX2MainLoop + + // Tail can only hash 480 bytes + polyAdd(0*8(oup)) + polyMulAVX2 + polyAdd(2*8(oup)) + polyMulAVX2 + LEAQ 32(oup), oup + + MOVQ $10, itr1 + MOVQ $0, itr2 + CMPQ inl, $128 + JBE sealAVX2Tail128 + CMPQ inl, $256 + JBE sealAVX2Tail256 + CMPQ inl, $384 + JBE sealAVX2Tail384 + JMP sealAVX2Tail512 + +// ---------------------------------------------------------------------------- +// Special optimization for buffers smaller than 193 bytes +seal192AVX2: + // For up to 192 bytes of ciphertext and 64 bytes for the poly key, we process four blocks + VMOVDQA AA0, AA1 + VMOVDQA BB0, BB1 + VMOVDQA CC0, CC1 + VPADDD ·avx2IncMask<>(SB), DD0, DD1 + VMOVDQA AA0, AA2 + VMOVDQA BB0, BB2 + VMOVDQA CC0, CC2 + VMOVDQA DD0, DD2 + VMOVDQA DD1, TT3 + MOVQ $10, itr2 + +sealAVX2192InnerCipherLoop: + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) + VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1 + VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 + VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1 + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) + VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1 + VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 + VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1 + DECQ itr2 + JNE sealAVX2192InnerCipherLoop + VPADDD AA2, AA0, AA0; VPADDD AA2, AA1, AA1 + VPADDD BB2, BB0, BB0; VPADDD BB2, BB1, BB1 + VPADDD CC2, CC0, CC0; VPADDD CC2, CC1, CC1 + VPADDD DD2, DD0, DD0; VPADDD TT3, DD1, DD1 + VPERM2I128 $0x02, AA0, BB0, TT0 + + // Clamp and store poly key + VPAND ·polyClampMask<>(SB), TT0, TT0 + VMOVDQA TT0, rsStoreAVX2 + + // Stream for up to 192 bytes + VPERM2I128 $0x13, AA0, BB0, AA0 + VPERM2I128 $0x13, CC0, DD0, BB0 + VPERM2I128 $0x02, AA1, BB1, CC0 + VPERM2I128 $0x02, CC1, DD1, DD0 + VPERM2I128 $0x13, AA1, BB1, AA1 + VPERM2I128 $0x13, CC1, DD1, BB1 + +sealAVX2ShortSeal: + // Hash aad + MOVQ ad_len+80(FP), itr2 + CALL polyHashADInternal<>(SB) + XORQ itr1, itr1 + +sealAVX2SealHash: + // itr1 holds the number of bytes encrypted but not yet hashed + CMPQ itr1, $16 + JB sealAVX2ShortSealLoop + polyAdd(0(oup)) + polyMul + SUBQ $16, itr1 + ADDQ $16, oup + JMP sealAVX2SealHash + +sealAVX2ShortSealLoop: + CMPQ inl, $32 + JB sealAVX2ShortTail32 + SUBQ $32, inl + + // Load for encryption + VPXOR (inp), AA0, AA0 + VMOVDQU AA0, (oup) + LEAQ (1*32)(inp), inp + + // Now can hash + polyAdd(0*8(oup)) + polyMulAVX2 + polyAdd(2*8(oup)) + polyMulAVX2 + LEAQ (1*32)(oup), oup + + // Shift stream left + VMOVDQA BB0, AA0 + VMOVDQA CC0, BB0 + VMOVDQA DD0, CC0 + VMOVDQA AA1, DD0 + VMOVDQA BB1, AA1 + VMOVDQA CC1, BB1 + VMOVDQA DD1, CC1 + VMOVDQA AA2, DD1 + VMOVDQA BB2, AA2 + JMP sealAVX2ShortSealLoop + +sealAVX2ShortTail32: + CMPQ inl, $16 + VMOVDQA A0, A1 + JB sealAVX2ShortDone + + SUBQ $16, inl + + // Load for encryption + VPXOR (inp), A0, T0 + VMOVDQU T0, (oup) + LEAQ (1*16)(inp), inp + + // Hash + polyAdd(0*8(oup)) + polyMulAVX2 + LEAQ (1*16)(oup), oup + VPERM2I128 $0x11, AA0, AA0, AA0 + VMOVDQA A0, A1 + +sealAVX2ShortDone: + VZEROUPPER + JMP sealSSETail + +// ---------------------------------------------------------------------------- +// Special optimization for buffers smaller than 321 bytes +seal320AVX2: + // For up to 320 bytes of ciphertext and 64 bytes for the poly key, we process six blocks + VMOVDQA AA0, AA1; VMOVDQA BB0, BB1; VMOVDQA CC0, CC1; VPADDD ·avx2IncMask<>(SB), DD0, DD1 + VMOVDQA AA0, AA2; VMOVDQA BB0, BB2; VMOVDQA CC0, CC2; VPADDD ·avx2IncMask<>(SB), DD1, DD2 + VMOVDQA BB0, TT1; VMOVDQA CC0, TT2; VMOVDQA DD0, TT3 + MOVQ $10, itr2 + +sealAVX2320InnerCipherLoop: + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) + VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2 + VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 + VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2 + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) + VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2 + VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 + VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2 + DECQ itr2 + JNE sealAVX2320InnerCipherLoop + + VMOVDQA ·chacha20Constants<>(SB), TT0 + VPADDD TT0, AA0, AA0; VPADDD TT0, AA1, AA1; VPADDD TT0, AA2, AA2 + VPADDD TT1, BB0, BB0; VPADDD TT1, BB1, BB1; VPADDD TT1, BB2, BB2 + VPADDD TT2, CC0, CC0; VPADDD TT2, CC1, CC1; VPADDD TT2, CC2, CC2 + VMOVDQA ·avx2IncMask<>(SB), TT0 + VPADDD TT3, DD0, DD0; VPADDD TT0, TT3, TT3 + VPADDD TT3, DD1, DD1; VPADDD TT0, TT3, TT3 + VPADDD TT3, DD2, DD2 + + // Clamp and store poly key + VPERM2I128 $0x02, AA0, BB0, TT0 + VPAND ·polyClampMask<>(SB), TT0, TT0 + VMOVDQA TT0, rsStoreAVX2 + + // Stream for up to 320 bytes + VPERM2I128 $0x13, AA0, BB0, AA0 + VPERM2I128 $0x13, CC0, DD0, BB0 + VPERM2I128 $0x02, AA1, BB1, CC0 + VPERM2I128 $0x02, CC1, DD1, DD0 + VPERM2I128 $0x13, AA1, BB1, AA1 + VPERM2I128 $0x13, CC1, DD1, BB1 + VPERM2I128 $0x02, AA2, BB2, CC1 + VPERM2I128 $0x02, CC2, DD2, DD1 + VPERM2I128 $0x13, AA2, BB2, AA2 + VPERM2I128 $0x13, CC2, DD2, BB2 + JMP sealAVX2ShortSeal + +// ---------------------------------------------------------------------------- +// Special optimization for the last 128 bytes of ciphertext +sealAVX2Tail128: + // Need to decrypt up to 128 bytes - prepare two blocks + // If we got here after the main loop - there are 512 encrypted bytes waiting to be hashed + // If we got here before the main loop - there are 448 encrpyred bytes waiting to be hashed + VMOVDQA ·chacha20Constants<>(SB), AA0 + VMOVDQA state1StoreAVX2, BB0 + VMOVDQA state2StoreAVX2, CC0 + VMOVDQA ctr3StoreAVX2, DD0 + VPADDD ·avx2IncMask<>(SB), DD0, DD0 + VMOVDQA DD0, DD1 + +sealAVX2Tail128LoopA: + polyAdd(0(oup)) + polyMul + LEAQ 16(oup), oup + +sealAVX2Tail128LoopB: + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) + polyAdd(0(oup)) + polyMul + VPALIGNR $4, BB0, BB0, BB0 + VPALIGNR $8, CC0, CC0, CC0 + VPALIGNR $12, DD0, DD0, DD0 + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) + polyAdd(16(oup)) + polyMul + LEAQ 32(oup), oup + VPALIGNR $12, BB0, BB0, BB0 + VPALIGNR $8, CC0, CC0, CC0 + VPALIGNR $4, DD0, DD0, DD0 + DECQ itr1 + JG sealAVX2Tail128LoopA + DECQ itr2 + JGE sealAVX2Tail128LoopB + + VPADDD ·chacha20Constants<>(SB), AA0, AA1 + VPADDD state1StoreAVX2, BB0, BB1 + VPADDD state2StoreAVX2, CC0, CC1 + VPADDD DD1, DD0, DD1 + + VPERM2I128 $0x02, AA1, BB1, AA0 + VPERM2I128 $0x02, CC1, DD1, BB0 + VPERM2I128 $0x13, AA1, BB1, CC0 + VPERM2I128 $0x13, CC1, DD1, DD0 + JMP sealAVX2ShortSealLoop + +// ---------------------------------------------------------------------------- +// Special optimization for the last 256 bytes of ciphertext +sealAVX2Tail256: + // Need to decrypt up to 256 bytes - prepare two blocks + // If we got here after the main loop - there are 512 encrypted bytes waiting to be hashed + // If we got here before the main loop - there are 448 encrpyred bytes waiting to be hashed + VMOVDQA ·chacha20Constants<>(SB), AA0; VMOVDQA ·chacha20Constants<>(SB), AA1 + VMOVDQA state1StoreAVX2, BB0; VMOVDQA state1StoreAVX2, BB1 + VMOVDQA state2StoreAVX2, CC0; VMOVDQA state2StoreAVX2, CC1 + VMOVDQA ctr3StoreAVX2, DD0 + VPADDD ·avx2IncMask<>(SB), DD0, DD0 + VPADDD ·avx2IncMask<>(SB), DD0, DD1 + VMOVDQA DD0, TT1 + VMOVDQA DD1, TT2 + +sealAVX2Tail256LoopA: + polyAdd(0(oup)) + polyMul + LEAQ 16(oup), oup + +sealAVX2Tail256LoopB: + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) + polyAdd(0(oup)) + polyMul + VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1 + VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 + VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1 + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) + polyAdd(16(oup)) + polyMul + LEAQ 32(oup), oup + VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1 + VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 + VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1 + DECQ itr1 + JG sealAVX2Tail256LoopA + DECQ itr2 + JGE sealAVX2Tail256LoopB + + VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1 + VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1 + VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1 + VPADDD TT1, DD0, DD0; VPADDD TT2, DD1, DD1 + VPERM2I128 $0x02, AA0, BB0, TT0 + VPERM2I128 $0x02, CC0, DD0, TT1 + VPERM2I128 $0x13, AA0, BB0, TT2 + VPERM2I128 $0x13, CC0, DD0, TT3 + VPXOR (0*32)(inp), TT0, TT0; VPXOR (1*32)(inp), TT1, TT1; VPXOR (2*32)(inp), TT2, TT2; VPXOR (3*32)(inp), TT3, TT3 + VMOVDQU TT0, (0*32)(oup); VMOVDQU TT1, (1*32)(oup); VMOVDQU TT2, (2*32)(oup); VMOVDQU TT3, (3*32)(oup) + MOVQ $128, itr1 + LEAQ 128(inp), inp + SUBQ $128, inl + VPERM2I128 $0x02, AA1, BB1, AA0 + VPERM2I128 $0x02, CC1, DD1, BB0 + VPERM2I128 $0x13, AA1, BB1, CC0 + VPERM2I128 $0x13, CC1, DD1, DD0 + + JMP sealAVX2SealHash + +// ---------------------------------------------------------------------------- +// Special optimization for the last 384 bytes of ciphertext +sealAVX2Tail384: + // Need to decrypt up to 384 bytes - prepare two blocks + // If we got here after the main loop - there are 512 encrypted bytes waiting to be hashed + // If we got here before the main loop - there are 448 encrpyred bytes waiting to be hashed + VMOVDQA ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2 + VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2 + VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2 + VMOVDQA ctr3StoreAVX2, DD0 + VPADDD ·avx2IncMask<>(SB), DD0, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD1; VPADDD ·avx2IncMask<>(SB), DD1, DD2 + VMOVDQA DD0, TT1; VMOVDQA DD1, TT2; VMOVDQA DD2, TT3 + +sealAVX2Tail384LoopA: + polyAdd(0(oup)) + polyMul + LEAQ 16(oup), oup + +sealAVX2Tail384LoopB: + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) + polyAdd(0(oup)) + polyMul + VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2 + VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 + VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2 + chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) + polyAdd(16(oup)) + polyMul + LEAQ 32(oup), oup + VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2 + VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 + VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2 + DECQ itr1 + JG sealAVX2Tail384LoopA + DECQ itr2 + JGE sealAVX2Tail384LoopB + + VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2 + VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2 + VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2 + VPADDD TT1, DD0, DD0; VPADDD TT2, DD1, DD1; VPADDD TT3, DD2, DD2 + VPERM2I128 $0x02, AA0, BB0, TT0 + VPERM2I128 $0x02, CC0, DD0, TT1 + VPERM2I128 $0x13, AA0, BB0, TT2 + VPERM2I128 $0x13, CC0, DD0, TT3 + VPXOR (0*32)(inp), TT0, TT0; VPXOR (1*32)(inp), TT1, TT1; VPXOR (2*32)(inp), TT2, TT2; VPXOR (3*32)(inp), TT3, TT3 + VMOVDQU TT0, (0*32)(oup); VMOVDQU TT1, (1*32)(oup); VMOVDQU TT2, (2*32)(oup); VMOVDQU TT3, (3*32)(oup) + VPERM2I128 $0x02, AA1, BB1, TT0 + VPERM2I128 $0x02, CC1, DD1, TT1 + VPERM2I128 $0x13, AA1, BB1, TT2 + VPERM2I128 $0x13, CC1, DD1, TT3 + VPXOR (4*32)(inp), TT0, TT0; VPXOR (5*32)(inp), TT1, TT1; VPXOR (6*32)(inp), TT2, TT2; VPXOR (7*32)(inp), TT3, TT3 + VMOVDQU TT0, (4*32)(oup); VMOVDQU TT1, (5*32)(oup); VMOVDQU TT2, (6*32)(oup); VMOVDQU TT3, (7*32)(oup) + MOVQ $256, itr1 + LEAQ 256(inp), inp + SUBQ $256, inl + VPERM2I128 $0x02, AA2, BB2, AA0 + VPERM2I128 $0x02, CC2, DD2, BB0 + VPERM2I128 $0x13, AA2, BB2, CC0 + VPERM2I128 $0x13, CC2, DD2, DD0 + + JMP sealAVX2SealHash + +// ---------------------------------------------------------------------------- +// Special optimization for the last 512 bytes of ciphertext +sealAVX2Tail512: + // Need to decrypt up to 512 bytes - prepare two blocks + // If we got here after the main loop - there are 512 encrypted bytes waiting to be hashed + // If we got here before the main loop - there are 448 encrpyred bytes waiting to be hashed + VMOVDQA ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3 + VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3 + VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3 + VMOVDQA ctr3StoreAVX2, DD0 + VPADDD ·avx2IncMask<>(SB), DD0, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD1; VPADDD ·avx2IncMask<>(SB), DD1, DD2; VPADDD ·avx2IncMask<>(SB), DD2, DD3 + VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2 + +sealAVX2Tail512LoopA: + polyAdd(0(oup)) + polyMul + LEAQ 16(oup), oup + +sealAVX2Tail512LoopB: + VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 + VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 + VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3 + VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 + VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 + VMOVDQA CC3, tmpStoreAVX2 + VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 + VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 + VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 + VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 + VMOVDQA tmpStoreAVX2, CC3 + polyAdd(0*8(oup)) + polyMulAVX2 + VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 + VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 + VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3 + VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 + VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 + VMOVDQA CC3, tmpStoreAVX2 + VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 + VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 + VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 + VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 + VMOVDQA tmpStoreAVX2, CC3 + VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $4, BB3, BB3, BB3 + VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 + VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2; VPALIGNR $12, DD3, DD3, DD3 + VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 + VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 + VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3 + VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 + VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 + polyAdd(2*8(oup)) + polyMulAVX2 + LEAQ (4*8)(oup), oup + VMOVDQA CC3, tmpStoreAVX2 + VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 + VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 + VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 + VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 + VMOVDQA tmpStoreAVX2, CC3 + VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 + VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 + VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3 + VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 + VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 + VMOVDQA CC3, tmpStoreAVX2 + VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 + VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 + VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 + VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 + VMOVDQA tmpStoreAVX2, CC3 + VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $12, BB3, BB3, BB3 + VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 + VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2; VPALIGNR $4, DD3, DD3, DD3 + + DECQ itr1 + JG sealAVX2Tail512LoopA + DECQ itr2 + JGE sealAVX2Tail512LoopB + + VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2; VPADDD ·chacha20Constants<>(SB), AA3, AA3 + VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3 + VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3 + VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3 + VMOVDQA CC3, tmpStoreAVX2 + VPERM2I128 $0x02, AA0, BB0, CC3 + VPXOR (0*32)(inp), CC3, CC3 + VMOVDQU CC3, (0*32)(oup) + VPERM2I128 $0x02, CC0, DD0, CC3 + VPXOR (1*32)(inp), CC3, CC3 + VMOVDQU CC3, (1*32)(oup) + VPERM2I128 $0x13, AA0, BB0, CC3 + VPXOR (2*32)(inp), CC3, CC3 + VMOVDQU CC3, (2*32)(oup) + VPERM2I128 $0x13, CC0, DD0, CC3 + VPXOR (3*32)(inp), CC3, CC3 + VMOVDQU CC3, (3*32)(oup) + + VPERM2I128 $0x02, AA1, BB1, AA0 + VPERM2I128 $0x02, CC1, DD1, BB0 + VPERM2I128 $0x13, AA1, BB1, CC0 + VPERM2I128 $0x13, CC1, DD1, DD0 + VPXOR (4*32)(inp), AA0, AA0; VPXOR (5*32)(inp), BB0, BB0; VPXOR (6*32)(inp), CC0, CC0; VPXOR (7*32)(inp), DD0, DD0 + VMOVDQU AA0, (4*32)(oup); VMOVDQU BB0, (5*32)(oup); VMOVDQU CC0, (6*32)(oup); VMOVDQU DD0, (7*32)(oup) + + VPERM2I128 $0x02, AA2, BB2, AA0 + VPERM2I128 $0x02, CC2, DD2, BB0 + VPERM2I128 $0x13, AA2, BB2, CC0 + VPERM2I128 $0x13, CC2, DD2, DD0 + VPXOR (8*32)(inp), AA0, AA0; VPXOR (9*32)(inp), BB0, BB0; VPXOR (10*32)(inp), CC0, CC0; VPXOR (11*32)(inp), DD0, DD0 + VMOVDQU AA0, (8*32)(oup); VMOVDQU BB0, (9*32)(oup); VMOVDQU CC0, (10*32)(oup); VMOVDQU DD0, (11*32)(oup) + + MOVQ $384, itr1 + LEAQ 384(inp), inp + SUBQ $384, inl + VPERM2I128 $0x02, AA3, BB3, AA0 + VPERM2I128 $0x02, tmpStoreAVX2, DD3, BB0 + VPERM2I128 $0x13, AA3, BB3, CC0 + VPERM2I128 $0x13, tmpStoreAVX2, DD3, DD0 + + JMP sealAVX2SealHash + +// func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32) +TEXT ·cpuid(SB), NOSPLIT, $0-24 + MOVL eaxArg+0(FP), AX + MOVL ecxArg+4(FP), CX + CPUID + MOVL AX, eax+8(FP) + MOVL BX, ebx+12(FP) + MOVL CX, ecx+16(FP) + MOVL DX, edx+20(FP) + RET + +// func xgetbv() (eax, edx uint32) +TEXT ·xgetbv(SB),NOSPLIT,$0-8 + MOVL $0, CX + XGETBV + MOVL AX, eax+0(FP) + MOVL DX, edx+4(FP) + RET diff --git a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go new file mode 100644 index 0000000000000000000000000000000000000000..4ac014f525cbfff4ed8a3b3554cd717396a18eab --- /dev/null +++ b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go @@ -0,0 +1,70 @@ +// Copyright 2016 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 chacha20poly1305 + +import ( + "encoding/binary" + + "golang.org/x/crypto/internal/chacha20" + "golang.org/x/crypto/poly1305" +) + +func roundTo16(n int) int { + return 16 * ((n + 15) / 16) +} + +func (c *chacha20poly1305) sealGeneric(dst, nonce, plaintext, additionalData []byte) []byte { + var counter [16]byte + copy(counter[4:], nonce) + + var polyKey [32]byte + chacha20.XORKeyStream(polyKey[:], polyKey[:], &counter, &c.key) + + ret, out := sliceForAppend(dst, len(plaintext)+poly1305.TagSize) + counter[0] = 1 + chacha20.XORKeyStream(out, plaintext, &counter, &c.key) + + polyInput := make([]byte, roundTo16(len(additionalData))+roundTo16(len(plaintext))+8+8) + copy(polyInput, additionalData) + copy(polyInput[roundTo16(len(additionalData)):], out[:len(plaintext)]) + binary.LittleEndian.PutUint64(polyInput[len(polyInput)-16:], uint64(len(additionalData))) + binary.LittleEndian.PutUint64(polyInput[len(polyInput)-8:], uint64(len(plaintext))) + + var tag [poly1305.TagSize]byte + poly1305.Sum(&tag, polyInput, &polyKey) + copy(out[len(plaintext):], tag[:]) + + return ret +} + +func (c *chacha20poly1305) openGeneric(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { + var tag [poly1305.TagSize]byte + copy(tag[:], ciphertext[len(ciphertext)-16:]) + ciphertext = ciphertext[:len(ciphertext)-16] + + var counter [16]byte + copy(counter[4:], nonce) + + var polyKey [32]byte + chacha20.XORKeyStream(polyKey[:], polyKey[:], &counter, &c.key) + + polyInput := make([]byte, roundTo16(len(additionalData))+roundTo16(len(ciphertext))+8+8) + copy(polyInput, additionalData) + copy(polyInput[roundTo16(len(additionalData)):], ciphertext) + binary.LittleEndian.PutUint64(polyInput[len(polyInput)-16:], uint64(len(additionalData))) + binary.LittleEndian.PutUint64(polyInput[len(polyInput)-8:], uint64(len(ciphertext))) + + ret, out := sliceForAppend(dst, len(ciphertext)) + if !poly1305.Verify(&tag, polyInput, &polyKey) { + for i := range out { + out[i] = 0 + } + return nil, errOpen + } + + counter[0] = 1 + chacha20.XORKeyStream(out, ciphertext, &counter, &c.key) + return ret, nil +} diff --git a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go new file mode 100644 index 0000000000000000000000000000000000000000..4c2eb703c327cddc1a3caea33cfc85e9b8dd59c1 --- /dev/null +++ b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go @@ -0,0 +1,15 @@ +// Copyright 2016 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 !go1.7 gccgo appengine + +package chacha20poly1305 + +func (c *chacha20poly1305) seal(dst, nonce, plaintext, additionalData []byte) []byte { + return c.sealGeneric(dst, nonce, plaintext, additionalData) +} + +func (c *chacha20poly1305) open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { + return c.openGeneric(dst, nonce, ciphertext, additionalData) +} diff --git a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_test.go b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_test.go new file mode 100644 index 0000000000000000000000000000000000000000..78f981a74f41ea6b06fc6ef43d3a6d599216f012 --- /dev/null +++ b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_test.go @@ -0,0 +1,182 @@ +// Copyright 2016 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 chacha20poly1305 + +import ( + "bytes" + cr "crypto/rand" + "encoding/hex" + mr "math/rand" + "testing" +) + +func TestVectors(t *testing.T) { + for i, test := range chacha20Poly1305Tests { + key, _ := hex.DecodeString(test.key) + nonce, _ := hex.DecodeString(test.nonce) + ad, _ := hex.DecodeString(test.aad) + plaintext, _ := hex.DecodeString(test.plaintext) + + aead, err := New(key) + if err != nil { + t.Fatal(err) + } + + ct := aead.Seal(nil, nonce, plaintext, ad) + if ctHex := hex.EncodeToString(ct); ctHex != test.out { + t.Errorf("#%d: got %s, want %s", i, ctHex, test.out) + continue + } + + plaintext2, err := aead.Open(nil, nonce, ct, ad) + if err != nil { + t.Errorf("#%d: Open failed", i) + continue + } + + if !bytes.Equal(plaintext, plaintext2) { + t.Errorf("#%d: plaintext's don't match: got %x vs %x", i, plaintext2, plaintext) + continue + } + + if len(ad) > 0 { + alterAdIdx := mr.Intn(len(ad)) + ad[alterAdIdx] ^= 0x80 + if _, err := aead.Open(nil, nonce, ct, ad); err == nil { + t.Errorf("#%d: Open was successful after altering additional data", i) + } + ad[alterAdIdx] ^= 0x80 + } + + alterNonceIdx := mr.Intn(aead.NonceSize()) + nonce[alterNonceIdx] ^= 0x80 + if _, err := aead.Open(nil, nonce, ct, ad); err == nil { + t.Errorf("#%d: Open was successful after altering nonce", i) + } + nonce[alterNonceIdx] ^= 0x80 + + alterCtIdx := mr.Intn(len(ct)) + ct[alterCtIdx] ^= 0x80 + if _, err := aead.Open(nil, nonce, ct, ad); err == nil { + t.Errorf("#%d: Open was successful after altering ciphertext", i) + } + ct[alterCtIdx] ^= 0x80 + } +} + +func TestRandom(t *testing.T) { + // Some random tests to verify Open(Seal) == Plaintext + for i := 0; i < 256; i++ { + var nonce [12]byte + var key [32]byte + + al := mr.Intn(128) + pl := mr.Intn(16384) + ad := make([]byte, al) + plaintext := make([]byte, pl) + cr.Read(key[:]) + cr.Read(nonce[:]) + cr.Read(ad) + cr.Read(plaintext) + + aead, err := New(key[:]) + if err != nil { + t.Fatal(err) + } + + ct := aead.Seal(nil, nonce[:], plaintext, ad) + + plaintext2, err := aead.Open(nil, nonce[:], ct, ad) + if err != nil { + t.Errorf("Random #%d: Open failed", i) + continue + } + + if !bytes.Equal(plaintext, plaintext2) { + t.Errorf("Random #%d: plaintext's don't match: got %x vs %x", i, plaintext2, plaintext) + continue + } + + if len(ad) > 0 { + alterAdIdx := mr.Intn(len(ad)) + ad[alterAdIdx] ^= 0x80 + if _, err := aead.Open(nil, nonce[:], ct, ad); err == nil { + t.Errorf("Random #%d: Open was successful after altering additional data", i) + } + ad[alterAdIdx] ^= 0x80 + } + + alterNonceIdx := mr.Intn(aead.NonceSize()) + nonce[alterNonceIdx] ^= 0x80 + if _, err := aead.Open(nil, nonce[:], ct, ad); err == nil { + t.Errorf("Random #%d: Open was successful after altering nonce", i) + } + nonce[alterNonceIdx] ^= 0x80 + + alterCtIdx := mr.Intn(len(ct)) + ct[alterCtIdx] ^= 0x80 + if _, err := aead.Open(nil, nonce[:], ct, ad); err == nil { + t.Errorf("Random #%d: Open was successful after altering ciphertext", i) + } + ct[alterCtIdx] ^= 0x80 + } +} + +func benchamarkChaCha20Poly1305Seal(b *testing.B, buf []byte) { + b.SetBytes(int64(len(buf))) + + var key [32]byte + var nonce [12]byte + var ad [13]byte + var out []byte + + aead, _ := New(key[:]) + b.ResetTimer() + for i := 0; i < b.N; i++ { + out = aead.Seal(out[:0], nonce[:], buf[:], ad[:]) + } +} + +func benchamarkChaCha20Poly1305Open(b *testing.B, buf []byte) { + b.SetBytes(int64(len(buf))) + + var key [32]byte + var nonce [12]byte + var ad [13]byte + var ct []byte + var out []byte + + aead, _ := New(key[:]) + ct = aead.Seal(ct[:0], nonce[:], buf[:], ad[:]) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + out, _ = aead.Open(out[:0], nonce[:], ct[:], ad[:]) + } +} + +func BenchmarkChacha20Poly1305Open_64(b *testing.B) { + benchamarkChaCha20Poly1305Open(b, make([]byte, 64)) +} + +func BenchmarkChacha20Poly1305Seal_64(b *testing.B) { + benchamarkChaCha20Poly1305Seal(b, make([]byte, 64)) +} + +func BenchmarkChacha20Poly1305Open_1350(b *testing.B) { + benchamarkChaCha20Poly1305Open(b, make([]byte, 1350)) +} + +func BenchmarkChacha20Poly1305Seal_1350(b *testing.B) { + benchamarkChaCha20Poly1305Seal(b, make([]byte, 1350)) +} + +func BenchmarkChacha20Poly1305Open_8K(b *testing.B) { + benchamarkChaCha20Poly1305Open(b, make([]byte, 8*1024)) +} + +func BenchmarkChacha20Poly1305Seal_8K(b *testing.B) { + benchamarkChaCha20Poly1305Seal(b, make([]byte, 8*1024)) +} diff --git a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_vectors_test.go b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_vectors_test.go new file mode 100644 index 0000000000000000000000000000000000000000..49f0da6b738c918bacb45666e65d919a886aa431 --- /dev/null +++ b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_vectors_test.go @@ -0,0 +1,332 @@ +// Copyright 2016 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 chacha20poly1305 + +var chacha20Poly1305Tests = []struct { + plaintext, aad, key, nonce, out string +}{ + { + "4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e", + "50515253c0c1c2c3c4c5c6c7", + "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", + "070000004041424344454647", + "d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b61161ae10b594f09e26a7e902ecbd0600691", + }, + { + "1400000cebccee3bf561b292340fec60", + "00000000000000001603030010", + "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", + "129039b5572e8a7a8131f76a", + "2b487a2941bc07f3cc76d1a531662588ee7c2598e59778c24d5b27559a80d163", + }, + { + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "00000000000000000000000000", + "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", + "129039b5572e8a7a8131f76a", + "3f487a25aa70e9c8391763370569c9e83b7650dd1921c8b78869f241f25d2096c910b180930c5b8747fd90959fe8ca2dcadb4fa50fa1439f916b2301e1cc0810d6725775d3ab86721700f96e22709b0a7a8bef32627dd929b2dd3ba15772b669062bb558bc92e6c241a1d60d9f0035e80c335f854815fe1138ab8af653eab3e122135feeec7dfaba1cc24af82a2b7acccdd824899a7e03cc29c25be8a4f56a66673845b93bae1556f09dafc89a0d22af207718e2a6bb022e9d917597295992ea3b750cc0e7a7c3d33b23c5a8aeab45f5bb542f6c9e6c1747ae5a344aff483ba38577ad534b33b3abc7d284776ea33ed488c2a2475648a4fcda561745ea7787ed60f2368deb27c75adce6ff9b6cc6de1f5e72a741e2d59f64751b3ae482d714e0c90e83c671ff98ed611823afb39e6e5019a6ba548a2a72e829c7b7b4a101ac9deb90a25d3e0c50d22e1fc26c7c02296fa13c6d9c14767f68aaf46450a8d0fd5feb60d9d73c6e68623425b4984a79d619dd6bf896459aa77a681ec9c1a97f645e121f47779b051f8948a817f84d1f55da170d5bbbaf2f64e18b97ed3fd822db2819f523314f1e5ac72e8f69bbe6c87c22daddb0e1ac6790f8534071de2f258064b99789bfb165b065b8fe96f9127cd7dca9f7cb0368420f1e802faa3ca23792f2a5b93773dd405e71c320b211b54f7a26626b03c060e1ab87f32ac588abfa056ce090bd7c69913a700c80f325bfe824fa", + }, + { + "0967de57eefe1aaa999b9b746d88a1a248000d8734e0e938c6aa87", + "e4f0a3a4f90a8250f8806aa319053e8d73c62f150e2f239563037e9cc92823ad18c65111d0d462c954cc6c6ed2aafb45702a5a7e597d13bd8091594ab97cf7d1", + "f2db28620582e05f00f31c808475ca3df1c20e340bf14828352499466d79295f", + "4349e2131d44dc711148dfe3", + "bd06cc144fdc0d8b735fa4452eabbf78fd4ad2966ea41a84f68da40ca2da439777bc2ba6c4ec2de0d003eb", + }, + { + "c4c920fb52a56fe66eaa8aa3fa187c543e3db8e5c8094c4313dc4ed35dfc5821c5791d171e8cfe8d37883031a0ad", + "85deea3dc4", + "05ff881d1e151bab4ca3db7d44880222733fe62686f71ce1e4610f2ea19599a7", + "b34710f65aed442e4a40866b", + "b154452fb7e85d175dd0b0db08591565c5587a725cf22386922f5d27a01015aba778975510b38754b2182e24352f019b7ad493e1ed255906715644aec6e0", + }, + { + "c4b337df5e83823900c6c202e93541cf5bc8c677a9aad8b8d87a4d7221e294e595cbc4f34e462d4e0def50f62491c57f598cf60236cfba0f4908816aea154f80e013732e59a07c668fcc5cb35d2232b7ae29b9e4f874f3417c74ab6689fae6690d5a9766fa13cd8adf293d3d4b70f4f999adde9121d1d29d467d04cf77ea398444d0ea3fe4b7c9c3e106002c76f4260fa204a0c3d5", + "72611bef65eb664f24ea94f4d5d3d88c9c9c6da29c9a1991c02833c4c9f6993b57b5", + "dd0f2d4bb1c9e5ca5aa5f38d69bc8402f7dbb7229857b4a41b3044d481b7655e", + "2bbca0910cc47ca0b8517391", + "83aa28d6d98901e2981d21d3758ae4db8cce07fe08d82ca6f036a68daa88a7dda56eeb38040c942bdda0fd2d369eec44bd070e2c9314992f68dc16989a6ac0c3912c378cf3254f4bae74a66b075e828df6f855c0d8a827ffed3c03582c12a9112eeb7be43dfe8bd78beb2d1e56678b99a0372531727cb7f2b98d2f917ec10de93fe86267100c20356e80528c5066688c8b7acba76e591449952343f663993d5b642e59eb0f", + }, + { + "a9775b8e42b63335439cf1c79fe8a3560b3baebfdfc9ef239d70da02cea0947817f00659a63a8ee9d67fb1756854cc738f7a326e432191e1916be35f0b78d72268de7c0e180af7ee8aa864f2fc30658baa97f9edb88ace49f5b2a8002a8023925e9fa076a997643340c8253cf88ac8a221c190d94c5e224110cb423a4b65cca9046c1fad0483e1444c0680449148e7b20a778c56d5ae97e679d920c43eed6d42598cf05d10d1a15cd722a0686a871b74fea7cad45562bacf3bda937ac701bc218dac7e9d7d20f955429abdac21d821207febf4d54daea4898837035038bf71c66cef63e90f5d3e51f7fcfe18d41f38540a2c2958dacde16304e4b33da324030f1366f923c337", + "74ba3372d308910b5c9c3885f41252d57556", + "9cf77bd06a4ed8fb59349791b98ba40b6019611942f5768e8be2ee88477149e3", + "b928935c4c966c60fd6583c0", + "ec7fd64fd75b254961a2b7fc942470d8620f439258b871d0d00f58028b5e0bee5e139e8108ac439391465d6658f559b1df57aa21cf826ede1a28bc11af885e13eebfc009870928fae8abfdd943a60c54fca93f0502dc23d29c2fd5340f9bc0e6ef2a18b66ef627af95f796d5bbca50de22c8ec802da9397089b25c6ba5262468e3977b45dc112e51896c70731b0a52d7efec7c93b41995823436bf4b0c477ae79684407c9831b487928b2b8303caca752b3edf1f0598e15831155462706f94ef3fa3a9e5f937f37085afa9b4bbf939d275796a61b78f70597acfd25cd87f967021cd99328fc371b5eb5739869520657b30e4a5b0db7c8715cbe275dee78e719b357d3a9731f9eaba95986479bb2004a77822fc115a3d", + }, + { + "b3d3128bce6bbf66fd78f1a18352bae56bfcdae18b65c379ee0aeb37ee54fba1270d2df578ec5b75654d16e89fd1cd0acda7ec580dafd2fbbabd32a8112d49383a762db2638928c8d63eb0750f7e7fdd256b35321b072dd5c45f7dd58cc60dc63d3b79a0c4a1689adf180fef968eccbcfa01ee15091ceacd7b67a3082db0ce6aeb470aafe87249c88b58b721e783dde184ccf68de8e05b6347fe6b74ae3adf9a81e9496a5c9332e7ebe908d26ce6b3f0b2a97e9a89d9fdd0d7694585a3241f240d698e69fcc050e7a959ba153f6d06f117848ba05d887134f1b6b994dad9b9e74247513e08a125b1fadfc7394dcd2a6451b504ae3e75e22f2b9bc405747dedb6c43ef4ccdf1a7edaf9451346123eaa63f3af113124f361508e255503a242b96680ae3360c8b13ac1f64d08088bb26b7f617cb0866f11d6fd362b00d86eba3fee68724e302388f119d6f92161ac8ce00d08919377a26974d99575b1032ff0f1976240c785c8b89e9eb2bf005e4be06b5371ffca14683fedfdb49e00e38ff27af1324177faf91599abd5990920797574eb743effdc7decda318ada1419cc8e0bfecf82f9c99792746c2b", + "7e8da4f3018f673f8e43bd7a1dee05f8031ec49129c361abbc2a434e9eaf791c3c1d0f3dad767d3bba3ab6d728bbcf2bd994bd03571eae1348f161e6a1da03ddf7121ba4", + "7ee32dd501dce849cd492f6e23324c1a4567bfceff9f11d1352bcb8615f1b093", + "8998e043d2961afa51ea262a", + "ba85e72af18cb5ba85a4a0d6c28b4ac1e5509a3a2fdb0e3255cbc559df5e6a661fc560c756a0264dd99b72c61c51a4b7ad56ca4c8ccb7e8edfc48ff3cceac5d1e8ac5fc87096adc4d0e9a27492857b17604c3a694cfe0e70b22df106c8f3c61f840bcd634964cdb571840e125e381e7dd3a0d97972e965f16f775fa4ce555124318290bf508beb7bd77e633042deb0e863631478fc3dc9122862b3c31264471bcce54e0b74040c8bafd481cf798f332e8940f1134d3027d6f28e771d15e154fc89c6c25fe18a5d312807cc2e623bb1bbb4f0b6ec71d009407eb54bb0759f03682f65d0da8812f84d8e97483f6a8d76a8417efcd9526444abba24288647609791578887ef49780b0b89f51b072cae81c5b5014463da3633dda105b82add0f9c2f065dca46eedd2928be2570493c79a996fa78ea6aec0996497fe2dc444432ade4eaa662ee2255f0f4b92d593288a8e3ffe7a15a10e9d33b0203af23f4c9fd2cfcb6160db63b52810869ff1e65423dbe2c4415884b9f8dec3c968e14cd74f323c89053a96111bc9ce59ec483832c49c53a648e5f0f797f53642ac60170c94b473f1f2e7d8a38e46460b81219b52081263027f74cbf63a75af3a7", + }, + { + "68d5ba501e87994ef6bc8042d7c5a99693a835a4796ad044f0e536a0790a7ee1e03832fec0cb4cb688cdf85f92a1f526492acac2949a0684803c24f947a3da27db0c259bd87251603f49bfd1eab4f733dec2f5725cfcf6dc381ad57fbdb0a699bccc34943e86f47dcfb34eba6746ed4508e3b764dfad4117c8169785c63d1e8309531747d90cc4a8bf13622759506c613324c512d10629991dc01fe3fe3d6607907e4f698a1312492674707fc4dde0f701a609d2ac336cc9f38badf1c813f9599148c21b5bd4658249d5010db2e205b3880e863441f2fe357dab2645be1f9e5067616bc335d0457ea6468c5828910cb09f92e5e184e316018e3c464c5ce59cc34608867bd8cbfa7e1286d73a17e3ebb675d097f9b3adfa41ea408d46252a096b3290e70a5be1896d6760a87e439334b863ccb11679ab5763ebe4a9110eb37c4043634b9e44d40cab34b42977475e2faa2ae0c0a38b170776fbb0870a63044aa6679545ac6951579d0581144cdf43f60923b6acaecdb325c864acd2c7b01d6e18b2b3c41c041bb9099cce557b114b84350131e3cee4089648b5691065867e7d38314154355d0e3ef9dc9375eddef922df2a06ad0f0e4357c3ac672932e5a66b16e8bf4b45cd893ea91cb397faadb9d9d7bf86e6ceca3e9176a5baa98b6114a149d3ed8ea176cc4a9380e18d2d9b67045aedeb28b729ba2ece74d759d5ebfb1ebee8ac5f5e79aaf1f98b7f2626e62a81d315a98b3e", + "63b90dd89066ad7b61cc39497899a8f14399eace1810f5fe3b76d2501f5d8f83169c5ba602082164d45aad4df3553e36ef29050739fa067470d8c58f3554124bf06df1f27612564a6c04976059d69648ff9b50389556ad052e729563c6a7", + "7d5c4314a542aff57a454b274a7999dfdc5f878a159c29be27dabdfcf7c06975", + "aeb6159fa88bb1ffd51d036d", + "7597f7f44191e815a409754db7fea688e0105c987fa065e621823ea6dea617aed613092ad566c487cfa1a93f556615d2a575fb30ac34b11e19cd908d74545906f929dc9e59f6f1e1e6eaaabe182748ef87057ef7820ffcf254c40237d3ea9ff004472db783ed54b5a294a46cf90519bf89367b04fc01ce544c5bcdd3197eb1237923ce2c0c99921ca959c53b54176d292e97f6d9696ded6054711721aebda543e3e077c90e6f216cdc275b86d45603521c5aab24f08fd06833b0743c388382f941e19e0283ac7c4ef22383e1b9b08572882769c1382bab9ad127e7f3e09b5330b82d3e0c7d6f0df46edc93265999eef8e7afa0cb1db77df7accf5bff8631a320d146a5c751a637a80f627b0c9a41b44f09212f38c154226de02f4906ef34139bbeacc3f06739c8540e37334392d38ba1cbf4bc7debe77c09b35d2200216db15ed4389f43bfd8ae9bf76fd8243c3d869546e16b8e44a6cd1edbd2c58ef890b5a84cda889131e5cd9402ca4d8271052c6b4fe3f2dff54fb77bcb575c315b9109f90b14bc8e109919808a581c1809e2a188d29fd34ce639088a6683f641925f5b4b3529baa34e080bb47fb7ad9b43d0d67c9e6ae7cacb50527fa74e56d0c8b20149f5d332d686d48ebbe634c2b5d35fc84c69a5bcc93b93dedcf9fdf19a1fb9b75f6df9692d16f6c3490377a06294499e4b8ebeaa0cfd840bfa05fde21c0b5e94d13063b3f5da7b537caefe89069cfa9de9eb8f06e4d30125de64716f821bcc8279c0c7ea2e", + }, + { + "89c1ee38b6697d0190c87a2aa756892ee09fca095df1e31aeedbda5750f604d9b8f2116e5b8f70ec57ea16fe419f2d213ef72b9be90eb5d7e98f2e398632123e2524ac80b31c6c0a07820848223569602d94fc16a3b1ed8c411bc6c74ed80573fcb1f3afce60b9d5e2c21d04f78665241b613abe12274a5343101a91e91f04e5d1f7959f574e743a10913e0817a32c320467f0178e3b6ad14b856234a4661a755eaf14b5fd88ef0e192e1631d14263d6a954ed388f5709dadc6c0f81d229f630d80be6d593d5e3ad03f9ded53c41abe595981d24ef27ffcc930e4d653743960f4e7ce4e251c88f55c16d2afdaed5e3446d00685c276728ba757520acb9b6bb0732a0e9836878d829e5022794d70ad8440a40a132a8c9ec1d3f0ccaf8c285fff425e9788d6150b74753dedb2ae8b36ff2f310249bd911b9181d8310e00810d42ef94cbb5a9d72a1f0507c1a382f892b23994fbe7360778b7efa9c5e03ac3231a57fecff1c5fa10caf1d26e84db0137049622ebcc3a64841a0e49fa390d1d43550c1346c20d578cff39fb7404fcab0982dde55f0849d312581d0c811a19d46f25e7a5e7e50d74d43760583c5cf335dfc11b2ec964f1dbbd0ed83e18f2027817ea2dffcf2b64a352c4fb8f11eeb4f1bfc01079251254d2112d103a1f12a2270cc026cbeb8b6f3e505abd62496253f93274625786b73997e449c1f35c742a593441252fcc845e1cef1b8f287dd311a0477407ce3b31661f7b2802c79c2d20d06e45f03aca4e47a959c6c1d7a9d377e1577fbf82a115921c3d94e3d9c204aa204a9a5b04d8a2be3269700a035371f4aaf1a42d92b9bfbee74492b106975b36d1e581d6ce2484f09e04fa91586c85f35e2a10f0d3c0afcb05327c1bc9d7429bbcc4627af8f76b86fc561844c2ae3810c84901ac09a1670ed3d31a9daa5d296", + "7219bd21a834d917f93a9b45647ec77102578bc2f2a132dfde6489b9095b4f7b740c9c1c4075333ab0ce7f14", + "a7f849b054982cc8a4c8e5e53e181feee79e0233e58882839892134ad582da7c", + "4c46854e9e101090b1436f90", + "ab2e189baf60886bed88eb751bf3560a8bd3cdb6ee621d8c18b5fb3aa418f350048ecf359a7d542daf7090ec8688c3b0fe85914aa49d83be4ae3396f7bdc48051afae6a97fca7b42c0bf612a42d3c79ef6aadceb57f5cfe8d67f89d49add0ea1ffd423da058297239e72a85fa6cd1d82e243a503b1b0e12d7510a9ee98d7921dae2754d7581e52acb8ab9e7f9df3c73410789115cef6ce7c937a5441ad4edf2b7a8c0c6d152d5a5909c4ce839d59594a6163364038c4c71a1507389717f61e2bda1ea66a83ef477762e7834ebcfaa8f2ee61ced1605ba1380108236e1763bf40af5259da07dd3e3d0fb2801868c2e7c839e318678687cbe33384e2ef5750a0a0e2d2e19e869a4277e32a315ed4de79357f6a12a8a25d5b18291316d9bf40dad2d05d1b523ade76650669c700a1c2965f4e51337aa5d45ec7b4981072779401d6d30ed69034053334bccb18425ac68460becf2aeccc75aacd3d6709f07ee10366ed848c8a54904af4ea71fc2117de133f01e1cc031f2a4d0779b997b82682433ee615202d5dfffba6c916f11a00551d56ffde8c36b303263e14adaf45b6eab0bedf344e5214ce52f071d2f40154d788c6870020791a03d2fd4ec5879d9026241954ed45cfddef4937ea3d0d45647f252be31411237983a1be340fc65ebab9a5620abb0e8d475af4e89e842e895eda0cbd283bb5d0bf20236c62d956de733d60ebceb42fc0c9adbf9b69f8d66551b0aca0e260625ad41cad75d752a234af7caf7902c2c5b62f04b6a8e019a6179d44feeb2ad5859ef1c45371e66f1af1fe0de63997266c290e27f0dd62185c53f81e0a50c296a51ace7c90d9cf0dda8b2d7e72a347f64c44262e2a544d1acc7bb05734dc1783bbc1903279092fe7fe434610aa95fc2ce5fc5ee45858f5e8337d8fcb0a468464becb1cef6b7e5ea48ba383ad8a406df9c581f1cac057d8711fcb", + }, + { + "2dcfbb59975f217c445f95634d7c0250afe7d8316a70c47dba99ff94167ab74349729ce1d2bd5d161df27a6a6e7cba1e63924fcd03134abdad4952c3c409060d7ca2ee4e5f4c647c3edee7ad5aa1cbbd341a8a372ed4f4db1e469ee250a4efcc46de1aa52a7e22685d0915b7aae075defbff1529d40a04f250a2d4a046c36c8ca18631cb055334625c4919072a8ee5258efb4e6205525455f428f63aeb62c68de9f758ee4b8c50a7d669ae00f89425868f73e894c53ce9b964dff34f42b9dc2bb03519fbc169a397d25197cae5bc50742f3808f474f2add8d1a0281359043e0a395705fbc0a89293fa2a5ddfe6ae5416e65c0a5b4eb83320585b33b26072bc99c9c1948a6a271d64517a433728974d0ff4586a42109d6268f9961a5908d6f2d198875b02ae7866fff3a9361b41842a35dc9477ec32da542b706f8478457649ddfda5dfab1d45aa10efe12c3065566541ebdc2d1db6814826f0cc9e3642e813408df3ebaa3896bb2777e757dc3dbc1d28994a454fcb8d76bc5914f29cfc05dc89f8c734315def58d4d6b0b0136ccd3c05178155e30fcb9f68df9104dc96e0658fa899c0058818da5ec88a723558ae3a6f2f8f523e5af1a73a82ab16198c7ba8341568399d8013fc499e6e7ef61cb8654b48b88aa2a931dc2cdcf245686eed9c8355d620d5e91c1e878a9c7da655e3f29d9b7c3f44ad1c70890eb5f27ca28efff76420cd4e3cebd5c788536ddd365f7ad1dbb91588d58612e43b0460de9260d5f780a245bc8e1a83166df1f3a3506d742c268ab4fc10c6e04bca40295da0ff5420a199dd2fb36045215138c4a2a539ceccc382c8d349a81e13e848708947c4a9e85d861811e75d323896f6da3b2fa807f22bcfc57477e487602cf8e973bc925b1a19732b00d15d38675313a283bbaa75e6793b5af11fe2514bda3abe96cc19b0e58ddbe55e381ec58c31670fec1184d38bbf2d7cde0fcd29e907e780d30130b98e0c9eec44bcb1d0ed18dfda2a64adb523da3102eafe2bd3051353d8148491a290308ed4ec3fa5da5784b481e861360c3b670e256539f96a4c4c4360d0d40260049035f1cfdacb275e7fa847e0df531b466141ac9a3a16e7865947572e4ab732daec23aac6eed1256d796c4d58bf699f20aa4bbae461a16abbe9c1e9", + "33791b0d653fb72c2d88519b02bde85a7c51f99cfb4456dfa6f84a61e10b4a14846521", + "a0a7b73ca2fc9282a28acc036bd74d7f5cb2a146577a5c29dbc3963fe7ebfd87", + "eaa4d916d261676d632455be", + "c9a631de470fd04dcbf8ea9f4d8ac37c3988878b6381707ac2c91d3720edbb31576ba90731f433a5e13582aca2b3c76ae75ca8881a463ecfa789910d3a776a9ad4800521c6baa120b2f1afd10f32ef8da63f5b69f5e5fd88ee84bf66b0666b15d05c4050f5358a050b9d5cf1503719f56cd48ceba78f29efe2ae8092e37f5134df526831532f86ccb9339637e2c9e9b9036f83cc058fda23e826a188456e7fd3f4ee20f4e4a3221883fe3232b49db607b90a8956133ab95051c9ec33a908ea7e81a1bfa7bd06c09f0143d07bb23a3feeac7f0d7720269c93e2df19d03605828c8713b84d183c9a50954c12fe3b047511ad15ef03a63355520cbd224d06a34de67a671368e6a8f9feeefe48fc273764a8c69c00314e5d693f159cb5270544f3c4e1760b0529e3303ab308e9a6d03835a3a42aef2df5f7643696f707a574d1dcc676aeecdd9947ebe8c13bcf15d30b2d10d2cd95445a307c1d22d39450615ad38f9302c6eb9dc05764b0503d6a7eaff9feb94834853b47bc25660207be3e7c0e27cb3127b5402cb016396e5ff07ddc3df29861dd68a17f53bf660b23352b739d6da72381b8d19a9fc95da7efb79330a2b360dce4309860af429e3fd10cab235c4acc1d80d9e20d67019375bd161ab65648400f308815afe63cfc717f7d0eea150e687caac25b6603287d44dca4a7cc2f67c3bdd54450bd3170340253b03ba054ec003070eddf9c14fb9dc595e228e4968524900cb5d85af6d1e658a42d744e0e7eb6995023823a8dc33528c6715b2e1aa607782c8e1ddddad72026d657bf122ece8685f6e92236e809139325e4a3c069facf94c10b7896995bba01eb22c7b3a87ea2114a7649d7ed3e83d223e5e785c66a75119beab0968d3eaf0cbcc2d7ede95d024041e6db39a880ce3e19efea32fb89a40a2aae22f407e5fd615e51e48dbd50a8b4ec27ce95e2ba1928bf699d0418705482ed0ed7acc858dfbd690403c74667a88dd5221bb79940c6c4a268379c10343aaefb635982c14f33ad83d47ced9682961540bd4f75804d3d48ba8aa67fb2e3a1db83fbcbe57fec9e4ffb1b575e947f8bd8263c680357960e3a39382974774b5a013f2f8514b3c63c21dbfd314fd5d927d82ba616d76629ac018879f54ff84b5808e94af4fcfe1cf8845b65208ca5510b5b593ce6c109611652cd", + }, + { + "c335b055b752e083554b5aa2cbb6556cfcace658d5c11b6b000256fd89e9b24c1e62a2d5b582580acdb2ad9869020465aeeabe83acd9eeacdc44aa652d5cb24bbe542073d6787ea32b2b3c942d40f9db2bb75ed7914c836d902dd2be89840948d82abbaea23952cd648e6191ce5b6cf912cad0a3165410a781e3650b676e5340980eee3b484008acce6a3e9dc5aa96d775677b8bbb8b323c6e9747d6069a169ea904d9f145e29d134cdbb0118647e8fbae638669efb9a55d50ed33568749f5304ece2193b0bfa6fc9a570d209ef61b4c59a2b5485b5aa6ab47d902cf23f7ff71c5210476e0aa727a01809b9f76b6ebcf58a018b3fbbe5f42976111ba58112b1d322f9312da068cdb86277bfcde66cb3607e3ea02a1494439aa56f302671f1f994eb3ab28b937043f5f7f3b3de50673ecea5dee8ba633c45089b852f0d772892525344ede6b521dcad15807b65e7ba348d891d47fc498cf4d50223d2794c64db9fa9b9766edb430be0c38746ab317b38ba9870a6d1fdabb70fcf89790bfe449b97fe01f6c94502aa0889f0a3bb6bdc65f44d1cd64ab88d4a7806b373f5080f9cf60183cf4686694f0059e2bbc5cf21ba0c3e8046e70d815f1444c3094cc29632c429f20aa06b49b0b52c6c7aeb8e34f7bcb53e93c2cfe2d704a5d0416876742c90762730d160e1869d5e0178dc366098ebaf2cae6f1f7563b555a52dcc194a5c8f718d50d27ee76fcce8e8991f4921fae85ea9476e1eab1364403120698b7ce8fd0a49cf79213f360a17cf1950f104494fad80adcc3bb1207bf250d57dcdce6ac8082a312959672361363cc227310b66ee8c04aab7b5cb33a81c0915e9c770a1cfaae2e8f44a0c65703927977a22fe58aef2f366b8be9a50da9376b46ae7562a82391386831febf359039ac326891bc58c0f2c34bdb6858859fc3cb4e392df65cbe2ec4f02c8425bcbdd1ee2562ab7d229d406d79a9c6fe4889c996c2f68d1fb5bbe3a5e867caa4249b934afd3ec71fdb088c54b15252f9dc1b909e121dbdc7d8a16cc00836652dd1f877ce363eed11467966f7ccb8f1a8d48146e69e04ad76a51937ad4f9cda209451eeca90dbdbd65441ce20fabfc8ce400fb4de136154b87a8b65c92740e9bb91d78521b261f806a2c6279c85ef6ac5fe1ea3117ff7c9f9832fc2aa6fab660082eb22344c1a3befe0628b6551f62a5014cd6194c42b8d475a50f2c9fb58c97e43ebb29005ed7fe54f0a4aa10074f1154152a9067d364dd7863fa082976a00db55b26b5ba0ea40eff48b90", + "f5ff810a41d4b34751e9942970d4c9f26b33f24689a4b1e4449b243490afc485af468ff01a42376b2bcb949b9f5e8d0b917f511a", + "a74271c184a82cb074c14b131fd91eb05870cb7c73c9e511ec8140bfe2f34089", + "2403fe689e239c2ed261b381", + "af9be893d5fd23aab42e6a2e59a8e7cb13d4f543db02af87cb0802bc1af7c717cd0093cc8244994cf21189146922b69927ffd5745e57118bea07a6afe7c21d952c13ab636b3c2e461dc9ffb3ae701175360156338be94b1fa7115799831019455cfaf5114010fe45f8fb9c77ec50fe06f2c5a32423edccb3b2210ee1200a78e1a3130c567542377827586ca8cf0c14c19fa1449a2cce9c039bb441b04e9c0a3f9a743b31c828032174fcdb7c894349aa68f5adf97dfe9294d24e6b5fed95eb994397883f58487bf5c57b0aea5268be7cee9efeab370f89805ebe5373ab2e93658fc078955ccf68b554dd5605005751ee8531c35ca5336a5d0ce273370c0dc9307779b86e96d2d1daf2620d67d43e1fb7800ccf250ca3c02eb74047c1d2a2bc7f29fff8320301694b80d0fd975f834337d00d5f0e4215044d52aa4ca21e6a9d7e03f186d7cdd5c48e3765dc926fb0a46bb0f05c50d9f69c9c507527a60366b7dc251aae1d6bb0d9c73735dcfab959f6fd4382fe2a1f6ad07affb0601bb9040f81b55a48f6a6c5f8ac4a2acc2b0c9a6c439198f7926460695fa11e0b0b017e39de5cf0d5d5f84d972b5eee7b5d1e0343b5485cd84b92ad892e5b23f3e803f5b363f2398c11c15be9f13e59922b0d49902dc8483fb142850b4226da2fb84e9b434a34f6bb67f575a9e57fde3354bc3077a876e260311bb2481bb139aa9af55df5074749fe532d7b8a554218a90cc7e7ac69db280bae5d55a174dfc8d325b9909a8da1016d4e162fe5ba70cf8726cdf291f5e47083d9929cd5e32021cbfd982fd0975f6f9baf4322b553cb3174b11c007559879f308419ff9e4e18eee8d3640cec8aea082b90f69cf3c7676c28af0265c24c91cd58a06513198892ce6ce1ab3ee9ac0a2e937b973a9cac06a039a54f8d994c13d42c59187f677352e5feb32a417aebec4d852b2595e7e67450e06dbd183279e3b63022a3813b37257b085bf8454d6890875a2950d20210a8df4f9da746722f62687e92f0e9efc3e5d526d65ccfbcc042fcac7964dbe147932c73924bdcdf62f9eae58d29e8567ffed90048bcf0566b952e986efeae4c477944af18bd243c3eccf8d88c06d07279adad037450cb8547a8aa0a74223f4851747c803cb21a2dd027e7080aed75038cdcecbc4639d87763cdd41829a1b72cedf0d722b180d0d492a5740ea7607b95f3201df352fb1ab28149124d2df5d5ec106867897b537302c3431402348f94d28eebc701ae1b49d10adedea38f1654fbc48885e59e6e6dfd413c6b5a97d8c35dfb07a6cdefe317bf61cf91", + }, + { + "4aba5a776ace38b6e2578f0007e770d264e39c49f588ca3547ad2888365e3a811994f8836330394587c8458eb0b6611499fd5d8e8527c3cdd4ec550b4a8f8c632384e786b420cb3be911c999c72aad60270aefad31b27a069ecf11e95e9d4c81213308d554d3103de4d9d6ab04830c2b8dfbd8bead52c44c21d5357f72810193b5096809dc7846c1521c6c569f78812c735aea21acaf6dce84a24df7234e8ad857f3e1346b27f5bd436113e2da950e4deff96e9ba8db692c7db723a105ae795da15b910c8286cac6e7dda8c172b70f61b07dfd58596684d61da8772356f180f74c1103ce97cd947eab3d401df44f7fa4cc7cfc25e280fc002873237e64a375b0b4797f4b4613c9f150090f44588ee8250ae44aec6546ec8dba0f0c1eb281cf66fa4eb141617b32b28441f6ddcfdf02d9c34cc62893b2b64dc2c26b74433adb3e888c7fea07b19c8cf39269c2716b9c35b7625d4a141397d6d5034b193d2657c6b2d6b0ba874c467adeaf3d501ad985d13be21c4ff6b326cbb671e4f4973bba49116a0399b6491394f850e4122969e4644c00b442b3da0d6a4bf25ee22d182b3f822fd83878ebcc713cb183651a67ca66677ea81b58b685a3a8e385d5fbb0147ddfecb558d881c914324c794db443b31bc15c361912bbbcba9e418f99f2a416d190cb29684df27c7f3ff6ccf339800efbdc4514ee00d1a89f12373804db4fd66c1affd467f251e73147b3248033327b0f7790fd7861a51773dd4f78b89e4e24b94df9203f4a077091bb9411eec78dfe3e1dfbb67ea1cdf17e1d6936bbb75b74055495449e9cb52f5749404610cd444fea3f0568e0d35a5ef0c395ab7bf0208044b5c4e2517911a9c351efd31f33220972287253fbccb1eb8f46960a36b68a7a6b4f5cbdc86d668bbf555fde8881e7faa9594da425ff8fb54526bf7cdc4af64899530561c06bed7fc04c5d48cd4542779e901bc48fab79d4d13850ad8247f51b9afa7d5a656ada25b6376d837cb0fa1b4016dfcfc158a39290f43f133b352ed52fab2f951509bacb41284fbdd849d8185fb7e7200f8ab2a07ef2b3b927e18e568dbeeba2c7a66e08cebdc6a6069ebe6656a586652f3905ae2bb867529af6a827b494c97b3a378408f44aaefbe86c613e11e7a44020a9ee4b62569dfc4c462300daec7b1424ff1c1849ca1332367470475c14877cbe76c820cc651c18ab3f18852b93994f93b568dc7f7b0eb5f07ffc4c9384c851fa9071c6f68ddea1ccf627f889c0471c76aff9f52b07ab1b86a7671a2b2f6b25c0ddebb66ac95737bf7e2f493f7665b5265eaa5166556cecfdd3062802724ec24f3978b903d0f0c24e1f0b8d967142bccfed0d354279223f4c28684e9ab611e9ef89a3f25993b5a8b3c0354931780501651236a78b58e7d7814f251b053605f4c0a8e7193b9cc1ee5cf7378e6f3c8fd44ec57bd91e62b09fb1d6bab60cbfabcc6792e6a32ea7918a9ec9180d05a7e1546d5d2d8bbfde2a71b4e427c0a4d28d0b6473ae", + "921a401db90935c60edda8624a0590d5c46eff3522e35de2872f6f9394e24126fd8143b68a797c995624fba0298b75eef974", + "6a4d35ae03bf277f587da4541dcddf92bbd906dff45d5ff23c0f60ae53b062be", + "231b5780fedfb06d724450b3", + "ba40968282d98849b19d867f8b564ea5a81d657516099362926bca4cb6e9ae02719d10c8061f53008c727a0eeea5e1e36c9e55c117e9434e213316c96840231a1e356b254a9981d4a6ca3c66cfc61018bcaade1a4486506559e6aa3a86bac980d391d835fd5ded98d10f1394d84bf1bbf2cd3397890d704154802f7864ecc753db782fd3d19213ae65ace4770e1bacf32d61c6730aa5adcab4d7e2e437888c11c29abba4890a17a00f67a53b660becd94092df0598df5ac57326f6860593a519e28bd4a39f6481e1a4748881fd5f0456a3cd9f28d1d1e78dc64030cbd8fdb2c5abdab3f13d6ccccd187e71e989f8c486929efcdbf2a763effa95af62db5cef95e9081b818275c69267022fda4b7fdb8c650b491a785b03d4d0186625962b6326ec3f4e176373da4dc1f83a14815adf82c6bffa7c6967d77528d0249754bb4d17656bc4a89449b16152a4a1aea7eb0054a8892f271138971507d2f3b237ba5b620f444544e4a8c2b1ab4f9168762c27478c9f776c47ee2e9ff05bfa35ed127f0cabe7cc053640bb8aa01f8359b74bf89ef43ca94c48fcd201eae39d1835957eeccd6b3a852f4e1bbfef9a469f42c764481ff8408fe5871afeeae7676b58f4202199aad50a596626dff97c8e60d750cc59da9f595ce12ce9afdce14481cb1e39994de8fe4cce07845110d6703dc59d34734e93e9e57e1c52d61f44143a2d290220a4bad5098d098ee65ea4b6757d8a9bf5485aa3d697a7826d4a285186f5da10eff707566c23c6a15033365bcb498c44487c72d96402d1834753fdbf86770239761f03e0dc8963766441da99c0813e4f1df5a1d018c8799861a396562eb24ce305ca15f4022d83ea3c56b68d9a7ceac4742ec0ce50f4d36273df26005ec2b051fa071b319be2d8a5ed26eb75bc1ea83761b8454db234d15d84d6706cd178981c1f156e6d28f774aee3e9a4fade022e71b52b50aa532b8bc7fe464f22d6eb169c69671875d614e987658820c2f584a4fea3008afdcbb646dba3d69020fbf503f121be3480344db23efdda0d255aa058c3ff66abd3a5fe35db977521608bba7eddae72ae801f4fbb12a1de4133039e046ceb8db87e465e5ede1d79a08c857d59076d7ff858942c31e15cbbdae6fc15c3f9545a0825d6ff8583c0aba8a7d143d27b93f6caefb98c0d83bd8715abcab2a49087f55a9daf9090eacdf45be08ad80b5df5070e1719f68c4cc8f8711083f0f7823a09ec092f22df95fe9e95114fdf82a3f6eed0bfc9c0aa65222609442776154a474dbc9e662cd5dce66846572e52417ee5d7eb59287d07ef60a9537fe1f85c7fa74fe84dea0da235ac7574335e6649b54a6bd33397df4bf4a7976c4ab868aa702766d2bc8d2c82c2d1c2653fc8428b8d1e61852ac185a3a0b416dbcf8eb54c44967ff43c44f2b32c6d4a9dbf2c2f3a587b430aef50f0375cdb4c1b319ac9aca486d9bb321141b065f52f7b6decaf1985531ca7bbc3772a561eb1efb8a6297075920bc432131a5b211bf25e35fa31e12833bc77a9de14c7", + }, + { + "6c0056937faf1023032df1e2bfacbbc58bb022eba25ffa020d4eb26f0caf0678af5d0b2f0c1b520f4843f107f0adcc7b5dee66ff4d61025bafb4cabb64d133132e3e423a599549a1d83aa8c8e774444462aa44b00b460bbafad5755ea6a872d4e6b40e3f4957e0229288ea79fc2ebe5fd9020fe4481a9f42ef14a196bd136aa3c779e311d0c333624c1ddc484c9aa7259cb609e4d0a826c0bdc7567adac01da23900b30ac4e66c100348584fe200747eb67e6287268947e3509d5d2b5d7bcd977b80a13f660d4f6956a8b938a82db75eab19e5d2a22cb5f3c9131e278eebbe096b5f49d16c983ac240f3fbe821b247cccb2c9e6e59546122677f49f56a07fed56647a6d3e0e09520d49009f54250c10e7c607cd5b4ddf81b5c4110c6490e9baf56418236211856f5a85feaebafacf92c0c7501c052f9dbae3beb7484f90f334f50b68571cedc67763b5161ebfd5a1709cf18c92112a4cf4d8f43d1895204d8a2ba5e14883a7bff75cc6060cabb77d38a909daca2417befd1bfc05a11c432b47f90c807ca4306400f67a0d92218adaca84a584a8bd4395c93f9b6a4bde9583c79204444634a8473b1244cd33cf980e443d82ecfac672b3f60e2e41ecb3c5a445d9e88c0e90c339a31806e6d79ee52bdc6808c73e8b7b24899966664d3c1a9305f31f0483e24e36fa451dc1d3f2eda05af6678971e2bdfb7c1461c9407c5c466f6b5af34d992a37de3809a22ae75275ddba0f4f9cbd4b18c1acd212192e587889a36bd73c860f0abe08bcd8f00f5ecdb95e1d560b586eccf530df0e5f3776d8dae2a01768bf1226b7ceffa7ce4e75879c82dd97db3c64c06d33cebc6b35854618355d80e46fa79c3e9743fce5b974723c421a077e7ec7dba286881dbc1d53d442a1552700fcb33f83f73c69a0a0ebdcf2f5d461649c4d0712c514ded268a31509f83c1ae4ff4a68e676d29727be641aa4487c08d4b90ff78e24c6508d69759751a1a23690ec9f8763621e8b107295b4bb01bd9fcacd8748e24d996fa70ef6f8b0992f4185bec8e920d7643159f9f604fba394b6611bff435998b2f097a9e948430899c8c752a1e83a061983f00f88ebb32da214399167932a1a83c1b47d09f77593b03cf6521520583ea4483e2d33e14ad60584676d1791779b532c085d238df0d3bae735d0078e0eabd63cc90a2e13d023983780afc8f83b1c14437937c16a1b7c41414c48cf4ae49587ad9fa5b16fc949a749e96032248c4667f58e295f999590dae1d99a2cbe3fa45bcf4a1d3f0356d64d40367f64b2c5cca843e5f7dd7b88a85d52328a00622e6c317879607bc036c9006d38652ffe21c83207c00f8348a7d0aaea5aab4c89077df170de6d41052641726eb6925cd85a9ee01a9e636346340e209ea96d17b0eb0921b96662ce9cb430fb6ac348331dd7133875769bbbba99dc49333950e4145a15ddb0789c4d2ccd38878080ca9e57ddc6cd5452790eec45482f8e990392e319609391fce0beba19463a9a00d8f1de9fbf22f23821de7d69fdfbf3019ed61aff79acfc5a6ba663a1e10da2b9ff7149aea43bd6c61a543008402309df0924de72c1cacd2d6120cf422e61fc1de345cc8771934d8be77d9437a09e06a9b2d51c849fd9a200fa714328d34f36b684f33df6968b827df916a599a4bc3367814fec21198e2213ff653cd2a463892966c72ffd42a26b3bb91", + "0d55dcd08b54e58916f622f81761ef6a2e19b167ac47d3", + "e42e1d6d44138f3d2bf12c951f454686f18d590fd30057405b5a3dc2b317fa97", + "1e46a7486c5a03fd6758d938", + "fd3c1fac10cc82e49235fd57f5aea0ee7a7bd6d539b138d4b3fb623aee591615c1a61228ef9673113a3a90a3687a12d4c6367d5f7bc67d422fdc4106455084d79c2c42c5e86368dd164bcbce7925bfffe7d96c13a2f49aac8e9d1ada3554e3fdc21aab00455a0f33b0c1fdea91b3588e7ad301bfccf9940027332fbdf966463491f7a33c093e0a13831ea9d2183294f89f414cf7b5876af04fa68d594430194429df74fa5915394427259e832bc545c13400aef6cf16620d48280798a6e49773c9316d79fa1dc758e54cde2e2cdb856092d83f4e9b698385cb976fd6cc2538abe055273a5b34a784182ea5e7d3ac9019a05de5e5afe4308a7ed2d363cd50ed6a52df1c616e4a82f607ced768445d13ae4884f2ae1f9fd8313924e8a1a8a23905c92eb231f638dfa6f4cb27bbb9844e05afbbe2ca4d1a3b3a5b371bf33c9ab6f82a7387d61cf8bf662097624145a983839b0cb9f4bd07556800b4054fb3d0bac94f44bcc9b4ac49c39f5571fac4e02ff09f08b3ed5add4bf8bba934e9feb773c0590b45c45fa036382f3fe9782ad19107d4630321e414b7b442b64f18fdd5219039e5740f34b3ce8925d1afe8a39e35ce8db086060bab63b9720700499f82db19a62897c6d845389461260303f9cf2bc7235a898b4620c2191ef05604a5c8c783d58009533a86b27c12b0772635d34ac53993ccf174c9087073e5e69b26c0c3d9f768507ac4d4e2af847b65e3a6e1b7a6dafb0aefc190871cdae6c60f0b1d6137c351d4cb211870791cf4cb8af2ea446f6401eb9ec8a5bcebccce898d1dfb13454df6b35b81ed6d7637e6e261e004080c60944f3a08e8e5fc7e2e4939e7c2607c8cf07d1d10883ba3ad43e2611826f245df571857ae0a7a867df9659f2082c19f94ce400132e48c7f8de2b102c7f83ba5cd1e785597a0ba0d73bb81bba0c00300d4bcd6ec25fb73105a46122873bfa729c0979d8d314ab7ea52391aabab513dbfd1cf01c2990c0a3612f4511c2bcf0f5a07e659a881a7f99c3f1fc4a46e66904427fe26a4a80a904c047d090c861a075c0ae4e29bfbc18b9620aaa42237f4c6fa76ee7491ee638ab5f1cf0b440759828e1ec519679efc776eb1468999a00f667e87199ad6891e98b95fb682e02517b024a6bb803ed23c944010cb7bad0733eccc12d6ab6030c6e88d510ce92e2f98fdcfaa1e37e41fbfb4e99589c0e8efbefd40473db42b3a73b57b22a2f8c9bdaab16831f1b117dd83a77dd01ee8d0c2e92203adb670f4fd65e618823ad196220d70e014c1aafd8863797c61c16382c2600062683ed3a180c70891717c52da15191b02f25d1715ebf33a5e6037092421989c942082f4b836423cc3e976c9bcda185de36f06265dfc250a27d2de0bc48c73b3bff704f3b386f962522f572108458bdb283c6ab3fd33b3ac13a406268fd5d97e17db9c0f780b4b2a8f761d15a4d8b3a0cd73357ecf4d26a6492ee069f19325823ef50bcb2f73326719a57b67eeef506fe8915a1b1ba1a637592268257b91e9c7c5d33cdd947967efc1952005d82ccef9a3ad7ef8ffbb6b658983d64c51242ba53f8f8963245b87a25aa9324c527e53f8c11d55f30aab598401589acd13f090541b3b057b162190f27910718b02a6b8ddbb8ca6cf40bf0d2848f4b76341bd5e78f476862bcdbe2d1bac84c0566fb45b21388221ecd8483d99fe603646b1a9f38a49230cf4dbe5d7883d73eece01bf", + }, + { + "04892b94c65685f2eba438322b29bf8439938590d3e0eb10a29e279d356cb439f6dfcdbc3552af21f7e753221012a649a52bda780bc589ae63b04b981dffd113df9fcf14f17e35e865880a769bb1bf40dc99b9e85e4296c1f2e1590fe02b22bfcaf2d4bb7009a4d692ae4c2d5f0b6d3ca526240368bac55b9b1e6a7b498d3b137f0fcfef1873c5aa2111d7811d45bdc26be1c5d49b8a2f36a999b1f226ec06a5fbd59514485abe696c96ea89dba74b4688101a239b495944e30b3609f73caff3114407599ec5c30a5bad933655de7dddef97018ae15acec46504cd5d417c5052c057ac5f1c6f69781cfdae71db2b4fcac35054a4aa22681027356d68b2bdba721466d130d53ba8f23857631382b2de450232e9ad5551bd7c872ae439e79eabfb057d2bdab8d4ccf02b3003ade2e1f3e514dc92692e4fe5b579c9ee6067995b6c168647ce5a13be8543c23326a3260bb7029d2030ec05e565ced3c5366d20a283a6e95201fd108640d2b96676df712de20e4e12fa53f85f22cb24583844fabcebe40eece11e7221f12c88670bf994ed08e2000236f86258c386b0fccbaab8b68ec6a26fe41491d540193c4c12d1391ab3391de9317f41f505f1f1d09ca9862a6f289a533d2b297d4465c956360371ea3c8ed36e0d1563120654e3a2fd69cd6c9267bfcf92e84cd64e162c84199d6e552b42c33857264b5d7a2e007797cde32934a3f8c68b459cd95bc85e7466ccc9910e8dca65b315c32e43c3a5da908904c42cfc8ab74126919ceeef1054bbdae6ca67b02f1ac5f24808b5eee24577e609a3e3935a24b9ebc1a8dad1fc96abe26012928f2d5782755f3763427dda28867d0b1ad830d3c3f17b9ec278346e5a9480ed23ad44a523a4dd86e65a610ee0de1afab64ace7a3b4918fdc14c6b1ce0ec0903994da9bcf18643d7e0a4e6c08200bb394a89b385d2cb829417eeb0f7dab9fa7306a330f82973cf0917b5ca99b585d2ff0e8584e050077467f5245ecfdd5942e4fc72dc26e5ab2ffc61f996167e68168cee9a6d3ea1e1a696060465e35da8c75a1aa380004faffcb0a992c627fbdcb4e97721271802cdaf08d214ec2fbcb389d75709d7a6b9d35662661c8961f93d4a705e7188613f3769114c55400809cadf60d3b6068c8a5ceef078785171b59be1140c6a754ba1de5ced349df63d67d59d3a8ca3c716ffb506772d57e9e3f2caf7fe346c4ad64aa6c37e43b9bbaa8f58e51bfbac31fa6137728f8e5b728025697e5ad5c8301f6ff39eb2ad595d3cb24257adee88a84fbf1ade4d7550cd9ab94bf48e1424ae83184c35c5a5920157d45805c2e0ad129fc7f0ec3c41b9d6fa04cb8918ef379b0783d1cc2863cd80382585fa05320ca4f9fd90353e490b384ed6c166c6f802cd7bd39aa43667246e8da96992db7537d472c709b01114e95febaac5b1a3c77e1e9a18c2d180e63f0d8fa89f6a1ed63e909e4741af5c2a0e47d4d3f8779b7696358f58060f3f461cceeebb390c92779d30bfdedf1b08ed62dcc05a545bd0ea915f42976e81dd8a50cc4689d8d8007508bf53e7da5bd43c3894968cf0677681c6b818353af6bf8ac205139add1310e5d363ccadbfa0eaf735808325e7f9a6aeb1bee3ebb4a27576a88811859c216b6f84371c43d8063a0d87bd326eb6d81c6896ff534ba2c9c14a51d2cfedf33a5c787279bb4a7ff65706b389756a6191d2f791254233ee047d40d64c2dca878a42f903fd4382f39a89a723fe11848fe37b2008be53f7c2d037981d6462a4eea49df1a2e074957afd3c9dfb4d218a309cab395afe301ccf", + "67b5eccb1790babc2dab5e0d1ff3871c3024177d45a2ae", + "259603e1c3af3fd0ce3257eb627b02e0c0a48ea2f175de3d8c36570a445e5369", + "e14de73c4b17581a7e0d0649", + "33522e67ef932da5fa8abe628b51f3abd5049951dbc982ea95b7769652d4830c588fa45e3fcff094c8602b9008d7b2f9bf6c1c4a8cfb515401c7c44a7ec42ccb967722a710199e121a41160b1ec581507e9bd2e2e506b10c4b5a8d6977435aa08e27504957cd49e756e1574c4ccbbdde937de35128b7ee3455d2e665c596c2e97c253c94e405f85eb5de84874c099b4a97eb8f492d28f2e4bc64b228dd5984e76ca08376d7f1355ba8e0fa60fca96635075417d8b436278e0fb91e3bfc7d61ca8c7407086933c061b2d318f46f352099e1d317d6c44098539d1d2c1b7894db668e7a82ff991864fae236570cc420a4229883f1e2242d05aa07e175bc6abe11cc643cf1786a4456a2de8c066fb1a70fe387f149ffbe8cca7b110e256fd0c09b1d3bd7381cfa82fa700c8db1e79809ccf75ea52d0b349264557046e8703a191ddaace00ccfc513db5e78810eaac0a99d7bb1a5725e722d4e595216a0e12f3a7aab2e623ea9e1dad06169914bcd51b643016fea7dc3f2743b1e65877f1fd5581bee5ef206d86494a587ec8462a170746fcedb2c9f99090674ee687382711b4610ddac599732453dc063518aa36f5b4129098fb9fddc02eb8f8cfc2fdf0d904ef4d6d06014f977b29d0e9aab4044ce9c662a18b1a8db1ceea97854e90704430fe9b1046b221b27ac79054fcc68c3abd6fab7da66e255ff0cbd0506c852e961e619615c944cd9a05c25abb63742f5da7bd9939feb0f2f2208c8ce82f551a9d4d70e935dad018e3e4e6998e39670221601c3e34716ba75eb4e2fdf53c4d471c444330514986de45cf44d77f793c17e36a271fc65e6bf08943aef4c66547dc310c7a430e3fe7a54898de48f69f282f52bbdc4daabdb325cec7ab66fce1aea4e2fd932dc1a316c821f5220ea437447feae2fa478adade7cd515a27d8c132d0299b3ca1bc8516c9d9e7c65c38c238c69f03e104eb42a29cacc8d79b808ea6fb233a5056201e3697f81a2d49ccd8b8efd1ab0fd407c16a210767d1d3ca798ee53a4bbf1ce5090d321b1a64fc2c5f013c23829f5b0d2737936ca71595a1d02711c8a7b0e74654e5d76376ae26977dd49c68e3c0a7b36e047d44be42d732c31f681bd7b1b4b339f004ecd847960377acd005debfab13d0fb88355025877630aff753a7cfddf6851e8bcc8ec37b8f9149830f47e6b601098b2ba19a4c0808e31e8927b2525cb82bfddc9b4bcba2b46bbe768ee278fb89010243d16f9679f5ba4f13cfe76b5beb16c7b28daf99b0873098115c2233ee3402ac0f6c899a2cfcc83b2ccc06676999ad48017c4ace507080a26501993327ebdcbd1e2eaaaa99f4998b716cd9e36eb26b4573a03fd1d18047198fdf675ef4f979864ac85d230a011c69d8b6c45e9efbdc2a03f195c9731b4cefa60208ba845c0978e73d082bf6d6a513b93dc805a4f5973f4158f60a200167ca88704a15ac5ab1f38ed455a426f7c6a96b6bfea2ebc1ae1247cfe5ff29ee81bdbcb53b03b89568bae9a6f311d2b20e31c2d91bd18fd93a37be266d0de8015d52e325f78356dea0b77cc76f28e0f06e4ec705d1328340013a77b0b6196f44b7712fff4ae0ac7f6afab9456a95012b7c6d387285487476d189977e28f6c9d1a3f736320d61302c2d627d5a7ac8cde4988056b55eeba27efe7e640f94c115762ad5849423ae138c76f15b47bd2a2bde2c492489b7980aaf1c4e32a155f858d7be4fcd0f8a18e7b5d97c5a08d7885d6d56222ef49542c7f80498a14a8eed1c092543aac3439966d5b5d0cb9e602f4fd795c09d652b64f9ab67e38f48c88d18e30a9774f37e9c77b7a94cc7310d", + }, + { + "4ab8068988d4bbe0bf1e5bc2fe1c668cbe58019c958dd2ec97164aea7f3f41c9f747527f1c0e5fdb2cbb9d2ad704b6955cb731f14403dddb1a28c5996707635e4eb5dd6ac33d46eff8e319cfe7cf6443869534ca9812a5b23a6b4ca172afffc064dc2b28197117115431e03c00447f87d9b45172c6f724006270a1d41fa094847cbfac9630c3a785f488c1f5cc407ca6f4cd18bac43cba26ad5bfaccfb8f50784efc0e7fc0b504b43dc5a90a0525b0faf3c8b4b7046fdeb1cad87ec667ce3eb6cb4c358b01393f3ffee949030ef9fd01c1b2b9c5219777eb6ff5b1d7c3ef8d8e3bc2193dfb597cf942c5fc50befa527fac0b44cda2bbb811b06ae87459750295371cd232754e2bb7132807d1225950ce64949b0650531800bd0074177677acad937ee008cc0bbfdf33c6b0552000238494be8be412a3e5cfa359e619d092c76310a76bdcb22abbe6f16b3b116b5f95001d20e42fc3c9ff6723e580f378475788eec265a1ed2087de8cc2eff72184f73fa5dc6e68a56dcfc85350bccb97135386d5b827c2d9aea065708f5c921454d1b9303f21d5adf19e00415acbd86d1e5e42d78505b033a515a435713649c50702f54623cbf31469f355c3be2e30dd8c72b4127764451d79e952ea1f9bb0269da56dc07060d5d9542a9c1258ccefe53fa3f7b6073cd38026256b45c01b6c5dc0d91e3139f30a8d1da7a076738f5bb23352693a8e3cbbb46226fa22416680013f9e3278913d06aee4a62457357f0a68d173a360af5e1411840e34c574b4c6b352f92ce33632911ad8b6710d357b7607ee19679e777baffb8ae3c0fe9786b2e97fdeccb5105ecfe81441f549bc6b50ab84b749fb33f8f6bddcb6bb733d6d5dbc4b29725b8741439b8239e53fa435ea29ed3324202b1bdd07d1987b0e06d8cb51013dad897ef02401290940ce3f2af72c5d1b4c8836299008c10b16c7e3e119e41ec66d9db6929ee09bdeaeda08a50665c052edf77b7dff3d8815046bf71d5015e3bdb29a4f507aeb2e28c536cdcc9b8d1e89849a0683d78f99dbfa90f94aa5dc08587657a8f042d718080de5d4a973f232f78c387b63c7143fc2a4380c491414a18b6c4a7bae2194b62e798ad7ec7d09e409425f6d0973accb17e4d860f8ec0283584cff076d93bd9b0c4873f9c57cddcebe3c3bc8afe793c6cb6b26c4582847b07446b7e1d9757de6bdf0df826cbc502bf88cf3a773866d3ff293034abc4afa3091b2126a278f50e47f2f66ebebb616e342098ab690f7f5828bf8cc4742c677d378893e9f188e8397bee983a9a0998de2a31798330f8db59a8581e1c847589bc0e2d95ffa68e39226cc15cf6cae5c4f5174e7848375391dfabafec202565ec2383721339f04c5c5d1da953d88f18cda65745ee8e99805e35203a6545a0416923b38c5db3c8aa00d64354bed27d7c78c4b257534bd7a18107ebe64d8c27b6afdb330d8efba79fd1fae480cd51fd3626bf8d79fb651b7c6cf752aa737a5123558420d48fc86451b358d270aacfa6c17f343b7a9956e6f64e4990c1b3f1e5097605edf5ce4247819b19f245e9a90758dd42c36699ba5cd7f3ed99a7df7eb155749f4b42d192c47cacb6b2865fb9ef2cfca283865cd06e40cdf7f89d76a9e2eb393e2e0ac0e2776da929f3f8e3d325d075a966d289c51347bd0bd523a5c81edef63ce9b72f5114c88b08b16edbd73f518096240a5b37421843173be8df4ac7c587a17ca6f2916f7d9a10dc75f81bc778a1eb730d12b51555cc414eab9c066113a7edba9a7f1a18092ae47f12f0368ba211feaf34a3b48a7ff5c91b81cf7c95675a4001c95a19d284fe4197fe8823909a123fcec5e45935da12416be1bdf14918414ad19b54a41052f5b8417ddbd207ee01d6a3e62fd9b0321b1c13d91d6ce15ea7b2ea0c670a5f5cb290ca8e62c26c6499104ab8e9fafb05170ede246bbf7313625d1fc9576f1609ffd08852a2f4b73c04f1f4eeecefe3f3eeb2185a618b6dd3e87d9d3fdcb349cc83c21f26b6c662bbb857aa95378e991640a160a23cce76153c134508c68ec54a5", + "0d471079ad3c3432b6de852ec71692d12d9df4f984554d458a9dd1f28a2697976da8111ae4454c9a23d1c8eae75bbc14f8b00e7c065bc290f8938282b91a1a26c22b40a6708c40945d087e45633a595beb67d8f1c29a81", + "f3dac58738ce057d3140d68d2b3e651c00ff9dbb2ca0f913be50219dd36f23c6", + "bb2d033de71d570ddf824e85", + "238c4e6be84bfb151557327095c88f6dc2889bce2d6f0329e0c42a5cd7554ab16c8b5a4db26eab30f519c24766b1085e11d40823053ca77adfe2af387b4dcde12bc38502229510606ff086265f45b1087375dc4a022eb0b641101c74ad566ab6f230133b7aa61861aa8202b67beddc30dda506691a42032357010d45adc7ee633b536a2fefb3b2143837bb46db04f66a6e2bc628d6041b3d306ff78e96205ab66847036efa1fb6e6a387cf8d5a105738be7163df9da0db48e3d8fd6a786f0f887968e180ad6888e110fb3d7919c42a7f8c92491d795c813f30ea645fafcddf877f5035f133f864fd0ba1415b3d698f2349ebe03d9e76610355e7fc23221c5c72b1b2628a40b14badf93288fc4abeaff5306d274f21938650ab236a39496d3f8a6e9086eac058e365d4335b51eafac813f9175bb7bebb75605909ec3fde6515694e119f7b6e96aa1d6d6454c3a7dddeacc83bf0c1f5f6c2a9dd2f460f3e5b074a33b8d7904e6988ae43a22a87f0933f812e45c4c518bf83e606bad4c3c55422ab2207e9d3cfcbc5819049f55e35b9663273d9d3a6f8a897fa38b0dca77eb6c344290cc007b68d913187f2cd480a40262623a4e95d90d5701ac2b9d858d70a27f0672f919c2ded1fb89134ac9a8ba6ac62931c832372abb70e811dc50cce264ece65e87338231f18ac007c5f68f3b1c5904ffbb2e1dc361d53914917770d66afe28c547d8cd5896d892cbdadc34cd6af348c93bdb8b072f38b085361e62ded7a38b4368824c759ec7d2cf4caddb9191e5deedc8b8388bc4ba2c0672321bcda3a7343c9ea71ef03750912f35624d81da5fa8a6ee676c4efd99d0c7258b844ded7b35d8c8233a316b508d79c7c0b3edabad5db9543615179b1c111bfd78b79327ac5b4155336d670baa592d441c810cb1b7c07f3d35473a45b57e780b7d997782aeecfc0363976fb608d6967844ed00b63ba75996054d090aeb605c195b1ff86f9d9ab5892d27632cbb59c06b3ccd69d33ed5dea9398f00b7c6404fcfe2fcb5924e4cb75cbcae0a1b084ea8b15eaa5847431e9ab70e4afe15b4c82239f6165e243e3b76d6c91d23b16edecad8bcb16898641f8e323671452034a8ec9b42b29cec0db210bad0444f1c5bf3505cc41d514d5a270d556f0a34333bd06cd6509ba253a6ba7a6db8f1a60c99f0c3d566a038a72f1271a178cc3ff890b0df1e7438c0c1a12d9873643e2d7bfeb92379545de50834abe2a345faf7ca49beeab87ee516dd8598b71196b8cdb15e7200cb5bd814338babd74c565faaf33d9a8ed4209b417345a1ae611880ea22ab2e894d5d14a28fe3835d3b2718125f0e6daabd85327455646290ceab89e579ed5e1d72a0172e4a6d8da70290b5022c941f3866f96cc4218de5d2622d13af6dab15760a1ec5d10918267f9585284058aba611ba07b1d5711cef505869831699bedc2b190fe1d578814065c91d87a8c8dc9b0d4dae0c80cd241f0bda3a6d5e714c894b7a48b1e5eed4555f103eb03c9db30efcb855df422d7451a6d70f28174c7ebff536dd2cd2891f6c3f264d632ca924c4e0d84b37cf8e06e6f2e29efac6cf008cc27f062441278dbc9f09cf44987e0e9ca088a48437b0b89efb9cf00d3d0c5fb449fd4b64e21dc48cf300c2d80a502cb583219f1881e78e647783d91dd2f3b389a1594eefd8ea07d4786f983d13e33cf7a34e4c9a0ec4b791f1666a4eef4e63bde7a241f49b5cf615888bd8130743bc8a6d502bfc73ab64d1184ead9a611832b7e24483a1a0fc475d9ff6166b86a18a3dc96910ff182cf326456c4461ce8acb3467f801890eaf1ce0b24791da9c650876e718c0bf43c475174f9712dd4a228695e8f8b2b23fc4a06358b4a6a8e1afa87a0280c3e098f218f7a6d6bd716f8c105a7eb799ba0220837fa5a96c8a22a826a6f7ea9d7216a24acbc7b0133210cc17c8190507badb421bc54997ff9340cdc1ee415126ac46a4fec9fee12d40f06300f7e397b228250f36d6f0d2ddad5fe1898ea690e4c7cc3a116a70bfaf6d2dc996753fffae40ba5280b8356b7ab4ffbc914ec74eaa070581fdd1d9e5aa2", + }, + { + "4d81b652fee892d575bd13dad913d976cf0517c819d5183a72eba995b1f27efe743451721ce34791a15a6b7a6e44f13d4a080563dd1d9d4f0946e5ba3863b9ac970a1fb4ed66458ec1b1092ff5fa6c3f0271a2df8e3f2e97851352be760b6a0e1589c202f00791b1b89ae0ae944ced96bd90754bcfa3e355b735132d407d3b5507fd57f705e8a8bd82886b16d459ac91e921dcb8c5bf0d7cf420a9349ee589a5e2e19ce7c944a54ccc1062a0690f3152300d0bf5cd1871c1391bf6d7007f7ce26018ca2a5c6f76287fd8c8e9e7f93b1806460dd35f7f95989a8b6f9a0aeb7c6b0346955fb50b8735e34f1ecb4859e34ea0f022ff6fb797094206a34cf120b7f4664c531c57da513b296f0671c8e9bf68d9e1674998fe52da04f627f516dee97c2b3c988216e9bd3f58c3b021ac70898651f1cfeaef21c4f417ebe92dcad3aaf50f4277262c356584f816a5a5862f2bd720fac10f1b86033371ed603bc00a30cf4da8f579dd5bfdd571a37af7d2a5cef29f9001bb1605ee87f24ec3b259f381a69b771f78d21c4e43bfc83a916e08830d9885c8ae8ab6367c05f92e5eecaf0488262300f83f4e3bff177590857e149216995bc52311fb9f16f4cd74e07c7868a39b699bdbb7d7dace4c6a53ca7ee6e11741a63a52a1d96995a6dd752356dec6f14761ccfe38a6cd8511204f8f0630a747d6e19a77bb030c61e0828436604a28a7acf4a5e49b7269ac93b93b99e9e2e1c0c47b377f7e44e05ec6659526afbdcd5bb172404ce5a9f8786234114c16f20cda6d4359eb873a4a4d9fdf734e9c40aa4db3ea9a98939210f6c62142dd144eb78191116d194bb766ea96da38321ae27fcdcc196560ac75567297984fabe6072c771899906350f74de6d18518eb6898b934b11e945d94ead02b821fd6682602e03e9c70a1ec67eed33874eb24dc83dd1035fba5928f8f62ba1282907aa8935ae72fcb881b3277ee6bebda8fc75d6cd792677c25f70c87b11e094298b2d5f39904be211ff0980e5b83e8ea4a455622d8be9efdb5aa8466c88ea861407d54d98112faa10293af5e16974861dc9f83b45d21b112cc367894c421f5049e49dd205bd7c15e6a70bc810704e2e3a3659800864912527f8be743acdc474a26246a81fc2bdf669b9be7a2a0c986432e1e44b5675607e7e1ee2a8dcb72d8f1964272926e52f909ede0ac8daa32d1d850158db76b959e4d83c9da4e3bb23fd1f5b26463045d6cf13d187fe74a50c09a654d52d0e2f01d66b9f8b4f4aaf4c69fa62a02aa876f9bc4871aacd26a6c6ccfb9bea09cafbd0268b5b65d60aa23ff504d02fad4719698f8b044ca1bb037ea6af58a06a448080dfdbe6a5d698d5db9da5fb4aed04a46c8fa8b93153bca00a5bf8aab64d2b371d072db2ddb688a9442e948f0b99236828dc115a2fddfa2a29e2d4e02ff0173cf734efd4eb687e3f8712be82abe1fac4be0c1eddda090803fbdce41bccfb58c43038991ba1074b281a09bac5eba58a99a1a9678ba26f8f9e3c63ba095f02cd8f3b56aadc5de60477efbf3dcb54b854f651cc72042bf19268554c61b44f2f338a75de56c3c45b3ba40a697f5f21c4557380c777bcc91a151e5676c2a59606200bd476cf98d20b4cdc64bc3b8670810a014871be018bc32fe239e287cfe8a7cbcd1e8b55e08692ccfb4ef871cf797bc0b1fd7ec37931e35b6bc5d32bbe7ae77b9962c179f96436e4a32f566298d2235acf921e38c3f1942fb7674b65e222d17b95a2e58f072c63aa4bba1ce48c303f4bd24d84963f18c5e670015c52342dcdc9c0b348c7dfac721b568effe2bf2f2e816ca3279bbbed823beede8e12fc5bdccd0f1584deb1f6ea1875e9fb350919b675ccde0178bb83a4aa5232bd5e8e9a1b8daf905c6197367a0d106532297ef89f3bc690b48224592c768bd9c50a63d0881370d475081aef052b444744b33fd3fef674a37898fc950f887ed482d2a51ae615ef5b1dfa3a23257e6a6a319a4e2080b2c4094bb09e4b390d1fcbefc4d6c5dab620f8b05b1bd5d976300b007e2b8120ef8a6c9028b7d925c795058c6bdb6711fc5fc2476b9810d1d81bd24637537716edd3b7068b802c531531df710d3682f9865530e1ed51b3b56d860ba4e972bbc74662cdd1e2ea24f81bf469193afc02b14143a32e9556e3f2ecef97c65", + "2538d98b64b6aa9258f9141840a5abef66d6037a10356366a3a294719c10d6c148b04cac66f63ebff052d730f8821f5e5822d869573bcffbdd636c7973433abbf38767597da5186df8ef9df071bc4ecade2633366102313e659db8d8e0f293d379fa2df79f456497", + "a5049b0aa153e282457555bf6f82b60fc81aa6fd1c2ea3db031478ffb74b5b5d", + "350287a6bed5709dfba3d35c", + "849670914f5fe318eb01e8849e536374ec11e813acdbbe6a5e82a506f6aef4f916a3a7fb2e41db3adf990175e21f2386d1805af9bbc32a6ac156b13b1a9505958f68599019c4b7297314229c467114754277b10e9f49a4d12837ef24184629c8902ebe2a23f740dc826b01f8963d47100bf617b314835e436104eb207fa9a1079b8feba06d9369b9aa8222d38d87096b73678bc5db9a1add59394530e678b6ec93a80efc6e8320f2909e3e891306d69b016ade0d30cde64c2c903b401f9d01a29b5cb8619dc68ad6c21900b365a6b657f7d9ca4c145fe598a94eeea741e20a9329996b17aba5d7115c93623f2f5d6927068d0f190b49eb885429d771bbbb3980e9293e4d664a71c3cb629d869dc97e58fc3d328331b11df19a38d61e1705ec4c3d779168abe049e9d675337ff658e00d2d610c8f227d1341d1c41f1c01d8b5d83c4b1b30ae4318da9822f46402ee8cd5cfe9f3f22d90a5ec2d0aaa0baa85e10f5295cc6005c5a0887287b0c867a23da1a4c2196f91fe0bd4f0db1ab324c26fe6088d7583f3cd052b7f6fca38e8b21f98fd07fe78b7657da1f586f1fbd3d2b4079e20f21dccc0d269d53a29deb7c7fb63cc291d1d2c50ff163e08ce612310d3bd622f2416e193078ce4e1463f8a3490578af96ca98e665468281f1af9117a2ed23367df19b570885de9d6594f09aaba4090bdd1079720b08d54311793c97bbe14433b031c865b059cb4f75db74779b82c4f83eb4bd829c62eab995027b548063d7cab7d1a6f9642da6cf7181c0ac71594b97fc2c84b1768f81eb287091f63c76623c61e7ba90c922c74d46b9ae5d8094d9752bc1e8020a82601c356a201e0473d540053c707a88f4baad37826152dd245c4cee6b0019583c61e4327fdf6bdcae53584cdba8a503b835bfb5df9d649705fcc1f09376eec96c3da1e105accc1cbc21d90f527041a9beb85f8cbb1ee8db798838bb45374b741618f83b5d0801a3af2f640abdbe74ec3dc15d6711b4c1480aa8d6084defba82ed221ba359c9744705c4feee0955c27ef468cbb816694516f73fb541e0ad4ccf99ec8b67ef090505d1f7c4c3a8ed7e291c820261f12d92bbc6609da6c275349819848c9112826674f243acb9a29ab73f17c8f8af12c7437c11972c824f00db7ad284e51b9b508a925f0664bb259b4443d56463bffc9e5d845c9b9f79b24c1f457088fadd281f48238866e0b92d6253638eb188bbaa8bf6a81d2b1087904974752697cffb00b4ba05e5b7b842a3d2c0a743e4bd691625788fbe9df14600643b1d161bb2916176b6ee40aee38dbb594ec2735d41369ed3a0c6dd9073f1eb51d1b77eb9a967b53670a8ed755f3b2b73a6cb50a9e1ea7549346646dbe4b801c8aa642779d8761b6c2d2e1a9995e758ab92f07c4eb4a23c042171a4b354f434ced5f6d9ccd26cd6c2506e5023dc076ced15566fdabc7364f4a8594cd6ec404e1a9470f52a83052390e4f7789ade9179b069d9f84ca2c7ac9eea51035db817845aded7405bee90cbe92364c8c7cf8a366cbebd7a972438f2a9881395a8610a2cd0c06c46b60cdae5b1f473f4fd6ec48479cf35101656f05485198a470cd36af22838e7ba3e28863cd8ba7bbba7e3c2625c1106a6be44c9e3d9b9938679b26f0713c62c3757a2dc8b2d9eed5e652220a7711cd220bc91a9afd7c940dd8be71616ebb8b2cb0686dfa161c6ef56994a3cafaec5e79bd0a2531fd1c1a42771acb101a38988bcba51ad85bffcd8c67aebec5b37d526b29f7b9d31388e1e7ad7154f8e65516f0d80a30b88c2b868be2541d19ea1d2bcbadd30e2fbb1b4678bfef7f200e0f8309ac0701000c52ebbcd6fa00cb85c8d3ea9c5aceeb3adcf3773cfb3bfc9ac764d031d7c63ab888e9b03eb9fa74554dab4719d426d0875a508c8c86b22cabfeeb70b0f1461db4e5f639d2a2d28a089dbcc48e3f34394ff1acb887b89f75d3236c8143bb9b06273c3878744340ea1858a9f383f8bbdc259250e23a3c3992bf8b7ca7e1a66913547710402bb538a8866772d11cf4214060ed091d403e1c9ca3af75859259f88656a1cfecfdb49d57c193e60a2223627c681a2fbc7390140aeddc19df035a5207adde4f5736bc542bfdc943ae8b094f4a8701618688fadc2284fb423f602c41ad8ee11e5d9fdfa67fb7dc7d4dce7847d4875b3af667168ebb6082f6911c95", + }, + { + "67f0494a728fbfc84e2f4a043e121ee40f3b12b31616c78e157ed970db28674318b08d8b3f4c538d7b9d91b9b0b09ebfebb07201c6398fdbb8684c9390b3d6a8636333a3b086302b24c2e5d47283935d33065efa3fedd5f755218be5d4618d38c5c1db75470ba06bcd853f3f08d39c3cd9fa3618e70b103c2d9b2101fcaf39c1701436b720d723ed5c622d6535c9a10ec4d727abe237e80fd20911ceb84a90285fc6e07f9d036cfa65995f9b6300a927d7d0d2b907bac9d9c4daa87c2438a583fe85029c886f96ed08f5886bf53292cc0265850a1f4ee3e3288b604dc305d0c28ad35e1242f4ff4ae988b6deba48aabcad2fc6cd7eaab0a63510f3f915c4bb9f9719b1d90db123f639d9d4f3227eafcfad769c2b204dd2555dc54e738909122022c4f92f751d25aef6f9a1187750e825c68450e6d1223c2fe88aa27194b492b6788be6eda80b9b9f053cb77c8d9fa15324f23af5147624fc00c66e947b004bf38b31e1343c7cd341b98abe462a5f994e51d343664968624a2ed0dea9d0299d5c5a7e9097fa63d8b3ed96f917f693654766a9adb01110fa3fe0d8e9b102860d5c049df3fe00ccb2ed62ab05583e6aa0a5134d55245d4f643e274def29d3fc86d79979d599458786a8338b0071f6a01609ee6b2e4bba9289e2df780bb27491890d0b5ea650e62df819b8f98aae99a1b8870ce6d3c7785ca957d5b4094946925751f0fda1d62a9aefe3937a912c1b49b4272f87eea7e397feb84c0702929959e38a568460811e5064b1caf5dee53f920c6e19fb16fc9214b5de1cb770b510533f66d8a0e7f6f04ba8ba41869f8018abee31a6042d3919e217359988eaa9db2a10b3caf7aaba43527484d81304f0bef22165f74e9e1031b545ca3d2f74195984cc237b76ddbec85142a06446902339b1883000264031db85fb19b46f320ef3fe316f750f2d3d6070dec5b66ee8ef20701f20965f5171e44c8a99bcbca7afbbd81e30e74c6d48bc4b0d72baf562da6581fafbe14b6cc597f75e53b305036ede219ec56d0c0d29571a9c110ffeeb747fe56f6030dc26c8d3841b868a1ef56840932dad9f3bd7f75573086571f4d9f0d949510a2577d2f8fbed7e850c73ed4c071bf9a656d09dab43a610b49aeaa57333f67d586d4f50683dceee4942db9549f68eef4c5f8df8a2330857cdf2fc4025f2be7d5f0dcdc74a9cb593de91282787b716d416a3ccb8d6d40fa3c70be4ecfda26a5caf3724fad3d98db16ab6d8f26defc68392923b69664b0c2d56f01a549284b042bbd43c8faec940187f190aec08d06f9a62ab03c9f610f64c0010a0939451d5502511dfd3da1fec5a38f64640c7b6db2961def257eee9a3eff944828e9557deba68bd8e42dc7a9c1570e35537993061fa0f5351fd3cf4ec36386ec4cdc5a2882d5f16703b900c5000efa63888d69982e5ecd3e329c8cf5f003e23ce03c55631246ca15ffcadb0fc9d5634252ccda812ba7bf5e343c44244026512062a68374ed4d8add0855dcc22b30148e0cef0f2886be76bafabadf3ae1205b43c6deb8a41c338114895dd6b49deb329ada31b350e02a1bdad4eb05b61b50f9d22fa2863bd607406f552713e302467ddc78213d584b4933202438d63f99d011b97297f5589f35b7e45ccbd76f02453b7a7668c2b1a1f5d1d63eb805c8881771faaf67433eacfb22f9b6fa58b93f9423a5fcf667aeec39751ae17ad36992556431bca77059a29353598dac12bd3036633d2ccadc18f44123e5bc074f4e5ca380095af062fd83b647015259be929011cfbcdc9bc5d0dcf9b688f0f5d74da95746f447a9e1cb5028ccb2827b45129d04cf6990953a6d8ee0e67fe6bdbd8004f4744cae5607fe7ec4a0f14fe603dcead3367b6870d8e751cf57387d04b881f92cce9772d695f19b36e2db2cf6a807c9ee83225f5c09a11b50e99855921a4eced8e631af7c234aa31615c00ccdd7c6ac5ae8fba6e29cc233765a891864c7d73dae08ed1a3c27cd423d8d4efb550597afee8356c12018f496637daec83575f5e38ed2fdbafabafd38483c239d31cb4d104e93d16eacc6050033a3c86929be4ca8914a538bf540b43d7ce7daaea317bee1ab80504846554879f900d312bf2fbb406a0edc5f4f809cbc68675b0b7f09fd1a8a4d52c0929b3a8b9c1dae4b3d599b976867e6a7e8736450dabf5c49c949544386a71419324ea4ce5c4319899ca510f50d07ace57b013655b0929f79dbf3cd629ad17bdd10109b7c53a4f5f04a16e5471e823c898362df43f57ebdd1627b33fd4cafca6cc065d9140acf0454d5f99be47bc87e0f3b4d4320bbf0f21e7c261bb8d5d615963beeaa46bdbe9b83a8277813ffe6132b23564bef5", + "74dfdc364097c39ef91c01b707a522e28edb1c11529d5050ff820234e6c0295aa00591e09d547e9671804d7825705ab44b76c59d1315ed1297ef477db070d85076693013bdafa92e2ff6a654660008b176cd4e8ae23b9c792be3f7db54cf2bca385bddf50a8624397cca8ee3cb96944164e3cb461e68", + "b3b5ccd7ef49a27d2c6d13c0ae77a37abec2e27e0b2d3530cdbb7f36792a7d2c", + "c0494bb7249f864f69beab46", + "ed8d6e964bcde1df68e7f362243073941fd68ac77929c8e480c89f519f748b3dc337b1af6231632c975167a8425b174b42c2c60dfc0ec85a0a212bf5c9aada818a83f9664c8712d96de1036b5e5d8c8298786b753638de3a8da958549f16eb9c723355cdf7b999aac464ec39df7d6c1607e81b88b63043d1c847dab618f1b19336911b4b0145c2a694e61db71e021282006d48e37f10f3b6314dd012a07618228532c28ca84a936e0eff83723d117b2f2db857d14af5bbd5948a0e53018b31e57cc2a81f36aa013a844990753ccb347fe98fab294cbd252a8b8f7246276275d2780511fd3cb7baa2fd1548184f968c422230f7ad73ae9dde91295f79f6b799e7d234dfd6573fee6d6ae748b0a8cd7ed4862ebd957390826f276c2afb01fbb4b64b61a1bfc138508efd630e77580867bdc1e96a48a694cf0db6c2a11f05dd0bc8769e7200bb0749f5798b6f3559de55d0c281eb5df22b731fbbc109da9c68f209b888e61240c4c0ca006d105c0a7f43144021547d3316e5a99f6c429f9ea2f17d77dc68bc9d5125b6260f79bc8b3b8061972e6757d87b6544f21645c0b4debe5224f7c48142c09f35b8e144c0c1e6521f04c170519ff744d61abd59a56d25a26c5ed5972191b25e78e2140f3ce68fe17be9e59a79f6c69619a79b83614c670c7736d19c27fd22515fb5b896a6418cc0b4850e85c07b38b995cffafd9f69763cbbcfa9d1bbea6868244a66a5cc82e815fae09f5775d28437634926d571c2b0d200855e09cbdc67d10f85bd4cc334ded4c83aeea57f8e373a950f135997666b653e8de47a3bc0059525720045996bff500a47baeec97808fe971d7693dfde339e8beca3598fbc053121536c30d0af10f8f5d8e5eeaaaa9586d7abb563fd69e88351f93bcc46520f6d97c1a49ba9f8f6a25cdcfc11b2a722910aabe7435ac8f0dcda9f824fdde80850f21a2d4bcbfd2e9fcbd14dec05c117a9796db49e2f0dc55e74c7f0f615bd049fa7d0bfcf197dcda3ef3de90762e6f6f9f8a8936bd04fcf2a97cf18ecc8f2f118ffbf02b67f252097e4289d02f264161f6f90f79e1e1ef8414b01a9e1a77b88c039ad6eda6df1e28fcfe9370f0d574aa9e857dcebb19eb7ce8af9b19b4481c9fb3e1f0db3b02af483f737ce3ea824b2165e7c0fca8585383d4b0a16eab2c7e3ee5c038f939a97bc8e1c093cc5372ee45d81836c988f3ab3e6ee0e5f9549e4b7bc381a2afac2074cf75ed56b0e757e7966cb253d549fb0902da98294c6dd4de3c2e166b7e45098d2729b1393deb68471d4d3218dea3dfd0183b654ae4092a79357945eea4b28cfd06b40d30d1b4b8f19827895f6f908f0fe511f74ec84cbab2483ca4bdfc6ef50178eabad79b18b58529c9328c13c52c2869858cc20ec36ef7717e1c743d13f9607bbdb0b701d9df6aca7366814e883d23e51ee5b0f20ef70e2c4134ab037d213315fddc89009260981329a1872e541767adbd5ee9501e7df4ef0cdfae9769961f8716ee7dfbab0ec89b3f62e987387d5842e124a69b07245d359052ada50cfd67472d27ce2c4eacb5421b62dd7331da54ebf0989803797f4c8c781d0e2e6477b421c7d5cefc8146aacc0012af3f1f7cd71ce2b1045d86bf48c9a13fe469a1865294e160b4975023d0eb24ed26837afefc250a914f86f8b1f5d67d65e9737e841519148d4dd5dbf2b5a8b073861288ec9793d4b113d71c01727f67d791852fc3946dc912d60fc66bffccf4c45d859eed9f0bfc7f89086df5d5cd830ac919aa7cdb4504018052d67f6a3ca012ed69187cd5fbe91875cfade381bff1e804ba59cd59f0f75cb46dcfba234ab9832c3fb9aa8dde19fc1fb30677ac1793a38d94aefd9ffcd4e777e9e4f6d49e0cdac6c16a36bc2f3ed8e23b80350e3be6d866aaafbc8cbf7c69fe44c2aa80651164803150c23ebe262aa669c77ca94d215895d2ee9c3e325a0bf2c61e419a41e0f7b1ba8ee0508307d49301abccd5b74c054b6c7bd1aa67cffeafee033761d8226d9dbd7214b130a867764062cf4da685deefa23693b8549d5ef5e53df85c19bfb3c43c6bd073e7a836f849587a4747e1a9a3c7194f6d5472d2e3e4c81784a3061fc9bd3b94862c4784974d859134369486f2651f1db94f511c6f59f41da0d75307191602730b88e4e6101fc8d392c87687f3be454dd92fb8ec380715bcd88aadb63717cbce4db91a36821a572c363759d8d0a2ab007e5981b78731dfdea20d900b14f0c5ee6a4a9b532ed2134e6edb4dc267f001cb88dbe43aac4aad453b839d035697df7de98ca7a9ee7601228a79004b89796e9ab971aeb8e62c789bb21f38b77b492c57db402bf6a42ad0cee169e9251d865ea3e5f79b1801ef1e53797aa6c7060d6f9486081", + }, + { + "04cf92a64cbe135f7fc1d7223b95e41d13f04b482018039f4e7ccacba8aa15ac79a752c5666524e527fb076290ec80a3dccbebfce3ee9b316a65fd130f12bf88b9124d1f7772049e6d0c01fef881a1d44c8dd02f7b6b60e6d15df9e06fb86929cab64842284de09659e19451623525aec2f5dd3e603e24319b1d120bd57b34a0317ce25ac9c2f022a4847306b998b57c8d92baeed0de1f6cfb3177d0acab70de275238f1152813b9ac87bf651f74e1ad079b9bd779ba4374ecba459865b5768d08ae7e1dd691d6821895e8380ac9e5116580e8de3a2c5326e698bf4c4d35d955e45772bae8483d01de2539e8ee1ef9539ee132d80d85fff41dbe406af319c0d7703292587bcf5959f49241e2b03a364e1b682729ed261d0ae45d74d77634afe667413ee210983b042a7ce6dbb61c29d18450fa7176177b5a74f032ea24e1d08b220f6d32a7a836d1241cacda39d6acbd26a62f9dbeaaf7329a291dbf0aed4a2cfcb85ea360947585b1215feaf70ba71eb2d6bb7081b2a21bdcbfdae6ad2513a9dd714d3d06c2c2b7e322a1db2d48f9df1fb44fa066f2bb42b196295ebb3c0898ad55d5b317986afaba0bd5e754cec773821613e908ce2bba6454181f9020b73e758df18c255c87df675cc6bb2b8d2eada44196ac10c26674167f94a79f4be515d8d6a1fd3228dc9a85a355b030845dd4c5f481d5b6e74acc66de730629581b022fbcff61e5dcfb6a7f511aafd577849a6b057021ecbaee53986159c1ba74c3e930c34a159f467f1e9799cd6c1151067c56769e43308c96c8edef8aa7634d909310dba9af2128cdb8c29b24d3ec2a4f43a1ed86d1791c9a670b240e6e719f01827aaa319bd3ff53959a776886a1b7c942a54f141e6bae8576d294e44333e6c5ad90f74863f69bf890126016b318e0f6bd2f0adb9bb861118af5f6cd28dc93d56c8a1dd080b8c810ca29267d410673fe367dd9d1353ae2bf2fd88d57b4202c21aa49f12a01b93acbe260492367bc219d3afb6e6f35502f6529bcbcdddce9fe8632efb034a9eaff8b4a48afb105d04e3fcbbcae010ddd6636992213750b12fb3e01ab72aa957136e0bae591bfb5e0fe819cac82a98ae8df230af399160594540640c6b1d537e7b5f1cc47b08127ae02c35b846de56c4c08773fa18d4436e14b76a7fc4bdee301d0af4880306f2f33328ab79f6f24ec779b2b1928704f09bbc5b0b7108e9a115e4959df79c80eacfb98649a0788867e23b2974b22e654ddab0494bc922ecdf17727d0f0efde9dea7601857d890bfbacbd93f7df794bbc254f50e1e17eaed2f5d5a2e6c58083aff68434730d406fb9fd02b0dd7bfb99a04aea812b6830fe5e05a044ca21c77a174bae8b58eefa11ecfcc1c977bc6218064c9931b5c92f13cfd05799f11e130869c293c1b08dd29c899365014fc8195514b286c97cb6dc4b8633e47751f87fbaba137b6aa04d072ae06c2b2f34448449f60b1272c1efbd4722a2be749a3d2e5450aabef1f7c51bd8324607668a8caf8097c2f358b1b09fd3525d47ec9a7640eb20ffdc17c4f7eff63df75dc7830c471ace3a727feb11533d6e9a2a08106af33069cf482ec63724032e81cab18e12cb5c4c3ddc374e2f75bcc99fc5da09b80a738852a14e8ac552b8471c6ad52e35317b730db2c13c277e06c643e0d0fbea43833de4d2c7a9247ff040e9c56f1ff7ea92049c5341c4d1478a14275a10119d934e8165152b89951bca7ee1399dd8232fdcbf831d8354640e698b68799d060ceb877201b2fb96cec514affeb28721e163e1648164b9e5722271db9b0ee1a7f96819fa1b1590e9daa598d9571ffa3882db9d034056e9b2785a8d13686eba61d7d45cf2e9ecdbc391739ce89297211472be18b21401658c5bf29fc3615924382d802a166d05dafe7876e70a0d081e80c63632da379766928a0555eb5e7a238cfa4da267527c66caf34dd40055f2801b29b3f5604a5bf3d46048bfbec2e24abd2fed2481698a4b5cd71f5d2c12dd473b903c9bdb978eaff7d76fb69951005681ed7b0257054eb3dd6d10097fee51ba7e8d565925e4091cbb78d255c9d3ab4ac0264d172c9bcb0908db1288c9634248f198a1167daa323822058decd83936985f83b08b1e7b942756a7af200af168fb8a091107b4443fd649cdc22106f9b9657c69f19be485c23b2c715b3762c332eccc44f380883357d10019f20612ab6b8f155c2af9e2ec340e5d8f45bf5278ac1fbc9f9f44d2f615d21007d822b244b1c7a0dbc182c7f5912485d6e4d74e90f60a2f964e028c63d49c6aadbf1df170e4914ca514139ba538207b1cf7caaceed4db8423dd1086b2adf15f6c0e50dcf2e12898f53c339a745316904ae03c38b417bcd7f5cd5ea77a4f06e65d56c24f37ebe72d271ac79b6ddd2bb8bd67f0727ead49737aa71af4f620da53769ca3ae878adbaea5a249128074ca3ddbbbaf5a68f9cde2a0e8d69708b0ea7f4c8d2dd4180882bdaacccf2a409a681c551776bd10439fb12b7548342532b371c0e045d8e8c895929464bdd4fe25f0533c66104daaaffed52446094978bcbb389c", + "001084c8a5175c0ad43108f9215c35886c82321c800740c6118a3fcd45776a4588ee0e2d056a37d99b40d2bd9c0845088a77240b7e65d18fef105d3488c77910b5873dbbf275948db5", + "d614d2e671066e387f7eee07bca9f9313d86e6a4d1371360900d670e11ecf1e7", + "674a516f8f59f9067e0485e3", + "1ee376e9e3c89b2147bcf75480ff0dec1d0e8cd45ba812f34c84124871d484b4ca87bfc8cf99f85ad452c482933801426e2737a97468809fa36caebebe8eed07a626b3bc3614ef1ceb54f9221ecb16f413f0bd9ed4b3010c40632f05223484af7bf5948c2fb8a3d2ce04c53e3f2682494f3969a0f8eb738cf93c0141799c9e6b68924433f0326991e19626bb19e6fbb5dd46baf39f92e830f9b1ff465a007f031891fb1f1799cc122d3ae7a55624356b5297bd5d948d9ff2e414cd8adf00a53524df43f398938d33c93b2c06bcde2679566c0a7b0177b4a873f35874739d550712d5cfe3d25c19292ba97c01d84224738bb25546e5c252fe5e5f260ca881aaf176a271a6fca2edbb2cf23ae6d4c56c20daadadb8205c2e33881867cd67ae6e59132edccc3601f014b744ff8eb6aef5e09b358607695d3af42ab8fa30e9fdf99ce54427ba9da3699de19f7a8f9be368df47ff0607601a91e7a5fa6e72be50bb32b825427cdeda3972a18a23af290986cde14f5fb9cbddad336f5efcd2d7a0cf3d5b23e54b702352fd5ee52d7e3479441497d56e17d5868574c56cfc421ee47bb00e9c75b84262a1b9e2cbfcccfed9c4c386ef0d2c1be9a7b7556909b5d72a38b7258acdd624de2396c75386e077c34f005f92a2203c82d1072c8998f03b1df22de832ac733977705453b1d72336b8d371cf1ed3923f462ecd22075de5df68c83ab1e6648ede7fd5ee5794a744abcb32af73bcb182cf97d36f37c15535c4107b7c8f2321f9fe0e2b6ccbe74204df3d748c05bc1e0e2c55ae1aee2d4aa4a52e98ca7229d6d06576196ac8e4b14a9ce807075cdc876aaf904c9962741efa8c6caf41e6b87b2ecd6636e2e58f3ecf576e5d8b895162545e618960ff6e336ff17eacd5a1eb335001633fa78c41ed05466d904ef9b81b643a043298c0e291a085e4e67da72e329adfccc407f800709865147db49cbdf4232073b7bc7ad89b3dd901d927ee08ae6497e0f2f9d052ca8d7444d2e2ae2197f930a7b1c8af38d8739ad298464169823684612cb628c484f710cf9c552551b6837b575a43275100bf800b7a3d777adc44d07f67cee5000422b9049dcfbedfccded0f2aa4d189621579b01e3fdaedc4d772dcc593316ca85e7aa248d219dac21c561d318a4936ac0d3bd5c75311486c174e0e2182affdf69bdd6a086534e4a602efba2b9363beeb5346539b45336cbaf479da6b15b226a9ac026482216dedb84ae3443b306820d9f05f78dca7090d727c7481d82c6e5df80e189e24e46f5758e453e542bd91a58eb51a89e07c50afb543c6b998704432e863dc4c0d0236e0672835a7b0b64e14f5ced2904e54da4287597f920bb4d542c35d3b0271cf0eec055656d523d7d2cbd667445d3e8634854f8616b7d7a7f3e14fd32651e9df40e1daedfdff1371f16d5549ed5646adf2d417e4b3a4d145bbe0974ab388c2716861a08296b862e4fd035163281457877eff89dadb160eb2b780414435784804bf4fd36602699d8c2f6a8cbcb509198c38e2df2edaae7bd7c93313ca98a9c2d24419a12ce35b0b3d68c18840e3ff8739d70969927c7db9a6569787bdedf5c99948a9e79b2302a83a71159f4c789b3b3f05f1e574f8a24c899ae3457f8e73f9bd86976fbddd83b1af337eb8da4c0dbac3792921597e18a2fd3a0ac89a270794529d370d36bb6dc7452e754e903781cbf57c8646b92d5d02842e7df229b3d721f9b981f9d61a48f00e53948a5dbc4f739849609d94aba3e3f5f8163d40321576cb8eb8e89953b608a01184d41aafc13f40c47b12240e3ad49413473c26b6843f4514be221c2af632d1a54cba230457f23f00b2608485c381ae03b389ad0a1671fb416de4659cc7f7a9c4b6d9807789c307d061fcf613b96a2d79e5e3e20b863c8b1b75f35c982b40ac8dcb7d2712ef7df94901facef783e8015a9a48574aa6f0cfb0bf6c1a3409028f8d62137c347f5a35ad6a3cd60d71aeb29bae56bb4590f69226fb4e08fab7a9f41e58f4d5784540a70e7a97720c549c8440b089eabd0eb3e4d37a2e54b1160572ce568f4256dd244decec31fec555017ebf488e878945383750eff26a8a1cca73e7d6f52d8cb229d5603360a3bffec23029ee34145c4aade82d486758e0aea9e1b7bf0b4bfbd4fcc96aab66a27fb463b48c6a6c5c5a60253e2fbc5716ef55629277a5f3b89c300e21bf1226241ce0d587fe3f5b11e47f35614169dcfaa375ee1aa589be33a4363765368f5666d155cf72e851d426fa67b982aac4dbbc29356d71deb0715b34e00b9fd8876bbb09ca0701b15615f05cc45e128b3864b26003e6ffe801c4e27402f37b8997e0c29ebc273dc03358cd22fdb68d9cd3b56ff8248a727c2d4ac65acda4d0e0f511bc07ab06cefcf444f1002c151b953d7f7b19695668a86683497c2a2d2e69f19a4997148d2e8d158da859c8f44437d9ce9db92f84a88e89cbffc74c0ef4295088e2543a4f7c6ae9c908bd987bcfd7a074f83ffaf3888bd7f430dc5a5bb70d223c21b1bcd8bff2103408460df864dcc168486f6a66d67ded366c6e10f50bcddada93627cda711764a57ec36035ebc", + }, + { + "ce72c93caa49bb9850774149a87fcf8e23a0c53701554468645554553d54190bc6e247712b02097b794bc421ca94afed34742435ca689d2ebef183fb469c060c7f4d7daa508726c9d2eaeb9c7e9a89b30faee8d9168607d4778acfbd27d5caa623475073ce763ca061273cdfc2c692d1747baa8a01b15f783b2e36620400082747599a16cfd6b630fef310c0b9a2912d1d3bb71eec16972745cd8a49cd927014eb0a2abbe0e1ebded4fb9e8d9e2fbabb6a71da5688717ecd3e08160b9a861f86904a41702b2c4fff28ed8cc61d468187b75bde3fcc5c0c0a642215fea83584387fc5a9aaf2f8a91ae535e0027b618a32bd687289c47e9428a1a92649deab825d702b076223b07c08e55c0b60be95937bfd0504c18398e924420f6e20baf07e2b1b858d3e360a461b66517c24e60f9fe314a4a4973c8dbc7e9d2a9f571a1d8235a21073d81ab9f4800b70a5f17f44d593e8792a2507e6a3a41042fb2a5f7e5f028ed2daa88cce28973ecd88bd125d50fad77b1fde61c38272057d9c65fbfc6789ce41315a105af14e277a0c39d75c34aed7538c39160eab1c8c47818743e8111229426c399c5e88c4d894fdaff0315ec885ea019bf9acb785f3380c37201d494a60b583fc130bc0eb9fbe9b90eff95874e35910dc05c761f8006e2f208b786aeb2eeee841f9a82d9966c82956c181caa4dada81dfa2e2d7a25007c2dc7f2dc7ad1bafef14581cadbee4d614a557df4931b9ca105bade8fdfdefc0d96eeda11c08500b1ca827ca670ba07bb0f85af92914c43a6f71226d6e112d487f1ae99b2239a63ee2cd0849d8a9c488a11f82ca334604a2b7260f25373c6db75656527890f9b772c6bfbb9f687f27099ea9d4d1efd874a6ff83cc36c039ed1690408f20394692ff054d9e6eccc6776b6f4b3c5f24b0052334d159f40b470a9b8799bbc0df4dbfe59a5e536624cad193160ef23abef85df2c9b6e6d4fdf16f848a2a446a77044f1162a278866c491982570cbc16041908cdd0efa2cde011526a3c96d4b39a23c5fcc53d8232869cb4dea871f4ac8afc795aeb1b28cb2d7a3669100a1cab2ee1a7f31e2a25a5c6da836e4b771ad57393305faf582adcd26045e26b618d9943358c615fb206258c8993d700adac7440dcd3ef34fdcb065e10e9c9727662b5abee160aa01d2f2ca6c203a76fb01bb08cee9fc1eb6bc7497bb012ed2774a2d263b9dd03d60c307ccf33233ee33eee702c8e3118f9f86174a97462d0e804a24bbd7f4f938c7f105bb23399967288069e1637b60f2f1883d88ce5a874ea4bc0a7ca0f3b568e4bb1407e4bd6f0d3dc8fe91345f8435d7b1be961c45e4b0f1ef2d92d2d30bb78e1fbf72cd2e7ffae76e8c2bce005195c2003bde46108f37ffacdac28fd67a0de62970b347f0ae3f5f3a5b1d3aacb2fcaceecaf2ff4a2aeef6f5a176cc1b74b234f5658ce603bc353e075278a4056540e43033d37a6eb2615453d8206f5cd294423811283bcd5d79c4afe268a547b98977ed5cf24c0f53a0533bc0b2889356cacb67e2f7353060f9e04362859b1c1f02f96bf5457b58e5ce84a6810d39d7c7f53faaec64db5d6ebb90c1412bdd503ec6bc240c277ce1f5f18876feb24eb6a77e5193e33ce141e8720329add079dc9735f0a35d7d85436f1dba6dcff9147777760b5aa2ec9c8b5e9fb4fc602ec8f754c99ab2372ff5963dbff3fda91865108e606b214cf7acab875197e78060eed52a798751998ce7c73cebc4d5f429f6729a5193d7593072d0921ac8127ba6e796107ee7b9fbcf7128ab35fe9f6fe501fa4695c19fd64460685f287acacf5250efc13899bcf80ad5a340d432a0b9449affda5c8fa090f008e01873aae7d5fbc7972451542c5c29cf9cfdf23db736c8a7112536b1b626caa63f3e4117044cdeab612fff8d8c194d19174f56ce761f6587349c48fab30390f231d209461ee7e18007d10d83ea5aacf199f3b00003259747b1d03274d3c3670595604bb4482d345ffe31d3e88c70da16649a2677bfbdbf618de1d651a53d573aada2eee5c01335ce5519a6d18a70f7ff0b1e66bacc162c49f7f29b9d3fe2c7dd85b6b355c9f9141f02baf08d2be87c36f6d2e1b2e90dfcd100886e306b360df0ecb146a6aa5ac5ad05b63a219ea65885894a386248254348ada17908d776f9b438306ad28b208f80d6b9b265500aead945134b9d388ed5d6205edf07c5d8bbfe0916d0943750150e09c76359d24e3317517ea489fd8a501dd93f159f07d19d00e86d952fbdba2db771910143df346b30a30fba908a1abe5349c3f241958f428dece7ad9a91cb42035c43573b87b26c2ab216cb4c21799f6b3d81acd300ff50edd6fe7868b9ba6c160db3418565ada027b46b63e5d4f3411284fde585ed3673b424ec1cdea678e4a43c262991c3c9b988351d6e0a10af1c959cf21b7a288f2e4d7b3b2c11b400b5e036df71fa993b72ce48d0d8598fe4ef1ce70a970f89b55cf4f07906a479bc84a08bf6ab25221de37afebbc47ea0b38b87be128737d7d43cc84d336cc6ffe1677bd802910a2084751f30398dd0ed09589b2befd2f3b40fbc013318c822fa2faec2323fcc52b43161f47aefc557e92df3050dc5f8b1c5a4b2f8bd7b2ba7aaca79dcfa362fbe7781a2e261683a4a862d5f83e34845a8fcf8a1aa73cd521e87cbeb71f20b20698cc34bee3b8628b1a3784596c", + "08b3fbd73d157e79ea9f61665d19867dcb8c1598c1d37b793606936d8aecd992a0d46addeae857d488b83be5d1c1639d4d78350e4cb08782b61bef4107c9d3a79d3d85", + "a56f38b4bbe83b3d9e562cdf5ef5b30593f08a1a166676c4fb0d5861654e640b", + "8726dc5cae9497936658f603", + "88420357d1ad70e7c7bfd55b3cfd4bf06cd4e9b4ed5cba681045199a06985956d35fe86b28b9a4599964930d05d230a23c55a6a152f67082a453fc31f68489df05c553f9ae5cdb3f611445db384d79af865e52440a876fc4153d896b7a2318dbc2a4495ecdbb2e9dc68022326d35289e82aa55197aedc266dd91ba3018c7b474ba22b4e773773f3e9890ea84bc16a6b235e4bb69e785c40c1adc15b0e0ef03aa147b0d14e62341e27398b84a53f72c9199cc1c94cbcad2bd31aa69c96b06d01775b8c0f80278a43f526664bdd430164863c9c9140ad87798a5b8f38dfe90d37f54d1137709d5311136b728e6c799da244294daa4c8b44bfb0acc603a16c088a081129a0d2cff55ce1c4ccb486fa0ecc3098ef2196f47c49f9d253112bd5746fd99df5d2be577617dc2519c0ad04ee49ee1d7be3d50492017108fffc9a414ea227af39fe49fb2c895fcf00d927bf4a2d78c466fd44df4768e6775d39fa5c834b60979ca27ee9f00faf37a090838f56275a894ddadd265a8d2de74265e4d8d286639ce8f01eccd4f551cf6b4429eae3f08902b6ce6ef422cf91ce8946d9403fe8064784895b62a7f5df76ea294132c59da6b9f53d4195c1e9000bec499c14cf8bad460aebb024a76ac50616f0dcda71c0f56dd3239b11764f3ed6ed06c049b2ad673e4beea391dbb854fde1f01b1900858b9809259f3906b34f95a1c6ce8d24fdf0cf7c2ab7bde2202a7f1482baa6e51caaccef9f541c377da620bfbc63955cae0e6644ec8ed6878f704f1dea30d6b50d4291892bad19b0234582d50c6cc0b4165322cff24a9dc2ce1be35be0fdb3bb7abb777ff0b2f4cf16277388af5a89220d59f1f45ee9cc2a0fd7af9aa8e9e8d548fd65be4e47e7f8ef58f7701f93a42e7ff78f70e807fb63513157fcba96ad9731b2e8f80da85ef407d5c368ad16f0657620bfc122ba1b10d7ac2bf46d8133a9c6fec1fe04882f3d5765da8f825e1984a4313f72b67d806ed45c000dd3ddedd524d474b9b5788547d0712e8edb4c6c586d0cdf8f2384f1e093a7f6dffea6e79df9cb9398f5d0b9a7cbd63d489430fbfa397a0d03ef916b7702f33a54ebab84a7055b7ec6179b0ab7722f03e126ed343b1cdf2af3763df7e3a070162535514b01ad86c6cb051859aba1cc4766b12c8cd57b73fdd3c65af6961c45395aa7b885dd59e115db885f644e1c94bfa26b3804f767601c86e2c7dcecd4daa59955e6a40991a4b4701e63fc82b46dc0ccf59af40a8583171375551c868436ede535705f2e6380c5899cddfcaf9e94314794bab98846cd5ba9e9afbdbe1ea7fec5e22e7b2aae59fa598f4d6c0cc6f936a616e11bf01a2acc891cbfa2bc53c511a8a3a3da2e3aa5907d123ab2a4a3c0009fdb5235a3c33718fe4c504e1539abac6370e06150c402b5fc2f8c32608db4ce2eca9d1e4b96371ee195f6cd632f5b972385f9d5d357b87c78cb4e2c27aa9851534de14de923543f5fd9d55e34d6e8b7e1f3f2735df80046de01f79d0321066f9bbd76299c7386d285f7bf4ac15e033e89a040710c90f87aacc09fb8159f93c8b4860247eef079e32d05707e88aac734a2eadaa853f528d9986e0af3435b5c5f44ddfdab9b0c9ab3eea97676e920f80d1794740067f9b229fb018c804e595aa997533a5e967cb79ee58eea18995a90ac08333f1c69600b17ef4f454f540dbfa8b502457761bc4daa876d9053ae1f55001b6916ce559dc6268d01841255990e56614e6f4ee4ce04472dff0657360d75da4e83a71c852a2585110e53137e91bd89d64d99b5614ab2a5691c876f15d9931b092fc6729c0732db5cc40f966fe440ff99d7d05b24a872f552c27fb0cf2af443340b153214b407fb9ca3750d9c157aa75763b0b7600959663889d00f392d6ebc12835bd2f03ad802a21d0228f1d2e9731d0f0051eb2d5369ab790d1134c38e28d2bc2d5d57d6d897244742c176559961a1e40c84ee5c8225c8d72b92352a011e3785c262aac115cafccc2fe1b5e81a677a0220f207ebadd786b93f58e40eb6ade68ddda5b66c5f0f6b4b95cdb8241156110ba3303beb79acbd54423315768bb43b4fe8c4a465e50c4e63bce272c4d731ea4c797e14b2de31ce4264e2479179b906f67af4a23c56e817abafedc2c7a65aa45f0c89fcd0baba60561a8d013e2d5e0bdf9fbcc1346d3edb20e6e9f9c410982e1ac43039ad8fd0ebd453a6788376951fc20374b59946a6803498929d9fdf2e0f5e58c441329a79d1232e957b3a9ed17231c663b4819dcb6b4e33d205edaeb7d7ec466930bd84a064b40aa67fd76f6ca005408062b45b5aed6f8161836c7160a8c8313dc9aa1c6d42c2c16972a1065e41aea9c58db7916e1670cb42a8b54d85498561b4401761506860b19b446655f8988101fb4c45067e30edc3f00df8d88ee34111dd6626d605d993ff207be09704fd8dc242ce514bae77cecd20f10d4a38435a3f5e545882fdc224586a04ca6a162e118d23716240fa67892b78faf98a17916471f7f121fb9f85497a0b34bf5aaa4ee1ed8a4681bec55d1b4973d4368600115bea70f20a37c9e942b87f6cd1e2ab70fd401e703e3c8334c75fc338508e06d6370779578fbe737a75954b4701bfd92028ec32d3d7ae606caaf9f049d9774f70efa707c1c1174d9fcb5b0a0ae2a961c6f58e48ba82c2db14ebbbdc24288e42879f547b855c86dea9a3b9877e4b105515bd78cc43465", + }, + { + "bf7884fab52251e202afd7b5b46aa53f85bca5fb80a009d8016e276579e401385d853312a884f4aa33cc5fe7360426bbc0ccb7416cc0196e2e40d3a825d5e0825a1394029789acca550bb28b10d847d0a4fe1111be2b7fec6b5294902775128288a784203031ea853c9c104c75571d19552e2a1359a900c5fc9455230968a5920f2ab23f5b9cc49739d4e4ae2c01c7812ff295899b954e9729a3bb330b60c51a8a7759e5131d7d4cf261fa1e62c29f91b4341a4fc968e7f30ca2261702eb328d628b7275a9efc29b50bcb9b27e5844328d5e8256c76949d30b6fea0d5a1c9abca80d3251fcf4ec4db0a5ff2ffd43618aa2e3e1694c2a3c579a2665f443ffb1eb0ce33c09d7285687cd55b6ca9918553bfb36a44860e09ffa0604ef4904a034108370195a986fe165c598305eb08599abbb3df31b1d93162397056d9ba5a1ac2812c582aa356310fafb4058abc5f157802e4a9b4bddb16e75b6db105b7dbc838f820539b76949b1648909104efa67ce28b16a738f1be104d2bd142d3ad1b1c953b6020a1f4cbb84d5c49424befbf2e6ac5c593b783a3f4af75477312528fa78dffd82fe493d821e011642bf1135a5be91fef909383953308dcb61b2f35c2ad259acd1a2e953c0ea6a03a97b384e39c94c33d3846c26b4f9f116abe572d5b7cb81886d6adc2d544630fdc1684bfb32972e051b9a2bd0931de63e025813b923944290fe1ebd5264ee4f25569a2088314e8d4ce8b91c7bd602b9d85acc917d60d30d5ef1cbb055b9ff7b0f999b98caea2517d2de334eb436078c90d41e0e34f11b93e3e643389f43b3afdc4f47a7396cbe0b4bf159ff27618cb835aac6699be1fc7ec840b767836a165fb95d06f2cac4fe15b65714ddb8a095ed4a5b57e63d536405931b6c168683763fe07c32aa4130bff787d4d440746a2dbfc584a502d809076b257482abf7f8ead7741c82b54c41acd41581148aeb4149b0c6eeb39ef7ba091c2e8bc72583b2fdf8ce7fad1bc05aefd6db0360c644a9760a9729a88ee4b2ab123d7238c12435b9f3b4660e74c0fd4a9b00aa614453d84fea01f779e5a924f8e79630a8bb6561ae19c7bc8d88b9d823b98285fdd65d4cc05e443944ed5d3cd4f46c7cafd1dd5deaa519772dd24f508bd2d588a832d5689119a2d506ff11dbf37d57a24e35ff38da18af07eaff5775d12dfe795fd3e1f0ec83c5f283d6cd76532519a15a18d93431893b1b88929159bf8fd21f62b30f4e37d540baab0e30ff3349a08d627ac19303fcae8b8e3fe44eceb66d30697c7ea051bf5afdcd8bfc00d49c8d36164ec9194a78a4d8b78826863e93b6a810354861f4a35ec12e5ac102f74e390d9c0227e67acbbe3254e5b892786e3a88a383ea9726485854a319569a678fa70392cee90c9aa83eee8df6800565bb8e083e78a064c0f8b863120efd799ea57d3073663c0d0e7bfb9b717ca1d6372fdf75a77fd9677791cb899fc8033d6d806de1e6aaeef525ea909666316d9d604c1207cbeb6f427c3acc1b02cf59704fc65135703f2a9529bb2c8fec992c4de53e54b029c3f2a5fdbec1008d1a70dce0c11251003ce62af712b9e4abe631902485404e4933f346f1b4467fceb65baf776d0078aae6a2a1f95b85a441b635663c75b485a8a7cb9a5c12192ac874d940e2d9b88cc05a2db9b5b35df769925da508112ab0b8f64a1408633fd0d81810baf2c846b222736bd826c8cf905b2c35633d6013f5565e0a5ec1492e99613f53530799052a0d70023339d1c394fdf9f73a590a2faf68390d2a823bc3e47a173782b03dacbdadaef1e67fb47a7cad71b6067ce5b5e41fc20ea1fed28578e9bdfa99faa657a754488ed3fc084faa7a05b0f6eb66da0a28e9ab26bb319fa4ee993de840948f94dc1d68d926b783a0bd3396a89970b2c2595de8148e87b87c21f664618af4f567115d403715c3d7d2f66d7a90de2c5237893a4c18c20494e3faf94485ed39ecfe972c36acef0d7ee57bf8755924c790ad02dcc5c4e15aa7db53eb6040244c3ebb7874676782e54dfdddc256018ae6af8cc37450a4cef77f21e2e061062ca0c2a514290c960f5993ec1ce9eea6d09d3293118237e079b6015b966361c3032368174d74ae5cce4148ea2b3690fbd3c28ee544c5c5bd7bc618122979d52c9d3d44eab1f2467f338e695ec5f95998bbe77dffac42bc2809d43a324e0f5feb4ca3d5fd951b7dc8a9e6276ee080079b68849b14c7573cd02c76027a856165d1043acf99554c62fe32896d120974ae71f84986bfa0c28fcc399246bef3ab90f8e55f913aabf339dd7ca6f0861a9ef712e77dd28740615479f39a37e746c7df2b267066d1649fafe0459f665f3d5e7124db43ab1ba5ff94989acc7fe0935e0bbacf718b33103a1355d97ab416d8263ab369e6cf0ee563a77f2f265fc3856b7d54dc0887ed439a421c14f733ec1d6da086536f9539d23cb8026218c5e783423b5f4ac24c8d5d8faa7186dd5ea34afe299e6dbed73ffa8f415da706442a48808a9342d6209f65ca11eba76f8ef26db890da76671971f65bce9e6112c8aa92523dd5295d748e28857acff408c161c0513b37b855a8afb0764d118815bb1b68f8f09156641f7eea994ddea20f4062607b9919d041c880b71592402a4d5b92464b239caf431a99dc67787e76b8e1d7337af004bcb88473cd16b3f7640e8aaa59ad4609f060a2cdc71a4b3ed22c1506a7050a63bd8ed68aa58a8109980bb3f2b9f9fba9599d7620b8c25e8aee739095789af83529cfbfce5941d7f14c8ae30583deafdc7c25fc34e75bbed6ce4f6b47e9647c12333ce08c7db77dc94161cfc43f7ea0bba39def8bf8ae61c6fdcc0de6308af963c6d9ef43916d0cd2cedb970d5937c9fdd4b888cc66e99363b5a04ae62a4349f01c3933ada64080741b1781754e4a722303faef69e382cd9823177e4d5ac83e76017124a7b1a41bcdbb9c4209e7b42c", + "eaae1c53919e2029c137a80f91704d0871be2c1870d0333d8bcf7f94", + "4c434cddb399e52457113cc7e16f046c3f8301f5b6c296979f8a091a9ea557ea", + "b633c1a0e1ddf4727b149b3d", + "f1de487001a580cee6edadb1ef6b700c861a70c6ef16274447b8c61bb10d2d1efbf104d5f7d7172c6a5cf9c06d886165a2919ee9418e2e8f803d47832dae5ef232ee300d1f973a6298c22d777a1b16264353cc731a7a683cfe31e0abc704460788c555c0c24f281b81d7761235a955c736f17f213a896b40a034609ca8456ec3cf5906d01121b7580ce19d89347b6a59c81add318df487b2442a7a8b5e30df78467abbf46bcd5ee5b994a39ca5bd8846caba6f02f4f1335b73d4e20be0b6ad85966f86d1bb857713ebf947ae936782f1f4929498bbd66bdd5ad6fa252364a5a6b46180e93b54cc321b3cf63cf23d55392475c6b8c8c9dc707924b55544151c7c55ae0bf391f793e52bed70829fcd32b2926600f65be0943d6a9a96547675426b0dca9cc7b0f5dbc9d5439d0281014c6c159d055d6bd89d67828ba7fd2a0570ba82996037f7dcce297fe6518331270f6fd5ee63d406cc5081472bc5f2298a9208dba9398ccf807ce9af982885897715b3c5742456f756d79c70434a9baf7b4b6664c9d9f5696c5256b74099e593f97a2d4a469cb3430d0c3eb06083398cabd58af598945a85c9235a3fdd9ba7686e54d0de9afb594b1bb030be8e6bb839f6b45699dbcd2f771db64b0c62bbf6c8672fb412d60c00b3d87f82ffff6512e8308877573323c5a2d6a216ce3e2ce07c9763835ae59d44d7958fd873e3995b62b1b347e489ce86e023ae27a6cb03ddec27a38fb233499a714acd89232a91d38abce30299f38f437f7a46df647f2be862c1e7bcc1e4263c2147b13ee5b345b7fcb973f3ac71db8bc12309f67ddb62659bd73fbd20664eadcd23a79233386aeec1a6fcc8c592053954ee53826cb9b6bba22400648887311cdfa5414c96d5956fe193a3729be1434d923a3f9849f6c419f77ea05fb72f3c4f75ccec03b7f7aef8c8e55c8c5480ee505ae1a7594e6a911dfbc39dbb0ae8656f5972eb644c64203a920fe0078f3d050cc5666ed9747c23df7853d6913005d0156e741a5ead3bb1b22e5bd802c303a73a961f0b60d0fa698041c22577b44eba5d6071de4b545d9f5de24944c151de6a189bfdc223e0507c74ff929f06a2e7497e8c63073294b4aba110a006a6e9510a9617405d9ee711831e085940006761822672549d1d1c70e50002c2227f6f304b9a7f11dc05751be2dfd297087044d2e20ecfa0c091478d62c1bf5f0aacd25bb0384853762a51144b77d30418b633c4c10a6eda7b2eac46905641da0b685f85349749a91cdbaa4027fc50eb97a7dea9e8cbb5b5f386ace0363803ba579cd16ef80dc40ba1044b4ecd0e81e382635d7855e2341b18e0ca705ff46990282fe25093a248ca04a1fff64ebee25065350ea4b9e5990da4dd2e28688ab08b6d6fcb54d70f6d74fd7e5e05d21c12f5b140839aa966aea9ee094a923ee5ec704b5b709ff009c20ed89a75468c48b505d07c7a5ba1ad54ed610886c9d84468eaa598c71b017578404c909dbca431703e0cb1cfb975a696a1677bc015a75db007eccdcb21b9e5e119c48f148c2cffcf29e245e52156ba5ba0a8b0031570e4cbe7b3ac4646353594f0c4a9424c9d97845c5e1a4b4016df9be8df3013e5269484cf32258849afbdd733189ea11783f0f64d3aba9b4f48818011e868cc03ecaa44ff0ab83ed12981a6df445294ff672f3a16d6e0d19b90007d4646e967e0fb1763b3c879f548e1103a75c94f3a7f72be78555eafc086c1c58d1761aac60b843704f234c55b951a1303a12705f2120f784c2bc1494432a94c835d908f0edd5cbb169afd2d38087ca5bc5e5df9c3bd970dd2da4fb2a00933538148ebf669a20b5beef0402e53dbfc3a0f289b33b41ca27eb2f036a22f0d02e0617bd01e8c74be264515c9b46b9ab6fc67403a35837844580794088a9d3c14ad9309435daa0396f48017be524856ab6c191350529962ead64bab33171a01bb3c144b23bed406cb05102c693ce5df36eb541c47e871acf56f2b47de687eb9b3511ae83d06b1f69fbcef3225c3469c304741437fcd0ff4ae3484c117f51d24b6ae1363beb7d85d9b61e01e3dee901b90f2d3272eedb384ddb4d3b9594b9c0926595e500f8ce2e5cd407bd7a4e2c8e6f4315bf693e8c961ba5b8a6c7f5030c68a6b995e9d3f9eaee9eebc9d679eaf72a5f1cb6b2fc66edc7dffa2370dd778ea7ff446121999afba7bb35ceabf626c6269bc466d65f7f812c663bcb2fd87d3e09ab7d71e727f66d20ec48a5d2bf0aaf0aca05d1546d6e974f90df85c1393e3d45731f71ec7b5cb6cfb4e5c29976ead6944a99df2045056e198b19905362d4e9b765adb65eb089233a8b3777352665489c9456cceed593c6590d9f3cc4024d0bb92e1a0dc619bf8ae65be77456c18f8171e4d2d846073cf5c57ba93adbc0db9799e3d98934aa6899372acfa4d7d2ea32e20164b79c71d7bd33c94f9a781a25cbcafe563462eeacaec0e8d9d6c0199de85558a3a05d1ee3483351915d8a4e65ca0ab129a2386a9e26aff9b912c588babbcf25f8c467145061b9b8fbbff19d8c6ded8527d457be7c926c8f490bbcd627b3002044b7729a52e94147f95772591616f6074047e758597f410b3100f9efafaa4137dedfd0edfa85b0927804f0b4fcea1a174622116222004d42b36c2c73d04781f2f49d080f351e57154a3980005bcfb0ea34288e2fafec5bfd01e1f7901b3efc71ae58bf8df4cd7c045856103b77bd78073f0174aaaef4a3c0e8b5b46dc92db55478f012dc1b7d513e215e735573257f105d2390b5366f49b61809033c13ed4e1ebe19ab89313c947f2585f0788a0c5de90b41ad0dbbfc604a0d414d0e5390a0f3c9616cfce4097e38e05888b8bc6e55e40368bacdba7e5b76f4bd8fe619746155c30b38807a1ad325b00ecc3dbcf23014e79f1c39af7cdd0dc7ea58ce733e6611b7eae069deb047aeadfc21960e614db19d2e7e0905a9873268b9a24f856c28059321a742cd6cb3d1527", + }, + { + "c89c3cadc094bffd5ba06c600dabe30ea19ad037316fc13b895fe0e14ac8841264c1bf25557e22b01f8e102c3af43adb8e0a12bf79d3fa0232dae37ca3688e07294e2c7ecc4e2eebdd3f17173351f2c15b0480d4d77bd70955ba86f82214004b622cc92f7bf81a5837326f6a83612bdf65abb33c268a457c45cb7467e074b342a17c711c748c74abbee31541444020a9ecd4e5125e2a8ea3f6030bd677be18183a8a34af16a85ad48b7015cfb036789c0a5daf68883d0c7e401754b8d56cd00ff605be0cad19e03989f608392c81d636de859e66c2aae403c138bb96a58ba69b9064a83e7d8877067e7f40aa0016e0df9b7f455d292a60eb621b8107a727a3378c4b7509d3ec10526c50fc6c66dd4b015c915e85bbbf701ddaf2258119c8b9a5132eafe61bbf38870f35f375123f766ed0d4f38b9364a86e56cdef6f95a815a8d7c48ff283c77992fc6c070eab7d7c7b517006e5d4af532a7c429912ebaebac27249b4f5112d870d998e1c450b98c05d08c742dc769506f2d7a004c24ebf84c10838b619653e27ffcc4344d8db0435e4cb77c0410cc734e36738a6b5f72a7600632d19c86b40c737830b0f5f104443dbbb031dc7ca51ab318951e7817b5d81de8a9aa7f5db6e2d5e7a3cbd8a8100653c048204ced3af005d00e7de7b445f5acff901c4d46ff133e92ef073aff1d9ebf55befc32f9ec38c9eaa6a1aefc974bec2758297e474cacea2ba4151ab1a3ca0762c64a5ca273169d29b83c164f77f266c01bd5075871e17426068ed7aa58ef0d1f2959b19c604eb6187acc57e2becea2da93ba23159ba73b9226034c7ee2498e0ba34fa8038e5e2c092a73ebd9329ea3d648d6ebd47e1776941ab3130cfc91089fd0a0a36f0ecf68293343f275d2a64c1b7d27ffeb3f667f4a19824706235fa5f3f04952ff08bb183c0f1aa1d1b0edfd2e05ed093543788f5d0ac6532e15f912163275053b202d772f381900e906fe070cdb00421e78c16b7387be91adb7b3b3ea28b92548d69c780ea578e7ac66eeb931eefb4067bcabdb345a7cd2022085fc494f118215adfa2443630bffc9faa8fbd9943c3140d81c7532895734a9dd20e31c326531d06f5623c252139c4cbc882640c457819c63f6ceed4e03872b246a3766df69373ebf5af1116e8d5e1b15745bd9dbdd663fd4352d1238a43d5d1e74b3edddfb1c9d460daeb49afccfa0712b7a4cf8d07ccd0599ef3e4e1c9b5c814f3a6f3a46fc80449b34df87f47ff91fea3618cab2d5c04cb50e8ad199d752d901b21348ae939d39c86cc1bcecbadcc6f0e581a3bb51e070507b41ea4294b35456c69cf55a2a3f1296f0df73abac3a9c81cc303d1e20ad6e9bef48de83fc22dac2cfc01ce9ff3f70e00ee49bab2f282ceb6859f989075814e690e36a8d16354fd6056cbff49c30e49b1570363498531ff0ad0979a4518e9ae271f57f883abf5e301c0e24a83f09335479698911bca90269a28c0e040a98e67c9e55f4c91542f921511dd980270cd490766da22306b48ca9309aad3b2393b7b1e9ac7afeff64204081f9c0a8f6a5396d02eb9009901ca2c0a75ffbdae3a38ccd5007cc4f6bec8fedd64086cce5c039e8abc9e23bd694fc8de4e858c89bd585ebdd422b492eab26f4ebbdc1d17dfbba19b5ac458c31320a161a52dea638548205a6ad4ec54875ca34238c059177bfab2d5be0a98d12b3932d0661d33ec655446d0283224af8ec7f1c6874add03448fd8029a71d3c5aa06951123c9fd881d435845757df50444e6cacc31a8cf7537a778d1184b96c3512cd474f5d1fd1214555789d24c8d173358e36400b2d937595109729d9f35eecb0963c0da60d2eeb52a778876059fa95d820d5d34e7948d389dffd53d34c4083d27c917879b053cc57dc43c8263e5dfe5f33c19dad0a7126ea6e8abdbacb318d37c305a183596ddb25b1934beff13a4f24fbdcc2064de8e0bc639e672ecfe45692e9f8164365e1691784b4f775ef369aeb135ce15135c20da95064c810592ea33316b9767caaef842f948b9573b2205ec57d3026a2f2244c42991462e233061549cf9bc66a7b4a8a0fc61f73883fd24dad02644004989c4721a0aa03d3b0191d7fa4d3da102e541fe463936c9365ba30681e706ca70cb3c8ad5dcc710de59e7d8a6247aa809bba74ff4dd182a38bb31baa337841302c19ed89d65e87bbed05465f4ce0dfe89b44d7e9266a8ca21d984c41109d813ca76eb67dbd4e39aa437ff98050c968ec1e40c534ab51d6b8ea2309fab08b3757e9edc5972bff316f6f2affbff458ac0299613734b30dfdad20f797d172cf295cbcfee3d8ee25485d40380d3480a9372a1a6e5ecd7c4c6a9d34027ea6c197f37e86e757750c9fc24cc7cf814878b8628326c140930dbb2041bd9ee87f36ebfdbdc34522cfd4e50c9cb48dd52d4647a06d08e0f0069c104849bf30c8e61cb693dffbc69fc0ab9c5d502a227d606a1dcd630ebd799acdb1e47ce2ad52ff53f6cf4fbd5f0058fb5db915702675ea44334d42e0b6ddae78b22b5b5f7e5aa36519e31278e37b64312479b14aef9b8f12d8c1f39faf920851bd53b13bae5490c847b3312b2e956c430f1d8deea91cf171dee5017e7709d0346d81600bd5f0c41da3f548c28aa50589b293685ba059cd7f3edefdb5d8cdea364f4a42153b0632ef0b7ba18610b71fc34a781eead1dc5a00ab47b6840590ba44dafc6a16029cf50e089684194d93dc881beb62edb7ccee6304a4e71a35915f109db92690461b9e4ea21257ffb62477c20feaafc7a78e2aac2301b66893157920ce9fb114ab4f534d61bb3d17dfb4d9ef9f79a736f7c1d32ac3998356aefc876d8c38722787d564e980a1f15056cb3fe634d71d2c98e0475c79cab318b73a863362f85aeacdcfc44e61b5aeb870de9ea5b5abd24e8c19ab05e45e1e9b8894deeb9d29d65ae99aa94b5047f3c1168276cc2e491aba52b5b03703ced28c63a167f0cb3e4bb4d8e4f0292cf3ea4376510fa49a1a5efcc00f23c3cdf6402197b81262e66e17bf4307d87ffbc2b37213b316bddd65aa9d64ce6122c4a1545c5966bf4fc4c6ff17ded787ca9a3b3cadee435bbba8f6590dc4ba30895b84d5b4eb94f4b05be3c", + "82abb4ff5457b21f359754f151e456e2c0a185c8363d15918bcee0d6d49f12564ac655", + "b63b577e719494032062e3f63682098dcdcfe26cedea2a40893c847a331e4ce9", + "9f1d08be539f1244f0f69ad2", + "88dcdb0309f8c4a96ad5560f8210eda1f5afb31b85b7a8b15525777748967d4ed77c063f65d64ef19b31044f2adc690f5e457faa1abe2e127b38c626eaa94053c9ae1b6b4d0db1f02c8404b50f58210cc9fcc6fa4ecc615631da631031cd6253b4a13a3e88295ffdc775fd4bdf29655d9780dbe02b0a82aad4c4088e90b51f170909c0f98ff93ca3926067ec94be05841603db4f913b7025a9ee34b8d8bc629ed827a2a9857e0814d36b83cba21e670f8f94ceb4be5757e0b8782895b5d8605868e4f584b5bb6a5f3a94edd9b23fc2b6fa06914aec970c260fc370aa245ca68888c90c43eecb68474c9e45c53a7da055f5bfe39b56769fa56264dc8bf4c1616e30262bd501ff9fc5cd78f73ad89e093feba0393a11c6b2cbca765ba025c40dd0417dfa644fce96db5a0362235ad37a317145e7b5f3c7213c7fb3c393be57a1cb55035f06da1f0bf665653c5fe8a0f3ca67dbcbfc59852694d34819d0978cd09b508d103017168f6848258493be737cc24c2112f2afeabf41038bea1f74bc8656d9910b77d33cc691a0d9b12f7c518ecef93423cb4871949a518d2f06e5427823324275b97110f8f88b0d14788741e617f4b194e679a1627da50376a08d4f23b005c0446b46d4f534ed85e4692e7946ec818437089425ee30e47de995e8774b61003801de67939d9fed7bf0cdaf625798d0d0d04a61a2482217b890168e36f20cf1d6b81f9daf1a49a781567c4363ac2f3ebf0252d5adfbed17f98cc264ed2765aa279b7437410ee8b4cf42932e5055f4884deefd2a979ab1328f97cb750b3b7e4615b9c1c61659c90a5ff6d1c736e785587ec85040fb2c6decf789c2707974bfcbd0c7f699627b31e0762321d55bcc6acf1aabbd44abd7766d397bfbb68c424b311611d9eeb6598ca3126f569f688455da8d5ab86eb01f9c96186858c4b5e447aa2b9ca11aa5453f731beed4e09f95bb7376e200212e2f03551b8b09a19d6910f25898d692bc20bf6ed3ac9a0276db560de5c9e264f4db8fec6577042fbbd4510bb7070086508ac451a1fda26582c259412fbf1bd60cd5e921160c2604fde559b5ed4df52b805010b225f999450adadc6e108b70f169a3d8da6efbe1cce1c4908b004e928e3cdfdd0b4c5f742fd72a11c9585aa3517486201b6d9a98739b77970a88072750d29d005a291546f13b576b4249d71f04a9abf8f653ca206d98f738af2a1203bf0975f0a40138df054ee834ab73a3b1d7036567369a7ae15f808904e08adfc84b34a0e1356009d8a82e51c3e8f2170908179bfe47be8ad819cb12e85b6b76bba7c9b9398dfc00f550e32c171b4d5f2d9676063efee0b0b49660c10260ce052dd00addc3359e35c25dc33066d4b05bec7d93f71e0ad7d5ab83d844c7f33137894327f464260688ea4ce9847046e7dd0bfa48d4e15277a9586b4742daf0c5ecc59aceea6867068b03c20aad38d04a814472287d809a9285cd4dcdbf68f3f4ffb794701f4c265b2dff4aee55c9815938689162e08309df150538e60dccc03d495adcc560fb831444b922a6375845cef5dec56eff2910b5bde5f25f0e550ab5a13205de91d20896fe04a8ecc2c83d1371cf381424f8c43d2a5ced374878405f52bb92f4fa3c15d29ec151508488f9b4e42527921e245a8ee4b5d6ee95797f6ec4374d79acd7b467454a1d7eda05a8ae104534b23c46b27581abed6afc3ca555202dda94fc2b93501fe78867730a84f6f726dfd7364bc240b65d6c3022a04e09c89e36a809fbf244cc5522315110e9e33c8a4e1f1396e3e51fcdd53d9ae94fe7bf6c6ccef0ce02048a11441de3c25aa9787c577501977e486f8dfaa4c81e3183e648311148ce5cf3de56878847a9d14c0645777022c158670377dd9553eb63eb17e19ebb06202be8fd9bc2b24878cc86f9938e5996751ad9ca04b636497199f7f27dfa0f5ba2a01c3a491bec6dc5113d127f6aae38fa07ce7539a0c1817f7f0de0da538f4d85ffa394784a42eb50994e28530e3997e3345db28bafbb836fa463d34146d9f46d8d2b28b3954b9bc7f84046828e9b55e2fd663e562aa95caa97873f48f0a003d2251fb3ddbce0b6072fc17e0d3f99b655b8f41e8e6986ef7526544222e2d402489eabed4c219540605b9f5dd321ad902708601e85bc874c11efedd072aab7e10272c87b08b9457223de9fbc3abc2d1346656a524e9c67d79d4053c4257e886d6b430f5b7f57b2e5e92ae69273c1705a3074d5066def69fadea1af8fa9b3bf4890f9cda4b1833e5ed27f22bc4fe4cf452880c7b53320bc7cb748c0af6e7550ffa84e4714ec18d208131ae9e3edc6cd6fa2c60ab8ebc1ee56eafc01fbfba061e55014b9711eb58fdd01f8936d29dd081565de0b175b02989c5ff374e6f58c3383e9bc00d8a93903e6a221c7475e15aaef77594849af877f3807a76e03bdd54ff0b192bf34385d24d858d6f454810ee48141d73e3acf1aa3d19cd4c723a634cd8e25b4fb604c744e408dfd82961e46e8444f001d0991af24b3b6ec57ba41fb45122afc73ec6b25f501f1abd46181247945729337bf5083e5821968502a5a696043ee696c290095feac000957f968ac61ccb572ab2f37008830ab9a81d02456190af99873450b52df1888c3d8b6b13df65a9bb36a4b6d0538a0f179daebca2bed6f94b4670560fc5471c3770f2d004b6a138b8243068d754fd246e9881242638c6675f1611f237146f6e0f72ff2fba96f479fe0a662a81f40928f5400a0bbfb5ed07a87f457d5febdbdd6f323e2a59f749e6fc8a51d08b023734c762a91cc517401be57ffdf6a52b9174ea153abf2190ae2642955c3c02b4a15d72456c9d2f323de6fabbf56dfa3b566f1aa688c86b662bd34cf2511cc4a30621b6f1f1ac382bc1c4fa4c0d4d5a30ae90a5e54a9fb4afc1475e7c612eeb7f0e09e894c2004cd04126df9359d525d7f090e4b531916207c38c3512341c84218c86fc50061043ba1b89ddfb21cd756b391cb53e8c1cd55352be05efe562669e3986c022e30c79a97bdf087889a392e6da0d72cc7ea208aaf23408df23f3a9ea9bf9a935e49c9994a37a5dd0faf1267d5f7db47cf64ae1d3ec166466b2f882eb21698aa375cb50146c0e660e9bbb38d7bbc1c1c6d8333f7031d6a", + }, + { + "68ca38fccd585eb14f953358220027046c14ef965478d3d8f206f63fef4fe3571a1b53e774b298c347cc1b69cc426d39575ccfabd5a284c7a87a0698cae9efe40543cb79f5643c3c3057a5fc991235f06f059c44a7200b509a12e864fbd748001a14790f78b54ba80cf0a4a603da9672df32b68652c1d6edd3be51cf969acfb0ae49c026fe0bce0bfc72b1ff4c47712b7a27b2cce888b9bc470b8bdda55a8d53a34d79a25947ad55b95e5406a5c5311fece3ecd46ca590b3b01b9055761da8196b21bbc468681922c66d286c32598b1e3d77f2a91d835ccd9eec231409cb2e74ede9385552517718be9f84f0f9100e368701dfa4843b7222279537306065a54d4edda3a02f1ab9edba3ddeb34dece9d5edc8797103eb942a80cb5ae130ff2e7eddd11f0cecd8f9a615d75963c44238b10ab1230d9db7371d8291feb2912d306efe4f7aea2773903d4be9a00f2bd8c03589e342269a79441c0b42ce9c6fff0a6e4e845876f7e9b342d25351fe2b1233b4f576db90ef1facfa617b96d17aa03fc824973e1c80f15e5344b0516fc28424b7faff47ea1ef4e47f6f7b50e91b8fb14027f05ca7e1bafa266a4b952cd0b9e4cab82bb4d61f99568e14a6772f36296f5d19cb04fa86ff20f04ab61d1a6f01e5282c99fe4c3254da46fb5276317be58e94b1928e3791af27dc6544f6d445dbfc7275fbbea74f98ee4aea647b654909f9fa9c88312d3759099c9d0070e3db6d55506813f8b7abe602964a7dfb9387f58e237dbf50b4185a50b65ac099352dee8695017e4dac644f42aecc3e415333cf76b08fc764a721b45d7b74f6b0a2e43637e5b4849218d3d4c6a01208f345d76af56631590e520d6bcd82627d2446b45b2c68e0be81b3924753a54f47ea27b1e08de2399b34470701c9697eedaf3248db9b28991cdc2c632fd1b376bbda279b6709d5033d1c0a3ee573bdd222ef1afe8a4397a61fc30a4e94bdc55097ecebfef6c00133dc0b72c17e2f93a11eae9fa9f1364f10fa595e8e1623dead10caac068aad3967b9ab2837dabcd8f96a77a25baef16ba84bc93661ed150ffddfbb0369683cd021e8f959c2b531bb1fa95d7a574fe5ff9aae35fb9b4a0a9829c59b932ed8634fc05ca88211da3e30839baadaea8fd9843e0e80d9598a7282500d157ee579cda5d57628e7506617d301c2adec5186708f94f069ed7bdb70cbe88549cefe1673d48c9bbbdc01d2af03945cefe6e25f757750de64cbb9d496a25adf7058f5e32c827fe75e80ba0e834e6a72344dd2aac4228828ed42fd83e4576254af5737dcd9b6c338377d46baccb02d00fdffaac12133ea0e75e791593ef3aded4ae4c9249b8d5cd20aa28cd652b9d750b88111d9b4fbe729e27882206b2f0eb614d7daaf6436816fd80d452ac71c7a7f9e8c595287407c6ab9fe8a242e98da4270b4f1d4ea7243c27f89ed46a567c643f31f967b5f12e518106f3d3e08178078cc714cb6e39079631966a9becd6f02c18e983ceeaa2106ba9043f9985b791027eb5dddceed563106bcdbc48a4ac64bd95e87c708a8cdc33811bcd16c35e193203e70ef2bc7203183fbf60d46bc581f1bdfe62387b3e6c0c4a29130d872c3f8b134e7dcfb080e7e03048c49c0e468dbc44eff4b02e50bc6889cf7600fba58c0ee409ce948aa684baef4956fd8fd4a9c4c49e84e2ff314b7900b179fc66f5fb4affb9ef7a6064354fad8c3d2d50e6f2157576f864a843dda8f547955c4d80a73d4a86b7aaeaecea886927a5ba0e97df740ec7e8b70bb650010df55d4b75f478b07b205b560d45de666d84206c1bffd02ab7b8d1c37f21c47d1711b89d16214d8151a8e75eeeb5c54c39e5a855d578708d314240a064051d8b26c6183ce755be38fe9597dd5b5d198532b1db083a4b856b8dd60bf1db197cf1df852eb6daecffd97287a6cdd4c05307722e0fac798507f75b03e9361d5627ecdb56a3b633938fa61b2673efe6c6e768e4e7055e6c1d55c7113efd3e95151b606bbf169f4296455dccb93da370150c54fc11b3682f092f30381c6ecd218a3d9d39442c8bea61d9a71b174a8b2c56e028689380879cafb7c4bc2691dda0cf6ada039755edf93f851446df9f63267f8b8f030c069fabbe6457d4f63575b5905fb927a5a720d52c351bfbc48f12440a91471697e6b2564b1a2b314fa0e6dff090079637287b635d875f120671561102ad27aa83d9f0cee41bf023bcd703ad670b43ae23bf01713650834cc1e95dd486757f0a4f6fc9337bb95738805ad5e756198579c886eb0ee77e4ba957997dde0eecd84e4c9171c84ad8f0cb23c6a289e037f3a8beeea7965ce34fa47cbd727baa4ac9e6dc3baf17049fd2386674b246aca5ef6b8496f1d17a3175f6fee86299232c7fff682f066cbed895155d475bf9fd4b5571d257534c88c93377b1a600d4c280d42aafda975eb32c740073cffa610b5fd2dda7262a2fff5da7a0f3a875c62949e0c9247827d7a49bd8185bc27967124c34b9725ee961bc8102a029786652c2571be6cf33be63cf867c2b48e5826b31b714a415fe05c27f0862a870d8fb33200719ef4ac8530a4ecf2597b4a7f2e66f078a7505803774889a1cf963083c831f46725a1ec5545d8489e53921d81f80ef99f5e51a2d5992c7769c2a7ec8bd8e0f2fd81de53c7b69b650a2d838b269185c5efd668c470943bd956e3c5e1bba5d3b927b10cee68a75372d4d6fdfa6782c05659281bc9bc56a2123967f4f50cc7ae3379ba21e1617553354b5030b3d3f0092c1824f5d47b97e6b4fedaa90aa2573e1b115ffc72d44fa8209fd8d372c8dc9ee00193b47c2a9a302875da331731713243d02eb5a57d5dc51c35988ffd742ddd75c191f1eb2c2214a1fc47b82db8ea708818262d9583f2b1b98a40b6ff6e94742f25661a51882ef28475aab12d9422b6ac48e341cbd6f38460333b5fa1cfd4d0f43aeb46c21938468fe3f7bc771972246156652d2c58b18c8cecec2dbbc0feb0fae9f6bc022e029111f94e8913c0ad741612a1426b53cff73fbb24fb7b22ab750ba1310ecf339fe12ced6a3fae17b4c429550794a8d68be891b0e30cd28e81de2fb2ecfee58bdf11794951276005eb8a5af21e03c8aaeb595ace652c5ce60a8b98f6897d82698ffbb2e02213e50d9d3f00bb42c8652d22bffb87ec576ef6e206ed6c846fd5136a87f38c9ad899371799f35a6258878418830b04da79fabd80e7290456fe17c0850a4c20e2e657f97f4a53e1a3db65bb5e71bf38eab9f56aa11e6ef71c85b8a28f04c271", + "ea196b6a64be4b0799b1c2f72281300c3a2577db44e5d3606b8b02fa8fc46c7aded7e442", + "7c86a2c06b7520d60023d18fe73d09c514ed07a91d50d8fd5bff00e7550faed1", + "952f492fe00b26028c560fc6", + "b3f3294815ce461c8843172efe93f73a8254e58a0e71953e35c15aa89a7bd9dfee967853dcbfba73d3b87fa60449cbcabf13b1206d0cb27d2c3fedcfa695b6d41efda37bb6db35449bd470a23787619ee48f981d3f0b1c8e121725b2289b6d67858a4f9ab41683bdaec8a913ca2cc292a9640efe50fb85a1d1f7b286f45d4448f85b3242f45ab44e3281d759db24dfabbae4259f127d6546ecb914d7e93e2c19230c67fba8a6cba6069023ff7ea3d8a170289c2b4391bb97a7b899228d032b36186dfbb29ae8f0e6c06d753f4c6b21982d49ee682bef50a5c2c8434510c5fa2b9c0349592f33f8d7ad6f7243d42b292aee6d210c61e3f898875b91a17a89148275031b74cb34e628d7b701775dbfcf87c79ab279a73dad14d8eed365eb9f29a007b7d2ccc07ceb8cdcdaece67fa0166e135c9a4b939426882eeca98ab887ed2e4888bbebd5afc9f2da3e9162527262b0fa85903246bc8b80df3060c890ebaa516781a2b2a138b98001287e12a9c68471912dd297bc0beadccdc31a27b7c726baf31510cd355a28e4ef786b30084af66ef135909795aa73814cbbc6552270d5e11d46e9497ba30d6d8cecf343d16e7e3357bc9bbfbc7c1dcaa5fafd8a9b07056129da02e6228886463474c5af1d670bc14cf2868b816cc71578ad807a37477341c8192bfc2e8b1f7bfd58827e041f70384f92bb4c6acc415dde5099a1c2b27b709f9e53d1dab07c87a042ca4af7a2a6ee57b37bf2bb42259d372ecfeaf1dc55ac3a9f211f16fef3b2d5f11dc19fd1f425c14779580b2501ec6e0a84220e7e12baf9e0fee3e8cf499a7fba6721a746f598f04ee8ab4df31fb8fa5ce2d2419d5551155c009f2780cdd225ec2c19f94fb9c8b785ad4574b4da766eabfa696a1994e64a2518d1bcade6390cc683a6e80cf8b163c3e58cfa1134ee743079347f08a89c81478668df32ce9cdd7b853db5cf7af13436f3bbb11bcfa8f6b6d727a1df84f99fb3a5c248b8fd5baf669b68fd9af45298030f3251bf0351fa9b58b0b9fba53ecfd838300790ebd689744c1b7b333fbed76c8fb96fc669ecc6695ff5bf8379dd2a3c270af858cc60894be8922d69fb9707bd2a7825f2eec4a5056e5e91714f4dcfa86974259fcbfd5f20d55923a0a9936fb20e5ae9670e2019336e15f530c0be449fe355a7a02c0938d60720d5b8f4f59d2e4213ad5251c6058312b43d47c44ffc8946a98797f5ace279d3e126da63633c0eff1c412febdd47817aaee466c639e43637c1e179f606780ab490d3f0b3c2d79709f1262305fc87c02f68da2dc32f8c544e7b358c3a5d2c27986a19d13fe736c60a3524e94caa55e853eedeece985d16bfa6c487bed6583436cf82077fcdcf90a05f49db50588f46550f7a0c3a1cfca902d66d25dba8d2c53bb5557cc1d87c8a407898b3c30c4f0852df92d839859c191228d0a47324ea9ec2e0ae84513cbe4ff4aff85e77b8587f1044bcb9775099ebc2f28fbcd1cad58a8ce1f072f2228f559fbfdd8405d86f8262c27c3d95e01016b343c6a4e59dec81b59bb6e3c6109a4cffffa85e9752ed2149b5624417c0dfd1a27bd2630bf59814f15820c43bfa317be59ef6f433c95e8be154a8ae94765bcedadebb717f0d8c24e01e1952bd104ba9620f067554ae0faeb78f13c622c45d97b2b5774a3e30cb07f2cf0e8b19d1266d8a8861f3772305e24ec5c9cb714806c7d705a3bed6385f8be4e12562e17ec3df01afb4ef6f7427c48a1bc0e64fc65eb1c3d3ff2d6687e4c275a019f5ab5c63bbe47e3680fb1802d5835c4d494f0f394de1ae47f81eef005127d0971c4589c456ae6a69855f35635c28b590c1b93f155fabcab59b6c7cd8ea1c4ed1f67093aa782c54329cdcf9bf84a40400de707b894587d6e08cf7fd72fa45b6709a26e97ff5ec1269b8042358f872a79e8c2db1c7ebffac014d6b6f71b0c1c1945ddedaf5b6911668059b61b55eea4737aa307c829309c9ea548fba2bede023849bd61b5a467cd1ab1c61205ce64301e2531e5d58d03c74ecdafe1f5b74627be8716cad0d0a0be60984c9f9dfeae24a6c4949170ce2f589326e0a76c447a578ea3a5e4bd9f18884f18843eb1a78aa2fae06a7569a97551b227c34d429c8e1c8c5417ced93c30dcc607cb32a365d87328aaecb4ce57ab8e74f0d9099e267cfb747a3bca9f76b5f6dfb543bc4b5c06c3646062ec14f511058eb2939601913f8a0f1785249cb72b0bb1c12a9508b23caf490537eec53f614f3e06592eb61f75c1cecfa514cf7b500b0375095d5db74556220131390b77d0db72711c0c7229a5769b1d2b3f5105f3a4370beb1cacbd93ce32f89f1fc833c7949211dd204616c013a3399a22f5325f1a00008f4c8ee7dc5bd7476848721fef843123a6213cb0c0b6ae84233ed01a77a115d06e08990b8e60cfa4f41dbc9505cfae76463278b6c6b5ac7c3b83284caaba4a6a1d739c392528ff5b06bc3b82e98060e3001279a44aabaacc661fb14e7581d1235940cbe067c6b386da09454e0467c785ed0b65d41ff4cf36ba5f63d3ff2b45c11c6c22d3ea8ebbf1d52d770e0ebf2ba0c67c7d3641c145cab474a88119335990137fa82a340c2cc8c453752a3aa801127a47aeefe66d1af1a26ee1cd0e6d935bd548f6ce33a9c204be02ba08f9fa03c685665375db7c0c656ddf3e441ddd96b0d2018beff5086cc63339f26bc8332a5e6a1422bfedb69187a3443c23b630a28b02f8075faf3ff2fbeef6cdf02ba4af47a765003de2254b69f487bb5d038759a33ce6885611198b81b0b6fc5d7a531a7a90dbc3556aa758db1657698cb3698b8207b1c1b589efe5d52790667ac483dde9543953c6392d5eb8afdafa205d325e314f810e9c7722cbf5bb76fd6502733149bf21c60717ff5bc366b85ee9f206bb1f330ea72f61a9766090eabde747b1eb9c046cc8713d5a4f8d4b7dcd7c61f2496c5b467608cd9260382b8f11b04c318a5ebb6411a4c7fa060e08c295c6062ac644bd3d10bcbfcfe2e3748eba66f65d904ff21147faa8475f508f21238d42f62b697249b9fceb905127f7684c8130cb8663f09cd25ea038078e1980237389337d1446c3a77bce41b37b50b9c3a020526e7b7b3bef370cd7af71b225700627060eb65693899d277ed130ec5ed9eee75d4886f31aa93bbf302e0c69c9c4499396b43dceb67c02fafaff8b56698308393a03f60babde883f00de2c66831f024fafaf98b2fcf37a9ce01d4f34e95c9408395716dcf83fe86c7a0f5e3e6741c3b63b6ebe9964f1d5005eeb732ce66402007beb3e6a087053", + }, + { + "9100c5b2d7c5d5a854bce55e82f94b89a268da7b66357a661dcf75cba10a1b320ae0e4e1a5b989f9766e57f867a3810a0b5b857191ffd7aece4c796f5694a2617486421940cc12b63a6aaea20d2fac188b318a1c3061cafeae436e04d710654b96a864d674768caee03a50ed6afc06f52d90115df1db5c9f1ecaa4f5da094070b1a447251ad3d4fb0e24e87821ee6d4e7e7eac7059080f77d2b36cacbdac1c6e5063946a376865458c4ebdad3c2afcbba8a82b01b03a7882eee42eab904a19e0aead4ae515b02aa2fee74f3a114bf5b9f320baa35b3225491653f4a69e0d864cbbd031d0805b727e42c2b9530dae0c01cfc6a42af8ca730e1d67b4bb743a072f0a38008b937209d534c2284271344340fae76af2b1dd00cf44b48ab8ee92e8f9cae8845e5a8d338f505cd1c19014018bfb6b7dad487e7c8c32064421982c1a63149ec16f2bf4fe7b50cf3ce1e33d6cdea8e98bf067077c9a0ec1bba6edd5090273ca719ebf6f1a0f3e56f021945cff3c468b2dad92a947a06a024758d7505a4a1bcbe9da3a03e97859da99ed36982a7c23572ab60071566b749dc34bee1d9609e87fe32282cc9adba633c9ddcbf359ef4a83a54af5fbb5699978b487954a907dc9739f4b3f3927e66cf0c338e31c272da0cc7795c72dfe60a5b2e73bfd77b8c6ea58122a913910fe29d3360cef5d398f29b024f0dd225183d538bed2b076989aceaac460e3d45e0ca7941897f151261a024b0adf6d5b62429420144497adde6557a3c53b7723471fb760b6a8b1dcc2b327cd939528f5d7bc16ec00ad99df12f082d82bf9fb7318b3d3ce5b84ab1e38d2ebcb6713c03fd0d62bd083c4af96b4316ee02b6953431c261278aabd96e28f81adf7946e3664446135c825e45ed916ccb941350c84523296cadd5360bfe3e16dda75db10da1f710fe796f3456f0911294a4735cf9968656345b9c3049ca47176194c86f36cf702538df699fcffaa254af15b198ac37eed0837b00cd3547e496ecacf6136c6648a535a235059cd75a3bfd0bc49933b379b72e7a8463c268faaf05f0b27256fb179c9d4c923a13ec6600f83aaa2bee13e30c8e676040c06aefc65ba238a29d403f3a8cc164a0bdcaa1a5f54bc1d35fa4efee0c402eccab1e92f6b0cba94e1bd87898a9dd3957a7eafd9d26bf70866450646090833d4b91c032428bdb9097b409305de669a58e44931b7b428bf1a6dc56177cd944b87b04eabd80c64e287a5758c83db26dbc06f0c772335363ea2fb9f19c833644fe3b3fbbbbf5f9d460412d287eef862ae676f258aa45bc8465667601e9ac46e7d77693936c8d67ccde94e54d746b785ad26aa38ca0500105b6870790235e780ac50b9e3198f5fe678ae3a4ff4f1d4a2177edae183daf2de42625845973fc544907e27a90d868f8634c9d529bbaacbd228a5b4ac7fa68ac208e207a022cce4b24a0b5b5791eaddc6b3b3ef6e5dba41855ff531de9bbca0a39ea743c0732772bd32cd15c4b7f28a6ba579d902331a88920fb970aa75114e14b891d42cb947e9eb14feafccf1393796b21099e52b21773adae8e550f93364b1c438dd7d7fc76994c51860b652974d04a7e6ead207610de149f231422595f4e9ced1674d98d0e15ee841143ad8613f804729524e8a5f30d451611676f70a60c5dcc7127497f4d27f35e7ba0e48f98e9022e0deac400e809170970867a1682c7d2f3ef2c632c44568abff76f4f804841ae462c7247147b6e1debe48802674fd55b2ef1be5b4604d5f60c35358c7d773ab3a3ad0ab81868c6044d4e06a48ddbffacddadf813a2ce09aef34f3b60b666245a032f021b87c81fc506166983f25930cff728d399f6dd48ea1c745ad2da7f2cdd9e3ee915f708db0d1f3481018db1c174ea950ed17247bb8ebc065186758e5403bd4d19a445e4a15519326696e4280bcecd1a903f525bbe1e521f94d79df8db4b35f4ef7bd990c0f2c32789a75f95761ca0064bf251fa00b409a58b979e56d2c44bc2302552f118162891bd78272384c739c0c98bbaca3fc46fbb5bfe123eb25df0e27343e38b5a0c2d0774443af91b64b9d4e0649f20290edb84fcedb3bf4ba491bee8754a32716739e5ab64deb6c9888bb9fd2ada1629a59b16934ec5dee3678dcbdcc7fe5e2f3833da9d1281669b1d108837eaae5180396813883de26b957037623825b0675df431fb06b35191c06229f84cc849ccf1b1e079efc2e575331cd77b3297d2908c048b82b7dd14883f3e707bf6ca38f87c19625bec47c11f54988a97205d27ac51a32f19704391af72021b78cc4461386dc3844a1b45596fede3f70e311eba92b1d9ac221d3dc19f3fdd080c2169348f2cc8c9380e12a7ebf69efa37bda4ca6f7e66919b94532ac43022c0518c04d0a8cd99e0cbac88b7a317a1dac5469534b4fbc64080196b44498e149b0a196bb2d6f59392a21c4a4523ec1ff922a52de790e42810fd9355471169d22b734dde4a3361ecd57e271a92132a8b35cfa91d508d45618ad8c6c1ea209405a3d1d3ee1535caeaa3f20546052fc13aff7a584ff79db1726678344098d8563caa2a2abf6fe5aa03d7af49dccf1b17be85600e7cfdbfff54282394b0fbeafda615185574fdff78d59ec2a26dddba1c531a1ac007cabf5be2e2f0a3dedb9174e0a9da5597c9de6d68911fc66ec9d2b1e3fd71ebb83147ab14384ee303d067f47a324a01fc187f54a98f1b0848fdba2ceb3c18936d503e71887d548c4dbc70b7eecac9ead3393f8cb85a84f1484f2e237b36b6d886f54a0f629e8bb05b0c6839c722149a5b541703aeac04e6eb230a5659b12ed0a668d018f75bc94258218c1f5390b9aee4c0b2836cb76a47da649e2425bcf4cc15c4d51d109e5f78cfdb88137c31b2510264e46f1c4eb6e6b3450ad901ff9517b47a24d508844dc85fc5dbcc079e2d09f301691f401ff5f36500cc66f0617eb4dba389d427c7ac778d78438506608f0961f818a2080ea56d0f61c40fc342b49ee63e730df61f757387b9089e1987977b7fa02d87aec2e4be24b8bdf7fb6286d190f9df870944fa910df32f178ab692fa56b071f57366a3981f51800ab416dc4500abcc19e0c6aaeeb9ca063470993ec749a0bcbd07604516b1d51175ebedbaec8986f67a4d9158f75b5f3bcbe86a83220b4fdf12a0242951f94ac7d52882b1b209b82c4749753ea4d46a60bcc4f3eed033bde2d3d20c25cb46fd907f7052217a0a4db143b2efe8875a59441f4d22ef70d0c244b2de6a7e15581e84c860a6326ae3e3aea6d3972e2de0623d2d852c9e65eed318bd3d86d29595575df60d9050e1740f884796b6657718a294adcf2303adf61c6b23933db93885172e82a78f741b8efc6315a2c88ccb6b11692a346cd82a79334e0c610734e61e6378b5e2ecc161d924778bfcf4475805a0823a0d5a54768d9272ee99b7c4a81b3d5dfe1a2f5ff34", + "3c77f30bbb698b1571aeb54653fcae2c23dc16be58603f0c361eedd813ec0c4f63005a1e69e533da93e820e6e4ce1308aa29c60289060ebf24fc9738e8a4874ca4e26a0dc79ee75b8607416bd554737f", + "0223c0a6052bb3cdc99a284fa169ba76be2df53b677642a606090a9267a60769", + "7d3981073f90c6648c5e9c74", + "61ec5230306b70113f67b340575b77ef76d521ff75b754d551e4177591a02351ad382b2a4067f2b3af7e8e15431c7133e98be9d8293d17ef40161dbad9a4f1a4f30cdd557bb9a8b03b5f1b277c850e23ecfa0fc2ab1102e4b1d5e836a606883c3d43527fc3aa26955964b144a9a56cafa7b174d72a0635b80e7b4f871ead3838a955a14c4b8c5c3c66fd86a5e4ff10dfaa92105378bbc5f76ad29727e5bc4779ba3e6dc19bf45020f6ce4dfb3400df05cac51577d58eec21b22839b8f055226b204e641783bb3305b4461172f1c1d48eec56fe6f82aae564ac6688d7b0994747d9b23a24418e69f8a4fc548f854f86baacbdec78b7597b138c453349034c8cad2ff272781e0e6799ef2f8addaf18528736aef21ef8c2d213161e36b2c7815fcfc40747626e0165684e46a9a2275c533d548e52a9952a556168195d602ead86f6bd699e97ca59f4cb2050ff148f5bdfec358dc4542ff2f700db9861dfe5ba377ec7fdc0fcb2501e72fe6873c7cc76b95b4f300857f76e6e6e370119f403b556115b19fee7009f4f6675ad2d174f44002e35ddc360f309f20a3a1dbf39d90d7e5fa2106c53afb0bf445e4cede59cb50b8a7a2c0961d00b2c251f2d815309f74a46a424838ee87f1229273ff3b66dfb79e3b1ce11bd60e061e60e3f37bd7ac896b618cd78388590f44b1a276b965a4b95f2e3a7a175b30fb45dc7a71d4b3a1a33e98af30dbb46a217c50046ac21b8bbe9537c02f05a5780c8a5d796bd6424fd9e9f3ed5932069bc050bf4a1898a0ef0ca756aa2e2269b709cc92e0c5192ab49d692143388ede2bde4923c85eae8f59db5c7711dabeb33743c692be6dfebd815456958b5e1384a109f891f433e7b4a1031d4f30478b05766dd97eb964a28f2f7b55aa6c27c7f4ebf4d47ee8709bf99915426b3896412a855798e392e111789213af537cff7a976b4509e0eb6ffbb8e886a3596a242d16d95109b0ff562c624e06636a3611f804f9b2e252afe8a4e5e868b48e9e734f688f2da2012d7fdfe2d3aca75fd74730a85aae90353417fd52b92d28a5098b6af358a096b859859916bcd5a8f779676c6e04ea461fe62872050af92d08cdf1124bde1e889ace3c923457ecfe0a635ec757907a131ad7c2ca3f60e1317880f843c5e63f4ba59ab2882a492dd1e070b070af6f60e18cca29541206a7b267c3f75a5327fd9b8ffc9b36b57b73b36e586541d15c85253e17a2581e8f8a1518f275cc79afcf2b5c88a16e9bf553e757df089b5db90a9dcdc1867b788fe75abb5161dd7ee1cf37d3f0faa793ddb1bbf1eca13f4220ea63af8ef7c0e7144d999ba1c5a983e74d48cef708c1d28d3c0a168ab87d0ef70f381693f0d438ce013ffa2cba65a8cf6b498a7120209564535b7372690329cdbd74eaa76765962720f06aae58338a10064ad80f5a67395db2c31d36b1f5eb777306395f192599d2f737327afdcd9f14b3f24155a3f974915d3302427494fad756703b13afcd1764ef9735e7dbff920f1253cb668e9f40632aea1e0b4620db162138e4a97e6f0729b14be4a7c3256250d5e7423ba1238c704503c51cfc9cb68db7001b2f597a15e77138beea02e11e0bb98a72f2a77b7260e9172fe7e60483114ddd836addd966b69570db5eb26a0cfc4f8a8b80d26357ed51a70165bc0dd11ad7467688025bdb532e7222ea12f23c44d08d111b0ad4acb2f5b3d6b45c387d541ffc84466ed57acacefb1436ef00bcb5b6211dfd0650113ac369b9f3e4891acb2693c377467b1e9c949cc0ea6c4a72ef9292964275ed397cd2b1ed25fe1aa8f47e90cde362392da5e53893eef6e4f61decae1a75e3b726f0596f09c3cba62aa08bea89984b484d5768296a5afa8b0759dceba530a169d22b81979212b3343db35ce4e4766dd251ea6a47f5033cc090d6577efbed441bb4f8944937e812f12ef17ede76df621bd4cfa31567ade18b74583a2b783279150d584ca13c0d4784b70156afdf9be8ae96666b82def888465cd3df349de427d5f5b3572e4f963d33f968e6780e381ca196bc04a6664fe93fdc8558b21b84130dfa2a646950eb2e927885925af46d7a28d1507bcc3c02ba98318bfebe5b9eea1bd47935ad869eb701cbc35a9aef5efad88ff54eb350a34ccef2e159de8e16135b81105bf799fbd86aa11653b5ef93a1ab1c367231d61b42b8bdb4f04d8d05396d53247d51890be9b56c51cb19eec0fd1e6b8cdc98376b6c6b30963ac7ab02656ff94dec0e3a0eb3f3ffb8bebd99d5889df98e6c77093c370373dd5f17871fb334c7eb12c6ca22deb75bdac9eaf24281c965dffe03da9c940e13fb382fb6be332797813710a7cd2e7720f5b9e53fc0d98fcceeea4a8e9f787e670d60bfc4a849f34571e5d09b9e9c28cdf2b2d888eca9bb31ea8b9239bd19dca86880ad3e12b1583acc3a6d1f0a438ce3b5a337487279dc4ead1b214272d455e6a2c8cce4ae3bb29abfdbe77a67ababeaff5dd9c96b17f589cd4615c0209eba5e4b1c7167b4b739ca4b9957185961529d1082226f85068890c94aa1f1c244259ef7b120e40114926a49c4412b67b4caef1ff3ce6f3aea3c6107b830cd34df9f4d73d7d978b6b9d5c481e9d76e83d649e742b098334838fe50d80975fb567642d3b72c461ef3072ebb1d03c0099e97575bae6a12cd2352d9d296351df6965d736d7568c2911394a73d199743526ba54dd62c56c598f4e78495c0172739274c0b8c96755e489765723a24a8704093a94544f6c8764dcd1ce6b4bf2917cfad27d85e4442b4e5bd577ea1a88c2b79d61cc1be01ee9028235b36444483b4e45da1087bf6d45ca540620de5aacc644a0d5c4b807b582c7b058e140eebca539947502bf73c9abc81a0e3a618b39d3a38c4ff7f94767fd7e6b9eb61e629806bc3d183bdade7e369d180dd2f57fef677e22ce41be7224f11723a85a3f1d14d7b72dc98ccb2816b77e625ce3db3e2c5753af8b079e0d63939079a01910ee4699cb405d4d9c60e4ac86a7fda3a4c9c290662afbdb7678c3a84c87ff83470fa8a416511a06d3216a1445699d7ad7e6980491fd596d39762d576b08fcbf0825243c1fc01ec8300780857c429c607113160a8354f6699b368a87983464472a5754fd58943fca6f6779764fbe6cbb510d5280292df02c4a7ed9acec8c95ad67ebcda71d0f519ac18db9b43b28244cd34fe02c5d694df57410eb54c5e1ca0f8501e7776a811d7ee81eb9d8c80b2ca50a012b5eecd5428af965b217e7fdac80be88a01f76d473105b027eb557a523f13c55e1670ff34627667649573e0f19dda41c525a8c96c2866a88bd73e66c786767e1657960f6676d8a22be1c6024158a0f0e4ec761148b5a3d8ea481d8fed94855be82479ba23213190054f937838f0e35e00aa74c89b294c29ea25ad7e96b4b6fa952ea8f1cbe5397b7c86d0b74ccc25e22c88736b045fe86110bffa0679f28a1f27162b51410498cb7", + }, + { + "0fcff2c29cbb5cc40bfd2ec573ecf368275ade6a00e5730b77dab17e437b46524b3814e7f470acff6ddac4e0c6b748ed112657120bca1d83a4ce01e74a473995804d7c74bd28732a02370ac8ef52b600790d1284d82f077cfe096448509dddd0eb5944a882b7d384efdd4dde3003dea910f12de82035651e3ec9668e66435f519da3fa1f5bcda34aaaf028daf3068304f7b1ec18e65136241a9db281e011d27db5cc9c1099405a4430821e2488a228805314983966ce5d806b0f014c21d4c9d6a066e63aa6407ed6c29cfa4a3e22ca913762ca9d31271d9c371fe858f3b22e931814cdbe544b9416e88f6026b12bb8e88d8285beaaa35be1c24339b5f567480d7b16cbcf6160e549ef4570a0702889feaa0ebc54b11735735b6e2850d5715e5087291fe8890432784aa219bacaa2b874b075c9628cfed5e76dfe38426f9693f6bfb2de49b710c101b2dabb7c7c74f12de9ba8f75b8645d25629568d12bfbc7eaada63364b6f56569cf21e54c95d6797e9008f3496c506ecfe5d6a010d168fb7f0e2ee3c423492df36a133fffe9b87d7ac070c32cc131fba6089cb7d904b25812e03cd6048504f7ef1736ee00ee6b7aaedb3dda9c6fd6437772fa5076aca9888ce55e906a62875979bd477aabb2f4598d32342aa10a6d187c6768f213117a9ff6d830603bb7b9b475002e20b2237a4055ae6af6b8d70e343e76265188a0f07e7820dfb3d898684d99966d4bb9e78b0e95f5044dcc12810a89a75b11474c8fc06c6e734407db91a072ffeb2be6773a7c6c3ec939514b43daf29feb3aeb7afa57e96d9cf0492d90bb2c7be613f2208f5f5f5898b0a3db8a967a75d065efcabdd83759c88086583bb3d422c6c6425525a1adbd515199dbe71350b77940813618b88fe139153974c80d968ed4d9e3f97a91b7cce250a7c963f880dc38011250b9a131f2b76b677f78fd0e4cd6f1465182fd1d644dc42db0bcad8df4ae9f456841765af8e1c1775abf85a69577ece6f9e9035e36c88be784397479e713be4f5434aa4c166bc4702a4916c0c003a6baecaa182372a30af6dc7e6fc4912d13e662bd327829f6e85340fe130001babaee64d211d6761bcc52993c162a692a10cbe7434310392b64792a777a2b31341995072a6b7d4538cfde74e609dd1019a9f75cec0896186c0f42e3896d15be87aac5b11642f74e11d5c2f7de9f07f848ff543507ea4d73fa8f5683fc6b41831606352c482c7a5a013c51e0db59d824582c595f17a6d2113528943194d6b5aadcead62516507f178cd0f76729cf8b81fce4e0138ab224bfdbb8f16f8ea6196b90ef90a63f0fbdcbdfb5320984be8a80a26b932d1db7ecf870dd67fe838069136ff9b9ae087779e82cacf1b06a7b310ce6c439047c26fcec0364ea87e4549a544d540256cb7c3ef7282fa792aad89e919dd89519fe910501f5ef88da43232e917730e742ac2539d454e066feb9058f56dd246fdbb674dcab636585a788b338ffe41f4190447a65985acb9613d02669ad4ad888004c65acb0ca315752e58f51c9ae9259f20cbe8a668a207a5a46e30891bc909108f53db8bf6f0f11549e621d4cf4763e0035c867bfe9e1192fc421c080b25289a78f4167fe517852efdb6f3ccfe67ad01b4337da2c18f35bdc151c5dc76ee66efd27d5fc784e4e6829bea4f8a41ec8bf61ff998d178ce9f4a10551687337d7705eac6cd7fabb3f2379e31c1d01e4dc63e475f0fb01d9efa3de400b5177e2c2d68f2ead89e9ecad62cfc97fd0ad5b3391d0248dd2fd7c75dcbd802d3463ef0af21eb77b07a3286a72f1e9439f457630159abde7983a5c74f7dda12b40913632afedadb691d62003c70a46664fbd976457544cef8ea863858505b1c596e7f745d4a5fb657b1c694226afa9756c40d9c49425b323ce17a8531c5919b24010f715b5f27a300ee37334931ca9ff5c83c3f0a87713768ebccaaa15e35c56f3536ba945e5d954c94c885c68325bc4b51fb55d96c8d424849ece9a812af0747d5b1dc240f71609439f65acd1c17086e025e376eeb79a7255680cd692fc4b0f5768d1985fe8a1a387074f58c8bfdea8e5c11ed379b845ce2052a5b24ef0c1a658923eb87adf5b01e6aa59ae6937564ef97421722c67404cb9e5fe07d5bfad2e52ebe6cccb41ceb1eb2760545fb6a3582bc4ca572b0aa4e4f0a2ecc56299f3b485d980501a4e010576615ad518fd2d43c1f79aed013ed1f1e1bdb74357aaf7dc84772c9ec62da43c8ffe11a7fb3eeabc3584a936c37b28a438dfe78f89de6b0d5597ac1bc55057544e68fb49a6e505db69af122c2a3ad06219b7f2a2955db0ebf55c06baac5e0efac609436dee484857f75a8421945484ad0c7650a1d3008cc85c938208f19002b7994524878d6ddf85c763a65cb72a09c3a059657459f13cb584bfbd754fbf2de904517092be4f1786b2bde26ae8eb2d884592fc9e84395408f8117e47d1ab30d5fca167bbf07e41a33c230d240e3aac53cda9f251e24659da57d721288252fe7ff3653ae3e47b86209e9344accef0009b99f2ec7b3845558f1d77b89fc9b61ebc1b589fffd3261f71b9631e87541e22ed100e694854bed771358f10fe452fba61875a605b8080cc39e3eac13708e32518f28e60464c38b782c7c7800df63b6e7e95ced9154ea54e32900f6998f38eb1e51c112b6949e2eb11a96b1ea0a68c1e3b5af750a99c9fdb2cae44c5a1d37686ef87b158d19343e23daf00dd558cfb91e6f2e18f8e806abb2faf80d082f657717d08ca4e9c0d30d9bc30b612bcb1a3a3a3843231059dec344c6c04ce625b3fe064092e00175fd9d38f8fe54c4088efe30d211412be01460a6d4ad8d0a618b00a21de0a383de30ccd72f119b27a08958729a999e8aadff21829cbe8cfe398d90476e33db4c64981383a9aeab4a27f3bcb29d4b3d3b3a6ebdd71d3ac546b8658e269959630de176819b153cd53d2091efbddd2cf9178ba6ee98e1a3df9a095db0a2b713a0988a22239f5f08cc8f9abc3d67d9267f54dd5dedbf01bd490b0b09adb21d4e5aa7707e36cf77034f01bf8c7988a2e8dd7046bb2f486878436371f1258f3f7026afee6d7f6560be67103ad098edc9665e00118d4879f58bdd677cf2e6bc631d5c517acbb6db8a1debb4fe7492b7daf0b7ec7df056637c23caf926a1a589bef1db29cd81f547afd0fc9e459f46108ffdfcfdee43515a771c439dbde9177ceaf296a8749be0146cdca2b26be8c2ebd6cfd9b5032b1f7a375307f54c2f622711f8cf8684afaaf17c4da3e83666c40d26adc239c8d1a40024bbf560db5787ed404763d4e70ec6635c6a4b82c10f8ff7ad42217613c57648716ba94cb33129f3789dc86f9c8ec2e8e90e6bba0dfba1bb3dc3215188979a09f33346a6647099ed0e624c9ae10f83da0def840bdb25b718e8d86a616ff46b5327b1f99c22937920f5b5bbd6b53fa0b32f24befa4a7603234e6d94be51f00189a20b15c49e8ee58434a15ae9d10b9cf0204bfa7ab1fd9e006b22bebd22b036c4bb4c9949cb7ecdf01028d9f12466e144b2dbbf64d95d65347013e192d428678f64f0d9306f97208fb00a70d4615229143dd8890725ee3ba6021d38d6359055aa812edaf", + "0c5fb7075f5e15a6733737b614bf46871e29417e4b140bae6e10081623f5c52f557c36b4da4b5a4e82920497514b1e6f745fedbf73f86ee10976f82c6cbd5bc13a917514ddd062", + "e70954c812cac03e367e99f7b82a6dcc073d2f679f965d524872756ee58654cc", + "5f6267f6b3b21423267310e6", + "c53868c0fdc14e891ae1bc257fbb13be210a5d9cdbd9d18fe1b474f9a1929dbba3f25222d8fe8c1be3eef22352100064b922fd9642ad128a202b6382ae0a67c8affb0c5bfa1a80e55c1084cc372485243df872d677a80a3ef1ca3589908bca621f6f50133eb762cb9c05775d13db7dd3eb65ffd3eef96e8dd42928facc68390f6bbc50b17e1ef5ea6310d8756dd177be2cceb63a97bcceaa046794915589ca022d90756b02c22e8634c0ed44192abc3b8b1e2814c855ab27aaae3bdd801a73e6209fdd559ceb59a94fd98a66d12a31a643ca2f4b07ed910bc390f77ab89395d5cd1d783d8940dad4447f0452991b209cfcd998b0c814cebd08f9ff15052818bab0bf51c3b72ac1020d3b0974fbdf4ff941b1ab9c01f284fe82f2fd89c0aeb4b9fbb0a74ece08b3debc7b65e7263e2922fd4aba15ae3cba7885d04127c8e06a67f244e7aa4556f8694a5db6653f6e48d6de54f9e4024d25d3236d4f933205b6a358aa1506f832ef7d556c6a1bfe4aabfce51f3b5ac64bf6ab1e665bddb12fe13db9f07a55db3da3886df36ddb89f3a4939b1e9e5b701301570e3d01c0b947f498dcc6af438cc15e6038cb78a78986da0316cab67bca3e28c95e6b7e6b36cae9202cf4a77a0e15d3c3291d267aeee172dd587a944719b9fbe077603b4d39d4302b9a6415aa07af309a5e1cf7a9379552becdb4bc6a0b5c85d2e63bb141c405afc58a8b2b4188b3883a24eedf98dd50fc54725c440ccdb03514a6f37cab49296b6826b6bc7d7ad8cac0a3425eeb6866d94119acdad468cefe162a29e8831c77aa83321e8ae3e20e968cfe51dbf2b63f4e26c61536e6be4f63d61bbd06af38023b15f4fccb8ae0356d924dbf646bff69d1ac0d6e1c7f40b12d6d16e52d1c15958add5708bd38c514e47fe623a67c9ec211cd625b398fa7fd67a23e6e9f65d42dda2bae94524372fbc1a7e0ab3f1c451c126135536e73c573749aa60177dfb68843752b010e2cb9c1afaf51c94a48cf8ac7aab3fb200aaebcedefc6cccb581848da0121af92d9f4be002f0c2beffdfa65c36bec80e7f62d7009b1eb719d24b96e97059e6b50a52662c2c833738849f342391514349305228b29bfa9c7cf2a931558ca8e704c600148a28bd871465b23af499c11784aa45acd051f276d82789c58b14f12619372be4bc3a285f6cee21d65648d18e61752d6e7957736d3385f8ad36702c451c61ed475997d6d9f11c8be5257d8febce329aa701028aa2b5644b8515a95b5e866780e32754ac2e6f2e31b2c04a4ad35cbcbc25b23e9bf49cb1a5d877ca30880741757c29303af8676546760016f1538991b37cf0cd24ad3b1d877e5e1bd083e4b990af6ff5c0b28e530db3f463d21e76c928c8e1ffaa6c045937ea171a9071827a173e231f50e95430ae4895932c88ce048058ce6d0a50ca5c1842506158e98bb2912a61c7991a2256c97cb9050a4bb3ca32594622756291340561e9e584dd2e096263b6ff8eb898ae86f5f24500320d2d0ebb30d84cb4ef876a877dad23a611b39bf0cba5e22f2850e11c298fa23fed40691b83acc87136f8fa540b1dc40d1b0d0bd489ee9dad785c121955a094a2c6bd3353e142c04f7b88b2eb3305fd00d5eddb391b73fa2b16a6357aaa2abf2059ec979bd3ce06d5fff1c325bbe5c833a101615750613047d8155ac0c3a0734cc6aaeae7cb65d7501cb95f9d6d1161d09c961c0681547faf7983ed2efaf4e0fbb87a06169ecff1d0ee540a9223a73f75584441d4669cac09c2dbdb8aa2aed74eb9a2870f2021eb16e5f5c3e79a24d7110af4bece22a1086d27642550cadfa4f0e03f2c032a2745e1c9277a4f67fa4dc74ba056110fed3a63f643567d079c9430b8d5b3bf57a9b3f02d486d870229fee5462043b6bda8d265c745ddc1b8952bf91828d6db2edcfca7051e74df9dd456dca5e04ba469b9ff6a8130aab3903c05659b8f31cf4ba4c22511493a36541ff9d88c708dfb714d52a3c0356543e6efad37530b598bb63c3724772907abe4cad39c896c62daf5b30cd7d37eb36a7be2494353028c76e8d148b018c7bb755c45d2a33f61944071bae8316881e9aa37e4ec2374aac4f8436ed3c7db2092326538f07fc6644e0239899e3335f73c1e3c4602b12d19d7b639d4968974b6b2703ec1add8cd930cbafff4158f68f06aaac83bb4a2e31466e2ddc247ad71c5f4c49af7defd1394e21819cc24c78380caefb2ce87c0d1050680313037def12ca21cf67bb6692d6e4a9e90a9c9a0b7118ac300c6c6f636337aa25bc59cf1d9749dc183803cc0ccd1ff53210352795c6edb49ff1e5e8ebaee7b3eda6e3c0c340fa60594115e37fab60133b8a3b39d2e63db0bc6a03973e236fca801553912f93feafd8b96766049dd2066f3c5ac9222121ee9d36cbcd8f713adc8779949941f8a8dcc92ade62e46e9f1b292d5f7eced14c3bff50a811cb762ced1f103652773ef946e18569eb5892626627e085d4ffb3102c1586ddf88acbaeed903b22d3e7ccd8b8ddcdfddb872403240bc8e0e46a068f55bbddaf90fffb9a914187aac2ceedf21fefa1fe32fc7bdbb9fd76dcda1fca7b39107d308d11a118e47499dc4092ef0cd28d0d9af84440f095b4feb7adcba198894cd89a324c60ed0b996c520d4b33391bbbef1997256af7ba7ec1069244359066af81543ca23105742fee3480f890373d3205236bed566cd22a62bf69f8c0f27b714f84a203bca1605865e2cc2f9211389e0df7a4b3aab9d10826639357efe1f5fe64a1bd6d06d0b5605658c4d2d12e1bec77e70ea393b0a09043dd7d6684bd53f4c883f2f6928d99ba91873d063d43600f9105d503b11d8dc2b05e34b4fcf18e78b2b6c97d3b2c9249a2f6566ddab2a8a67fed6c9f8af2f4ef98dd579f2d4fb572e178489c503df5d5f03bee9920db347a6e734ed72ec7233387f1579c13725599a33a90915ddf03725dce20fd3806abc1029a20732380596057830ed63b6edcaa4d4418871bbfd58de1d1f2800588ed207f2016e11abd1baf1895f6096e2c75cc5916836a9ddc09cab4c28e53fadbd7d3080088131cc270095315b61011b0cea5b4d64b647bbcea54d20be1eec0992c72fc9c9771cae19191cf6a6f1840acec1deff605626d0a0d79ea8fe0af63ea75e80f8141fa8d7ca6f4c99dc7e78aeacc67762ed0134f1a0b053debfb9ccb145800b9818c2deb46f7124e8655f37c3291af107ed75384afcedb44518ca14cdea341c9657ec638531011cb957ed6b3434b736ae8c8199684cc58862638c5f6c07e1cbe8ae68c5582b1697ca9dbdd01e97023138a9173d6b1294cd99514a28102e6912b1c87ef22cdc611133bcc111e95c355a26b20a3d6f0ead66e932c5e1229b0fc17a7d6f78134c69beb362ca75017b1bf1105ac8970fad48acb8313cb3ff10e9d72c4ff11f95c2dab59575525c98653a9c7d31585a3742267c062d6ffc7a4303a3e81a45bf39e1ce2097623bba70f216aa612c64ba06ed6d596ad6abbdde69d56ab45e25ebcd4e485824449550232be26f987c14008f67c9db9d0f709f567fa44502b9e0839457e5f0aadec0395bf5c38ed8de7529708e58c0a895198fc8b2570fb6e68547630ca7f313526d392ac4776be973205f971854c300454d5", + }, + { + "95a17355dfa9d378a18ba20e58aa4b8711ea1d6e3c65e0b2d3c6382892c7d02768437d47ed50bf8edc619c340be7bb1cd1d88b0d3d6bbf1031f738c4be09eb264c686d39b92cc7958e63c9994a84b61b5c412999ace8a9dee0e2a29eeb8dc537f63271af5f3844ed9c0d86e6913c02ed7d2b862a132f08f311aa92fc3757342d89a5dce8dd20d5792d5c60be9862ab168d3140a061489472f2266f297da357064833ef2554c49f8120ff40b961ebcfee1d0f8e7e5722f049485f72c502c9cc4afdbb70517f0fd2a00e12596ffe285d1b37eb998e0e89d756e9491ceb13e83610a3a66122b533c2c3461b3244438f5f7a7af8088881dfdf6a29fb563ce38c4c8632ada8e7e06baa2686dc6aca6bc944e5c14d6e432c4dad554803912b8fddb1c18a59a86bc452914b2efc1599c5597f87a6edcad33a7728827bbaad0a975ecc22b7748d7cc71ec7f51adc8fe0350e67dcfb31af35a8d7b72391642e29c2fa4b796ed8f535f6bc2b1198baf1cec858aac38959f83130af55c21383ebd57d364eeb0e442104004c1599060667ce5e1191e76a89199a386e5c4bf147206e7d6e598bb27a90b3c6a54cccacb39a0ac42bf22eb40bc8ec7925376a6c57d8eac6317578ac052b72ab773f572ad961ee05531cb95ee5a6d70add4176351960fb4bd673f7db9f698616a8dd41823f2f87924c40f131e6c83bc40ab1f92312f46ee86765c306cf4a1d77275ef9668d80f9d9c1ea0aa7b2456bbcf764e009584ef1c0b4b4c683fee3fa2641f48ccf7485a8356fb3dd22f848deefadbef8050de9c5c19e8c449c6f3ec2b1324f80a7d428dc44dbb966d40244c3af03bcb410a57ad1430615e07553a22686f1a62dc6cf090aaac3707ec5b44274b7fe28c7a3a298e7a8adc71e016944875bebb421babd2b64809be3454f25b90723e2cec68467ad2d14744b15de8f9c397a505a340e85998e207cd46fa18d76c46f458af4ac3821c0ac6cd68afb72c376c31daad1a2435fc2bf333260c1a82430edaf2499e7455a93b1301eada2e12365ffcd36a1119664d0c996318a3e55bb2c04dfc5eb251f7fd64f9d83f27ea6577d748e1f85248355ed19867857dc3383e01249cc37684b0eb8e891aa663801e4ac8f0331b38686a19f0d19f6e94c7ac95ec395962be0a4e3c8358d2f6d8f13191e164ad29cd1733bde8c31c7d8ab90366e26cc9a06707dcfa60bfe139a112db827778ac348fdfe26892fed61db7e9849a464e3aad561797b6c778e0688bbbeaf3349727b4670a2d0a08f317b0dc9c4b12ea85c0309d57e754d0c7bd5c83985fb82f776c968189908a8ca83b5944767c2efc3c5f898436de54fe8bb17224012a437896d9fa106a749d12aff657266276129ec5ac12fc7a77eb06296d2a2a876d931e479d3ea201cbb4b1b20bd81471eaa33786c624013e1f07577c2171f38f0511c6924078a40c2d55ce392dd2ab0885e29f4c06907a1597c181b933853838970edad7777ed394c491cde27478eafa5b7a36520aa0779261f94b957e83ce058298dcfa07b08ecc425caeb6c599a11103d7631e77daa0d9d3fc6f42703d57f2c624ecddd56b9a27b848de7dd28f8ed656f1e4decc95a8908217e2f2453ae50b5fc1d9352d735ce5bc2b538eaae25501d449d090df793151811443c64f28d19eeaaac4081e10edca4c4148e723ade8f7e7b988b732ba08b3ce4c8a0d655bac4ff66048148135decd7727a49ac59d82ad470b5479c55d3d8399b790ff033d3ef99d770e1eacecdc140480aeca1e2167553cbbdef2090c7592b40681b733b0a0d127beefd49bcbe8904c975a5ab8b1afe56d7ed7667b5cf92f537ad6972b876843364817c20400524097ac9b405e4b35bbba0d12355a0b54bd763b4491b2acd4e8e4fcaaf8fcfd398499d4c4e81ffa93ca07a5ff51a1540f178f43a931e07e1ad56ab5ce57a2f7dc3ccca114dc9ba8a6934e95f4efe9f3f76947909b280ea5fd795bbbc0feb3ad2b704e305cd9d8f37d178961f77355eedc9d7f77c58e1db2f7797eb8682255939293c3ef7dacd2eab46c4cbbdf929aac301a13f59831a88fab173803399d96dc216abb9f079e79bbfab667ca590266891c8a7ea4bc1724573e5c5a67e9f1341b5bffaa538e240f78da7733237999ac86141b2ac0324f17609b71c885630c90befc3b027a5f01e33979165ce2a00968c414838446c2aba76e1d7fe3707c742f68af21d30e23b637accc848f6c8df820a27bb4e94e5090ac6e008fde7cf3fdd5931fa891335ec8d01b5d6f77db57a87dc35d6701adf7ae0bf82dda6511c83ab4d7d3460b221eeb3d6c4aa537924db5559b1c6739040534fc330f5144c78bf99f5f4faa715e85aebac043e2529197a82ca40f65a8149a9447a9e58c61618600b0c5ab221420c0cee114a133a648dbc2eceb2894ffc329376d1eb3ce7039cf30ff6a53038b23c26c38739fdebc7b919956ca2e468d577dea6621a8d66b78075ad26a6e6d8e20c9b694698540d516ea2bd108625e5fd038b5f1e19c5d5993b82bfe16897c375322dbbca81c81cef6ad900f0ffe5ed02714c208a12f5234d78e32ee07af155ad1e1077a0d8938f426d8f326c751f6ee66c8f707e8493cbfc76f9ddf1ea329e094315a91ba9385e16c890823db0f0231c7f939a042665009d5edd8e48102c515341fa6eea33cc00fb5d82380d735b29f2eec3f61428f7b186d43fcee46b2037ad1aa6974d729848cf1a80dc8ddb0580c9c876def06d8f7642cf45263a655ee77f047fcd76171546319622bf71283f3bf0b519e123a85765779c8bb201e99981ed184e642f63aa61f9cc206bf45fa6e514bfc637671d9cdfba2891bb112a3cff438a6372ee0dd3e7d9f352ce52f8b367b7799e1f963bfe50638f0c74b94873fcd3d66fc1e342a8bd36fb8b88f33eefabb78eca4dc9c89e2c57aaa010f2140dc5ea7c86cebe2f8bf42a167d1d546cc80bfa9258c35af6efb1a090c293a4cf588e4bdf5c090ee7fe38fd7b5551e71e5ce2b0b5a50bab95bc4c257edfc94d37579816b4a2249ba05c991bb2ea02d047e480fc8a8ba71f48f344c6d20d140a64ac20184e45b4eea14d0953370c237ef0a47a7a2f22997715dd3ee8ea52f24ffe12674d571b3bf968454ca051701e411499bc43bb55bbd033f9b81d4baa6c49bdd49614efd20d58175af868ca16a9deaf65216abbdc3beed5f30b209e786a5b4c006f3bd27d93e9d78b51a1a2fb7f5160a0bc1b7df70952ea1573888ddde3d9dd5314b0d0a899a733eb48d5e6c7274667e362e4da6b37c480aa4d0d8730e66483fb1453a3aefad69942ac7f09d3c571b6275590938c541336a121bdd20722550236a9a5e4a37c7de628fceffbc260b1e9b6417c4295907937b13609b8585ebb8f076073abdcf19104ed80ffafe1b09997f115d987a552be5689c70fe125ca702d2ae4d807d5690bc2e90b72cabb0b61ad203b34c68df21c16b92bf8def5680b204ce327214c32e4363d5600f96162a6819dda472acc6441858f396385a16fa5ee52cc0f9ffef3d53c49d535aa37db2cd4b573ff81d74006677969ec1ad891082b5d18ca5b0b9f975574ccffaca72b805c9f7fdd76bfe3dd384dc953255a5b50b7731a137fb9aad42e77d3da1eff5a7b9eda5814993cf2d289bb25ae1680ffcdf419e073d38b4701021adb2019359bb70ff4cca930be7bb979a0678f20665d14803d8753c8ce54cae92feb026486ba747a861daa449863bd38cb4d5831aa6db1e7f404b0c3587aac8765aeecec686066ee7d11321574f04d3f3da571e71222ce07277eca7ff97607", + "5e24f34a8d53b17bd0c2aee5369e3276dbd7e7c2ea0990f1300fbbb00831b76655aab1e2fd625ecd", + "c1d796f1e651a1ee825855d80206baff6818cc8c247ee6ce62b7531e6e9ac32f", + "240cb25aaae4d085bbb747a5", + "319e968ad291ea5d4a057c38f7afa4ddb9c9565962fa1a7b231e397a268ad8e0c5030a2df09dc4f99402ddf2e0d06e753bf55e1b318b3e5ff0108de2328d3b8d53e23e08bf7d84d59fededd60d47bbb52736b0491f82c616eb5f779c496abd6499555035e4513c8613e7204e6bff8d06dfecd9ce38c6b83efd8d0e41f84f7cfc9ae07113237987a4b2eaa87f7e0a310155e282e57858244e9071712fa026cb781e5a4bfe6fa1bc480e534096394459a3d1354e2d9a54aac6926a60b388410fd0b53f7a3a9116292f37406369c22ea674418c4deeead171e00f74f5cabae5d24a0686a4bcd8ba99aea613a23edd0a019a319daa3779c212fbdca9d772fc3fe612cf178c2aca2aeaf6bce2433494027a474eff699bba95fc7dcf79ca1d77b1e097439a9050a5cc78e0b78bf2e7f50f959ea2986a59be3880519cd84d0a673acb0432feb1945c603e70748445c74600ccfec60efcf9e4d02a7df5f967de4b473f63b0b0499ff4ba350ec1182f3a0ac17ef9ae28945fc9bc714c49909a7c1e2f311aa6ad7652e22e1f48bb51cf53814a2125152813752d86c7f9468a991d0ac84b1a2f3969b8081c228b7f5760718036e26a10e211ff04ea323acdaaddf9b06a08c92ed663d0fdf13fa601cda45c416c2d3803dd9b5ca29cba57e59cf4ad93176c65c64507b1995d638541c90b381ff758833a2ad67b0de44c280fdfd82b3c6d4353ae30b33768863cd3169a2032f26e37ddd57e7da1673cfc7375bf6e6792495a2b434155d684f2a6f2b919f944469d47be5aa7da74eed69d871e6f65c3ae08904a9ad042ba39905188f0b9158fd14094bd6a408fba6ef57566d69eccda86bb54cd3ca7381f51bffeaf8bcc1ae8df91d22c359888e21b70f640d6f3726a34e6100ee269124747f0ca05110f63deee07e3628bd6aacf926036ccec02c0b6bd7259db52ea8b7a686b36ba1d0296c85e43e25d72ce46c66a1e646301dafd2f4c502281e6f949011cea69459c026c65bd130d6ef06be17b23a9c9a84746e39d017b144135025ac527c1e653f233770cd68e9f232c3b623ceda836843b3e9ea313cc6a57d28ce71ccfb7265ce73b06bce1447220645e6f66caeb06b55129b97c8dd8db54c94d771504d24cedc86a8ec706a9f7dcbbcd7fc7cf38005b2913b1cfb77370bd23183ac7b5ca5135a2738cc91d05b2b22640469e3daeb6a7b0f14fc6652563663520f7754aba624a35e5d24529a6ee9f5ef0d019d83c04f5a93a38b68cbce0cecd42a11aae305475806326aebb4f673791f50c9f90894add51a0fd7c02807efd8c1bd21fa717a860e224bc9fa3f40975fd8d558e4844a09f8920256528450d77e546604e2ce2d38efadaf39a0ea3ea12156174aa8a20481e6c1190e448564675f9ca60bcef37cacec5aa218122e7bd25b571ff10f54979d62018b779a2a3d5d7d6cd56ae31efef2c844ba50ff9da88eba7a8e0d9fc5388a805ba4ad35eaa4798e395d2fe112083cce2f11cc850d25ca5c6e60a9996cee4789ca99d519daedb62f4fb1e535b742a35d71d7390117e93821ff18948a78c1fcdcb90a5f1211327d7ee0663ef16ff446e0e22d8cb7b2d3d05469b1c02864f4a87e2d9715f60c9e7be841e308d0a5f6c50161a4a0464aebafb88e0d2df8cefcead93c9623106d5518a9852f320235594be10c45bc0cf06c9daa007100ff97959357f9be8e49c870d0a11c884213e266c35e9131439fb3654fd5f1abd1e778ccb02b8c262753a22653a09272a0c33b6b2683c9045e8f967af756b98dc1797ff605c64ac5bda8252e9ebfe0e4d8d7ca754fcca5e3de3c4b63678da095281d76d60fa12ff4ca818825f346b9c4e426cee16db5818d78a527a901cd088bc2983f9b83430b50683018996996717a1738439680b68e3f61cbdcd0f0e1a6b436af8fa05d3ce2228054e319bad1dc6ac970c75313c552fc1136fabc302fcd1d09ef1b9138d18133a772cbd9cb197ff58c6e898f9e83e4e27206f3b15b6bf2778aaf9fb38e0d50152f8dbf5763816132a04b4b2e9639584b3dc8ea6d95ade024f9497944200ab0aeab206ef099859b9240aaa15f737c1e0fe6d015d04f47261ade4928e3c2ca21d1f5ab4a3f571f2ed92ebeeebf2493e6e39f0063ba931e165384ee1b5081f5f8d26ec24716757037f5158d35effbe67009080ad7b0381292a513f312eb28328cf5ff47a6599e36c14277c3eb5053c5aca530ff5954c21c03fb3fd5fc0facdac36dd819b0495fde421411e0440991da0cc4a20d294446115c0b79045037fbfacfeac574da3bf192fec4bf38c27cef71d03787430223b6069ba6d9273ec8679736a832277c657862ca791b559a5054ee8c7c07618083f75480c8aa01cb086c7317315911802e6cefb15bbe20494b14d97e3a885806db775c216dc15949e3b724f7cbb30bd2c46bd5a2fd6132352c2b21cc2b47891dd9794975f70a6fa7a0791ee761ccf4c263f27f64790826c1aa656c39483e029baef0855935e7e6c133a4035a3699925fbde131ca62948879373346af35bd7fa52b8d6c3338f213bbd9c79977c0d710028d1d386df614c5faf4a1f8fe5506a9af7059370893ff6d07d91383baba67a617b5d829e0e2eb20e541ed5c34be7ef0eaf6c6f6f52d7ca01933a2a4e8de46e422dc95161ba8ad354f6bc7c8e4cf8ab5e08607530147fcd7c9481afc621c5a3230a05e2c4db79db9e1e73f43556a8e8f0dff7ffe420282212f23d4c5f6f8d2febe129b9fe5ba7ddf27f72ae898a4eba270b5d2bb3b6b06e38c546ba80a9b2bc46097d0b47db5ae72485ef2c6419e856c33c2d66a861b9d474699e730eb8a8992e3ea9c1ed74316687d5d9fc611189eba2aa31af5ba8e81179866dc016bda977c59c595e40001c8ab3a4a44cec00ff84c6dbd9ad4be30bcc080e69b9398089d6ea464a70f536ace3b447693301c94850606d0de1299770b5f45e6d28f8ab83e3ffe52178522eb91fdaa9e4a696674ba0f52ee18e960b04415782f018d67479081b1bf9b4c9b90de026cbb66bf7d9d12cddccdd9b2c8ee2f010892571c6f0c0feac9555c71bf61f9cd69553cf7fc2be8d058e0c3430e134adb1ba28985fdc4f0cf71bd3cd09f5f82f303cded0de62f98404477bdd0a846c6c51e3e82ebf72f475afc8e6388aec57206018ba2528ede194345cc1ee95cb2023793f692f708aac3c9e8a682af36b078f5d6c7a3ed07475e9fe73b95d1eee048ab898edfee3fac4beda45f03eeb64b2128f6df9453ed77c6010e13c0270c068f704f49e62fb7410be90ffee47584ca2efc5287dae1f63bcc1819e7548eb9f0d8a3182f9ed00da3817255a2ff735876b75cd21cb25e86aa4b2893f9e5089dfac76194563f9a14335dd37ef06a501c89623caaf6feb4afb792092dfed515ba7518e278c341834a9dd17b50a0fc860b62ec621b69408cb3fbf7d4ab88a3e367fda84c82357376fa9b1161b739361c313b99dcbf4122f3870c8175093298cf432174217398928983ab6cea4759f18e7a21d71fe1b0f3cda05d241e12db0818b8763bd23d958d6e52981ce8d84cd6d82640d2000874a53c0bd14949ec99e48ce6c954ef0d08e6e319de5ebf7e142f25c0f50ff13f6acecde6a270c8d8de05ef4c310ce9e92f40f6f2b77d6e7aa3f056d4a20f7faa7cd0b93d82e3972343a50a26ff462caada10621bc953b73913944246d2a4da25fa52cc6ee1293c436ab9031ee2dc79cce39f139f44d473c236731257c6f65ca4d383e39cf8d33923afea3c80244021d36e0ed43230c44e7d1a1297d35464861f9149d869f26cc51879027169803e43c898d1b4a2a2480197500", + }, + { + "2158abc2472e1b9c061da2c01d0ad9e996fd687cccca331fe8a2baacd12c06f284b1b5cbdfd067e5ed09a60a137ff4a97c5c26482659680ffb22bbcd4ec1bfd272749e52440537320fdd3c225c30ccd98cf221b34b89c247ab7d14f93ed3ccb0486a028c6f3abe7e17fba1742b6d4db85f6e6baaf82df1a3aa059de8d9699821d39bad42d56cc1ec67626092cfad4a2e1cb5d814e2cab78ccf5474a8bd0dc990a877d37de394694af6cadcc57727f393dccba7bf955f4b65b3c00d71cdd701754ed4f231685b7b5e2557239d7e16305be2d81a773765dcea25ea5bf2c15d670f3159409ab5bbf8da121c779132a8ec1480068cb76b68a19152fd83135aeb228b446225f91d1ed4303a4bc16cf3ad8173b30d2a1e75ccafc8c933db231efeae6260d45c7ef230ae2c7b6f986f1c19e2cf260ded9cd99d64a2d03fc5ee3d73509e47ac1c39dcca655839fec75517a9243eb611da8fae3e317e7df66cbb6abd59b16975eb463f509e784e65cd660ef1a4c5027e54b1bc862f397c9cf4e6594d98c2c2830801d3a679220b46881a372cdf3aaa33eb66b91a9f36b6941c0fe1b4d2a437daa50b811f2d8c65b5a69de185d78bb9c2f172dc90a89324c5a2067974aab14f4fbcd06ee95cd49e03717f88480a410afbb4e68b5c79b0211cb69b90604cdfaf08af1ef10cf28f0f630e97ab18d9b5138d9b9ee9154e0b3104a6c164f2a114fa5032eb5c247a6b87880332a0dce7b36982515297a05dc8a4038a09f52b1def7b4fdad8735443fadc462c7c22132f8b9581de2d213bf5c53f7fce34aaeb24263afefead5341a72f88d3acaae6db367c5c14a97d4f9e438e1e11c3c8fde7ee37e5ece5382e8c68b660146046ef96c24caa6bc9fa0a0c88281e4bf01b32df5218cb3750f9c4b8af24cc106abca62d085198d14ba2ded3cafc1fbb17519a696965a1ba5f65720e893f1ef3fbc5200316b9d4615bb23426ae53e1c5a57b2f0ee0d0c83f353b4ebe7a6cb17531d278478b4ca8e6ffdd0cad30ed73d568a2e44972ac88a7e7d665614316d674e84ebc739b645a9a4166477254ba47bc5c2b05ced88e75bf64da21a7f1f71cd946d84de13ca77b7e0dc2f0617d371ed96323a83bb11dfa16f81bbde913d9c259b10f3aeeb6b56cc4775c25f49343cef667763118932c2e8b47ec745ac537b37746ed65fda2d1c11a2de60ec02adcb79152e8a9e614d8715cc4e6b6891d6a0063576560fa3621146308222432ffdbc351c36c37d844a934088fea92ac54920facf870a62e91ba9299dcb6cbdb918e2d54fb642c3f0d60489c4bda489f6c584b64c8f19359ab25f388dbbe636c4d90c048f5ed87024dcf9f98a9e738163f837a07750d61203254a80d120c795f9c3aa791272f9474fe330da81a45be5ac838613d46c25e781606862912ff88af393040605fd4d55d07e2052227c37ceffcdd2d42a08bbab69140dfa4406853799893daf768af546f915a91b81d0da719ebd45b8b5f1641f15621959689e810217bea18e3996c532ac6e4e2e4f289fddd5e5968bd6fa9aec5ca435c532b6c74a7568c8aeff9dd19bfc2fba3b484a191e2faf9a069a24e2e6d928ac0bdf635644cc1ef3bbacc547a8e4f1d42d4bed3b6b8cc56216fa550dc37da9cf4d1d1591d9348594d14adc7a3fde5e5d1a3b9875c85de7df483cdd0baa86dae793e0796d14fef1f649de6079acbec6b6fa5f2cb2bd0481f5316f00dbe5dbc379bc3cd6d13bd8c775a727ef43e6a5fad1051783b22c05a75d64a8394a73fcb430299b015563c8cb0ae0aa4ec750399855411c076d21aeca8656f3d0cae084fb0a1ffc6f73b52a7ea5d4bd6d24e7057a3811719533105fc967439a32241f2d3e3f299da2deb821748cdee1a1c5e71bfdf88d833bade2f505268f375a9e6488cd8e16705cce91d15b60b2fd269a19148296a7be348aa349a12270fbc0d5748e538afeb0598081a4f1349217ceab3c4141d40f765ea2bfffd530fb9606601469fb131a44939be984c07bac8f26d8c068accfdefb729eeb47cfd6ddc646e22031f53a7698c6501d86cbba05e282d64b2f962a1b08b9064078dd1e3f14006f45f599bc8e600cabe6d855fcbae8c3060859202361d929a241f6c0711ac0d050b67a1d44da19e0b0e236adad1f60a327c9c34b2b9c64cdde5b8e4f664f2fc70599d44a63ee2b14d051c27d71231098ecd3d4086038d63e84547dfaa39db1a92785e38b640ea0345062a1c185b25a72862e7ae6574114eba592d6492087e2580dc5d361c473a614d647e66c0a30de806f4976b69a8b92301e68794ee05b96ee116a5fd5edf5eab43dc1103801eec861383f17c2bab9f2d9126c1802b7aee0c909309ee72679ab644abb9c4caa54add283b5954e6f881781e42f849bce6554c7a5e3becc5d5a209805ccd4a0117272a53807e3978ffb19641a9dffd9034490a9284f658599961daf52f24f6464c2099cc9ed3459d84dbde2ebbdbbeef25c882a9beda03573bdd4c6a0143b14d634a1a021d5f9fa23a7ed0f5598ee57e56672814412b6c7c08b8e709fb98575fe2716100d000a20a7e7200d800e556564c7e6a8da9d609b18ff0bb8a8812e96b834a6b534b0d5dc97f5da17f42f8d58e763f1b201625d1a5158c2f9e9e190921637474ae81d278002f197f7211540088931ca8a941794e56067ef4a497fdc6fa713aa9f20c21f23c3a71ae4cc5aed459ca7c020bf55162fbcf56a066546660c5a009b8ad2aaae9651c97b1e145853a10013d1bf68e7df25dd492c328f823ed982da54557502ebc6cc56d4d0bf2881bf3c536ea53b4dcb0886e73b066969dfec343441b9372d7ff38454c4337d45e2b999415ec48f19cd05f0f80c5a61ec369610784f47a5cf3b2a13ff5d8145303ade7189a300936006846812dec9ff15500f8daf47236e724d72619af3a6cb3e854cb8284d5b8843dfe056beaa45c40a4541a98c7507feb27a605d6e07189c8c5554a492a03ce6701d3d2ec782e2c1c8346b54a963435bdda3a93bbac1d837172cebb9cd18903d25cd6bed404eaf18730a6d1c6da0783b5411770ed34f35fa6c11a4292a34565ff1b23d4200ec5a73e6b7905458088fac19f6aafd35e0e791f28bbb2cb0117ca1c3a9e3c4863e487ce5d8c14dd140e9eb4794d87d75b01f683bca84ebdbf19dafab716421bfac9e95755fd346a0cd31e8520a55c7ca652ff63fb4e20ba67fab41e11f7390bc02363162097802c6a9eb18b430d07ea60064d5b546d15bb68cada79c113848136e797577f1783e9b53574f9427be3a28230fdd69d139205dd6c7e9e7f031fb6eab70d69ce905384c5c77d084360aac590a89b2dbb2d339899b13619b455cf9f0cdc08db6c5b5f3223dc3a663ce42bcc8cc6f947f42cdf8dde15a6926b753177513a52be95b1f0b88d2a1ec90e49959b108fe204bbc29199d7382c42ad5dbaff970cbd2dbeade54bd70415e54daa805d396361f525f38efc2bba3fd818f9d7af0594dcc341c20f18c624fe13ce7e7108e1d2fd06c58b03f04642c95e3ba00d4035ea0476ac138f72378d85050bf60dedc90af38e96f67fdc38483a73e847b41d31b894ddcb234f02b0d507bbcb15a8941f9c23b592a291cbeacb3ed213f2f044aa842275a7717757467f121294bba6b357c969e96bfab455c6f328d9e5181d909c3f0543b17d9af7fcac099067b043be79aca8e5a75c3a6d4f6246357a63c516a3ca595447f34b43a055d3070517c67ec36e636aca9ed71a001d4f7b81149124deeb7826dec3697e183d861d544c9c17baff82849d599e9e77ed19f801aa1ce095940674576ff270ac788d00c429187e299a03c6f3a1646a8f7d6290287e70bd1276316ae624da929c67936191abdfba45e2803884e5a3136205a38a841448968a7900709dda033a42969bd3417a8d865d0dbee1f261f4556797dfebab278136a182a63e5ca9789e3f1371808efe06eb0cc5ccfe26c0538d573378035afa39fb7cdf3ad889b277c8c6e84954e74f3ff3140bf13bcb45c822784125d23b5eceb73e", + "088fc7ba068f80efd8d4d62813c93c1eba77e9ff400c7781314abc901873ce200295da09245bf8fd2fce254397616151d94b511957c89a881256182ac9e64acb7b25d4a080cc9daf9ac2f231235483fc9fd415f69caf7eaf0597", + "78d5f86b071bbf8a185e5e2d54faddd2a9e26983b1e7a74be0f0b979b9f4af31", + "d9ce7d249af9496e99c93b36", + "ad542824b49fc520f0b7ff8ce2bff8b3d47baacb4a1c95ed56a306483aac551fffba48e8a8f5e4cc536e9266182f6811d070fb9282f5c542cefb4993ccc7044b42cfd6fc71793dc8dd2de23c630f9ceaeddba45efed9d7fca25fcb07d193c000822478b19c2ee9fb31760cfe01475ba8a003db469d1130318a79345a29d054a9f9412dca1edf6d8f1498af5bb6fdbbd3d5f9a244ff176f62742c53779291ef6294df6540d841f4ee8c7c58fc8497ba74d9cf7947add5373427d81ae928305b93dd26cfc65e63b0ed0812ce759511bfbb10aca98f2abdbc9055c4e5ab82637f6a965bb74f592bdf11118b8eb79d50331e76cb4d10c6b4428cd4ec2ef4cb727bdba2b5375f5184d77772d0f9fd3a3c579a4a548b9c2dadc22c805ae959617af49a514b43f47af834313ed2e4d1fcec2c4b9ea87f328fa3d23129a36e6c54bcd08f7e30645de86e98ebb11bcaf99543503eb1e024bc9fd51fe6bd5e6d749033f2452cdf28b3d0f8a304111bdd26dbde641c02fcb15dc21b1a9baac5e86d35b4126ed1cc8a2c3c2a5b94c99fb9b2008daf1a0c090633bf9e31326428c75a50e821b1e72a6504c9d7bcfcaabecd929163d365832e8971f5efebff99ee3f5b95f957e8904d05b410936d8a81c60b4947f8605c58e5b727d491995c76fbe06e556c8ab5cc661a0c09ebc98d61010050f68b31fbe1f9de8f6481b2704204b0164d8433ba4dc1076908c782826e9b555e8d608463581099a466f92bfd6ac9796eacc0ab771a3f11d03806b0f33ec04c69cef6b87d58c11acb5d1374450ce61ba159456b915043c5c17cb03f0ba66d027105bb6fff41e6422f13e2a466f073358bf68149a3b577cfba7ea08b42f83fbc5a2aff17c5ee7dbdac3ff97389f5b8d1f3750e5c9be651209eeb9574127ea81bd7619da16d1cfab85754883543f6474c8c0cc9d5b80e34bf8262d2b4798f9917bcab4b880339397907a5bafe7d149247fd735523df3cbb17ae5e298846ad3bfb7d4f902aa549b7667d3ea945b002e7b209bc83842a7b120d6d27ce80631404371f31d1f61efc5423e1822032a1cbf4fa1a6b6fe79934a202d5add8c6e3595e49be3dd9553a569521c50e9653bc684ef2b73c3526ff7a0843fcac9cc9ecf46e63df5b9328a54c576bd299a366bbdc0f83a9de67b03f1da16244bd6d52e7e4b52c4ed693827735554b05b3a260cd01a41d7c944d0b7b58ae4b0eb052da34bc22b779d7ad46f90f3d4049c097e0adeaf71bbb30ed24b32ff5c7a65177db77492c2571e9cd99f15e613797e319ea7377038d53b28a4cd66a697e5e8f84cf16bd0f0430b34826114b4e1d1ebaaf2939dff7f9f4ce7c0861e51701c42d9cc9e871018b447ccaf4e402e3d63be164dcdf6799314a389ada8bf5e51a35148acf627e51481b9b0e4bec09c9e6d59229721b151fa9adf8323001fcf33afbc9a949643172f39b0d10ef57b37973683fdd9b9eb46e63054fd05ffbef889ff8fc8f251b0ab41fb00757ec1964ef373fceb8f6d148a7f7c89944b3cfc240d091601b23046188ba70a7cdf7b6f96eb93dcd3d24d4aebdc4a29a749bfe3cf5f6e1a025b62982ce188e6b57245d829c9fc1dcaaa5309a8b9557b8824a78eceef6e977721de4065b474ae008642b974001a5565ef5fe4250194e8b861cc45a8691c461817f10b646fb526bf0fe7790bb0db29d1356e8c7a197ec78df8310431d632a032b5490c2a458eb8d4327a9679d7e8ef8739797b0e820e2c567ce3562592e862a1dfcecd50bf77fcfcd00518db65ee0effb9eb3655d5d401a4a47808faa596d17b316f828cbbc14a7e018a0593da9320140a752f3824b5fcb66aa4c3cb94366ee8b821b09e7bea2c04ece15e8a7be1f58463b525e8cfcfc3fdd395ec5b0575094313557e632d0a65e3099e3c653111a5fb4f0eb2aa710229fc055a2bfd8a7147cbecc10823f1244fbb6894af1408ff9047d6483ef83573b5421b9798ee387dc38f166b11de6c33e9785e9b3d9d28bc24c37890e4f8f8ff24cca298b44d6fb1c6aad28cc634a67dd427205285521a172c2a4884ac5b038e261e38faf0086a02aa29195713cea335c47d03d67fa0dec7a8cb21db741519f5f0ba0143f14d71e33d82c75d6a19b3f7a42e6c16d762354daa2670ffa55bd400637de9cddf9e7964a03b4c8956f36bf54d89cf16de23e8c52957b52eb4572a11d1398be72bdb129e2c1abb58c65cc291bb7b0d2dc326c6125a441863a6c92de0f47a355222d58bf10af0d297a86a98b4e933a8f844fc7f1bbc8ba77919dfc50c41219e3db309b92ba056349faa758daf360b8ac05e43fc2069cd46e63fec399cd7764b111467fc65407ac06f5f84a3179930f6215ac5ec906146c19e0d3e162e77a2bca3582128284282b251cdcac03ecc204266ac3a9cfe8d8854008baf89c0ea0096a400d6a0d2f7c681c99462cf0105f7a3dde690ece0438fbb820b9c73c6cdf6208c336831101b904526cf8ac331d879d71615d8b1f750ac7f0ec692d97a5e21e17e194a98c10172b5c4bc1049a8743188ae7c4d70384a7e68c1353aab7882bb91aa383821046ed0ebabb4b2dd126ccb935f48646b299095cdb71ecd5cc402e4635a3f7a3c8a6f54f4076ba028dedb402bcc92f5668dec3d91dda7319f58382017e306237e42480ee2c1f5930564cf16fdf37a3434585336b8e4535bba87311cd47722b9da727250560624a5dde48a2090ee44592d2fc06edda634b600fad9f843c6b2eaa0697b42858afee8191dd2a31e5685bd104188e2ccb057dd0a8d4d1205d7c846f5b8ec0f06bff61c7f47ac4da30e1bc80a4e95af79b14a83e9af2e0f195cb92d14f752a5f12ff90a05765be453075d799694848fcddb07859336ec101c8052bdc273d4abc313cfb351b543fa340dcd01bf32fea59881ddb8f33c6023ccea70532814ce4a2d0c66c846347b86c29dfc34f6fa4db298911d4367c59939020a3d078194e6a3a3c5126c24ed182398468e77fd61a5b1271f5cb2a97868876954c3f7179d6a045f4bd770f681cd82216cd2b1ceeb4e724b3fddeb74481e662fbd7f5dd45bed6d4f89d21b8dd9c1009ad2b0b16954e97993ab8f3fdd9d61f8db102a945591b4552f419971a9e46a792dd8392c8d9502767c82d9b4f69e66071eb579859e9ca070cad5fe3b7fcb77b8474926ea991ce7ad201421f8a79c051b762a066027ab2b9595a1c97ad57f3149f5872ed4d8e99195d47bd3c03bbee590a50a99d8048e912aaeed797977b52f0240a6cf2c865b108456881adbfda60cf701454da17bae879cf098df808f34e50bccaada2d3edeb1aa73cfe3c512d814eb33897b6ff9d67d3d682517cc333c3c2552adc99860b1f0d1076390de9f84fcc9e802581f77e14f5254da01831c70cb8581630dadb44209377d90447a1a21cc8a2d6d897db62d8420afbcc6ed85ce42f3281255bd43e0afd3e86b27d3b957104ef54959282b0e1b381a26f16057246704c7888126055af5a1f494540f01897e8781e1a5c0193b7bef4b5588d0e9b9c8de74dcdb63f03f7b15cf48fbb71c7c3bbe9329e3d326988bad7d0cb85537c1e0b3cd88f37a3c7765f548f99e495ddc29daed8c7f15dadf2e5b79def91dbbea277c51a5da250e66c305604bcce4789ca2df9a10614d72824ba8e4f179f35ccae7119fd962cce13b282f0f970ca6c4776374c4bc438f0de98aa04fb3cf23d2c6800a4a666c15bd20c486e88e688ff9e5fce906b4ae96ec7c3388d7567ce6c8bc61f6d2373b93f9ddbb02b384084b3f28f54c9ddda232d3084daa5fac5ca356ac0059f2fd3fde5d6a9516d0954653b699aa986f70733538e19721daa41329abb95058450e602eb5726ad5a8b81aa474650659c6f7f6f53f8a6e635bf35f4b1191e0dbefad3be756c6141c7d55f007f4fd131e5d5eaa120ba31cc32b8d4c69d4fa784fe0af7dc272898789c774e7995cb252eb6c8e8053c9e7adb59c27f675952d161dba78bdfb15859fdfe4fe4a44c01efd394bf51d43c600aa9a527d9c490971e188e28b980e77a9c6ea0a4ef6bd38d11b47f5745ecdb", + }, + { + "9cd1c25b5bdab9b9080db3e5e05dc749e0783087c310777d89307138613bdffe0ca259677c13208420d4690031314a11a97a986d8b0fea143f5b4da0972c9ea3cef80b4b0b2bcf2bff392c306a764113f0d9807be86a9027c6ddc85d096600d85e0b236937f295362bc1679537a8a9278229a36a9433925a105ab719c0b7f11fc31488fa071d3032de97c81540713dc29ae02c2e13be8823183f3cd9f72ef8ba4280b4499ee47c7c7c4492bcb5cf7e4fafaa7ec26906e58146215a3d4f52f792d3abdb718f57ed0b9b7fc7504e45a0fdf01ebf5924a4da6ac635a715879ea75a4983cbd9dab9e47638acc687f16684e184443aa9e81513ae4abbc4d1596b2ca3eef77cc9b0603fe90c0570fe6cf4dff0381a99212fadcf7968934ac1ff7664ed6ee0b61e41f5074dfb774b676c2b57a445f1c5749e95ed062837c727ae2c151c0ccb3a4dc1429bbcb9e62325117aca566b8fca0924b70f4defd7749d0389b90f55f35d1635f8d2efdef514f06fde46db6e11e492c8f4dfb7cb5454cedd0ddd32013a4836321a25110f3a017f18475a86583e192132f8d8fd4c2dcb2a3aa95c3be3a57216bf9727cfd1284eea6fa870c8e689e91982c116ceeee2f8298b55646efad684b96eab883fd3d629437e9a0b6523f47ea5b59474a4766ccd01c13170bb08f47576a0fdb573d4dfb65279c1b79cb535426bcab60f4022dc42e40db29f15a6148b461241bae62070389932f035e7257752ef2d6130503d72344b24d360cae8ec11fa2dcbe04d3b18e66d081b552e93a71dc0094d1046bf4491e318f2ae00debffa0b8ada58c5f23e33fb598829ec2f46ad3894bd7f530210371a02e51ae0a414eb2eee43f3e08126dbdbae04c7de4b7416df32953234a6694ea84e6889f27c74206ab8144a393a2614e92adcc77550dd54827387b619f004c13f6c4a31e8bf525277669db0a0c3c589eda15063f12eb774a13e2aba2f2f7b6e9bc69f8485f1d6fc5773acf83671812412d28704003e78a17da25bacd1d61a6d9cb9f121abc71d023bcafa713b7c954e4e1c524e5bcaefd86c4a843e209eabbd579cde0263fc059ec6ff10017ba54fc9c2a1171d6b06f5d85079167117c12e6e5d0c71c008765fce756fd0f1141fbad6c1d2f32cd8e80429611a9a78dbc8e738d458f9ddce58ab43c77b34db9befb25cc1a588998e8dc2efa75c6883244fbbf9a7b4d6750c81b8d3fdedaf98dc61f49d067c369409f984b155ec347a3bef73e2a44957b0ca0f84c7fc335fd89453759ad0ac2fd9a5b38afa9fbe74daaee7bc52301302fb2286c21fb922f74d756de84519171fbecaa9b869682d431614ff6845126a4034f10253aa244bf89ab8e0dfd1f7fe8fc1a8472a10746d26896c8ece7ef80eb2e910069435518ccf096caeda63ad692455b04e6525bb8bae27197ca5118a57fb9a5d8fcfae1b9eb7874d91eafafa0e4fab5cb4d0173f7e3e58fae369843a641e98f3ee460e8cfe95d98f7fd38a8d2235e9d6050015833e6d7d21d7015c3b1ff42f0d3a3d9a38d373c8524752e06987c9408cca550f08c38c2a9a8d86d5ac7a04bab44254ed15c7b5670e0747788e11b81adb0d29e3d0b50d6a429340ee0d44a8c286fcaf9bc46403d26b4a4af95b021336103c1ae0f1274b33bb8b21c8cfca8a56c639f18a9df45d083fa7019aaa14d1ba50eb9a4112e574cd70969640602096265a87b1f77c0e00bbb501555f1626196611b4a824991cf10ab2874a12a8e0390267eaf9e3f8f99eadfbf40d111a26772cda1f50743c417eeec9c80171a83a730f246cf31c6691c96185d672a0fde9ccd7091c4b455dc93326913497396e0a4992773caeddcd783e534eb0f34b99bf23a2db6ee738381b5fc94ff603be014c507888ff55557793a8c5439b11dc5a347f35a2666eda81cda4d1c3a78fc4f3df3c7bde91d05524791b67142c446f60c3a4022912ddabdf817ca3280b671beaa496c935661e5adf39c1f4650563c5c807c8f21aa59df926199c4e2404690ea8ffd7dd65f637452ff93995fe9c5ac7a322b9bdc756b7ed6f533b9357a4a1ffa379dd096f144e9e0d87330c238ed3c6b08c8478e23b65518ea1e4e64585e5e9fec2f26dd7400ce4c73ff0eacdc3b07e4f34f6316f5b82fefc66e442ecc92bea8c1d58635d644724a3380e71fbbeef4bf3e57c6240ff603d65447f510eaa3c9ac794fd24f844489b7c560c7814fbc307e03f6a213eca5ea40fddf51d8731b74ec5b472bdf8ba59751065ed2461b02c41ef96622e60c0d26f9dc78c24f94372bef7e47cf09ed565ae3a52d39b02ffddf1953f1ff500f1659db9f1c2b23534702c19ec1cb7c18166fcd33997d53874c7cdb4e6c2b4d82751911913434e48b37a61a0971861187e5decb7f5c1ef6988bc1d6f7fd147a623d8bf361b0d7ece88df6e1ff8d037762d232e22e51d8c6ddaa9dc597b23ff9efbbfd416cc53e5543253732a23aba151cecf73b3ecff21c6a9fd1f24211fc21cde9633aae918ff1c6b72468f1de7e0ecb6539fa353c069fcbe8920dfa8e2fb86782e3062462f7eb2a2c441bfac21ab62744b05c70b6fc3c9f8e3a8a0c5a4263ed256a019861ecb28e20ce78e2d93f1a1def669e9652cb35d105bfdd5ff2313d27ab3eb00d1b628b4c20f42efa23390802af96a8f261ded3678ea0b780e1f4a88d23588a4ebb058adbf9a9c62ce2ce2f8264c874c697482e25f8d5a6daca4f57fd97d23c42d7b71ec150d4ee33931db5f7d63abe7d72dc936bb23a367c798e6a01509644284d52f9ae27d7d1bae597b2cbc26139354dcca0fff6d76c6065d661b66ca5eeb9f8d85810a029cb95b17e5173ef8ab92d475a1d3e21799e874ff04dbc962c668ef4be9f94d85b2a99d97c0db8f6b6d63e00e36c325cfab9aceaf7597113bff0086e8fad36eac7c0b443de6d3a8533789616d4c863df7200ba795a3b8d0a2b9568bb32af95fa604a3e3ea778c3dae159e1b612458584564ffda07b8aba9710134242b2d83d23127b51b9e41584c56f667b71bc01060240f3a2bc7e5d438e7095c1236e0e468079a83a5dbdcf132d258e9ed18f94d3c098867d06d3c09544565677b454be34ce567f1c143e2f3153bdc0353d65090dfd8f7af4633b89a781e01f4634dd7b0323ea1f38184e697bfc39a1299eaa278c39a2709cde0a346fea53a61f211112450b318d137fe68f6c102085aedabd2b045fab912da5c58d8019239f3a44b18f4fe30c5352e2e2bf030334a1dde1dcd23178636f1e38ec9e42102d8c54df0b94b207e804eacab3edddf89fabda6c8e1bd4e17ae31a57716c679ee8bc7de4412fec3934c6f3e8b4c1d1447dbba0fbc775dd3258f789ca53f1593cadc710fef6fd282bb41c0468ede5ad5b914e4758b4148b0d0c04c75ff6208ca3e79d92de8abafa4ec70ea7a4e454f0759337ce575c4954584e2bb8444c34e823d27b025d25fc9becfb4391df9882452bca0373164cd76e9af316df3f5bb7532e22557b485217254d5ab72ce349620f03758219b259784d4c9f1c7beac3cf08e624742e768b53b3d60ad0b94442c847b84a516a93d9b7d068c44c43980b4c7e2fb0ac964bf05a11fb2adb4f6d938715dde88061b238321afc7e5e84799b02a94baf3f879f89a98ab474ca12085137d639b837ebe069f6dcd8456141d063eb1c032aa392a44d1d58b1e77aba38a280625ab84e3b123507ea7a692c4acd1756c031fa52d637703ee957a993804c13e296cc20c1de55c9b8c032e50afffc51c02e5c12f48383237cdacd005b09243d9fe05e51cea42b77645e5c6f4e48c10e671d216b90a48f0d8f5c1dda553217f5126646d11a62587eb0a4ee0efdaf0d54bc2eb04cd34f5a529b682ce09a34d5acab2c8db58ed6244f7b024e68a14bcd5d7a7daa4dbcf490485cbd38e6f20e839d2b0142b9d766f9527937bb1a737877edf6122ba306bbfb5379243a6b22bdf85dcf3b079691f0e90b28a4259c1c9d8a02afa5b5a661a0f9dac52435e7d22e3591593d37eb2e10f646b51be2d1a96cd4490289ef642ad93eeffd64d7cf830d60dc4a98c768a9bdbf6ec9923062ff04abf19e8b65b95494a9420971018c7e6268b8fb2021a4ddd103976333fa52389643c711a980664e29a8479aa9c4091c2cc2074ce3ac1ab4afa217d39c6a1", + "c22add33457539a957d32dd07ec9110f8cdd2f00ab6ac256b4bc7732f63dd3b867b0ecac262555", + "e71f9a3dd457b4064df1d9055889f105af175a2d10dd7b8729da0d0116c2d9fd", + "7df9824e774c5f86d83cb5d8", + "689683c9e7aa9c48b9fda0cfffea0458ea0c3dedccd21efeb06126f1194780917c9f4f2f44b1daceec3f6b1f75506f4169bdacf12c1f65958784851056fe0b4b42a22aeb043ab35ca73747346ac58c550324c4b849a404c94b8860967b6fc58aff25dad0556f1952c045b91f56ec8eebf6f552c18b2a0641c037e6c6538b289601e1fd5a7bbe7b6e0b224124fec341bf77615183abafb52b3e30082a0abfc2cf224324338c132426011d9f800b382e6b834896ea48a8247f149d92ded7e69c7800096076cd2a729a1fe41c70dafb1f855ffa2ffc27b93e2f5f6827ade7118af60730033675d84de9cde6c260d3d615a945dfe0ed25f33b6cbd2c0e204ee919219d85c7536f4700f06fa61937f8dbbe9bda88db1f4ba8a8d195cd385eec62edd9ce673880800be9aa4430e5c10a5908f6dd349af70f32b32d8db38a7d73821af47b993b622bf168565082d07e88fc48231a440469adeca59263302438ece96d89de11cf8057454d1bfe8e4e36965a4d82618834a0847af39dd8776866d9558a5cff79a1cc9d1e3c22e050677e54ead68b3cf0094daa01330d41bb66708a8bbb8a196fae5c77dc6774629d38905e81d97c5b16d755182f687a8046e55d148419cf9c12139fee50c0533b0f04a805723ce1ea5595fca5b668e58f6b3b396f438308372489b640317cfa3a79392cf6d1afdd8c3359557a83790021a4eb418fa189ad15ba9be0f74182ac76076f102ec171117a3d16ca20b4d200e03e54f1f0ee6308e463a148c0c85aac3ccbe5781cf45b53a313f7c9975a45d1853ed9104a860c08634a8211b87500b5ffa3d8d9d56f22256d485b9b45b24d3873159adb8ae25966cc40f164f342519e88d1ead1e711e1b2bbd4be64c7e83f056f797c2d3a5cf7c5025f92be5637fa7738a1bbba55f761dcd1451ce4b1e85a6628b629a2f7917a86363b01516472c0f8614abe2ad1c9d5501b2a44a68e3eeeb34a64541125bf49138bcd15b7c82dfd40708414b85107d8b982c4f99783a03c707a37787a91a7198063f0e8a2d52dca61755105faaa09c063c7a0849570cba1aa7ddb3600eeba602c7e7c9b90ed00ec731d4d1d8e4bb42f9e9db21616c4aca48dc27b939428834404331288f03c2b5e887103c51748d0257519c3988f6492eb70cabbc2dd8a8a910d737a678d0970ec48bef3b81673bd10b687b37e11d49e7cf90c03c54826ecd833bfd9dbb8174274dd45b139d08371d5d248ee33298193194734c5863adf4bca92bc282bae2f47da5201fc240dd0710a22a8d922faf92c2071a7eede7ee17232d3b6ee5f3ebb1a8b230600b243c860968ab427a5f540912e5e7bfa0271201f288727f2bd5173539d5318e5c1c0a71cba4d9501b91c3bffa7bb61b3713f1751efe94a66e17d2b42da51d13c3df40f4db988dace42a6a1b9d138c4f590b7227990711afbf8f56fa63f2800cc019bbd4a7b3a0983c9b9e5f77562dcad6de96e3b2eb85cd99d28a021a10d6734400a91369236b48ed68528afc68f247d45c79318fc5d634ecb0f3ef8536d8ec2e877adc3308be906c5b96777d0e05970023e5c5dffed12310cc97249e4b95e32451c9acca8394fde699deda57e938bed7167e62e2cb62357f82fbe821ee73b4e09c6e2f512515412c2f27805762a8493e74a3d30bb409e499002a97354381318af28311ce484bdf7c39db53f08f73ca5793945e13fc8c66d503fa95506b37ce134ce2945d75b424ca6367ef4ed47b9cb8ba7de80e773279bf23ac888eb105385ea958b1b49b27c8db6b1e14a5c8ed5d28808a7d0b6bff1a58f24f9c57fd8b8f477a9d1365f89c698b8ba923896181299d474b93e05d3c915b10a69e61910761a6d8644933c593661b0828afeca590ca18e702322d9140d98fcf836c2f7a4f72b59eb529823a52ab05d919c3eee4db2cae1067213c5070450a160fd52fa44bc9bacc5c136701cd7adb1faf484da376477da08f6a4dcaa37af47c7b026c2da9d5fd0b30741357104cb2bc0d3cebd132b5fc7c873ebeceec5492aecab95ab393f35b93b923d2ca071e6bd8522c3ad8598a05e96646504f1620c045aa5734d665acbdda0ef73612be4ca4d95ba069041e042497f7b10445869989ce30f55206a1feb4e64890b7d1f7e9df2e88a352674a52ae4267c06592d425ed1d88101cf94588135892218ac11f3976ab2b47a27f02eb887696c94b13d48b4370eb11222274b5513a0fef905c66d0c1893832ffdb9b333178b65338fd8b81094d8f86f2e4e96a47e72032cd6fd47af87eec295c6e980f595b57f79abeb4654c4039fa03ade732b1e579551898b801ecd6e0fb1c5fd198335834b51673d074a8222640d2a969998f5b878bf897fdcf3426c4e24a7c599e5567643fa79ea5d20e7de581a873ee0181e3632a4e304f9dae09a81f882d4061ec17e588793b160c93a926874d5a8b78727f88de9bc125589a9562db5bb1c01012bbea1b2eeab68877871ce83455db43cc48455effbc71c436aebe362af22c6a319d134f65681c4d0d51f9aa42fb20f48ae3f7065664aeff5d8349624a5d79eb0bef3cbb2a1244ee445f560a6bf7a796b2c950a37dfb85ed5be11e8e305e835c9e077e676aa5ce23edb1f74806278548e3fa35059abc2f032289f9bd76043c8dd1352b6131cf34f66bcd0e7f1d13081f5b08ed0c69136f3b7ad8e05e9fe99a9b73624095f96740c1f40074e5d92ffeccdc0f15502082fdfcfc97a800be511c22b875f2832b2b891cb1aad2a17c7bd0be4427a4549404172f7c14d5e425e14498237c26a7813cd8612d048703cb180f1a6194f688b4644304950b078692faec7a2a5c5bbc482f3a7e8ef2825c4c19032a7a79a2908ca9774c6403e6b15625c485f2dd078902aff769dfee2dca9373704bf63ad981b51f61253910fd48c49ef10e3938f35ca8dd491a8e569baef675df30367b093f1088ebe8f876191dc32055481d074e5e47a4bd728efaea9fee3e83d8556255ffb2fa08194bdc66897d97d1557186d5f873169461494a83368ed8065b9a033fa4c2f07f7c60f945b60479e3c89233d58f674c0c6fa5918150bae0c6de2b65a09ccd490e2ad8571745bc37e70982411af667f3e8e9b9f7f75d863e5fef05c1f0d2acc7c86585a83ee32e0a64a9e67e75b80def5bfeb7cffe6e6822efa7a9cf049689b58336b081c039696e0fd3b2a2a6b0d177c9b3f8fe5cbb1c69ea93c1235b2c5b6934f603127eeafc4ed0728161612acdb2ba894a5ac376c4ef1fa8d49b4722379e5cb39752837395c413dd29a2a88c03849b6fb2221fd85ba6d5a50ba7ee9c09ecc5e6dc66afdaa1b021282cadc68f19529eadab809341187d57cfdfe01d0798ab8a94277b9b868612e575bd98f70de80ebe5f57637c511800373262eb5ac3836b03808ca5d5f732f286a5f18a7b7fb8cd8f60e4debe54731c9c524b84694c5469975443964ed28ccff2f4e8e0cf4c60c1c8a092e986cf12fa90a994e4f26ac89fabe8a0d1e27fdc00f1d3d3fdb73bb76809f93ea113e336cb0a5438147e454e262fbb7d656aa1be1288839bc342b48ba7d0e72c85a2e24be1a97dfb2db85b5d850481e62f3b11a28c6407686e73d550b9f1d0f010602e82af26813d2484a8db2da0814782c8404b2865abfbe3c98a07ffb37eea6de7992cad73a9b81ae96a9acb13ba213eb4111d868cc73b0432d2b6c2d7e0e0ca7ccbdce86d01576e1136871a07c76498eae53fb7ebf2e85fb8561d10dfba740400ef4495ece7eb33ce3bce26344eddd88cf1ed8028ec5fe8e71edda54dbdae08f50f8df6295f6d7ef1163f62262a200456a7777d0565d7f5832fcc7ac144b5c3e0ce3e5c9b7f880a54ed5e80662e96b356ff58f2e372b1dc0d73cb8b96c72caa9e5dd312841a8be23f838bc706d893e1a8a48b2c069874c293c41d00226f73f987aec8686046ac4c0c972c991c38b98cabce30e7255dbf16039b95dc7d103fde630b03441b15bd2c214763fece9d6778d1c6354d2c9478c226175c02cb006006715fffc879a6a2b4111f6234ee330d6c84d453c9ffac08efda1f380110a8ef8c2fe44e2ed644cc3e0146b4d02f76586fbb6d69b827be38b9add444e2bac4d7165007cdbf2ea8c4b967fc1bb70c68b229f19bc3f79cb13ee6265264885f04c09a96583f331ed46de3e5dcaf08313ba6053f3d0c1916a0f", + }, + { + "3ab6cbeebc18df951d371e0f3cce2697fb367476bd9d50ca9e668c77636eeb9d24b68be0ce6a75eca194fbde6221755d57e9d3148623de24896a9becd98789fd3d14de0c7e53f81fe7f3fd491472a66b5b797fe19c5d0525c7a111a0289a9e65ae7c712ccf694cb75c490070bca7db17205af9bdb7fee27f9ff41fc78ebd2d3d399e690908b5c064ffc0d5bb67b0d2880bcb45c2ca2741691b6131aa1e5ee758fc50610406216905e13ec049ee92d1f95e16bc283dfd91595ec2037d20ead51d3a362140578a4538c80581b79852b0f6686c1ea66aafffc872024592ec1aaf2650d167a75bace024b261db4ab48b401cf85ec2620dc12a7fc37012af8ac1d6db923d82eee962129bc4ede578782594708357d29118fd10dc6d228bf7e461d2769e556488b776237b6309f3dc2e884cb2df1f43f71c53d389765f805ac053d05fa835e75fab0adb0f13ceeb425637f43556372d728a00fb005f7c5a20cf2b7f776066d60b70b11a848005c6d63dba0c93f139067b39017c997dd6b94c0138c3619e9a6d0e4b8792cb8d58a2ca12ae5d03e7637f2065fbb9e2d1722fd3aaf234488ca157d829e9a3b642458054f3dd58da41d7fba6d2b488a327b776d1aaab1a364c710e755ab22b9cf7abf1eb8949c5ca20c070f275f8959cb00c6d5ab7879003f89f795351a4ef4850e033d929f9a349b9133b2e0bd1cabbdd381594bfa697b845100b96b5fade05db12de040b814ec49489f39f5abd5b37f570cbb516636d5b7378f12872d02d4de20b52ed8ca0b12029a4c084621bbb578b870ca2ea79fd5df1ef8664bfb3b1a1bf038e4ba33f6ccde42c5146470c9dd293aa747d2372db1561617920142ac1d32e4f1fd18e8b9e72b7efb8fefc56d08f00450d23b7e8381849b1385ddcf9310a4850dbd6db7a4992690190655760f557a5027b5ceab3743365ac9041a5c14bed1126c4eca00d7e0a0e0e6f666f64bd1466387150ece5835192149237d5dd25e703e9d3a4f652ae04601d6acf8228e4e86055394c3abc9dccd02f04a60c298d101260b408b2620c137f77e2019fc6eaff1b234c56dfe922b0192656254fe3356143e969f64b7609cbedebcc8cb2b68bcdd9d723b9c14669da6cbfffbca2351de51e87db6afde435ead0017682b8014f91d9734a9ab9b374257273e114a8fffac786d53183ba666d8a67e30c1fe45bb1bdcefb5787afcbad213f8e36e78d30ae1305df96bf450349ade655cccbb17d887f79e00728abb449ea427fd2d0af80e3b5607a74a57dbe5264131f2fc49cb74415974b3d43ff872d4106ff11b680f56be06fdf85ec9dd850b1f77f759337b9a9ce04e611036d3f45743e562abe4b959eba7424a712fcf7c3f3773886aef22f7cf6168efa83cd3ff70b9521cae1b6689b2b8c423d883a007bb138025f2a31db2147691bcb365ac242efe40cd09a746cc501ae0289e80205993b07f86538d486803da14b74fb0db6ebf1c2bb8c36275137d654c1be56c65891cd50f705247d85621fd0d61ade8c05cf4ec15b84e8adbcbe017d7d5743d5e91025e0154a5d9bac7c6b8297490e9c195c5d74e046219c042219817a5c56636c7c4382c6a01d721d88f4b4d20250eb5eae5f3ef481dbf8a3f47a1d51d080bd4cc33f12645c8481e57835b77a85a2d83301172782f22026e69a43376ac4f5b78734c9eb914e6c76c6a12d4127cf195ad030825322a279093cbc40a680355d086a27f3fb7560713b019e7c286d96833dc60590e9a709f2e3c632894668e74ed20e42cd83a23ebea3dc3bcc49d14f8697541780fb2072dee6a5672d0d4e7bdf5cbdacdf5fea9e03c6d9cf0faa1e954172acc26dcd344bb3d9b2e0e6015cc55d19713d795bdb7c21b44b305e69c69fdb7261483f9693f36f45d356462f1ba4498de1c2e8bc3e0a70893acef2006dcd73cf15b265a8a5d4ed792a34a846d8f1d3b9b3bb75f1c5e57a00b36c00203973ef4e2654f6cb29e4445318ed99f0de6ca992281e83ed03feedb66aeed6a461c6f2871ae95343cd9797e58430d5639d7ef5c59c78b29f76a055e18e2b85eff177770c60ca4f2d61e612e617e749b4653e7901b62ba02dcbf50e59219349120ac01e6b8a6e98eb54abd16b921a1ff85898f90fc49a3c8f8f4ae9b0dd32c3e7f2e1527c4feb67a496390f28532f20acc71abb8bb4f71b434104f41e36b705289858a4e8430b8cd9449b0198ca2244923cff1df0f63833373c275572de5a9a77b23e5ff54aebce8e86d02651f26ae32e69001e5f3951967579ebe8574682cef8c12dee0b18bc999f8cc0f07e2ad3ac94d3caf30c1c8a8295756aecbbecbbb4ade8a2b8015e52a0eb1290693c6316d036e0c443fc4ec591c32f7e7f1b3933c921d5812233d3c21ee5528822b59ef2ec7eb62f7b04f40cc8238a473ec37a07e54f8907825ccaa1421c2964d2c756be450dedc011e1cdd9045720421b9a4a00e9d3076c2fd10d71ee36d5c0fd2c7e42396b034a4cd0245027449242dfdc42c8af4a34df1b4150097726c9745247b78bb2bad5fe8af94eb13ee1f41dbd36e56d801a4c9c5b9ca5d3c26f4714b6fe9f69b87567426eb6f4ac97e8c9541eafc19fc90d3b24aae0f76c4f3f81063d206ff695d638048c2cb023147a78332939d2f2470d16f1ed0e5d3d4dde438affb2809488b99815e54938fac3b02deceaffde310cf422f9027f364f5e79da5d2b5af1b4138ac9f9d301f396b220829c1f60cd2b54ef24576e5ba6ccd4802900db1bb4eea57de7787eda0e30fa90cc19f099444488699bf7c442c398c2ed989d084c8cadc97325484e337848c34562b3dea6f7670f935ed3d5216c970e04351651c1c31a34e862821bdbcbde202d91fed38965e31cc3b6f1e52288f327bd0a787ecd92b3b6f535d1d000b0f02d41ee01ca54e4e6179ad7fcbd60f0e41dfa5c9cc7ee4f7de3844fb385ffa3b24092b30be697f1fd32c9faef29ead346e42fe2ab1d312901b678b43b7758edb7eaa1c2d038b4cd6a7dc759a6b12cec955bcf4179006a7ab6e22ef15986df107080d340b8870e2304d57caa87a9961c04655d7d66c7f71ca9260e02aced131d6de65d256d6b487141c51bc86eb1e4721742f07d09e799b30da7b5ba94c8d701ae34271ba06f8ce134a7a9a2598d1570cf05edd9ec868cfa2e41b4c20a8bc4b8bfebd45f5a60408f08e931617746d1464bbe1f3844ab3272ede635f771f9af30e483903ee4d0cdecbaff4d31451e7791dc97c92042fb932fe1c82652c1d682a55912e33de3b1299db076cef594458670dc4f911f4a244e2bec757dad4b0052a41235e2f5e60b929682608c16a61287826218a1ac3cf0d8286555d5b0552754685c365d4342f0d9c45065daf6786179da791a86b50a5edd6fb4b21f09d9747136aacf79ecbf52b00fb88b0630ec7f0a6699901ba4eff913a3ab33ac85a71ebb51ed343eac86eebb3e79c16e664078ccda09e77ef8e0919b8cc447116b65ccbd5200fbfe86e9bac5637b33c9bcac9596b57c14ad5da548e96a8ffad5f5c69247c68d464c770011da7b45a337f138cda6b4e15311879bfaf12af4c61fba596780e6adcd5dadde372823da6014122dbac70f0dd896a8d387d3c74df282a659028d06cfeab3ae22dcd1fc3ce60f69a0d678aeae0e5681952949e31ccb8975cd167c9d012f4b230b1c1f47022eb1a3042951b338a734cdd17db0ed483a621650deb3510efe74191a94611dc212c0c73b117a73b8ae41892cf176742bd98a7cb73dcdc53b42df56d640739852335f8d44d901fc884286b433fc285fd5b3db8df0a8522cea3182c071f559c328b8516c9252681a94eecec7ebf626c0a9014d9aaaa0c694d14855433dae06656657d1f8a939123d28e00513d72bd3802d211ad7c1e06b9228c0d5656edccad5339bcdddd5e01afdc01f10974be3187804324fc513ba583b7b2da1e9096bbe3d078c1adc6c34d92c54e9c49fccdc17d10e66962120ee5d9b1cfe852569436270cf7c4c3bb12568050e2ca4db08bbac16214238413195dd4d936272fca5d56d7551b9b002df1807ed44abc84c66746387b79bc9e830a635c308a7bfad7c2c22cee6d3d0c5ebd8b230837b7ceaefdf71a67a3a8eaae0c36de86b2d96e759b8b53f8b8604775eb7a7e13223cb21033dc87d775628581a954085c2d66c1c8f225b1aa86091061738e7495cb36a5ff032dc678904bfa39a00285cd6947865b6d4805e3411644b4a4c94a6fffe05ef31e156bae6165d801685dcec195552d029d22e5de393a82ddf3cd3de3ad8cd6bba2325a03982204f07fc3c21518ef17a601fd743b27f7191bb446ff61d3c61d7608777990997e911932532e5b3235f13423756f5b6c786720cf6682932c90092", + "50772c5a0e156ba13a9d86edc0e600021d56f7d31e7e452a74ad53a6775339c7ca6521d87a8c79b42900a1e9e6a1ec03f7e3d615611c3fd5c9927c40e5b508af1a298794b60148df01e9c9e78ab5ea8198c097fadcd6cfa6694be64e00eefe1a1885aece86f6ad87df766e692b58ebc41982bef5", + "93a2561a9904a1787a10e2a668cd6a814f2877a7b512698e94796805875c8d1a", + "588d9bc1d98210d9700ef488", + "165d8c9eabcd5e93e6eff7be122c8c242e1a7f284790c93324f924efabcec4a4ce48262011b7360c2833143d645ff295453853c92f0c48c6dfc2af7ec58d9bec0d13239c7e5593cdb39d49376c6341263df80c0ed2ed79fe9899d0c07de93f6ea95a5dfd307e49bdb5672b158a4df623ee86d54cd1a0fa9a60ce39d1f5f4b6b0ce9daf2a61a907cff3bdd3f29156ac439638e0910d728843ae17ea7368814ad7734732e7c023d4954e1cd5fd19fc9b76e9bb84b61dd4371478917757b14b366b4bfab4eab0d9de746088ad43d8742e2b9e58faff15c2eff084df5f4316111d5dd7d23cc0b1ee1000253f26cd260aa636f03f64a8342e531ca1515b3beecc3ee07a29184988325322d5c09754c278231f92c0d980adc919d4fccf4a1da1d37f1ddb58ca997d6d700946199fa007c43853b6caf5f8049233584087fb23c3952414ac487e452f0c3898486d04e5b008b843122501f9c8a294da9159a04119ad5c8e9f5c211411e34559d3a7bcf2ac10e0174f94f3f2968c80ebdf4498de172884dbdad0acc3a887f9bfe896a6004d54cc424567d53f1198ba33c56aa460edc6af0e437b34322c1144854bafb2434f00703c1992dbad0ceaa0616aec60a380676ca11558cece57a936959d6c2ffe0647eeffd37524fbafa9691f31499701b202d9dc9980e79ea517089eced779aa45b522c9ad193e63ea8b64e8a942f630d44370f23b7e9acfedac51dd9f139f8806b09a8fbbabc76fec3c3721fad5087a6d41f93973af8d787d8bc74a3122d99ea14e2f30a3c90be4b695c8b269784eefafa52d6a79e785eb47a23d72f037ca572b7029d2f37baabce57658119fb02c5b659e3aadfe0052f1cc3c0afc6fe4624533d9700388713945c20c1d175da53738fc73f48fe57fef8305e796b474b6f8d3fc5040042373a13384237d95bb045ce0c20934a964a8372acedfd6e559aa84180a86311a3996cc17bf7f73e5d85d4db2529989e5836edad490aaa5f56d17326825aa20608fd209903335de4b36b79f68b6a52194f6ea8ce42570533df650e65b50c367f69b9f08c32b3ce3e75318106b8b2c6b6d09369c781fbf2aaa35053af215b621f833814ec4778ac683de0dc22c418b077a917a6e405ccbde9f72ed523aa696be1a6f247b096b9235217bcf19b88d43178cce5a7d82335fccb4c079e00280bfd272b9f16ffefa7fea38d09dfb2e4874553b135052595812aed3fa15096abf1eebf9abd598289e0d156974de4c2654c60825d42b662ca7439816d9d3a0255f40a4965504f643f029da535d4b109e8658ec570e99859382ca0ede0b0495d508c63c7f1eff3f648c60e9b773590cc663a751178ba7603a11985ff519056661b9460c1aabc30e83bb0073a927682a06d1b8050c345f7920c1a37546d79587fae2a92c803a986248f90547f0b6c0ad0552d8260d2a0dc3cc76d092ab76b8c12f05dcf141167a6ea300bc23227933396ef6fe9d51a1ba5a754485950f06cfa6964db2d0fd1d4393cc36f0592fca25ac1a6aacda2a32f548ed20287e3d291661848a62d41504e4fcb1cd1785617fa5786712b3005f1a1041733df6cf838ea3ea0b93685889bc6b2857d80a9bc0e7a66f7fb3d805770402f049889311fc112dccc72a25bd127777fd87bf5ab56d39bfe6be2b45a8301c2f324dcc50b27540200d522c24941701f7293b8877ac84cf35638507c7d912a3a94e4384b68c507412df65d0c4ca8ec2da704bd4483eb2e0d13b68c0c2b68c106a55b9710ad0a1436d655a3cf3c419d5e6f027ddf5dcfc896a5b316a7dae9290a7bf81aed539a647c8c98e24e7ed6a4f7f00a11134ca715e5826625c250500f8f16b40de048b095b5dd08268407f58a91c86c36ca5a2bf4f8fc682adf1bf601da24414c74956e1a8fd2888b5260e980c32f6678a4dc4ff73220c22593d23144b84c2ff56920342248876d15ea54fc100c09a81b802dd15f030bda9aa08727ea49e34f0ca8693e0a06d0af06ea7ceddbf0584adfdebeb20510bbac683451d9f84cf0f4e85c34d979e550e07e7f414d6f1011cb3dc28d0df6d4aac113f2d5b04e4486ee2cdcd4157dafcbbd55e8330a7176d1b231d9f47a63da9ee30fec6cc2c5aba3a8c6154f79997af89d972743255355647235ee939f4f305ec655271e0cd562ff6f401b86dd5826c769298445108ad0d9e13c504551f74c507436911331db60ef0ea99dc259b13cfcb0596fa9b3c95cd7fc3b1611e3b012b6719afbcee7548939676dffc372276aecd08e6a14251407cf995266545427d49ae5ab245cd5d534c52542fc71b3973f0b766f3d234c8baaec8b74eaa8ba90abe160b4504769d02e08d7af4e7ecc167780c619cefa58865169b674b2b1e10d82f6560ba0be41a781f4afa46bd722566d941a8e6f87e4a5c03d89685a22a3470354f2922e2915f9d46288a5e8896ed13617dce694a595e379f25fe621dde8ba73d865976950954e5bd07db147a0fb74f87cb06aba49b073942b82fab33a878651df73df2721ef800b658bdc6c359d396f684598e93f38e79639b8736b02dfcc124fb9fc199c35f2fa1d0dc39939c57286e58a7deed7b6c76e02b99a14d9bbf11f65d8eb7fa096fe4baf0f78cb34736499a0ca550f10d7edc8909dc34b039e3abdf1aa67a51d37a2eaf4c07022897d4d8355d3325bcf392d91d02d462488ead90b366e9645b956c3802e4249d34b5b2b2484a1dec15a9477821df6bef5e1626ec5ee9832fc3bd0b63a3c4100d32fac3e9085f0b5ba43123f54beaa7ccbe6ba68231649f35a28acfcbbf97dea2d6cfd96025032b3950ec8437108d0f07baf1bc89e3afbc2cdbb5031d3cd9e20b19018adda466382059229e4c8c54b455eda4280bde43b36afa96e146e408c7104523d5f565d22ef86d4c7cbf9c6e0d0b30e37b37feb9332939c642eacfe19d0dae1259d3267635051ea5f9b518dd74786e45fb8bdf72cbe3753bd50bea2a961b49cc0e2d589e77fd25ebd962463fc728b1d288c38a79a182b124d345872afbcfe792d259e7e5334311244edc75d05f9a12eadb61fd3ff79fe8c097eb01a4ac1f0c339d3be74be3d96b0b6a15e8868d043a0f2007ee8aa51756d78b7a78ad90fd9a26afbcb51fdc20ed7a3947f715c833e363bb87504d8efc9f8b93a993e2e26430f79f3cce203b09093c9b456b1967212eb0db4f7688d4dccd4a523866f75c9d9e7ce07825ae34399c5607a60b771866a647b6d5e1e20795ca906e451f367d8c40ffe79a2cecfe7aa47a402f8d49be9084661c96ebb11f1b48e7e8abd2978ee626f962e98f99db4eb3c6a52aa2bb2e62194120ce1e773b9db784e8c9b5adcfb70e3bd5717293eebf014e9872c5c1bdf3fb296cb88eab5e97a5ac320092033b49f37d840dac23021c19ab2a89190f3c8dde927f6e6b41874bf71ba7747a616682bd5b3f17a1dad40f4993a1b186ce4f44afb4e36af7715450bac62cb1527eb8db1d87bbc4d9c99415d16660e48efd911e02f5777a77e72733af3c3f5315dd0c785d5212b79c46c3bccd74582c57cfac0d50fc0c85370476913f9d8e8e10d0f6602f2271994972de49ab1a91728713c3cfcedb0e61c270b5fb331a980965bcfe10b41251a0f7915d5943f49fb139626f1c424524f2fba3a407e77dd7513669894fd09fff4185fbb997b4e4677f6ea0b52892f013f1691bdb38eee9307a565e396bab484d91cea9268f49aed29e319b0add900b6a75f7461db5486aaf5366f98df05674361308931de753c70777de73337a996f6d4b0e06d63a69849ba7533bb0e446f062edbd6250e61a49f4120f84efc1cf74c1bd30cc61a2d719fa76991dab119fc814a7c56f48bd584c7935679c53bb0ac78905b5d961fcd89a4b567d17a5182651cb07146aa9a94972ce613e8ff9c878a8433c0244052f09980a52d800e97ba65e8ac186862def58c72b9feec91266e26aa5075b3337c7bb8716b3acafe666ffe2df32b78f9995661d3ba28f8a8780436aae1da2a3e6a0a16dc562b8d5df6f68391aab73a10508e0f55208f974a0505f0fc0d8a55049a7b631fc94fab91459ae1f199527362695b41972e50faee34c5cca9e35e8682099f5e9652f88cfe9fa990ff2154c89c1c2a4ed6bb8a889fecfdf048ee0aae7798c55d6cdfd062cbca97ca289578c832d658ceaf26faba54c9c3ee9eb5bac80698c1441b9cba287f749a5e30d5cc715a01c89353ceab0974ae77fecc1d2dfb31a5101783cbc002c73cd155dfd14685c2f9acc170dc437c649b6b4720b676848a7f9b56cc4787eabe72f6e3f2aed776f9bb1432fba93a63bfa44fbcfcb6eaa9ef4b79b32bdbd68cddbb9897cf5a02c6f99fc765790092edf0d5bca7c55cf232a03fbb6f3eae09b12e09a9b49a538e0589394700d16ebd3", + }, + { + "3497e8d61062e6f2084ebf72d00e9a47b550591edeee9746f31ea28039a1646d384c4348af293ab778f92a4807c48fbd14e8dbf3d67339c991dc4aca7dae38b5fb7bfeaaa538611d328b653950f4f664dcd257b345917cd66dc6a1ea75d99f70549d1af9d67b1608077b41576f38bb4c0a13ff4fa47b251142c6fbb79f9a27f43841ed0ebc0416c37f571aef8fd63b99e93ae88db50e9ef7d499ae7433d5686b165579d3598f96d9e7b1c876870310703df8fdf2069beadb34984f676eb7d3840c4c5766dcee3fc39f0739260a499647429339482e232362bc72c92a299cae36e9069cc5f4db8893e2c1b9ec0b4f334de26c951090b9724c2b3b7655d8248bc12a27861e020eb1e4cf6ad0dab903279b6fbdabff761d4ba159c1f631e681f210a8782faa86e08e554b5e30046157a0d1144bd08a691c2cc2dd22f3c3a4e5d44c5d03f7e3e385382ee4683345c0d316d41ee75f87038b49e0ad3ca45121789e7e7b95615e1a9a8dfe02c044c2935a97b141f639448182252ebfc980e0411e5fbcb3c01acd5aa7cc5d67101ffa6ab6acacace5f02d67155c26dedc071ffa66dbad26f67a819d46de0556fdffc1b4ab6d60905d8ef873ea1e51c62571c08b4c6db242e733e02e11e5840ee445c290b2232010b118839b37d4615c4521e8928e9ad475cdb4a3de9928ec7e6daf0e20d22e308347b31e7e877fdacda0c25f2e5c33a329e84707816ff4ffdca30dfc753c2cf883df16016795db34359e9363fac60624ae4d2b30bc1f2f99c23d953779c22ffca145fd08dad83c0f76cf727196799544c6c07483e0a41ca2e1b1da5a730956154f531d292b5a39a229ab13bf24a804eb68786e481c8aebfd3bc557afceadc41d00e1472c3b80ce652be1245089283bf1a1a93abd3325bb6eea121db8c0e1d6c0c31decfe9dba63c89b881824b0531651fc500f2f75ca9e5fdcbb179c9ded5d600a495ea704c2709f4a88c4fadcda4cd82a5b089f25a6fe0161159efe03fb5e0d44bdb5487f25e8c9adacc389860f62b06a6a4f8f104d9171622f70652ace736e8b28b70a4d9fd3fa4b9784d1a6e6811150d0a0601d31d17f6041e58a1058f99b80b0a6cd4f79c79a104b6bb731ecc881bc68e1d99ab358faf43d8504957ea0152e46e27dbfaa17d0f58287276e4fa82ab78a03513d5b4c3199d1362e4fd6447d1c26fadbd011abc69332ed0181952b391f2e8a5c89d68e22a7c451f69a9573b6bb6d918c7e3d52116f3f12f1d43d2af46bb450f58bde1732a268293cfd9cf2b90a844588c1979a30d6ac21aaea4b9e5500ef4a8bcd62bd70cae6acc8839f818d23c615e45daf14335c36dd46817c9b816be60c3848caa812b055da33f45bc01721d6fb7e850fb1e1458f27c70bc34876a955aef11f5703cfacde03a039c3b75b99b2d91fc18b00071a28ce25eb169b946b49858aa0885a4c665deca020a3fbba55d4d9175fd91e7901ec9eec0239806e8305f8238e5270f4af5c94d0008f8a5564636cc33c8a3d3e76db2a7915abe798b0dfbb3e322b33e188c7b188573bddbb9e4a7edbd4bb194b9743c4aceeab449f8affddbc2b109eb3d84f3b2f8b18ea2962680437241d82bb6146674ff1abee7baacc38d5dcd688b425c3e3b0dccdda3e36de755afcf7155d3d7cac2e279baad167e2a743b82ff8ddf3db8ecfa9680ddf468339427a4e9fb8ca4ce6f1e790c24e7269912a9989088c65965b0efe68ed44eb26876674261e3e72042f5995f1a7075b3932f4c23a8027d0db35ce4322122f489995bcc0b3fa32b7298c4c1b3354766c866a2fc0ea5690c58c5e08ae7037f70accb3ca7faefc37d78883f2bcd768285dd2571dbcaead813a0b8ae87cc1df868e93500d414c4418d5c80b919f73b9fd46111a02bfc884f9d30ee14fcfc1d55d54256b9572afad4777b8d8172c911472a22e7461f6f85aca063c19d6fdef3351149ee6864e93cdc54ca5dc7837f0ead91f5e3b155795df5dd1f933cee8671ffc05058353995019e5f6f55d2de6470605a5411afcd7fa5aa8f38d77dbf496d7fa9c5a4d35ab661aa15c77ce42bed44763166160ed5bba954e470c293ca301363f5b837406ea8ea746057588c34acf266030864d8c40e2da88ef04c49205fad1607d456767d30eadd884359bce04c12e35487bc1885d9b104c9fd4dea4ceaf054cf46cb3c77a619ffe963acc9bfcfad0447591ccd32cdd1fccb1fe7080ad75cca2e17f695ce0095a774327123f21e2839773506a9f2d896bde87dc5e35512ad733aa408f8a49e9018d1013cc32f550c968a03308cdbc73ab444f0a79a13450d4de906369da4c6a675d7e338f738358dc238be4f047579c8ba7a60448da541cb9e57f22bfcb8c26280a59b77edd0f5a009a3ef1e2958d6d3c3372840dc6a0c6ab1fe86aeb7590137feacbfdc7da57c77595b8572b45c4677836ec86fd8c4ca8ac351397aaa3aa298d752754507e1cc514d41c3f1ae0a692179218141f65bccb9acf6244730c6d00829455d21371972745b3665f930cf2aa9f0abebe6f7b89094aeb4dbdf7bbbe794f134b6284e289c995ef2929fc1bd39b259259950de29e57cdec15c4a7d33ef6e689596a6ce23301d25c2ace77fe699d90c2329da4d0f471bc093563dc735ac2fdb32c6995606a67bc953534939ed1236003c004d3b47590beabf39a1e4d5d1b00898496e9effda68433da17d1ab3a32aefa3681aeac116c5705077552649153ed15e9d704e67d8819579feb02d91db0d3533182ff43ee5648f5cc9a595ded4772d61e77bd9bffd6f29fc1f478dea44c32d5ce3118bc8860b254fb0bb1e85223bf709a7c0b9a52fd3914f1b1f295fd246bcb568388dee43a32df45e3c798068608a102143b5511746903255b98238003eed68776b46bb0e64af6c9118ecf9896709aaaabefbc1f58bf45b45768345b560ae2cdbe4d7da497736da8013c4098addb4258cafe7823bdbdd715250b707b155248d39fc6773639e4de3b201fd3cdfa1526c4149ee7d15bbee680c956fbdea844b1470a287d430c5c7e2d7b51fa756720397bbe214c19df3399a989958732d93979e361f7266e53a59bcef695435db67cd8749d258e7d582726e1bcad1395e68d7848849fb6d74451a53ae6e8989c64701102959f7fedc6a5cf8352e218396f9181f33037ca74886fae6e57460bbcb71cbe4cbb3d3a81e2090434eb1d6d5baeee4ede251952ad88001ce047279cfe435a4afe97847f798d84ad79a11bd44f09222d2f3b7fdcc47ff8a4c61f40c4629a0f603193e0aa2164579a05726e547c9081abcc0087907f8034469f740a020e19623fad42e9cea64068abb3d6ff2f6680da328061c200e1f646816a5083786ae5b71728a0e5cee14d7a942379c389fa9dbc7afe7e7ae075c061df11e4587bc90f92f1b077c091c43a25e7b3e870ad852c2883aba2632063c4ff74a857ef7267816317f823a8bc5dcda311b513be3a40e6bdeb89210bece50a608e624f00c9d063e0c8878884e45527f50a3ab4447a9a01652322700f087b6f96ddbe96a68ef98656800eda6563015a6d3c0eb1b6a9b21cccd58cdcdd074b73e40a098a980210ef831ec9e881cb42ee07519fbdfa52d9c62766a2046dee7752f880dc9082ed7f050b49ed8d14307b1b811bd87b6db2419418e49885d20fd7ca8fb45a11a1da17ac2304393734b552b5d02a303ddc72d1f456697a287851f207054c18a6262f5349348c806841d21e11fd4e4ed9c01fce1688483e009930079f7d2045a34f98ed83256dec66400a783d58c61619e6e42f6e2c6e6fc69e76651b96aabfe643ac69681955ce595f4696b80dadd1f3910061be6ed0840d47e928dd93e7c3d6932d3ead820d06e2539d9a604a6b53db6bb599da851de7cc060faa9af76d708a9aaf371dbc3eff0fdb99702504c3006f789a49feb730cabe40745837e2c8c17c77f999333798431231b337357637a5efd1eeed891fb7475f2c9f960e67578adf50241287bc5599ee08d0237f08c86ed9b75b62d612a9353e48cb4cb022d78f73fba1fab7f794a5ff64c97e6c91ec464847a81e5a5253989a1ee54a41bcd9b4b77bae6e72421471a7ddf0136edc59b72402d57e542916ee47fb3988b7123c6e8debddff2df171d4ce61e83c3d41f36143c9df97f2f68639f1bfc2a9d1fe175fe9f45e17e5cfebb330d3f06e15e3cf58acaff09ea576d896359a3f06985765824bc499319384e4c458d4326db801c564b0b503552bdbec60752b670d82cc8fce9028ff24ade3e805b81a72701b37d4ccedd72118b20d792739e035bbacc4893ded88619a6c499f246311947e48684a35406c4ef279c71ab2a74f6e5313f7900080f19aec3a39109d4aa41c930c66c84cd2163f4cdd59fe84a86cd8bb6468bce45a56d09490e032da844e6d90b436dd874c1cd32a75d1ae1d3e86d8a2ef948649eb56dd7b360f55ba5dc34a12f9279945436c6fb83d1ed57ba4ae1d9342a3dc2df9baa82fc9fee927c13439ba5bd2ff9f3e6f577b8d2df731db14c51db8a14bb15bf3e125f1ca4cb2fe856c5a576cf995db5010687d0799581c5e76d400c1855bb46680a631cc582f51c589a831", + "823d0cd34e7450550da9716c1f456ce0cbc79431483a6214939266581b0e899e4c95719a09c1ef166a618289a6ee6971b6fea3fe380512cb977823b387ac51d341c26d4a835c61eebde37764d2e1d588df7886177e98e3151106c898b3196bf4dbd83f5f", + "a4639c22fc7f370d8500a53819102df5e86c541c0ca10e8f6564e50b90c28f34", + "34a04df283c45655a52bdd84", + "cd8d1b2e5f65ddb3c0da8f12096134da22ad4d541444964077610aafc1f77f8da5ffc75bee807541cb6eb0526e78d57fd88fa9d9608914cf391ae7ccb8eedb0aa711889f9b6192601163b271c90df5d69fef487b6c05a24fc667469cf16cbd5afd58fc830119fc9f61b26dd50a96ed84c96825a615a3aee84ea4c950152323b20884346b25c9e2a6be3a93505ba059fbb114c224bed8f05f54eab76b2c9c23a0fd942eef9696ff67484b542c8347f1b1fd7df7242872b3528c9e45030447b2bc85eaf191963291e4223b75778335e5f1256618ff87bbd68b5a9e5cbd2ca1dc8aff4625c834edf8fb0d879b1f75ba9b85895a6bb4d7569a41bb3be6cdd020065bcc69b44a8fa335d9418ea2d090d8061e042e8e1a6ac03a6d5525079f14274079734ed42c5c9ab9986f0fee6bc9ee6c485e233e9b4d6de70664902529a135a5675ae129353eb2c00b73f226e84fe8c594272d6eceaca28b6da30492c92074250ec80beddb7208f9b5418944305b0864009b3bbb3dfbfb4cc2bba3313f8f7c6c19860f1dc0f5d7aa06e3b551adfc63dddac980a79d72bd2225d54a87a93717291c7b78bdfc5521f7f3239d5564fe9c9559dfefe76b77efc2e75991f31a0134529a6611ab9ef076491f2d2d81ffc5774ba8f8009dd7e5881e09ddf5116fcb5a44e576aef6cea91ebf52c56c742049639392cfb8b280dc2229252e04d8d394ffafa539290acdd8118656e7e1a4f7bfc0bb689448379e8cedff7590a09a3f5a29bf819fd87297b96ca07431a29a07ae126eb9d65e21824c16707db89868e127f17614a536de6ed268b1600a8b02aac2bca54a09b7cccf8e184448df334f95b9f0221187d56da7bd422f09b4d94228098b563df53414a5a86728962a2ea63023d8c3f03847b36db7cd189ccfef3e623b14842b8cccb18b4f80f01b32a4cec48f3009b98ffa25dbad76089c8700e90848da74aeca81d01f4dab2b7e844a3e48bef21f33c92734b821ab382bdf6d0b1048a9866e676b78ac9398678ff626d5c173a15a0a7514b2544405dd54eccaa2791605c87d7117bc9f8c0ad84623a9d3a2b1733304b492d4dec38f7981db9361b03a2837a95fe937976c7f4341a802dbf583366fbe368a3af3f92618046bb55696cf7af1f465a5a57ec5908621f431ffc762f35abe892f772a60a3f75ad8401321f67981e90083fdd1cce40903ce56a629120d6e13c8871523c4d848664331966298c8b31a5bc8174a8c14f61cbe98ae7ee3e90bc832b04318864d19a9b8b6d49a260f42bb120cef9afbe704faecf0f428d917ead9f020f5e9d772bc8f29600f8a7623d8971c1e3c5f1a3b094191e497bd70f85de124137cc4b9fe0617cb73cd44b89aada072625e25976e7aaa5a8fe9d9e3f32db47d1565aaef0e84d256bfce6aedfa1a2dce5a94976a2bb9a0da95941fb7ed444990b0e0e87627e35f3235a998019650a5e5cae804ecab8cf729a5c712f1e7d17486082dd50cbeb2ee1b0be6a7bf08a66ab3cf1fe9f49c7083f5b8ad183f32fb35fb8a41230e4041bcf0e5ef54bc3d21ecc1fceb08d95d745a997e8f2fc3c0f6b1b6c1c02e03ff02ae0d879d13eedd42d9f9949ca7ebb785764162ceb6c6f9944dcb3927b2f4eab23ab566b2b2bcc0c7d77b82579e88203602264064ce98b5b1ed992c1bb13edce579ae7f5e11697b493749f308b33e47512533350df5c07c3dadff656197884f359cdfcb736d29231aea1524b56e06c92f5a98ea663543f67e44003f5b41907a951dd792468c84c5e0e1b46149a5c9751295e153990b78c0cc712889a21b299b0315150dc50aa3b4f7fb0079ddd39d263a754b1dcc595c76ea9fea6c120384afb38d4bd40491c4689b1afc9dd096dd0327c84802bda6bb6b7a8830bc6c06b308ae9665a8666a5551ec954eb72adb827ef38f036c51698a28c92dc1c9e25c267532da2c04c1bf27f5b683ac750c3ef53a8460dc186331549bf82868f9327422c09afe1cd15e161bc41a70cab2f973efcfc8f01a380b86a432e1ae540e09d404d93d22a20dd5f685a52f0acb863dadea236288b1714700f23d1c19e40e219e8ed21f6a393e541abba850ffbbd4030e5f6567b7202fb66d86cc2a0beabd495814f6a50690e8d74cb8b093e4d43261fff80e7a67ca06dfe808899cbef84c09ece01414baac740cbe4c656b17991868e2a136f4785a0de311aeb18cc95ed33fbece22aaed8cc1e47f58cf6c09a6f92c96f37d2d2485b369093506f5e9f8534f8569655277d0399ddd3d33861bd40c71ac53a44d1981cd744d79202322d47a0228356c0e27efa2ff1009cf2a416fb6e8844eb76b8077a4a3961ff193e1c95b222e72688ba48be82ec5da498e58861ea613782ed1ab50a95b5cc236834af98e61528ab18453c20ff978551b81e1bcc0ff4b7092bdd9ab0b946b7324b7361ef05e1f7d7f6a336281b4bb2c671a95a6ab84be6bef1b9c8c3d2536edb8d79b40637e16d7281ec5243016232d7c9fc07ed9dfcf555055d8ae65f12ad150da81f62f2e1e82b3adacf6d623ee4759ad61a09038905bcf1dbbab671dd28fc1d10a0b7eaaef73a5862ab449bd84c8698d061e79fbe52a86739ba945a01353e0f3916667bd7b4356cc65451c7003927f2aa738d98245760550156dda529be741ce3ae1afdea0de35ada26ac241fcb5d518e6ee7f9930baf88bacf8bdaccbecfdb920f3b26285439912a8902ae029b07f28c1dbcfde780cd2bee6c6e5f4520c5c7ff3ab5448ec86cfb270c39586f80041f3764b5dc77dc5ced0695c89671cf90ed34c4067b4bd938b1493c7902dd94be824810a00bbde4915d138fcc7584790bb0b6682fc0799cd415441ac90c1caa008c7fde3ab4a3aae478c64991ebe07e6c4587d3046c9ebb8e125e795f0be9266bcee5a4e4355a2830c5b34e583b0355b34b89c08011db6f6b8371de003074704e8cdda37ce42c7e395b6a37bae3dfbe67bcfd1f125c9a262d56883ddc028773988270aa30c6dd326cbffee589f38286533e1d5c9486011170be591beab5e0ce98837cf91f0a58d69d872e364aa88daf9cfa71bad167129420282d99ed5884a1276dfffb2c4100c74a8b863b063c07937f2e9c12523deac4ea16178863d975e3a5be5efb5ffbea994d07f7ddc5326bed1f5c9415c1d4ee1667e3a581499bb573595158636ad94d84f7c6e4b8efc2b141f2bfab7932a050fd88a8c7b21877cddd488543db5b11138cc808e1248b6e2ef492faa8a32f9d93e3c060b5cec10f03794248f9662ed8c283a8e0eb493824e2750ec75b3b1292d80ce002083a3c64cc487afc31b20f84a778f386b012ef7bef46e638d0f1cd75487ea46e05621d608482637b3e642a9a2c5371bead4386eff968b3e007fc263086d8a930dc76a8431a4e6907ae35c7b3291075d1c723f02e4895714803c0e97d65b04c0f27d01d5d68001bdb3bbd44dfee1eff1754fe8c182cd9bc6ee273beb2a444ca1766f747d86f36cd8cef6eb1dafe0c38b9327a8cac6e83e076099188f02721cc4de3d940c3ef19d9b067be07b890c798a79ee8c44d96c5e05ee5d5202d941a674378386233a83bc85134dc8c46a7531b2b952fb277d8089cfb13e882bcf7545f0605271fe38bf4754f98dfa13fe6b635a62bcf962553882a8f28a9a5fc0b3f85509b702d4a7555d40c4f7d10fbe80d48b4826995fda7d15f14aa9b95fc6526101cf09c97fd74baca6bd26b4fce8a57b0726e0f68118969ec067e9ca39b2ba59fb0d78eb5cec5b872613b1b76763b3217d859bd6d991bbb5448bd4e49dd6597ddec9e46afb3f71d254aba828c91de51904139ab19138e36e6996a207da80323d96077c97a3e8994296376d4dcb602f1e77371efe8b020b7b6f6f7bd2bd733ad9c06c45b77a2893d73b4a8a57707969af74ba06b2fe7d4079bcad1cfeb3689ab95c8b1215fe0a855eb431f67df4ea589dadbf055086924e42cb142c9031e25b81e8e1167a54008ba1ad7fec6794f203b27f3092dd72bb766c9653a72b2e25c965f53487cf3baf74eb7742702380303af8c0a61cca3eec78d4b709e35e2cc5bd586263d9f56fc12454547bc6165e3f070ce7b2bcace5c8cbf52f987568dd90237cf190dabd4ee7a80494692a5379b013611f4eebeef8e1ab9a9c5ba61926095545e19c3dd61b7b404230729aff7d82b6bbbed6b4a926f6e49189e3bccb578fcb3537951fe9c78ac842350ddd80133275ac0bce3a669183776fee8288f874d29190b452d65bb7d8edfedc6fa0ae147102b92041af6dd8a566932e016763b60a5b9b1e3667f228cab075f966d1c525ac19d12046c6409345799adfd7154b6d8b51eeb1eab3a132ac6a2e08acd1a34bbbbdd019195af9f8a93c6ed5463765173e669cb0d42b6cffee1a4b45987853d43c02f920819f45a4fe0905d8c65aca182b4bf56fa0dc51cb53c642fef003d92c13ef4bc1bac571cbe2ba3673a49694f6311b7dfc17a4069759177930b179748d4403c7259e10a5d221cd0a6b745966e598f894e607b779dd5289fbdae0b4348141ad373a62c76aa454b35b39a7be875598bb30007fc300606ee2537cfcd7c22b6149880fb3cd8eb53054d698a0d20f26a5c3ce468255737a68706784", + }, + { + "5622aa8d2f308dd468a7e4959ccc01f0e80d91f79df65b8201eb44911f6abc758c6703bb97908fff377395d33f96c328a4541f414b7ac34c6607dd85729afbfe01feba988e4997c6bd2c99fcc35d2467b143a8fcbe6b49247226a9e4c0a4e3c1a29d5931e6f1f7a31d90a0e0edc4479f08ef9bc65ae4eacd0b93b1cb38948dda31e60b18d702bbf5935bd580201d1f280cbbee679fd834aa6be576a37a037eabe989c3c18c7fb61fda8b9ffaa8bf22b57a101c19e850c454353af7af3d755b26ff1ee78b9d9daa78294972d108958682a5a29c8ef260e2289ad9d7d74f32fd4e51e5d9ee828366abccd97dd56e035713a6f3a1985383c0ed5d98c4accac2fa1ba7d30a295670d5224952f7b7554fcbfb426c9496f054834dec48f9b70af3d2b1c6dcda1c4daf3e9601364e57851952c785e65d753be1c22729bbde33aeb1e4748dbe90da6ecf716f05bfc68ad819515dffafd33a909562b95140ecfff1d0747f8e0459fcd3ca6cd8893262614bb4bf4b639285f327e7ac782898781968ec98f6f0f2f3c4bc5f9c4691ffa7ddb3662816f8ad092095b598bd4d10d6b5fc6fabed619eb11dfd4d638f4c0b6cff7194156a411e8ad6d3229320336ad52fd9811c3a1fcd571d1bbbac67c6186737ac7ca1ed9b2bc46e4e578f81c164b09ae5cdd4059a2c22b5e7ce1dade684e49200867f9bb1430aff9b99805cfd31f7e3fecbe898f70a4eded86b8bbeef7050eff6cf8ba71395a7ae2e270a2b58010e56cdf6efc4003da3d8a82e96979ee68694b6113cc9a6e377d40a810063830eb95005a81405e5b7de8de67424845bab1911bc55da6338513742d237a555465fa54b07ba50ed712e7a57a39fdcfe4af50f064ae969823aa1c40cd86a621ec90769d0c1babd33e8388a8bd76689215b9827a5819127bb32ecc80a562a291f3192eff34cad2635e5b0c0bc174add72e2041864953f1fc72be7d28111fba0438d9036da3d5c0f220ccfde2319bb96fcbfae6055ed7f1c1967ee9a78e93bbb77cbf151084d602a5a2f087d49c3134582c1a5d7af24f4c88be26204cc9dbf4368b19470fef49a5823a2d66c65e9b1e8ab56bf5a7bb3220696840a6222caa58a7b39fb792d95d25038a8bd9d916e853cc5459640f8b8468e3d51f05f1b95e996cee40ffb7ae14cb289094f1b77d5573c1aee7c12a6c3a1e31491422f272cc5f510d4f18ab63d3c3f468c5abd61b2fa7ba0768d46392e2a4dc06c7ce79841dca916cd33cc0a700b50fc660e5d1808d8b87e65feb89428055495823b2dc317d6d9e50aa5ef7ab14076174ed32f56abe7d410e58ca40e92f8a31433d0d74ba7b130b1561f2b075fa11ead744d031f34d82f1a64d428f6cccb0a009be24b42937bf3e99a1ef1fabf0fa7335dab52918382abe756d3de229ee8223aca6d7c5de87047838e387d4e472481a4cfd4365256e13aacb518ce5300f18dcb5e0a28477a6fca08a74756ef6bd8933bacc98d02abc7ae60df7cb3e06d41abcc4bd313c543ddcdea2424d98ffc6dcaa83658aae11f5841ffd4f5df42368a0e815d2146a0fe138b223764b133d17cdb08d485e9f3dd2bf2b220d1f4565b02d7b9231d592130e4436849f49b1a70772244fc0c38da372a8c57fc80ad57828410a5a16ac6d14e093997fdd5b26e4cd4b248e0ea221715ae6e112e1b68b09f795540e31b1231244bc922207b906c4f42b5302dd7474286b653b4d1bb657134bab117d6c349fa0f121c2f8dac9cdcef510c1c28545eae0ab163db6cc84ca182feb858c10153d0136f00a01c9c7d0bed892715dd85c4e73627c3a2ef0f43710dfccacffd1d9f118c9fb1a83b2eb328b8da3e955f027d95294038184f7b895d77532c7570cb86fd6b37a5a66659cf1e330db3930f302838706050c0dcd91d532d49c89d144e9a7f864026ec99f50acc02bd5f11ee88495ee8991ec4723b189f84e03d992fd718b5173ea1b033ab7d3568dc4656648fb54d28d3119b0f293a930a772c394f45ee66838f17b73a94eca27033f9d5c2ae22eb813386905dc024673850a087958eed191d04d05798bcf909eff2deb2a0009d223323b290e3d6f71b2797a2bc2590d54294a5992d629336518514032614a04847c3fad8a7d1cfc2f86765b48cf58acf892f68b691fbece38100e6a71487ef5c4ae934f1ba03b4b26a1967f70ef1c697202e4eb22a3a95ab3b7b524f0241ab4d2adf3ee5e3f2974d0bfe4419ef0ab11039ffc26339570e74d260c4d5a16f22cb4f60b03253487f5e46c47836ce29460728086a615f78d631d89a06790928455889f58adc3d0a3a84ceb2ba9cdb00a403080e6567873b985fd59fd9dec71e375013c12c51cb67d599198f36f58fdaf897e85dfe6f9896cf6d35a84cfdc6834dd9447a2a10e1ffa9fa8edfef1db9e8b4a245b211de49e04b7e88977b4e1ac9285f43526f2452181ee0f80efeb1f6b2533b656519ae45652ccefca81c17714476b497e5d8e9fdf6c9f504c7a7fa7afa36df5f4f8da5b4b973b1618fc8d2d43e866b235e5420551d1659e5bd545fb78a3e17d9cbbc8e842f3fe6be07b892453ffd689d5188f26f9e4c545ba0b3132af12a03bce6914015d026d3d7df661c1e6384bbb50dae24abfa78079a2b1ac41c44c7d82a59183f293f12011e781d3cdca2f791afa5b55a9f2d6139587bfd74bfc54ce91e642847a33b48c1b366fd8f08f520b79ad5113a0273735aee71ceae361a97547fc09b22fbe4e4ae4ae13e52d65e0971341aab368d1e917c8f5f2ac57ac119f981b51b7c99ff2be3e16935b7c73e28fb58d332e6f2c36281228c479c4d6095cf15b14baeb0769191dfc649a70471a25d45d4433797a5b8ba31ff567e60ec4d759d99244d0fb5dfef7c2896809938ddde0d2015a4c5ce5ef6cdb5752da1c2a33e5bc78b6b7c6a5af892f0792c28560a357720da3cee3833bbeda8e98e6a8cccc6535831cfc28bc8557b4181a3978bd90eabb34b99eb7e55d9263e6790ca34561d8c87ec4e12b4a38df524318db00a9b5bbde6f5a8644a818a88e91b521d716fa9f95bf70b109b9905bfca926fd42ecb9114c039790abb0392a41ee4c190536a89ae6194befc2dc4bcf7562bcb84f65c99b69612c0511552f53436b6c489204d3881e1f67e0fba3a061165d2955c2e2e12c440d31556250a8a5cc04ee5e09b1d627c14e08bce1a92df7f6475db92a3ee57e4c16c3ae677c44237122818ad457a29595ab528744707f3ab7ccf3d20bd94047e013e647802a7af14cfc7c11441ea6e9b9f960fe69d03911ad2cf3a8f633e0d647c71dc7e188c92e75353fc953d6a30dd0040c39d4355b71524f1a4872fb1ecab22c8293b54bb22a80e1e3d4c886d2988adec26f041dd0565cfa9edfe5ad9aa7da1d3b8f68fda9e9df9dbe98148120af6ff30e6400deca6dc9593dbf06c856d0d582503e7ffa185f87c6e7ac58184bb80b4a1c0c18d669e23f9791365fe807356a5763ea418c39d94311759b29b14324fb6f3104359ae66532779b825f92b7c9ea2ba43ba7de04eaef7a86192bc93e17286f1b6e0a01c33c796ebed8f17692eb9237173a051c14e4869afda2643bb98c9ac4ea94c6bdc1401c80190df6abe988d2f0b2d80cc7bc8362ba25c6e5df4370a43e156aebd6aaf856b3f64d5fefc622d078faed40b760a361966a4765adb809dbcd74b7a41faffad3a64823860e5656874133c7f8a46b5a3ac591906359aa4f171ef6bb2ea6b5f24cfe25c2fc7c1973bd5d3bb5f197002c5ca1bccffb570f0265f5cd949c7386d961ac9c5e18b5d1d6030d8bf4a48c10f12dcdb11924b02b8ab5e91f425ca62bbe42b80c6b6dde3160ebbd55803966716734327058e29bd39874f2eac199067fdbbe8c372c5a688d3615e2b65f4937b67d6a26c64cc2a9e5379cc00925c678f174f538915f912e85b7014c064a73bcc7ddd38e1a9627ffddb4bfd6da764fdbfb45048c9495ab1a4cac5642f6c9ffbe97d33cb26964a23719620df3d85dcfc392c4502759fb31a6a797e99e51e94cf9bc79ac15de4e5cf7a05aeb88a8ab4c3b6f9c52b99794503f2c49cd7e230a67df7403e552523249f29d257b35c0c7712053c3d9eb583a1a7473d7f296d25a66566e4ba8b08de2a31b082e40c8e5b1e93985b324dded3f52511744e7e99f4e3ffd99d8ae17bb5122b37f637c5525558eab18a378f5e2cb56fa003ed3af8d139d16ec4b2ea79c415b0ba4d750ca2cdf653582ee3b65a9825fb9b123593e36e645232163cabda515b959ed0a1419e9894f6c677ac200fd11babe3503ec7bfa319f1b9559d94a6f82945c9ca8667621a5d28920949a1da644cbdb58b84742e9d65e7f2027b99fba4dec46f642bd17e88fa109143b26ba7fe285c89add0b74a369f3d381ad633bfb4f72e1822ff96aaf9a73b3c59a6e457cf40e17c1198c64737037f52d9b3118daa3fa5cd3e3c7738e3b3743c595893289974a4aa0d6bf1446e70964823a7d5cee67b9b25b7125d9ac5d1d61f2a6947c3deec6deb575e2fc5cec60df26de3c0545e5b79156dd6af33a78552d1ee9994cc8501b7dc5fe7a22eadaf201a92e06ef03be705a8bdb4db65392d3628c7cbf44cccac292c93cb5a407a7a5a0d5ac9fd95b0033d6eb719d3f14609190dd40d5aa1b983cd4c4e278cc8a1e7d5fbb0d39060d6cdce8de6a17e2dab973a7fa594205e17edab6514372eb51e03b0ced6402fac0efd3af49fb8214a505cc9f5f0ea5308d7fe6dec369ba154", + "9f522375925222a04f5c95ee14b6386412025903ecad0bc3ab78afe1145136b3a3592835ab4ad6faa66be9", + "d1ba82b3ced3e9817642aaacedf482e79bedd0560ef2754215ee792514bbf8e6", + "bb21211f342379370f2642d3", + "1a6683805d3f478ca1c1512b9846468378f83be27393db63956e151ec408368b47334afe610249182f54c4d0a01b704db2aa90a9755b8feb67ef9301f0715d7d6bdfa5cc4497cef1142a43eeb42f7c413e8f489af30d742a706d05a40a0c4a5991f9e2cc5d9fbca6ad3767682e20c146ac35aef38dfb2a77388b738fa022158d5c802e5f0761096bb45b50815ebf09172759521b5c5d459703ebe9ff669ee4d14a86e5d0650b597f4a082ba0aef366a924ea378b91c3262d99f48189eea19c76c0f644079f8415c11033cf24d30d6c149ab13ca5c29deafdc816e457257361c1af4b915da312d2e6c7fc712faa27be3e67c893f9005a0e2c28369991c1dab22d38961d1abd6d94c4d549cf491aa1f8d522be3ffa6d214825a5fde3c94c4e35c29b8d05b2627eb12c9d94f450a85eec6bc963a279a37c2344ca36eb604c4bd11c2bf2ecc0dc16c2c365bbbcad3541bd54f8d0bdbb3ca4a087b62fc19fcc1c13984eab807d2a6a1386643d90d412d027bcd0a638765498cdbb1f4cc1b91b69bd241eab3645f225ece85a56e5008d6094041f8cca6b9a0ae3b15585de6fe0695d79d348f8619431ece40e736957a7627224fe92bbe30df5124f476d97e36b5b08b3787e8e00f0c10013068eb156f82f3494a35d6edd5f7048d1e91954f1013ede22eca8b4ba41699ee08decedde87139180a567c6d169b672af0f12aa09ce20e9cac4e78b8067d31ba4f63606c00d1d787b868cf7643fbb170f8074667c9f7584d36af80b4e6557724013618c28d0dd40bfe9d4b25761b3c99558af528c2d290d04b09821bd7f992c044dd61dde9395bd0c9ddec6d0bf6e044ddf0b4b2d6753f5acf2e9c904caa4e9f310578527b85e6738803758da646919989f735b09c9a5744e63fed2c3982e59fd29d2baeb9771316bf8d29213a4956b66c78d5654436ffdd82d0d572530fd09507b988d13fd743f35333237681f8abbb301a8ea870159f802a57760659094d0e4902036c5a62c563f1fc86c4238e1ce89f5176ecaea194ca112fbdeefbef4fa7c203678cafd34486fe58b2af04f84a1cb620c6e123bfd96301e0a5e5e5abcc95d28b852d0cee2f51faa73e42f22fc335f50de4c3812ee14038633a195083f3944284c1086c34995832c3cceb7d385b4ce86af10685c16005495121105272d1d739c584a07ec7801c3667bb280987a8aa41f9537e9d1812a5dba5b385a0b71d2e9573c6f3e9ebf0bf7267528946a6aa6f43efce908d32525cdc3b825bb11c7239f1de412704d24c17455b9382fd6a873180f0d5d44dc449320973d5cd0d4e67e83946b6ef47e5fc3dabadd80751f1421404e56b1bce748b7bde63c6975ca81f3eaf52586a55242c9745dee3f7c796d4508e818eaa4fa50490c1a79624561b98d2e1139a328806414c905372356a22393ea0da51c83957029edd8c2dfcf46d9564264d74c1c0497034ec018b1dd4c14acebc34b6d2c1a616937c37b8b4a0ee5dcdf787a0de1173798ab929b72e0fa83a6c9b9a99d8024328d9c236a8f57550a4f83e8071eac76adb55939f85f5b5f514174b670a3e8dc2b54656f6201940a81fe4953d2680ae4ec58635ba74d15efab3e06dca6ac269711ef2d4dd49f731e24a92a3b935ebbb3fe8d001cd4062669ae4baa62c2947033afcfaca227d88a11769f87456d5cd1bb6606891e71d63aff9cd5a7d23263a78768ac2ac54ece1441fd37d096cd27e916e68891137fc3cca427febd1947cfb4d7ccfad75b2ec5e809c132111eadf25a73043d68333139bd2435de9941bbc61c5c509897cfc19a21645019eaaccb6d06371e3d0570c09c7556e41a727e44d9bd672fccd1f89cc7d58761c16df8fb75fb8a1dde2caaf088f02dad91b6489114398740e6798f3ea8c7b0cfd974e160a0106d703d9589ab09aae79108e3212f19cb950ea9c0798a1532bc2a065d5900a12054395c0545b0878ac0b1d461f553dccfc2a22bf254ced88dcb538e3889549960b77ba6237ab1458e158f4f46606372e797ec9d9ecc6534acaa1218e7540eef11030bb9c3e5a7816f3b33a590d970619bdd2dc04d5c6f4ec38b7cb4d525234b836eab57f65dd045e02367eede9049e219b8712b8d6fe178080c5f77b821f1a475259ae571a5578eb3b48863162d45486f71a28ecbcedb35b320e5b6401f9e7870aa5418449bf47502626e1f42abf481b48d5a6819c640bfdb64f873d583fc4e40187940a6c3373ea7b47195270a8657898f55568985018abcea9bce1c155d95b426f91a734b2a14ec2c7ca2011a4d30019fd9b3ef63a804e9c30c3de2651c4213e90285a4ba100b31ee402e8a7f23cf9d4dba003bbf982526bc63be5af102dca34e7d362d6fbf6f56046160d7af33b364f2a86074d1c0fdd54aae89b19480efde2a9caef9de7c0f9491e1cf43a48752cef405a0ff16b0fc67bbe433a3c1b9661406c3726092efdc076febd60c436476f24dab1b0b8f8893986d951ed72282990e8b1526f4dcf539b22c01c6a7eb5577cd540a16a81296ebeeb7ddda72e60fcf2840c5b42c5cba30eaea5402f267d1d04bc80da5ef0dd2bf3c7a2be986507617c9bdbc96c6273a0c9e586a0c48c98b4552113149c6f79557fc8ace0b1a512fec3aa09ef191f95c2163113ac5cdd940f0c2120509bc53c3ea493c54703effb902ef752c830c61e85636ca95429bf16937bf6786b3eae1b277bf08dcd69f521a0078d633beb33c9aa0cb33b238e1021ca67df122a403a3698452740bdcac81d22ccfe4ab5f835d1961708d1faf6d40f115f16c6094ea37a7ff15e0534f62c19a6f4ded0967be337cdbdd2a7c58ba16ba2e4c3686e9d075c6fa7d29b2a0335ab4940d2a95c4500295f4db84ae65e46c54b7300909cc5411c725a31fd962d239aa0e2007c285586b4c778e2ac7afec42cd8409a63d7cd9c677031f43f4aaf04258dcf1270c02a4764177aa66db2d8f860eeb1fd06d0b27587537410bcb641f90aaa7bfc6f12bd143f66e7c933a0f3ce6b5048913e1b2d79eaa6c19e7255d5eabd24d5f12426339541a22d600cdfd1781a1a3894740887840aa82e5a461fc324285b0223ac9b95c3eb88160353f168b3d4ae8a2e87b7715b5fd2671f66e6eaaf9365b3d9e3acd9a749faefba6009783771177aa4dc91f72fed7a5bf6b1b7738b84ac0a07b4a5a3f0a9134a39e1e7e3e2f9a92d5644295f31c5a356092bf07c709b4c34305ebf50e857a4f593dd1cce0439d3fd125c1ede1a48f583bbbe0eec7058345129ef78868a96f8a76ba7fbfd1c5eebf75f3e0eeeb9db87474b96f321b87fffc02433513fb467fb74e2fc8feb498d51530c753e9a173e95e0edc5ba9802641a45db281b2e2d87d409057b4fb1925e834e90fa5619ae3a9237d5b104e7ac67c2bdc31001eedb4ec7064b2f72e0379bf8780f67ec4b195db014a2d130e77b1778efe3dc703f1310a566a6d3b5c9b12b1d4e25815493ed1510a516a31ced3b64ca49a783ad63ea71a57290727fa31386d2fbfe41f12d36a618c6c28d8f10405eb3e0a33e8ac2e4133ba75c688c8c9a2bb33c8fa032eaf3ea0d2c27bf89269c4aec55f8232b292e7fa9fc24527184f19187d9d8a3f52335e2feb5dc6d997b9b773a79a31db832b752e5738963ee5d61a1b426414975693f986e165e52d46cb059fdd4f48f008e96d4c1a48306b7c002fd0c861721656074cf11173ca65cbdb694c79f58a3f3365e872b24670b691682c10261eb1ffb2b65da031d070e31542f49704b77970a78bcfb4c4ca517b4c966a4e8e27664704f633e90cb7d7917dc1d3a8b8b7fcf59ea3a8a81305761923cb182cebdd59255803a14ca8a75fd007670d79a25eacda1138d67a0fd1da981529dbf182fc4d7a700ba498e4476a1d415381c9e2ffa3bd46201cf2e454c4aaedbbe3893bb4121a6de02cbecc1f319155eb8c99d1030103bb6194bee51e74fa01f28dbe16092955b9599d5c1f1c3f356e26d48fcad7c4cdf0eef25c25273dd62171785c9d2c5a01b1f3da9b4786b1b399d890e2049b73c12de2fb7177f2bc3d9c645398111ebcfd83b73119897bb994f998f4a6fae1b3d6361e171059dba0bf9de9af7a5a1b21641790baf82a36278945d649cf5d310f3792fdefe8c58986a48118fd94647b786e47733ae703701e18992bc1b143b1da6110a98030bb9895c14d7b8eae1a155a550e219a5b6301b6d26d7956ecfe4c7023eec1ff62538b3606ebc7906a1243bf8357f593b6cfff32e3fc6b51f6a0ffaecb658d526f7a5e9faa6294e4808b779f4832318cc184e49e8957b72bea0d67366e040cf76a85889fc6b04e84afab0d02947d0d83e0de19f12966fa8372f6e82ff402bd7a69195eb1a7864a3375aa9e23736fa4d4b0224647e416474c01f72b7d4af240d7f43395b5b04c8fdef1165ce1d56ee8ba0e350e6ada893e0594facbfb5f0d8829ae203929525951584c21371b86deb0f76ef5daad5e847135a6488b35ea33e3a165fea502975d6421d4567a229bf3ce94605885453610eb9c82f9ea743bee9e14776bc3076a29af268cc72d9092a492d9ff08c345dc2eb2f8003b561d9912ae1198c58107f8b37a08b35075af9863110e6770425e9d59c2dfff9d9942c8bc3bf7904c2a952bcd573706caf1ee14420564ffc433c0f5871c4bda916f2530ac75819ade49fa1de21edacbbf6b7075dba21a84989411c566b7c356b81803c7215ab0f326a6b8910dbc62c1bee3af51f105fcdebc0dbc56a50b22cf81eda563bf8c2eff98b476e8", + }, + { + "99444e82c6c4c47070b164f298ffdf6955ee5bcb3070b9aa95ce658db4db084d2056cfe61a93568b44ba7ddcba5d450f4ba0da7b119425a6628b3416663c638692326cacc5c237097db5e537122b465dcb21d8dcb5fe831789b72deff3907685c2e23187a56990221e755930a09f8d6cc065487563cb8cec82b9dc754952fa0b342c92d99522fbb39854e338f470a4b4d5ed2a39b8b6253b7001b0b953abc588d757616c7a5d1f12b1024aa572ef5a47dc8480943aa6cfaaa78064fb2b29830280e46efa418d0cf38f57980146f2482276c9b6b16f865b1606bf1131e894336979a163ba2e70adbdc746be0d38062fafcfe5603e6bbb55717b66a263fbd5cc7476302ea4a0dc6167221f745a26a309f5886934f4258965a0ef0803eaddd05e54008df8a0695a078b797be59f1eef95a658c99a7d52001d4108212ce5f18a39f1173291808c980b0513f1a531e03ad7380372b65572d3967af4c25fe54d99d664cb67e557fff05c12e10143c13b1bfa3e8db093ff832a7978ecd85d3971349e3c9b83939b73f0ad55f1f1162d0c106b99c0ff98442911bc15e9194f5b4ded97e9702b84e31b31380c224f392e5fa5c720a45f64cd7020e25a3931b5871e4c708e77f4729225aa9f48f9d876597d3e79219dddee0efdd16836021dbd21692dafe121217347cc128fc5eb051e6843978ae17478ef714957a84c74656ddd931cbeb43e32fb0a448acf2f90ee98d38522b4fa9aa36be4fa13306e799d4c0cb90ac0f73cbc018146d1b0d6bf48aa446a5e3e0502aae9fcbd196b36b6b7426fc10367febf687f05392fdcf878863de2e47be7e625d0e3e3e94e199f055c0fc65f76c41ede43231873ff10eb854dcd6ac9b550ee8533d16f81eb0e86471d4da69311c47255e78ac8e79ab36ce880d6b135279fbb5a712adc5c3862a356af49e9c10d5b16f4e5dedb80914868111e194745b802a0292c7c8564de28ba8e71a44f7eff6573e5434e65d496cde5b5e62cfa9e2e9ac85a164dbff5767983e71dd2661d37d9027a27674ebe3433731a606db88e0880e91ecea8134421962b3f68915c9f6a5e1992c56750f99bc313fb30cb89384c72571a1a6a5e3c01897b691bd70985352217fa8a67f3252a06205bd1a9931d1cea3736559572561fedbf3ac4c8bff9ebd7f3753ee69a69ecbac4be6357db7f4213b697a828edc716ac01da75c1d46098c7d5d6ae6f3f9a2903588c5b340c9d47c234efea21b700cdb8db4279afa2117677e824e627bf0f2b179c864ba823926a57825478395545f130886bdf2a7c55a2647a888c3998b750343d9cdc602e46b7b09a2fe9ef74db1ffc46fe27c254c927ce51b307e96a571da7f3f907223fbed2daedbcc96197e95edde7859f3b4ec6099f791089e368a68a5ba0917ddf4f50b93c0c839ea36cfc8053811f8fcfe6986e5fa9f743119ecd6c3e5fea1dae3ad7eb465a89e9c68569190688a8d56e4143ceea3b11fbd9de67173d5134ec8b0bd7d16560ba2be52345ebacedc01a2e03e8183ef91317d87b2e15cc6301586ed829d438e4ff1d074408b332c8ce60ccb6790ab08c228807509dd4b39f2c227755f6b039f5cd413ad6f46c9ec2cc6a79457529d297b1d9e74ead9bedd9bd652fb31568a8e2a9e2b89e4e57601bc1d960360232cdb30cb502b950ef930d54c2c0692a684cd44b0472995bd2b41dac1553ae47216253d6640d2653a033a862f3118c5b5d60a662d240bda5f4da51092eff514f61a425c5b14b19517ec1b371d240cc30a0739273b34f18a72a69b1586802a7caa6cc8f5817a8a995695d063c9dd26c3d45feb0f84dc8a0773151cf9a537664f942f351599cfbee0558f441f5c7ad320cabe305f9aba570ddf6407749b6db42f9ce94526a8f4170e735b1dcfc5f0e090af10e039db3747aa9b4f1f26acc34639ac8b60557f7753e2c261a29852932901a4093b7f307319cbb228e26eec289898b3f8ee236032163293b8caf64be3f7ffed236f1da688d958a1bbb79dd45026884904bbb936c1ebca7aa6b0c68aa8b667dc1575729e4ecb4ffa82ddced2f4571bf902c52fc4a0ea3f47aaf5c243ac2a1fc19f825fde5d9fc8d06d97a351eebf4ae1846aa62554d57cffdb3f3377695338f8d598d723289ff3962796e8065632e7da9d8dffe2636cd23eac15a60568eefe3e77c561906555268cfc1e9342417b1cdf090cc16c79939b15a9311b0210094087dea22833f74eb0e35d44259ecf327dc84f3f24b8c2bfce7be0d97e00d2be88a150a0d557ff963b4cda60eb99935951d288768b4b2649b717133517f5e3909744417c9c3102c77ddd285976cba2c89e2b4f297665632d7c8652847c4625038a6670169772de0550066ec6c2018f503cce79a333ecc0a0632334df6959d2e3b052fa47c5c84d15ceabdc80bd6be0ea2a5a8d5e374e0e9a613369ca8d4cae3d9f98755560b27b2f6e47b01ba390f5ddeb732c22b12abd225e26ecdb639b08f3237e488430b3b39f0b63aaaef4907cd003a8f2b4c3bfd721d6c3fd3a5f062d72746606a529ba34251ddec4026f40d262e9d527ad84fecf5bb2cc8601c2a38437098aec2335104842ff1c455e5d17c136ece8d461d7a3bd9a60339c22d71059e09b3603c0565c0345684893b56054ec4d3db0bf15546cafb4a03bd7775c3157e7676bb7bdb7baf3100396c563eba1a12952503eb6ccde6b6d0a42d456743c4ddb97f5994fa08c5fa41315080eb6b928090956bfc6252b232f6e0785d233c3adcbb9370b59c35b0dd66005d516befd1fc843df8e68fab19858b91e2aecd1c8a88b0fa3d4c2fed2995ee87e65976b755fbf44ee183f9fa08848bea325807bce0b7b61e03e50b2c7af9b360532a17a8250cf6068fef0198738c82a5e58961c54017e343fcef7076e823d63b4deee472fada7989ca7a213d06a4e3eb2d44b16e5c94b1588321cf6c45a5a792938b058d667e1730f8386dfedc50ea0a959b78f12f2949b34b181f90bec622515227dfb8a5f6e89d2e559c0ba686153b218d2c50b67503018e22914ce9b49d3bdb7cf38172db1ea130baacd640c111614e3db204b3b50641d8978dc14b2afc27a7efa819cac6bafa8166d1c127e2237520d57ad38a80146217a12363cb1f8a720e328cd8f846d379ada43bd4865e4aa633c479bd448d205b2e43befa63486c717af84a733f1dececc127c047850aeeb8ce677612f5966e23d92c1d3c758aaeef82f862c1154fadd6766e1dfc780bb447732a5968c0c78b9af4a9d669338458b57cbb77910a24678092857c0b903152035bab6b1c73f7b667a08cd0d31128888de3ff1fed24866eb60beac19c1b139f77bf0b9332024999a2d56975e691fd7475fd93622119d0d725bb99c1d6ac604d6b6be09d6d29360fff9f84e5318259a67fec08a006d9772b9410ec6abd4cb828b898c625c2fc35c19cb9a6cd3b0073baec7b5af254d21de8e209539f560bc80ea38e33658a68262622cdf35dcd6618b9e272ac3644c91f27d372c6297d8e37201c6a86a7d3accdf579c15246276a0009ddac4021755f4848d10f714e9da86eba13f461e6a12edb1aef2d6117986120750d609682bfdfcb90ee3cde8be54d45f841a6dee2d5b9fdc4e65edb7ebffcf3cc5c8a4e1c6919ac57568be23bd8283319ce11fca3caf968b057432f163f22e29cac30b8154a646ca0ef4fdbc7770ee1451fdde9e9d651992d94c843d4eb2570975528ad9f8c193f7c681a43df28242547010e30d75fca04f39247c77d6c3715c25fc261ecdba16844bbab23e4d0482bd1565ca9b526ada9b8f5703661a84b23070d85f3e8265b2ce10750c5d798f1a8ef4d51a473ff4d2bf4be615566ac796db9fe61a224bcce05c31ecb9ab7bc43a609944a7c9398a7875609ddbcb556296f548a117847df7d0afe48a5b504e85b0d7ca589103d3197933a744fefca795e1e036f964a4f14554d5cfa0261e25d6e5e02f86e402906d3637a2352459cb1639f20faea6f0e3fbc6a39becb1b1b3a791e32e85e5bee31be685410adf0c11190e20b7a5119b90e83f2cc4f0de8898606bb6e64165c95d4c5eae472daa6836a888ee4d9a79de72b8fb47a9c9c0323a2be9106d4ee9ba8b3858c256032a9caba37af94df4c7b0adc2f8478cb879b6d452d73191b0fc1ce944df3f4809cbf3ad46eceb3ba4abd9679410f45c8aab20dd72626f235e7c0c934b4beb4507def24ebbdd7a507943c81d54bc69df578aacd9ed0bfd3b7809dec345ba084d88fa9c34d80685415a4d5eaef9b88e51432b2b2037186baf123a6257e47aa56d6531923d38178e8264dd315e95bfafd8dacaf901e354b0f58f135d638df2c0f32453205c7aaeeedf8c102e11cfddea9a98d3ac7c385d71b760cf2afeb1ebe1d64f0222b9b101893d11a74ed175297c1dfd188a2565fbecc6bb07b56ce3973322a965dc5a675587890cc65a71efc68fdcdf1a023505ef0bc0e6b12dca5860fcf1c6c94c2e2ec3a72b8a019d69c82d36a73738dc3d17d7fdfe992bc8e18cb5d3437f1f619dd318b95d1a56b6d273ed79ab2655d83e2dd63cb6f1f5987eab6bb21a7b13b84e2c619b36b842192c3f82c755d8af840675b0bd67a655d641b1886c3c9c147ac87615ff3e58085a879b21dd63c1616a3712279ec87d650a2eed665b797ad631f0ec312f343979cbc49b99385cfa92841cba12d52777df565545a1deb07800a15431c0987b4a543fd5ed6832e80ab6f4b4d9c9ec419932a6ded4759f5c7630a0b80139234b8d53117acb4452c60b477ad50157169a89bd796e2308baa9395b513a94747611c7978c82dbdf48d716c3ac181ac2b2a4702c02a324bd4c5e089d989d020ebec9963b5c721a95492158f54973b7fc1828181acb3cc8078ac095136d97221c60b847bd2a52427383ab68cd1f10b92738c13203fdfa0b78baa09c1837be2498667c459", + "0ce980442336d0f427db869a6799baa6785b5e030567c588e2a7d2680e96c11b7f415fa27730969e0b1c3973b5f3192d4e773153def6dcc09dae29ac44eac7c42c2666a356fd4262197bd5cf6eeefcbd662d104423ec05c19a2e6ddf1834a3445a09e8b1062a1320a5e8ef13d6ebd03c19e1813ccd86fd68b46a", + "1ac8a509db7bf4acb80d8d394a5abf47c273b2093f50f35049e749f3e16cb0fb", + "47cc9eea11f9f3f9aafa23bd", + "088888333340b3a057b05491fb2402301c8654948aa6d5ee1ec75eb045858c22056fef0873d6675f897126052923a47a30675b266ffb6181cbd29ce2da3720e36a227e4c6e53328d789913c0d9cd149a6e49293996b1be7d6c513b24d876445a950e723ade3efc36907c840b9b8cfdb1503811b4044d931a0009b381fd60a5bf1e73d16348cb57eea672709875fb9d56908dbc729d5d7d322a17a41d0f62c9af9a013ab1e19fb7b6c6e7fa0c0b18bec5e3d3e92546c77e3753193389e5fcdb6a6a1896cba461343e71ef7a156b136b27ae6f45be9368301cfade203e9b53824d70f07de9abfea1968b8ff8489b9804422ba05ac3c3adf23ba0848817fa51febab5e9b5500100310479e710b663f064c1ef101c9a5320367cd8bc6e52081a32f070e7d3fd6f4210cdffdb9fcab1de4af5b06a7c6d191dcc12b25b3053e58952bfd1f723afbf570796946c1df9579ad14ea9c8c30389c1de4d1e845c764fec5eb8faaf4c558c5eb5113018c6a21ef653ac7d7f5b6c7e1a8fd48c6f423e9913436202da176a86731287db7331db055508acc94168888040ee37b3c119c8a0d88360241d68745825fe480324a944d56e7cd0375d4d33a5fe7a3863c2aaa899b2d24f65b70bd804039116fe959c32442c9f0b5470463523eb4336985b71125fe5235cbca0c88a6f92416d038e144de5ff8ef6ca749a9e239f02db505bff8e16fad1cba8b1500445f067a674142b6413e9dc0f432242d8301879bfc11fa86d1ac9992ab12319fea8b703e10a13bfd4b017496222be26b56af3ef67610f904f0ca8a3e7cc249ca8122735a542b289f13922904ff23dd197f8883c7ac77150d7331316ef94e0cf13b6ad95070420513599100b0a6d117640b781c622ed7ef7ead29476b3c835bd9dbda2203930bcee7ac01c3b9c89da405ee436ee652ddcc3e96c7f1a94e200eec9a4a226f3cf7ae5725068916e73b61149497d11dd85157f895669f51978d1bea8fd2afabb18d082365daba2682ef623109988b7d0e27ae57bc14d86603f93b5ac040ae52d8db404ee27e6c34cd4246f40eccf9d3f8637a4615a4006918b01d34709bcbebd02ea72958d54db3e87d69e6d783de2f1841029d6975eb11f9b076c247108797d5368c656f888092b82aa81aa26e164e038b359bd68801c22fc107e4083a9d85fc254b002ece9d4545310b0cb22ec1af04a7ee31d210ede4b605dbdbcb70e4301989422ef46edf63f9c96de9cb3f70638b51df5c0abe79b7af8cd97148f2b7bf394bea0f7bbbf6925f83b901b87a6079f2c3b38a98fe1a86dc7f48bf97553701834f557451df4b41e7db984a34432823585380b45c1b84813d6aa21107cae252923fb4673cf660a541e65610ac0127d238285f53bf329b62169f3e42d5efe268dea62578e97da59a58a1314a1bd46cf7a7cae772814130b51411082e30062fdbda1c9e14d6b2bfff89d0379d32461f3b8e833b105f6a89532ae748b5fb43f283fc86450404e8befb8442b65e338aa0408303a70e9c27a1d923d9f2a06e7c6159c50bf2e3ba5b035420ecbd9d0b5fae478eb1ab72fa714f99d00188bb10e60380fa3a3a318c2d359ea3805c2fa0dde17ee52a504f70d6b466bd38d1dd4196be336a9ab4a9e573d1bc6404018a119f688c1dc2a8ed1433e8a8ebf455ce3808c245f0220f0c12d28c771757763bd111ab829294e2429a6f7a59858dfa1fe0b806e986d40aaff934589fefd75ab91097a979f26bc9352267efb2d82c4738e4e6c451b0d5adc398f546c646b9e6b8fc84e91651a1252d5b805a857c7798d102d1e6f90749252bc53588348ecec0897c79f514442fe3b27608c95d0cba999a7e0fbd7f601689b4dc63ecb9ff553ff12eca3e9b26e3eccbde28770bb6aff7c864ad6be77fc09f81f90df6efd0c4025d0916ab5197ab846dfe6121c462761d9cc87112ebbca197b0a222fd34a15b824b7eda06a56a6ffda760fae5f0b527e2798f01e205a3f47947a4bd190f6abfb1dab2e3a53131af95d593bb57e4f4af506440cf20636d9fccc449d9565bf43dec8b6877337ca5a43900c1dc600c877b290342914e909aad8c5f0755bc25652781535c057ed5ab2ff8ad4322a8edf3fc1b5311dae6361a7395919725f4cd87ce0ccba37c64eb3618f9c5a53644ada569b90cd07184fc048f1b589eb29852909e75e7116ef96a268ea85c2bd257cefdde9222d7eda875a2a3abcd3a02a1fb470ba967b20beb54914b8b0c6ed464ba978088d7f8b30d098966b0bde82a8f1210f5d0c3405c9bc73f703134d0b6ee13326f65fa0b8154f4e30808997d4afbd060285942ca1dededc3410a099881492b5730ab7bdc2a4cfd0068f67766d60b5d4945f121459d2083334ac878d067bef644b9ee427bbbd6c9351d7b019bfc051c05ac301ff3792a1c687546dbf6a07a0cf56717374bfa1191c22b7753f6ae02392f8aac9207d1ad0fcd57c5c8b35817574b7dd90a00cab75f508f8a234eabce6618305f94746cb6a8573389d336bb67e1b0d2b6e9bd3959ef344e1eb245b522c35222813b8c6e82df48987436b5592025e9786ca63b6d1a064223bfacf59ada713c2a3116611393aa8446ea79b3cb21e96d13b659ada2d6524686fd46ec66c1b4d8f5ae7831840c9e3db64d528f83a1cef1e0a586a783f8306cb261ed9c2905493e74d35883fcb39cfc5745c282104cc3ce804999231d13e1bc6f2c022f05999fb57575bbdaf00d7a990e17dd2f8b9dfe66a637b42f58ee49ba60f2dd9718d09d7025b6061b2087bc35f0a8c884f5b67a5e18c2b4e857d3b48b79dc7cab6b72f572d22987566238a7153ed6264578424f1ce091fd05b7f14563fe12c76104d3373367af3ed3aca694a21127b5912c0b7eb1ddf9d4a9f03f660d49f7a7f0fb42797fd112414c3eba2b75a04282dcb9645191fd3dbe376e7f60ab40bb7ca1e991053a1912854a68d7dcf854201d1f2c26c6cfaea32e29d80847e6288274713d2ca973b91dab97884326b280c6f06c65b8fd25d314be29139961051a1d8699467d02b67991baabc9b05629660c243ca3b0477362d5e6bf9eaa33beeb52cf399846c77fcae11a89cbfdb2058e443ddd44fe202a3ba5c2efce937d78b9639781b8b2b99077b433189cf3b0733ed73b59bb194c9a98c5aa0cba6e71d1c5522f193defb9e31fd2cd60f22bedaf7008c2fb0b55a8dd52731dfa2bc69b40f835ae95db040cda6a4a1588a5ba4769edfeb7369c1e9a3b1cda293255b4942881d94d771b7b82460004875e71be64c582f2830c5e80dd6de421a311c5852f4912bea1451b0328d01c7029867cf9af99284cdfc1e1f0aa0d8c19ba9bc035dc270b45724247137da5d3fc4daa09e7014fe1439889968eb23fe124f067825d5f7b304f17a983580e009e0e51630ea0006dbc74a30b512cd9eb4d0b315a0ffdbfb581609ea9661b0007cd234ce43c17c92269a7519bfe99c2ca94b5cd3e7654946e67b37d4270a369266db6804336a446022677a024d44cc02cb04108292dc12f790578a0d61cb6fada738902eed3afdf1850bafcb279f18b5798d7466752c6368a594533baff5dbd17974638ecc41753b184845206c79bbab84dfef148eb7f1390f8cb7346a14c88caf540c241cad11ce8869be3bec85d029ef490fc5edacf94fa962be39a33c8efefcbb6b43960d5bc35f8fb72038af3801466aed141b50e9ac7dcf1921f7a6abaf320ff02ac34bbfac265e05e27495e6e027e673a48a874e6f0c33827a050fa21c2efa789c1e3df2ecda95fc52ca7be35dbf17ff6c73f37cb236e5131542e002913d177ffb21ac450e2542e24b894650007c36c52d90f83731009a7c3239ccf11829cf0fb6510d9924e927f14d6a06f8dc772fc9b028a8bbd2d3388985f3e2609abbd08434c46642b97240c9380a831bbafdc5db77be63a1400cc9a4f7362a689b07a77162022c6ba7a1bb9f0446a0b6b460ebdd9111132694fa5f1b29da39be66c5179849ae9720b2da0a012d4bdfd1b18b8fbef0d5c32b92c351dcf2c599f069c3b53f622fc8e904f27584b2d97d43f779abcde6dc1413c0a677dd187b28cfbcf7fa6316f0967b53977432d45944ce8ebd2e265c0bf6b2870c75ae808fed52aa35421ef55667ecd6f9d279c9b91c9314bd9411bce267d6ad52b1d910b3e65147c3eb6021a0af98707408e66bb11ca5abf5e34b2bc85b144fd06ea56f5d7f8939fe0cfa4862e7f306de069cf85f4aa7aa97c6848594f5a6dbcc718d2af77497f4b9d5ffa217fc301127071e9bc9c2c9222ba90e286506e384f321e622f05d81c114953d0f7e9626b74f4a6bea8cfb86ceb4575e5cf4fb84e9efac8291d1f4153ad3cd9a34ce0ffcfbe30b6829c0f986a4f85d63b602ab99ff3934b1e0c46e55d56eb479b79ca0729beb59aed783e9a3ccd55db8d884733dbd93f9fd7a7209fb92fcc49826b2d4356ca676f01b0981637897b3d2f90f37bfd73b214a398a8e4e2f9e5abec01d8192ca690191255dd8304a2d95a69331288bce00385f462e942f4d694dc3560a263c8ac2b5cd1d2c63b90ec67c32eaf5bd947bd8ac730da9c09ebc6888b0b4f3bead157aa9d31c2802df8ff0e4d69b7abfed6f184bf35a16ffb5677ddfc4682322128932d57fe4c32f21e190e1147d8e673ae407b1dbbca31331310b299e9f3db08ebfd2dad3158562c2e47addcbcc831cef0194ac8ba9778d0103c2955c886d439967bf788eae688f2a7459b0ef3bd16808e8d768b8962a24588d918ceb2cd1cd611b504019f65216beca212f44600cb7fac77216b7645c49f18064a3acdc01399315084dc9ea151ee28534fb31628d190bc540ac6b6aba572ba51aee89544015e6fbca2b3c2330f2ac1f68849e99e1a1f7f523599eaee22720392ea52259e26f1101614d4edae481b3783af4e99082d75dcca549049290731bbadd1ec0a93789ad5c9afe8bae44e35b3e59e562362964", + }, + { + "0410d1f8bc890649c250a3819766f4496f339a6384e34acdd72b3a87266edd2a7eae223a372883f978277a108d6e59fca1f35f25d7a9f3aed42d35fa9b12241ac04754f76fd8f0e8ff6af88cd851887a45e89f1c9192ca66bfff605b128575d2ccc9ca3ba1ba23a0251b2cfd6db577b29d17ce2ea998946997f5c4a97a397c46024681a400a54425c071232d269adfc3b1adf15b4586c4dd7b8886f5c1023bc348bc674961ac6e221d914f432c2f06dddcf738227dfcfff88485ed45882809d0e57019461c88683919b87c45e78223c37a5be5f758e4f0dc6add22f2062bc2eb9bdc31b8649af17d526ec339f0e6fc6a41e26299c65276302f982235c3e5205ec1521625ec08a23e766577664b73d18d5533261c859c4cb4346feaf7540a56155c6c3a4874dc86ea42fd518d71221ac65541e2dadd2f8e129e7809f2835f07dfcc4128401dae2b5fac7ced1d9e07e3f348c6cd26f55b3893d4418557a18c366dcd5eadea0dd84ab95437d6f23eb9e5877fb2ad740ee507e2268c39c7186f34e5cee2d0dbba1a940f516a018f23e716a399c317a7a81f89cfabc296c432cba900ad79db67936f76e4d97874fc5f8a9ff84eb7a0f6d629c581ec5c451e27ef1ed468f93bfc68b2e0412a543d89dfdd812d9421236a4be9eb374531556c207340886c7b84d42d651557b952e0982f62c5c383e92dced21905174a5a836acdc3f2393e770d6cdc22c39575a42ea406f36889dc9558aeae5dc5f8b84862850b55bf4accccb6a8ef793d641d6b08235f70ad3b0605eab462afad1af80fa003645f4d302b03d81a7d167e9a8187bee0f76b1cfd7006b2d2b55fedad6e8db1d3ecfe031702dc327ff2b0197337d7542f42702cb276de852b3d72d9acff8a7feb8882028a5e340950e523c41cfa184b3d8878effe56742994e60240e58cbfd01541d39fa007a9f0ecccb409c6cc540354ccf35223677cb74e7ef7330bb60420f7d7bf97de6888cb343cd4fb0928fe5df5f1b018592ccfa7aac6dab57cded573b5950b94fd935f32cf332dd85b2b36501de6687612371dbcfdf77279d647ed8bdcf81fda8b7e0c5ab139330d64695d814fc6f761fd141dfb0c8f74e2d7616db3598d8de40b993fbdd272ca37db27b82aedb08bebc4a8e6d0385ab20fbc20c215ad50fab8e93975bcab3ff38667abb0545b3b3f20e325f01b80a32a3cc3ed51703d4b2826849ee22fddd5b544816599dca0d8fc84feed9f7e90caba53b70bc3f457eb1adb89fd0b67d2c0ab53264430c61d2c4a1b19ea99a9b453fc6b5ebf5fb5ab799134769c9b495c479c828bcc49a8f993c3127d5cbc31afb89c0e78fbc323755457ebf0f3344d3ad1cfc59d186e96ac31a9298e655b3d1df74b95f30fb868631053540388a13d597002f689708d35a2365e309bb96db8b1b94ea4c8060c2b165f7f19e72056409159371ac9c44f6bfaad9b9567094d18c29bbc8aa2c8b5b82735d20f55284fe68186004b4a4fb644fd52d9645b277c1dc238a764005c1d2791ef36e71786cd990ccee4571d9a9b1aec757e479cfa645e320bc33268e05af9cf90e0e616ae7f237c637a99fe15b4ea8a3232262d96855fa248920a28ec03f77ce4dd93925db60ec030a7be455ba9d08edbf6bb717b1a13c3ac1deb9821e21505c0a8971d5ea5dd8e4c9cd3a845a336209af191150ba5d9b8c2c450e3a765e8670d7f846b2461f971fdcd1942704f620a40f4204b99f9035bbd543f64b927cbc7a74f32cbb12c3caef955f169a45374e4479430e08d333c4a877baf41a27a0849ca3a157b6651295fa71ac94b6e3d30b5d160965e93d2a81b4d575cefd264399c9e4e17059f4064465b2d92c96ac27e3b221499b5e642d033992c236b905c072faa1e34495f9890bac6228330e4016c061605bbfc478c30e1b8534c49af54785972aca2d144328b0a540e3b3810a73e26acfa22f48652d53ea521875475ffade8ab50b9f08245fad753350f63dc4e898948ac7dcefe520ca47394f8e993a6d13ff68a2f78cf294f235f5f863bad10c4f5bc41c3ba93cf5e076357f0f7fdc136f34b656b1b8ebb3eed1ac429c7d4edbc902f7f4bc24ea9c9b200b9a9fd7adff0c6445ce1d2171fc031e3e9f8b8d6b448053393c8813d91333d4bdc3bc5bb2b8bff876cd29e8b92cf6f7bc727517b6f57ae031f3040b0637dfb40b8c1fbe44cfb6bb9cd0a445fd9b3daa1da2b1c4a82cb4da1fb8d525e0a4d9ec30e9aa75b951214621c58c1f60c9b97e6c6b330497e7dea790a3cd8158a76d898107ff3a5910707ae60c8a46c633b522aee83736d005de60b9abe202435f8bc4577b0eb08b7f2b617bb5a831e95d6488459bbf15919d764b39684d7cb7c9310f343fbfcfbeeb212a90d96c7a26c1026c5cb171ee4ef839785076e5084026077455c73404a2653f333e9bad555cafc1a9613387a02bb1287c380d7478238bec8943208de585bd18b448b6099565cb3ec70ec6672a778fa6af9d1b17b0970439da24c7bfaa74c85ecd8e5852e42391ab2258024ccf91e37f2f0e86df958b197fafd12f4a45f7990375f1665a14f7f5374ff7740f89677ea8660587fb80916b30629a7aa88213bbf80512421a0a37414a2eb549b81cc85072cdd87e4e69d97ecc63f974e60d20de0233101c3d475d777602b12e2f797e9237570085b0e9f48d4dedf233eb1301ed4621f9736946eadf599bfd79157c0b4cc31bc273f5c6f133a4e3679ff6797d3c9b76aff4bd8ad40726c1703c3d8b78f0974b748d0265b0a75928374f91b48c2d2b2c11d8b6e5efddb75009e4db72e562be59efb0bfa06808c89f585a43d4776ef08947a77f277526777f0b52f1e0b5a03aa560fa45c8f30e584b58ac1fc00b104942b7b86a3cdee1abea349dcaea4e058faeffc567e2c3b03e1c5c4ddc675e25aa15de1442bcf5ee972a8c5204ca5794694759c13a2d716839dda61635043bdf1a09e35cb6d93b4df3b7a00871f79cdb4ee69c79041dd14deb7754107b8fef8589d2d240ac1d8eafc52ea847263512651bbede2fccaf6da816b1b892319817bb6af9fc17078ab6cca95f03cf8426249fd4f2bf91921d39b8cee24af07a52bbe54ca7fc4422a310dbf2149b763ac0060fb2c59154d2cb0da1ad4892279b4e0ce7f5f92c189c3ce48e518ff48c4ffa9bf2b02d4792f84534958dc6bd2914ba010aa32d133f6a07bdbb87a237c7acc3ba5cf101efe947147ed4eb3bfdffe5fefa991c0dc8760586218d286944c52d0f221e0101f74826761d01a20af187f9ec1115e9e98bff6fbd7c8816c15d33c07f51c171490997bf269951218ae92b66fa3150d3bd40336abccb717e18b53e8806fff94009910f202a5041b5396d1c339e6d075bad4ab66a0637d81eed1696e4068024001123204b8371f0bcdf0ce07d79f7c917327f7138a75947846fde68665e9c767fbf96bb3308abffe7a8d05512c81e39fa8dab2334f46ab9543921ca97be31076dc7b2a0d05e90b7f7610d1a391b442398ef56cde3b18737faa8f282572389b4fb3c55cb8ae6737257708c808bc0a414bffae293bc69cba702ce2959e1a30edcdf64985a4b0bcc927c5912f819c71cc9b1ff5d6e5929055be72ea5c8c1a4a591093deb5449b7e6b60109be1ac0cae472ba31e1035ae65f3214f50ad699a077a2de52f7180addde0bd78c2698470b1af13cfbf497d243c9e738c4cdc265356543885c5b933a299f01a5b5a9ecb0b4ddfda0c28573064f6a3f142801795d66bcd5c31868fd3207fee7bd98c47e4da26bee64e1617b20cbaa34e3abbe31126b06d5737fc2b577b19d255a519397f3ff8668d0e7d401a37e368729e4b83c5fbf01c32ec478967605cbc0675f685b5eeeb42fc688216a0667e1204c995c9c485e6f7712d80d88edc9594528b1907790549756dcc8b0d32091f36d2b4009639e68daa130e83a1ea18353ca34f431c548d91c1591ccf8b25eec1f7a3c18ddca71b87bb290a5c13229250c5e193e1352072f6798ec504b3b4c6aa578737332f52baea7bc4468fe6d8dfabb9728cee93fee50c8caa113f5ed7e9b55e21e98d73a377ef68be7e4e965dfa50cf863e6285236f11ce80512c573ae2b55bcb43cf6ebabed6783c250f991f5f68a59dcb2ac13a3c8fba8dbb11c79dc6236809f2d7c4b0ad3cecd24b85f1aaed9748b8c109f2fd98ac8a53bd52f18475598d67305117de8e03b0d988a2847539cc2efad520f86dcd82c08ad4b10e490b9cb03bedc7197bcaca55526cd9c8a5a5f69f7a1697e7e31aa76eee597c386418e89f06b0b9817a83d6cdefaf9594548b33cea1cbb585e55df3d3b66f0b1a88f4b98ea4720f1ef5e6ebe4958078ea0bacb8ad776e325ccb252f81943b9b1c2f54aad3c7baf1bca0dda1355d191f69c5d8163c464898116dc89201032d1e3281c8054882f60522d3a65831bf779a854fb0c195f85aa66522386625658457e74d5c2fcf5234f226da4a579ac1f11f11a1e0a6993a4dfe5c856481ebe9d8d2363401058736f7ad104104aa03f5c91496aaba2fe4072d418d91c2787a9b4ab0cf4bb65681ad0392ef073cf2fc060692b0c0c194c8eed5558098cdfa3317ab02626159e40e5c76fd64b2ef60b8f5f368b6b4fd7ea3d2d3236aa01d9db7c8a01929f9fd38557335b926251ade1a0d47d0c1444e6416218781c1a51e786dbe9297b78fcf0d0304c62929e00744ed4e14af926313a9849b2a464048bead075044bee013cbe318920c4172138560629a0ff4fd229d81bdc7c7fd1086ab17d6efd5b603a1991b33a55ca5b9e2051b7c140f7937adfaf474c2f284489d9b1e8c71d58f126eaa451407eacde9f0e86504f7de3ba4d830199a229de2bf39014baad6dbbc448501588ceb2575db0ddae005b81ba9914bc22b6d600e2c990f7843e553ff29d8008265eba7dac7b5b5a7ba6dc263fe0e262a7b8638a81f4720622c7361554b61d7b04c7f8b133440baeead7d51ac8b77d606fd0eae1c55ce7e8141dfd68d40ae3d8d2dc8a061085b4fb6d8a06263183869154618329be6b01c2890f2b5d0a0f25dcdbbfe2ec3597d79311edb943613fd4b59157df4fc2e1024be03d98ea3cbec7186ea9f4a431dc3743b9f0871b205bc0c1b3a001768", + "113b261414b4b7dfa028668ac8b0cde5734120124991c54f4dd16a87d181efe2bc15f6d0caaeaf6ad615f59ec5c2833904a34b4d34109c82e10609b387f995430e8c13d83ac34310d838af9efa32d7fed6224c0a33", + "cd762390b93369f1e207eb15deeaeb0036f5331e82480d180f84a76c3e44550b", + "e88c14ef96c7768f5dba9de9", + "8d6aaa27892a76fb05a2e96cef9a9b4b7ae0670a12cff95f7b076372456889fbd3b9b4fb5fd98b3bd85b247f15009be2f4e7a0329dd118b6872199b314e159618ede0381dd97db28743461ace1a694c0383d8458150a501d6c45f4b50d5b1bd47e61a51f9ed4929bf2e564f201ed0e6825170027d93e482c1ce268459d2f81cab41f0e7ff281430c16b34a29b5c76630dba72ab9e751bae41122b26121d91f2af271a23e818263f46e05fdd52f319d58330bcabf66637a368c0a8aeeb20cad1916d966e5e0b0de74cc67ebe57e3d1fe01e9743d42a931cb4b98bb762ea43ab937d1e5c42eb08fd56e70e911bdcc1ca4ca0604a329c5364b262ce2de282b4732ea657b89300cc7b7127ba4a2d08c13f581f024fd093ac09c2bc245be60c80e102405597fa8082f4d28cc954a93217edffaba3d2a397bb59ee89c8cc0f33eded78f21183bd1acdce64a923dd609a0620d2911f61e81fb2c8ccad8ad9d81157223253a121ea2bc60d6a3670c563fe06bd75688572b3be83cd31dfeac6b17cf8455267b481219c42034b2252977f32b8e6588fb05166498fa37d17c2b002a655b5711bbc21175348225fdcca041b1f97fae48fb1e222c5bb46b5202191c00666b7e1b2d84aca3edbee7a97dc0f6d1330e929226f8a76c155e973c1ab62c867e1f87be37788754e51825ba31af9f4722b5782ef782fbb70c391a664f252d14e49a805e94790135ff6bd881a687f98b42da96fd34bf240eae4914488af739ec15f13f048a7eb5fa94af14e8b6ac5fae714cbef6268b114813ca2a3920a7a9d5eb506a2ca211758de292047eefdb5a97e18530dcd8410495fc42abed91b1204d9b8ba9d6aed11d2d0fa0d931d46f93f2c1a560ef9f5f7cee1497be770d3cb07c534215cec12c1458bb57aab4d95cf4a15a5e3a3bf8e650206d5cac4af3193d169f1a57638d9a50f6b7c6985d42f7138b9226451670d7359351c2affbca65680557693d03458341198b8e13d0ea6abb7496edea3cd4dee2eb93695e668c7c0901c6809b8ef434e88b85a8b22cab6508b9560fae62900056b7c5c29a8c899bed45a2b5159a1d4929476ef350101317f77f02d48a039cf4cf01c56319cbba16fe908c49ed6f3face88867c0ad3703452baa7b86fe58a00ab8f740b4e8055164b0385dd3fa44502ffbb99cdd843bc3287ea468aafe4cc298a3fc180f284dbf78aa09e0a2f7d8593356eab016ad8dc505420edd376b66598a3d0aaa848fd68c4e07419b8b50e40febe2b6b17ad07726fae1f87e86abd01490a0ce24fb57b533c765504ee0a9ca154187bcf5e6828e3addc7597532643cfd992558d63b1acd00e7aa41b9765094217480c08c43f4f0b3f0127120699b7f2a5ac07c655b6143e467777cdad4bc21d4b57da4d8f9b9a7e4523d8c6fba3614b7f7281e80ff0f9004577adcff1b79fe443c80ca9655ecc102d5df6aab2ff6c3401f344b77666c59ac7d5b92bf4f1e2322f74b75e6ef2bf43ad9e018f164ae76a91451e5221bdf5b65a4fbbaa8dc31e6063b451edbbf4965307f8e65bfae87b15f2453083bea8484017228a9cdc6edab1a28834eed8ce07430f776b916b3bdd2340798955ce9ffcf114c3f6a88bcc4c7b6f2e3842426488c340d00f2c4d2d6fd3b6263dcf7a57f5cea6c77efba7013297bd3320accf033acc0833aaa8e8f95cecba469704214f54a1ed581349878a591f9993371f1daf92e55b2a4faf8f952cf785c687a59b3c258daef1b6d7bf9f904123c7384a859933c3ac31e33edf648a1be4d6264ffade860915bd118f0b9aaec2eb8e16b2015fc25e68caac77a3accea53b9b178f6cf48d15029fac12963b4277df037b7a494cb29b1d9e6d2148531a1f7360519cba5657c080254f130a1cc3ccaadb4298d7ea0223897e63d798b4f4909577cf9b491a82de0275a246bb1211bc4144574c8ef176b382262c0e087975cbef33cc616d32e0131a9efdbe8ad3d9cb5f935d3f4f409852acca22ae2a6e7450e9a426ec3b9183f93b4b7f89d850e1c7053c661936e0cde23e831a261b319b430da45772f0fc0113679d06f025983bbf37ecfba35eeca28de5ff4815a490570491266e92faaf8d0ad4ac8df106faff8fe3c8d050ae9dfc03a01ad177c21d7b653509a80369a668a97eaa532dc9867c32aebaf89ed36586e1ebbe1045347766a354a86ec1e8b2f30c8fdfbb6c5d549e7a84db81b73fb828499c5c4be0d4b2b7ffb197133a0ee18abb5a4e371be0ec0a6535507029316f8decde30833ca47493ffcab781d028edfb91c138609baf1054ad52a5d8ccb98b3ca5b138f253d99bd556afd80f71b39f36e0d96fba4e0cbdb18926894968aa825392f12d98b6497ff85a0e4a91c97f37ba1dcad30fe688b54008b925805104a61dc22b712685202ecdb073fad9b10b5b9ee2ff781f23fd41ecdec87f85b369a304b85bd2af126d08f79d8a9e2bff0b18607a95c4efe35941c5493c94e3f2f3902e79f4cfe84c138b83c7f32d7c5a125b28c6107921e8ac92f1af7da015b46a2f9169369cede770292eee8a5f40d080ea1c267c33cb7d4187093d486dc3911bb2d6cae036cb508e81ca783ab5e95cec751e39f3038003081a252eefa7cd913baf136d4e27076251da9cbf0c7d2586fe02b62ec786790ef08fb3ff3d79bd06868eb1abd9875920e14fccf6dc144e898f578b7295fb5f4e84cbf683722ce3597aafe3195e194736fc317ed03ebbb00d956ce89f7a41a334020e1a88da355d3b47d5bd3965a290f6fbf5dfdc8c8e6347b4eb85151e53a960311582235f3b546ca80a670dcb628fef572dfae0c101bc08c80f78d5630a793bdfe402592c316227f2333b386839a67e6ee8d9396fabc9648ea656a407670efaf80966034958f4a70fe7b920c79dea3d5a0ff05f3ed0516537d51a686efcb258520936fdd415345251c9ac1143a41be295cf12da5d4319e78e1c57ce20507490e5213ca7be92afca8ec8b6a07b33571afe6940daa2afb0dd4dcc1c329474ff8e13d740488e5ced552074fff695a04fc1b70755245895a1e9c387fd9514261dbb0f600ae03f4896e795d1e72f421d8572543243d662f6811eb9402b6a3b8dbb0f32de95bb1ac01b1287663d3b6a3f52339a4f6b27789e15519b2b59f2f4fc8fd33ad1a6e4d02cf0ddf8499f45746da424ee78e72847e3cd3833551b6e6fd6b1aa98c688252b57a1d97660ff006ea1b970a0b8fc7d2e313ffd0b0b85299ded47b60cd2fe9bdd7ebace4b0c1072cdf67231a475045990b35ec761e1dc1dfbd0c402296566eb4b9462979d33c9d652a9295ae70943f38adb212b48bd8ebe82722b1712ab6a3be6060297e2aa54e7d0158e4aba6975237e7c7a1e22b29560b8d262125ff2a6e5c1332acd0f6b5ba15b4a82d3631891a01530321830aa8f2e8ab6b41bc5b5356957a4d0c3bc3eab04df7700305a95d0f9cd18d486c675c963876b25b1a0f78e245deb40dedd14dafdaa9d614fb06eb2538c5411e13be116c76fbd3377ff212eb07c5c035612e4cd7a1de2ceafe95832eff88a9bdb3595cc19287fa40b8d244afe9bd24dca40db49893602a59640d7a1b8e7475825b09cb0cee111864deba9d3d1beac03664279910accb9fac534ef099e398d7f6e3235cef7685fd1ae46e47da093135741894273c0c3486197c26057044b10faa57244721328b47e611633d16d3e4776d90309d68ce4a60d3ecda26c9f39c1c6da67ff79fde4977efc5653d79ad86c3b53090003bb72e78aeedcf4c8107185d9aa65221df4e2104640a1a083845c01000370371fea2a6bc8ae43fbe290949da4e559d3867c16df16b143fdc807616f51ebce8d05bb03c2b0bd587b95e3f6a15d907aa9a5b11622ddf4c81ff9fda4bb49d3e9577551bae649cf64ac0cfd646b02f6f16cdefde09a55e77afd16c74e8a3d777d80b7cc42c51f618a3c467968631119f11ca4385f0f5713e37ab1133b692de475db1d44fbfe9d274b9a09e673dac88aea74ba88cde8db3c831e9b5a0f1e40261281e5aea9d4dfd48c5d9e173f4d9cd56fe7fd610909c838bcbe1d6c729e151ecb4caef511a36a14b03cca7ec5d0feacb4647ea5212a11d18cbcbedf78443127680ac0b1bb65120b4197570288226830e2a92b380e32387bbcd3be2c77d6c7722054d849be9de459cc1832ec3ac8e7f60fba9c81cf5fbad37d228eba137a23227d56cd24970340f2b7599aada9d2424cdba8b50c2b97244dc83f7391e2ceba5bc0a11ba547c142126c791265b33a3db6238321a5f3273ffb01e42adee17b898153e41818b91413ec4f6386ab3dd48db875afe659db9eac94d16f850ac179d087d93784d607349e8711f5f96fd514e8d096de8b4a74122ba914520e93a11fa4adf006700e122e2531e1f39340cccbab4862708d69c117d3efbebabc14a0231916ae1ee8285727c9fc980051360346d53dfc76aa5a11fb1fc8f36f95f741e913bd2cd1031e508b320abd2d3a62baa400dc439969eb44e6abf8223b29d4025c3d1ca08d2dbdbbf9927c625270543e8c0cb5ac5bb5d504d224e66a1895719e4f975d819a95e54cecfa59ec8e385aaacbb023772fdddbe093afaf5a75e63a62d51926254e5b47da1e9b05851196644b9180734d05810dcf3502747c4ece652b67674c02aae74f20d07de2ad5993b3a68d10207eab6be5be34e52ada655aa96c1d82df9b24c2acec35e8f0bec9131c20d0ad8936880af87215611b80d07d7a741a12d8145bd05066c6ac171afd8684b92f72237bb0e4ca4aec1ec280e39f36928852d5d8d02fe463acbad8ecefc103083fd4298f399bb254e7bfa166638460b760ccf2b0f5fec0e3875206bdc8ce096274643824acfad71ba06441c74788356caebdd2208f6f077b056fa9d85aa4357e93bf064a776f5f3b0f288d0afdc51558c8f25cbee17247364c2bb24637dd69017f92bbb43024d9c773439626a02bd0cd44136a642c9c5ae593f32eada790c31a6704030f2e07f1173cbc0dabc410bf9864214c298a6283b3631acbf94b8371681ba81eed1aa81ccf258252d7f90fe733ac770b9744d0170cb554b39e6c72e05919cc237f8f4d7f3545f4d2732f4c9473c77401dcba04c0fd33efc73219f31c08dfab26abee9a7cd4ad3584730768fae899fc", + }, + { + "9c73ac05648e0c50a3ea3a8eea70841e8e06669c1e7520c5e25e093769c4b005375c0a9cea16ec8e00261ceb96a00924a66fc0c4e4e089c63e93fea857aead8e0ab82af4ce1682cf3c9fbad23fc3f7e632b7aa169834ddd6c7db7e1e892cac93e4d787b2ed0a812aa93bfce8fef3ce30ab794743ad241974ff989288c43e1ba815a25a03acdc2d5517293e161d0c46c8858d0b32b124a6b0bc3838807753288cf6838fa25fbcf876e6368c0342d3cbc860d6fa12faa1c2b7d9fb37504e60dd44e36ce74229dfb80f1545125718dd1f78b31a8aadbb4d6494489ce596fcc2dbdf2ec22157a1d966b61e780d36552daf084739b602861a96ceb67b65b23d40916c02b2c3a38c2a59aaa266e1f8939000dac9b6dc50d1731e87ee833a2cc3cb98c57e5b680a85c1b428289520bb252096efd7723fa8e55d2fd4e16900a435986ab3f3d2bd799471a1bc07c1772ce10d1bb8805a6065b8903999f9393d2ed1a7e1c57a9e3e0e10dfca17a04143814f5f3acfb99a34712a6e0a24a7485279ef343e69d27c77e25b41f9fb833d7cd29cb6a15551d5c77b43d19feb19f2640926a272f81eeadb792bd474ae11f080ada72103f8f7ca733a9b1325b50589be2b2b3023491afec246d336f4e4277592ce9695c68d5f39c8fa4cedaf51776d7ca29ea0ecb89eaefe71e5f3560c68e8dafe7da08cdcd954d626418677b8f3f45b9194474a32f548a4da3bfae6a3e2c0a25f602e3b3a821160c397d77c8bcbd71c5f1e669213af36eeea30d48e12953071f55eac2fe0bd8fa355671fe032f6fc9214632428125a16fc8aea8a9c7fba0d7518b9a4f876349ccb9bbbabcdb2a85fc60b83ee1ddd041967efa4036e5e10e377c9886f40bc0b0b57c7b724795f843f6a072e87e532a04c21445090a360731a2afb896ab795750e5c2c33d58bb714f5be427ca3751df09661402604a09a1eca95a8344d3daa5b99d68e6e6245825704c5d4a73af197d052d7f75778917542261d77735a21cff3f75d6159a3e4b1a7a9854ee376e6b3c8bdaa1f353b957862b2efd50d10a40007026261a546124cef979ad20d8085d53e30f5736b8aebcd3cdaa349ea474af249ac53eef2653ae1fcd5b3095538de9368d307d45df2a19acd44e3b78c2da9d5d9fcc4cb61feac5dd35f66299845bc0018c3d476b6761083baf33a4621e41cfae0e0c642de729fb2d206db6a4b976a635b3fd911b5e9946fddceb6feb2d2f893b2bed590317442037a1d6dc5b5d72910160221cbecb53bc983f1c736c3bfc9757e9e05af1248b28d651f521af67b2a0d7e4bd86a0013338404fabac7b9833c372142e6338a98c0efb7130aae8e34bb0c80937680a7a904aba3be735d41af9462f17b967b13566bcb697579f8a9340429c77baa6e24ae1ac86d8d25ae3cb9112e34a7a948fd141367898c5f33c0635c87de06f603b510cb229df0d0d9a9e107de88b12686c539ed4fc54c8285afde0c8ee502919a125cbcaf4c8c89f56e90d3f641f97c07326956f7b5d87c65b689f39b8b84359ee0f14d2c7ed621ec67f5e2a8ee5faf21c805187edd95e3941ed62fa95a65473a569566d46b87c0d27ca37b6b022a8cca30a4480d392ba15701d1015b3648958cddfb614983211bffc4966ac6c1f691f19bd9fed405a02c06712d62a775f73353f3949c76b6b7757a4ee0410fd6d20071abfe46b09e72b70f9f19b61410ea67037e037934bbefaf09cff018a5c218176d165d1eb5cfd5c46eee7b82fe65ea02e3ed7b18a86ac7b139b7c9df79e1f6e6f85304ad22d97190c7ec12c651fcc835ea434d92ae1444e7cb0dc644efbc2ae70f2f94310805c1d0f2d49643d05e78baa1c54d4fd99137a49efde88dba1374c94208fb4a0ebc1a0090b043610ebc1bb08168ff5bf936ff9834e825eefb9ab73da2b287b06fa2b0ff52f46061b07c1131e4108cde478c767b749b696f3520acd8d3338842d53941282da289dd1e9a0e02aa9be0f127566c9bf2d50a27f6b6ffc9e9880bbfc14ce7eeee70cb0c0ad90fb474efa69b46123638e8405fdef65fa7e0e7b29fa8fe8696edf661f9003a08b4aff85a4a3e6d817655c1d533b834da981b8c37c38abd5977b3ba71b3f57967a471c2eeaf2f6f258431fbb7e92f91814b1db80ea775681f282290db170942bb7b04aa2a331950b74a4b6e337affb4c51c6cd4c4e13ce3095e73e4767c2731f72bdb225ff572163fbd8573378427fda194d165750d487f6bbb63e1378a132fb6ee5115e3c32b2380b096b735bdb4d651853bc7928346fe3ea9df7534f2a4eae1f5ffc4b82ae738db7df0103ba4e68c2a2153bca499bae2439a57778cfc616df16032aa8a19e26597d275d2775b5ea17cb25d204b18028eb25a053e5666ac47c6def151f7d4b68ea62c601d87bfbe04711c24bc34274be6815024d7b7d01e7dae10cea6e485348ab195a83854663cc5826181b688cc9c091dc1e0d491fe51400e20e6f2a51a7d56af258e038bcbc80e2c4ac4b41661bd33229d07b39b59f3aa79d99c1ef41974a33e02a7cacd6fd8f9b99cadd0fd6a031f070bd3a364c64ddda0e9fb94036f374171de0b3f4ee3380780e6d77d50db9d58e670fb4a364827d631226a3491a27602808141ce657ad6e560ad62b088ff086e6f03b8a64bdf7c7d01e7b19289279509a9d6d80e50aef3b05b5561e4556952c46d0b6ab8eae735eccee77e570e1360b7ea38c53ae6b8eb420e4c2663b57827228392db6e79105a47f7d89e06ecfebdd63783101d3bfb5f494785acfdfed41f8166faefdf0b49260222c4080ec2c6e4f949f41784f076ce37fc7a34fa4e547bb44e6b9359b4b95cd67d64e4402ac83973bd50f8adc7c6e4c34019bd8f6d3843bba3d7155890712e0ed5134e00db877398d86b459f312a6272431f01b057446bfb1b8053acf181bac79408c7708f3a0867a64e06d7786849bb874a6bdf8fd6daaa572d5648ae100f4318d6b3a811bb0fb709168e817ed83c0622a7e5b17ebf5cd5ecb21d9ac32ddddb039083144c93cb55a95ad72732132d54bb120639d1620ebd142b58d75835b35cc6367012c93c6772963e9ac852c71c0dda2246ab845469997fc170d8f62334bc5aa4ce23e036967674303ec6f75bd3d17d197d026de69beda70bc59d2ff95a899d28ac7e5e42f4d37233996a8e6d3b0b86b80df49ea8e145b4a6e3e39f3d6c3c6518bac45baf97cde23037709d737b242b8918ca31f90fe59ff2c83e2f347a954d3559a8e4f075c620ad36be20b1e24b3afa156cf3255192171ad0474e4adc9b7f35436325b92945665f038611e5d14bdfe7b7d20c09642323346a717f460dfe7b5062a0098be66febe9f5fccfc747aeaeff81ba08e5dd2b1a489c998ea9970afaf9aa03859073707a686c492fb3f7ddb27897ba5e75e578bd82114b2ba85525a2002927909c970a04035334b64b1169c3a923211e0999db8baa26b6537cdcf57c051c0ca1b317a5b66ad96cb5ebd57994f99ab202348d8ddeb343312f1f26ab2442b8c5f5cf6bab394418ef2fed68c3e60275e836027515b6b946e5d86d91fdaf49c2a5182d5051726840a156a8653cabda25e1dd9af693533d782caa09295952ebfe6a194fbc8bb7fc2c0da5914a506c6f31490928dc5d6554890f5eb268b09d671bb6b6d7416dd36e7b78ffc5c86b34fab43d22909a87e5239643d5fef373650e291be56b89b9d90431d8c9fa44fdf4f83a1689d59d6ef833b1ce31a44197b36ab298d53b51ae3f8387087dcb0571c340874c1524ba0d576bdb88101c1fc387d25b5c0dad0b4d309255ad5d5b1e209ba56db0c927bd209399a8a3b5c8663c9ac199a76ea4f49e364a4b93a569b3400e20f0d748adf7db46a07efc68e43802a5d1a914759eb2abe8fe3e8d67f2cd7612bd4d5a6a4535b1e5b3ad4d97e54f3db7f8512c9603d87e01160b6908d8df1b952c750071abb1565e5ea3f643f233faeb84278187ff0089150bf21ee4d13979fdae796f592ac5b88869aecc5be1c64665edc8ececc87502d36720b73859313607aaa561d56a195dd3c7292fa8f0750ddd3df9ca056fccd9d6ec900f45c1454c6ceaad4154c69e288dc85735b8cc42950a3c5f0fab2be8811779905c3ad5a9a6bf56e7141d863caa4e93e0065f229b695efb790926618b3eda1b9a15f143bbb09aa3c4b72900617793417df364185cc213d5cc3a375778117212266356e214f085d8a7aed908256c4aa25faebabc70ce913c08c89380da06920069e8e27dd867567f152f883a9bd2dcfb8097b7f065482d6d11c0edebc67feb3068cead403503c04b324885ce1a62c99af9808a5ec8b7cbd978b8c43e37b06e9f7e1ce0b31fa0fe52e8842002e6e99cdf69263d31de080b56c0cf94f77f0397fd1f77b13e17af90ff33b00119999df802c33534a13d3ff7fd0e8cf58e8f8c8bae033cec1aec7d191f2d1a39c7b731c97a67fd1ca43c13a24b9f97d92e2364dc26a1c9408d4659ac7373e53a2a1704a47e01c0223ed4c489735b62a27ec67ea46747e4f48d3da101b0863bda9d3f7f1b413f3e7f130208875e6a29dc30a78198ef658c7ca32d7d53b4b92e51f8ad6d39ecabb800adc0870b2ab0e85b5769f346ce7fc371ad40c561f9f3b2f2a01f2b8ccae48c78a41383cfc36b2a1bd41d61a39c24144965d9aa5ecc5d506c7c7cf9476085bf049942d35caefd77821ad925b7fd3a006213abc1e008114c848d45cbedcb8af264cdc5c07bc338fddd1123940e5d95717040325048439dccd1e298bead22b011ef76d26a390a68161b8bab29e8409a5880cca9c8104694e1282c9fd64f50e73ec6b9a9ffc31115de9cc0088400a2dc806f85487fcbdd60f409ffca584fb197156b40142e512a0dedea1571ebb74d6b26d3b4a59e9105929a055cf3540e8a6a79ca7ea71ba8b40893c9797e81c6e9a7999d4d382e52cac95727bcac354616ae1094552b3d0a33d0d3ac4e547237fc0cd54944039b0eccf335889f6aceb518de496e0986783c564be8a4a05bdc9c67b1e5abb480b98173ef091259d8c772b611e0c09758fceea3e59243406edfa71fc452d4450b55b8fa5ecb543692c6eda3a6ad3bfea929a18ebbe5ce2ac4754989c71dced37286cdd1512107e4e7f4878da1c28b4beb2dd9a712a8d1d61d1a5fe5382db8aab4857b05a783e98e77711c1933a7641fd43dc6e6e597bd03b11ce8e94aa094fe250f03cc92ed5b0a5e7723911e87b0f3c476d9aa0d96adbfb395a8fd353cfb5a4cfe27deeb82e849f90bdb17928b0a5702e4010f7aaece2d43772a78b325d2ff24f9de0f7bc65974d2348c64", + "bf96bbc17abcd1f56a9f22ad164d25ca72f8c996f1a7a66d6effe140336da4f20460b47e1c8573872496343be35a055552ceec437692b0e4919224c4ffc8b603286a8245eff5cc148b004f6e5a54c4ac22b0f09842a07cd332a09732694d3591b8b7d6a7ada2bb38a30aa7fd5e6baa811b9a195d3a96306d", + "aa2f714d3a184a9883f4199e8e33fbc9c92b36fff2d59f07a9d0d335d7476e81", + "36c79f9f14d431cc8c077439", + "873d0617c986dc9d83e9cdfc50b1f916626a9d9e1c595dc7ccd99d1e993d25d89b04a893c89e205952eef8f1733054bbb55fa5e1b07135787d4fcfae226737b50cafa2c11276e8708451be9b4d7f662e98ef6b705c5c4fc64588728eab1dfee22a0a92bae61828a7394977b0ae8a3b6d0126a23583fec025becf0a72a28891391ac1495732a7a4a1d43a63ed8eb37b280b6d886096fbc4f77aadbc5e441e996334d0e10cd7f3dbba9bb7efb147297986509a07735385c681e0543186dc166291edc3b4664f5c8ffb0965c85bc30ff5e7769a69609c69ebb68f35d104bafe3dbd3e2a40e13865f19bca3612e48592aa930eaee29440b4ebc1c0a59f1c54519857c929709b086bfddd6d4a30940b592be48e0067976099efe71f45f956182dbb300e8076e1207baa32d59c1afef7f34171bd66099d2d7f07b39d16d0f8b085185bf2554c6ad66bcd656f07979e8f19575a116f5c4fb9700ec3b46a3254f28afa1ed51348c1af6dba26fd398098a76d7bfa2ff195eebab41330ef290bf75205a2ee570a2fa46bbaa74aa6ba68a0e63e2731dc1974eb44794f3c89ba58cf96f7a070fcca678185711d97cd9d7d8202351ed589e0b05a7a190e60ae4aa109254a7bcf7013f8addd07a64145e21226795ff7c7b1c225f40ed7c3552da8eb18b9bc9bc70c2e7ecb10c8b20c54f04b6e27b5044a7a67b558407eb330f2083444375c022565c45fe817dc00c7d24c23db320d15949b0b64fbbaedd310e73e423fcebe6e1e98a5cd232d97e6466642e5e3b23f06525ac1cdf8688650cd366b1b7ba2a9033e62d836b14bb73717757b76b9673671bd3d3b2a56628f5a309f3b86ad32abac0590c50f7c5a22e0a920d88dc9fbcb3add08b900a2a2fae4178aa100a0e645ab428e0e79bd90baf4af2755e48262b64838a6fbc21226e323c0a1ba5703e30738fc7b5a7df9eabec6199df5ff6ad58f9df5a734ccd6509e53ecb3de1c881732e26e52ab848a0335b04b25f2254aaf8c130c78b0c9a40b60d402673ac7ec7311d0b00c45bd176bc73ad81c2478611804f59e3c145110aacce922e473ef346f8acaabdbb9f313dd3f8d0a937d0c048e5af789e2e09a816146f9ea28170909caf2572a2f6e2d0d511242909de2815e9ec586b2d12183ddbeb7dd70f32424097e2ec28b4ba62cf78f547e2057a4c050cccdf6b582172343742ec8c85e2847efb1595bccf89ece3b3ebba824d2f097b1987ec26c6e5710544739d54a714060fa91b7995cff0161415eaf55758078772c0271d9d282354e47a25b673eb11497a6ed8db82267d65ad47412300ed525af96f943c5336b1de88676dc346e7339230032463d305b0442f934018bdf0242768511d20474c6ecc82fd752c0c0ca5cee1f3e06e679fa5835540f97870d47ccc6bab233290be7a3bbd4a73f1dc7682049bf7b3cbfb6687479c18d246e3c07161df5c889ee95d39cccd989625a8c9e80f951f8b1832f6378e05daa8566477d7fe547e49ae6e822a68de4df9fc4d6500d5219c3d3bd8887bd7f695151ba378da17c2e750399f7482973510a386721c59683a86003edb9f0ce1ea89bd7bb8a25c222df7ebedcc1b56c8ce18f367b2cae720e0591b477f6ffb498c3d7ce59cabb1b01d7cba84d7180b4b2a165d4b889a6ac361720e768f2913aa50b0b5c88e55c35bb4df4fbc4460338809605f1fd445a2bcd97ec1d2f269b5e779a18c8f215bbc5555c745424484ee5436119eb8754f5e9e91f51fe715353596baa1fbb0a690e99691636e6027cbd4b7be752bc278661e2677070ddc12dccc262d3dd47160345de51359ee8dcf2f61044f95dfdaf323881b2bbff68af6572348f786f6e52d1309cff871ad58148307d7eaedc93ef037922b6092ac62171433adc4934884efdee3052ebd60ee115f76f9dbd0eab7c4c0a77b4ce8078209d23d81d957335f331965b556ebd54732327b5aacc899f9ed0edacad9eb98cb845867f249efb0e1a5fa2483227f78decbf7f1f32d060ab0c01eb985d83920b2cc24b5f9a0d5d869e980129d3b78277fb87e5cda61e340a729d86b6617b8828dffc7c37d4c38080ef3515c2784935973dd184e0a8160f84bb78bcd8a5e691760be4a4d41ed6512ee436ce24650c0e17e7d74b5e01cc39b21e21514a84db262d673f24a82cfd5dfe2a162976171c538b24af16429bf8ed5fa8e37f89ec6e7d63ea1d83ac1087cf89e8f43161f225108889e922493d973e36b510074533cb1cb22174d21c4076959e4191a5df880a8b868b95a9cb5151a7ad47375fcd87725660cc0b59c88ceb86984941268493c49b8aa2baa8c531ecf497853ffc3d26b926a379e72188e246d42073041fbca453bd558f328881c8f8d9e099e898a912530c4be499f2b32229c359ea10e0befe6d94cba5ddafe51d164898166e890b22fd1eebd5724451511dce1f8f7431d712a3f1e50fa5f609da686253311af255b84b2106b09b803e94b51729cfa0826869945d46b9606547e7e33fd9961cf15b400d0f5e01d8fd4d92a83ae526934059d4514b9e0005317a70466aa0b6086d5fcfed201d958a0de55fd23f0919ea29b8aa02440031a9fc206b9feef362a73430a4204869354ec81b6fff92eca97e7f1bb12d25228eae466b8137b4806895ce34b57dc14bdcd107fe160776b0e5daab150ba06976eb884eaa574da393af4de355381c7caa4f611a2ee70a0c78df93a4276f55e6281997b4aeb36888a6d9638cc95444047e5202f41f8bdd787f1ff44a648cc7d39f05e49e5d6989fedb194c526780709763da81a780db0d1534a466cce57e11dd3a4c0e273d9873af1040d52a90e20101e1f80ef296d45769d204cd5417a84e022b6b336675d36d9cbdb16b0cbb08f5e240012967c8067c92f97f981cd19d449084400d76adfb7c610abb73bf21e161db04debe6665fca79d71c8cc50adc3ecf0e52d07773478ca97b8e9821a5704dc58acc647a5bc618d2b681f17942c46c266c73ec211ca403a7d47e42e12c775b370cd500d70a4aac7124f5f6d2d4ca78e1c17a96426c326bb60379ceb0c84a86200f3b450e5e9aaa11f45440f5260eee7675a8b9c47fbc58cf18a651a1dc7b39a911442504f12c103054bb50f15381e512dc6e3af7b414b3db26fe767d83a2a53d7181fec8f6b196c7874befd6628b31797ee3c9260c7b7853b137893e36696e2a47277add98462ea9a0edeb7d2d3c0f2805fd7db64c2c7eff353ff2b36f4de862a42779ffd4dbe77b6a79bc9f4ea3e909474ead915fa3fa990bc82b83a670b163e79300b627fb91c4502e96bb9dde00f716ae6ad14dac647c9f7c2e5b2e505708b5fee996b8e9113a8f4f2caaf414061ee72e76b8bf47ec4f781bd7c589adebc2c267448247e30d659998d8037783494a1fdadcc819d7ad7ea2674f75e10639c3d3055046a00814ddda0e463185454a4455d60b9780250183d591c3db6f27373cd2ce4f02f206ae10a8c32d71226e7cb8d5b05909445977164983c0073434d6c0f2bb62bda66a16792d6e53a49ccb5ac3e285a6baba935f30e9d1ddb812a018ce04f29e2009ad678ba72b6a7112d6e7cfcd3ee7b058ec954a6fd7fd01018a6eba6209687c3130de58147b07bcfa02ec1caf30b59daf87db4618b4a5fad34cbc8014a7529b9458e05eccb9a77ef1621aa95513c6fa4003b0877ffa6d48805e7867dcf53447caf348228ce926233f65d553146584d6ff3dc3ed3296db9bfe69dec6a07add13037b3aade118b2ac3c52350b9691a6cb32356ad93377059fb8ceab68de38d96876d6d383db01f3cf620e47cbfd471bf6dd1f601210482f7c3bdd4c3bd37dd0a7507e1f0fe515151634813dd4ecefe97b52eda28e7a7129993b0af311abd3a07bc463f3cbbcb4fb0eb265a5835663fdbab0d8b8b5a73837ac98ced6582348fdeb41ac8ea9e36f9818ab9c0a41bac1389a6b518ea17df043dd50550f32471645791bf59855ed695b84919aa5cb688e569122786660f06e3a919ef9cf18c355bb397b86710c367362cddb0239aa1d32d489328e4bf92b3abdc3d0dacd76ef1a1efa28fdb848e708aed6780e2d8efb19a2e26fea56b4440dc3eafd796896d73fd150bbd967871f5e6ee5db58995f2f85cc2a15077d7d472bec2e30430af6891193ef03dfc7761e2b3b3b54a72d4f1084a8fc541526fdeb0633dcba14e9485b43065aee8750397ea88d9ff13417149e0fa145be666e6f4afdabe7ad8e4864e777c20ee7a2842db44dedee22f3ce2f97d72919b9ff6059352083be816a7515c48c5140a99af8e81b9e18b10074dc73dab55fae66261421629c8e323d8134f08beefbda555660a51e4b55a9ba4573bdf0396cc413145a941c4175aa672586f7676027f9fe211db87fe07a23962f5b1ad8f566f0d5b13c5146457276f307a02e1e13d00c5032a06d225248215e4bc4be1b672f1eaff16ca95da42513fc4315c7a6663f9101aba80224acbf0c87fd3a2ee9dedd1808c1247c5bebf3cb8d77377a508ddb484ed91203a438ef5ed3ca14e087102bc5f3828d8c3437ecf5c92eeec0331ed93ae33520740abae9b7bfc45f097da70adbb9b9b879e46a7d655dbf75d89773f737b66fd8a8c13506cff7b44bd85dee279ea7053f3ed8447fe79c400cf23726fae800449d27af5e342ecf776378e2eb449a3af27a40fe4a9806487b81c942bfe1a4b0fc146c971a13f83669e0189e337cc9fa2024864436189a9165ade6b864698ecb797ea05fed0d60f0ab4b92cbae36c72ccb5aa45337cc02dd086afed9e5522ecdb75ccf389fcd63c5a4abbf60908e39cb3268c76a08687588be67a856a841eeaaee8ed016f6640ef0f5acce12ab8bb58dda380696e3fb22d0bae0788c4fb79d00cfa5ae3e479dcf7d08b45f4592c2d2a7f8081d5a9398659613ba4932ebfd7382d516b2648ec4ff4477648069b9b2e4decc89547c16ab82a0ad9cf293fee5adb17cea4c95ab7b8e386dcae6acac63ad0d1d13656dfd97d5623dbe45230de597751321bbe5a03c879c303fd7a0d837d48141decb6df4f0865717628c85dbfda29df9a8a69b2c956c75fc66e45c08960c23bbbc706e48395057f989dfe675305067b3ed8d046db339e504d5b2bc978ab4dc261d8afb325c5e794ec79d63d8db53f9dd24b623fbcc202679fae8f7d39f7f7e0667b142c714b6a723996e5254ad2ebafd63c3577f8909981ce6b3eb1a6ad67a4e93c45ac3b34587d153ec5ab67a2697a9741610d5a176cb9b5856bdccb98f69421061c84811dd6660495d9f30548efaa69e36ead246d997c95bad0ca3fdc1a08b4be31b12daf211d3e29d585cdac48af8f2268ec304bb35d", + }, + { + "ceb1f819497c0d631a9c9616655f419b5e3470fd3b19cd0e4fa556bd26cd9df57e960ec7121b2a2cb7c0421c1f84b77eb8277bf341490190ee574d1424eb09a281176a933394bfea5502077486bef23ee66e3127b732b7a58a04b9aeefc35170dabb030d4fc3f8a4c5ff194bbd0b89a379baca30ec81d576868f25755276e62c31e93a80ac322571313ebcee494592c3ff5cf3ecdec962645887d9aafdbfd62ea910af5542d4c7731283625bc9f41ec85012b42edb1792339e6cdd9c2bb3cad4c4792a064df17a5f74dcbb3dd0d90620ebba4fc6d1e1f9704dd60c798ad64d4e5077549d68cefdddaab81a7a91209b7ddbea43accb3d1c191328929dffdfeb4f5740ecbf0ee99cb9a1b73333d7ceb0b2b8f35f84307b9d44a42fe1a30ecdf2650dde251bc8c1d46978089c50d64c028f40611370ddb0b481df9624ed63165370f4788bbc396026b268c2023e0f04cd4f66e0bf439074c46f0ae85d6dfeb0ddf22868af61c8d5133097156fa61a3cf5801db5c3ad29871d336f7aa06d2a7d5f52e50eb3aee3c7de7bdc4d21f68a1776a7cc3954f5c071282febc89c1545fc672a0a1bd8eee2b769be048ab58ea12b356d658a6225fb8a55e752f1fc97ed64c2f87f9ae661514f1f56d9d4e47b001ae865a44b8a9fd5df8628d183bfbee781b6661c9cc76debe6c3c5bba840bbc228206673aa05498a8c715b0f3019f6b2d05cce6c233b5809ff1dc4a75d7f69859fcff94ad442d460b32f6fe348659518c16385e49fddee9efab2455732aedcd17dd51b5117efb2ca1e21ae6787437f48a7042d46e11be4dbcd2932ffd70fd154e4eca5fcdc57c6fa79746100b8e1485fe575a5c79089a25eb2d55d89e42eddc81b82c4f7da8bf153ff5353b7349b161911bbe0a14483fff6585d7f3c8b5c04a6dfc99db9548f0c53e25f0b16fa212f0bdd10ad2193ac18eb09972795f42b3bd3f4d98c4868989c4af7a760f1c88ffda59faac73256df1d607644f56a70303d6409c9ad716149bb58f01b4ab8ab475e4af1257d47049aa77adf9ce54fcd22b3d6ec60484da903a6991ff052ca37b01428d5916fd92c17530bb3385a805b0d57476e9f9417a23ab1c12a038b61b3a0898831f9615d10b468c3edc24448d09b8f3e3a2355dc5e069e880929eabcc97344fb6ca5587c5ac1404783848f531f1e915941e7359fedd328f7fd12b3c685f8c1f29d1a6ef7dbae3e5e32cdb251eb43aa2d2ae0cc18b3f40fb006c2778cba387e5852ec4f2d9b8e8ccd5b3e1f4781c974aca940c45d35d30d3b9584c750bd45a80f32f73dcd85c99ae107b92888839c342cdcf88911cb974d611b14b1d85a59e88c502559d6eef3b7f5addf7d307bb25c57aae669767db6d798ca887124e159b0317e09076cfdbe61aa9ddeda189036703b1cd9b1998f88325910a37ef1fc2e227a382ae635e847df8625b99eb6ef0ef10ce7a2a5762ad7d03a7a4e2b767c4df0b477d6e9601dc8e6438184f97193ea7d7a8c22f1b6fac1f0740f1beb8b68db40e0b22940cff2261273aa0be43df561b88184a9377e6a27f27942dd04abb9448b6b6ecb3a60f14dd39b58b8d94e1991cf9d3a071ba42e0e1d71eb211ca466a70fd4724a34639707feefbfd73dd9680d76a214924642a063b38b85cf30eb763fbfe889f34b20fa4a10ba214d938a5a092c6e9b73b13bd664c75b34f746aa360593c0f8dee0f328f0ad4a3e40d498490007e573b8204a1ce7a550deecfb15f18ed5ea6cb5dd95a68adfe4cab37c13b383f8273b1971580016a8df02a3f4f431c9de9e7ebb33244512080fc5852278081b9f4434109c3427441329e8071d19d0fbb74fb6ea73fbfc7c0ac1012d3a0948d94d7ceae9b0112ec43a16cb582f9c53e7eb0ad15e05ceda108fdb3dc9e585a332018d1cb19e4a75d86041308fdd8476c88e4826931601a3a5dce06fc16512f4669f10183d5a8d15bace4649abcac07358089aeb1e9b8fc3776f3239d5442d3be33d532097e13651af7c9a5b465ace9e626889800318447b8876b45dbbe1989e1eecbfb5cdf5067c71a0d7b7fba6555d0edede12f7228d7f9841dc532274f24060b1f52da6fbaa179b81ce962723f43601d248f8f4d5778c1653e038c8d27828836d562968004003810e9aa9318edf3260272b54fca2e012f6c04abe92c2e6152f3c3e973c7e9abe8c3467bdc246f0226d1b7669bd577bb317c571aa8758bfb694fe4dd17ce78f091cf6c6de3cb601a9d177128fce8d42e652b490d90c4f8fa04ddc71cac300d3dff699be3250bfdb2136edb0057af3ebcca77ba5b3ca34531810c5e2d4c5b5b3bc4e71ee9e30cac067b7706c326357fe0ad2a4bd9cd811b4e9d696bd9b4b70579ae246381210f879c769e5f9cc3cf8d70e9c94ab74a55f5d7bf61a17418b6edb6db4147fc40cf98c75de85421b7d192919add48e5334ebce2a06e56b915447fe085b7dcd677659dd55de1f705c389975e56e0338a2ef07ccf5ec3786407e8449d9011641786f1ecd4d3d3da975d61f5a442293e6119ab20686ea8cc7681010421226838a95a157e2de948c536aabadafcd4095dfda48e5613272289a8238dc945e5f1ef30075d5de096131740cdf23da1fb8b9fa009e5b321083cd93bba9271909460c09bbe1e8c54319394ff85c291814e21215816d4791f01424abbe4cc4c792d0d04db1b812f4d24b44caa76de2bc50f4d1d1611862512d87fcebd3c0b2659082b2423bc5360d107ad7b8e8ba7438ae4509105d6b618af25e75c51e272aafaaddf1e5a227f2b2a2c96a8a83dec23223cb428136a30b290181ee20a819cf52f6c03798e7294a89f3b5137693d5a8b7a0ea38d78e43008fc4eeaf6d077ebffd3ef7952620e0af1395c38a289832df391d1710ab5b103a1ffeea8c06684c03a74399cd63797c770e3f0136d8331611502d21fb883136a82f2034358880392fc3d2fc274b799e59b89f8f90d2a5a123d3c21e5bf3540323743858fdb8912c7c6329a3aea241075ae097ebb23c8cd50f4ff46b42486e65bda6beba5f4fe6dbb30f7e61b1bf690c9f00f7513c83274cd21bb71563257a20cc38da2b88c1063bd0849c8243058ee205853342085a8edb7545f0d96a6af936a3d4612b95676665eb02e72e0875100dfa444f039eddde1422ceed8d38e6c3dbba25064f8c6cb5786f9ca67712b7840cfbd40f99b1edadd4bb9a61f48124cf3b49d68bd642404eb1dcf428eeabadfba6810a4032f8ed06b38867a7098c7744d54dcfab8f0ff941ecee69da9916d54097e080cad86dd08bf53833fec4aa4399f7124586223ec70e2c31e8c647be06df9e86a976f37901e9b134e775de2a0fd53d545c5f92236dbf5455859c138b7bb1112427049d29ed4f5dd5c43cffd3113c276d9bba910879e55efe817189fc239a204a9ebe738c0dd161d10d60a51e9dcc8c38861d41ff029ffd841086803320a17ebf5ff14b6cc2ac3dcf0ce2eea9af7ae23597233599c2321dd2b99e06d93f84989e75e30a388f47079c2af545d96f270e064a43a00c76bddf2f5be5089a69a138de844216148a1eb0b413f58d831d9b8967df297455e7538442388cdda12d157fb25896c6e2b47696c76b234a88bed4f09dfd64f2e4b77627ef03049030190fe271a5a853591ee9218a0c6b12cb3f02683d665b211dd1480cd44c9c0566ace7d751902babae14cc3821374bec774d54b4b4afd5d1811ede556a7a5ad02642a878d2d32380e7efb9082604f49d51495105f827d77945b5cfaf2f2980566b28ce3dfbf1bee2e077eb067bdfa4cc28f5d2211ca99a615e69118d9391e3feb9b13cb4a2fa9682718189ec612db889228aaa3f3345a091aeb11f41420240fbb47caf567646d9e7c762d3288f8bb2b1165cf049a191db5042fa9185fcd180b04d3007c376e0aa3d427d66d10918821f74736816044366463df7cb3ac94cea167cf1daf2d1842f130295e40bad672a22da9238ded69e241395f04d5e3c3875b8294faafbd3d90ed56ff3e01c5a0a3e349d761273143686aa26d408620c7d1a35ccc430a09e3f750d3256298c6068c0fdded270f308f79d2fcba591d723ac0cef703d8f0e7c051bae5b453abbadfab98bcc297ed4201b03ebc195c2e441cfd3b10c63c08868db36c320707ecd6a37593661d70a81f30e6db4a32f98e4fe6b950ace55923631c8f95138781fa2af78d8104fe39242f1fff6942e8e782dfa0d37c863caff9492f8e5cb70046d207c4630cc29c20e1ac105aef093261d8d335456961e552ab14d107cbe14e9de912f0e5d58d16b729270208204469f917af4e710123c3bc38a4b3f485f2926f058344db105b9239829441a2d8ababf04aea615c0e350846d9bc3b5faecdbeb450f38f615f119ad1b5dc748e88107ec2fae01f0915174feec37b3e7248ed2699d0a5fb2fc785f17d6275fbea867aad815acc8a6fd3ca4ea7357d197e5a30082ad5f35a9d894c0aebb206c6487163c9cc20442c040e6aab33d7b4b221e4ba4cbabd975836e353129559d8ddcb3c97876cdba360da0e0c1dd5b0cff7957a444027db985ebefb6154453a221076c997d3954b347f49308d2ee14d1676b75ab6ef365f3de54aaf398fd96b9040253813ba734829bc78a6db59e3f1c0ab4c878a72d6b8681157919130fd3171126994dcdcdcf68955ad64af8156702c92f7a715ce6f7ddfb70f60e80c92691efbfdebc8cae252108fb6c0010d303d9027d4a5e63413b5fb2316d32fb93c3ea52a2a7df50cc0058c76c58d73f5bb041d9fb9f3c3cda9bee0c0920079ce4f1ef8698ced664ce2e2b3b86027ae2b3bcbbae5bf7ea3693d9429cf94938dd3a2763d3f53937c46763ffee6579d018358bc69182b1c7158a09b18352ea618c11c45f07fe97cb65faca535f43237879ae3e0a31efd14679daf8fd2ce25eb8f32218fa20afc586a98fd908d3fd804cabbf56dcae272328011b252dfd83e5f0a5fdebc6acb04c5540255e1322de5fce9db5aa4cdccd74dde8990ae51cefd6c1edc1879971d3efb1f94dc41b2b23e9c9d89415b46189914a229b2f3e8b05ff78c68711385a00e9534dae6f79d15842aaec575e4ee0f098028bc74016cd3f8e93c6a0cb21a0b574ee63e367343ca9de28003d76e02d0ee2b8d622cfa3615d3628fd02499eb7bd8c1aa1f34edd9c2d059c6a7c7c978a5e4f60801e03e17c3a09793c5217f310a30db1965b8e328893cef20f4a899aa8d9fa28f7fe0a733813ed7466046776a874273ecfb57158483f4a588ad4f232adec5ba4ea651822780596de09fd54b1717bf04130619979a0e3d12ab7c35d64afb8099a1d21bc952653742f50c8e1c244d10374329cedd27fbefd37815a9b3112a4cb2fc587c4ebda381b2b01fced45cdf0b9ff8ca7d10b65ce42e728de183a82e369486a2e3345664e70674a5dac174d6616d90de8e472b62759df057119875483cfbfb103041751747f9cd12bb31e91caf79eb2db1168026a4707dc618f30", + "e45eef9561f3acb3672b4f38570256e8cc4d877e2998e72b022e33de8fc20f7320fe0882f2b53559e084923786e8205336a7d15f3fb88a41e7bd20767f2feaa02df2221fa7577988db0bbf61f3dfb429868688c53e130725d0279c505686f083", + "475a44cde0cc931edf9a44b0c1e0001766f09ade023dfe6b59a6af800e549b55", + "7812a320691ca8442767a51a", + "eaa577bd67fe79ce4586f43355c94528e306c1678946e4f7a907d2a8ee7f4281270502522119a8b09b6f05d864921cb515fddf6a1000fc2f67b52d0627998591e2acf5b6faf71c278e5754b2703662ce670dd049da8d6e280c2b84d6a9b29ce28980563c40e03381a49c54608b72faec9b272ef05cfa41957d9eaf3e944b22610c725d8efea90aaac6e782848d368ffc08784d7fe37ea1effbbbb34952def29fc511fb10a1282bb0b6334328e4d00529a44de3259b522553a07d524dc75f431cc9670127c15670c0df419826617cfb5ebdd8788d5f528a9eb1e61324eac5c1746f339aae2e2e2fae598642a389da671482128acf2d69814258d83de98f186468136868b729aa5f0874fef2ff2575a1f87439d64e049e4d0637e9c99ecb7275417af654541306615f30b75a6caaa563e4790dfb28fe9f0e7881ea2d885eefdba99efa7f878925ce7d33e86d888154a1b03189429fe20af8fa3a68d65ced9b690a709031121425cfcd7e1890ed9614f9dc3ecbd0e38c6c84e453e3204978ddc1ef8d7fc6cae28c61a472d8e089e23209f0c36e80c994af771e6505e72ba90e5543f6bad6dcd31fdd468b13533a0254e44797825764ac1f63747d8d6ca019ff16fa732068ee94be382c46b168050ba725379df31a98ab81ec8eb266a3c3f2e1cd95e5f12b3bc79b8b435e4d94098c6184631cec57e9d8913458889223a2a4541f34d2f9df380f34c3e541fc587f0a6cf08c82e99476060eb84709a292f4c7a8551bda3a9eb6735787dbb9d7f1e83937c2e0e49f2cf6e0ab0ad84c40fbafc3c7e61886a8629bea816972fa0afd0f617b6340b1af19e341875e97565c8eb0b25fcf68696ee674d2abdc29396bfd0f282543d2b72a239c6470f76d3b5bff6d1d064e6e2d06f9deef2aae8a259c034373efc820f9a2fdbce36cc27f35dd6386de3b49509d0c305757257f8674d958c580a09e768c0f6ef237416fd53c31511badb2e7cdfee636508482f01899e72052b46b5d844799cf94708520178cfec2b61c8980fa7dfaad8915b0b75ce6eb57ed4a01edcb4a35c1dfcdf8d60f3191bbcdfd522a0e321ea41c2cd87a303522d0f98b82dcbe53232ecbf0e2528de7e1be75569584bf2ec574687fde67ffe9827ebbe78f2e5bc4fb368f3c9b0f588c97f7a139bd82fe86eb605b8e29cee75d07b510da1b24fd62cd2fb366f1621e7dbf268b15937f7f7ea4acf6e615775a32c90733769996dd2c5aebe08ecba73e0bc4781d33971992b2764c1b08aa972859cb61b003406479423254a01ea85a348ef249d408157cc0962d1e24cd9c426e6e6a3784dec6fe935be1f6730b01e8683d97e21d8774b2e2655f85db7149e930a44524d4f86004cd687d8a528b6ceadd890707458cab62809110ee28f61a7277ed79dc41e573fd4a59fabf15393ed4c21bf4d5138ac843e80bbf5e1c39ac2d7f2147f35996eb51a9e835db63faaa196b8aef1823ad72523fbfcb35b5560582a48a25ab770e7528e4b3ef291e6f62f5fac916e2162b3b56304287e46839858daf322b0de083d1691d6bda44d66d085ef0d0ad364eebacdd0a43a4456035e58910d0b2dacce45b1c0beabc784f3620a3e4390c345df6117b86d4fc386523b7ceeaecc21233a2865ec6b63bffba6689fb3323402119db8f0665a4730b2e26ca6411db04f1bcc78ce6272159ed2665a286f1ad7758d6d90090a6fd320e697dafbdfef575077e282b825bd64a4dbcf92d1fc0c6f795154e8466ee4b318f2d44b6f81c52523ab68ff8367e01090c2623e00b4008e784049df873a35c29e0abcfae7acbf27236adba0b913d19a15b4af4996669aba4c656c317084347ca962ac8df15cd2f849f522016eb92de4de62944b917d88200ef9aa2def0d13e5f4ae09d2eb4a2d0800af1d704cb01975f6d59768a2b50e39e78116147fd6dcdfbc08354c1b4033bf6772fa127856a4072556a9f07bd7516d01ef41bcb519005c0a3b2a04400427ec033f1b52fe5fdc1aed8e2521fd0fff663e203defc39d7546281a98a502b8a470af16cc62a6581c9985d7ca516864b799fcc55a803ce80711484f6b81591d2402bb1499c95dfb1dee9846679c22853be87c84b4547138dc4fd46b4e79ad12773a5392540a595954112f0cb1d9be4d4eb3aaa4286b6c01520558d58587d9d7f0df3a0282011ce01c9c17111d10ad61b3675b1826c1ad37fc562bdde951b43f890555d6f74ac4fbdb9abbe8bc1e80bb6d52c13de8960a3ff8f65201265e82981dbe39e0d65cf3f1fb6c56e11f9786210383d0150a5e0cbbdb52ca8b2bc45c12fb572657380df369082685b3de9847d5014beaeef815d63e203cc911061eb53d89a312d187f9f02760bfa71083fb643f5d8c324c410070b7ebde250a185e7359837899bb1568a43fa3418f39c12feb03b148b924bfb98b99352b1fbad3f07ac8e4302f85d1fe9ee4bf7507972670ff8beca105cdeb037f1cc4f944d6ca869d0281653de5ee93a7362420fdba8b01a375ff08fe27873655953ec1c00f53613c6ab8b244e2fc1b6babdca5311428d06f57aa4882dc870165deff75ba877dd2a04d1799f26ebfac97a1be53a83ab77dbc2cd4aa45bd779f61b1283eae1a1866ec8a9c150dd0a4deceb2ddea1bc0f4206cd435600a8f190b999b952337d9eb2bdeb3aba2cb2e7000319056629dc1f00901f0880278509417223a3ea0919fcdcf12bff0771c7cc725bdca292068478ccb2e1f35ae8964e0601789a73e7e7c1769ba53f865910fc3d0085c922d7f7849d27b6e7503d521371351f9d7dfd5afc5df0effdf6ac49617fa228501ad72154a73e07781dc4b07765dbfa721d95cf1dc41e161cbd34fc7883a25e3ba6b03e504b2c3b98c8b12ff629b965c2aefc26d74faff7f784baf09c3fc38c487a9d1f5818261162f97e9dff70cf42eb5dbcd7bebb66d68f26d917ddf2a3efc0db1e3372b170b4cd18da507e44c467943f73648dba74db1053b53f989e481c3054bac22c6342fca2c26d30a859a1312e9c353bf921f68136de2b1589747bc765153927c31ebe749dcdff98b5da84c4b66085451b4c87fe1ba2142f98636bcb268c33f7b8c2b96a6525298814578377aa189dd73d5bb27ec5cd2110d8751c18a3110273df2595d4c3a00809bdeda70d86c4a8169b7010c9cdeabfbc3dd3266518226d0ade9bcc4825f18198c854de329fb8fe456dd3bf35d89bd9d2384f3f3282f6872351a18a2f852bf173ea4426de6d01b3ef4b4685aa82df7dc45b99617a8b8c8a0c65a2237b3eaae8267e1f6c453f485432529d973924a080f6a1cc2cc18f804f53209383ce3601ad9361afc331707be1c88b4370404cb7fe0bc538df04adc5c8d9ced94b4c474b19619a53dca3fddb434cac09ce10c0293fea04e8e1b19fd3ff3d174baa988d91cb604fadc59ac0b61f4f87bfd07eee20f7f3ffd96766dd6f3555cd48da7ecd71d2fef34ab082678bfc4dd007669b3fc7a937a5a46269baa7e4e4e43eff1b2b847ea70b6c6c23905d6fb2fbccd944251087ac00c35c2eedba30641797d36ef9d3cb1afc0e3e8930f5b605a847ee77106995bd44047294d04350194369c5a7bf246d1108e1d18d9a638be0c051f695ce86579db613cd8922e86c683c91800b9a34fe6339e0dd79472daa662f78f04f0151a3acd18f11faa4e1216222843b521fb998c8490ab8bab27fde36395b456501307d07b484b453b189fa339282a634af30fea99c9af8f877e61871fe743238b2cee6cb69dbd17d574b5106ebe4b0fde4ef42fab469a5ba7d62c23b67d857f1af6ac981c320db70cdbb6be41bbca60bb7a159ee1c85cb82e0a220064359c06c660b75de6b49839eea68c80283b75d9d627aa4500c0c0f21edafe4a2cf7ee079d5310479da06ba58b142614fe69cb236c51447d63db31cdff91485b46325c26d40dc6d608d46a5e2fb01df06064a022ddf6d5cce0147d5b2a5aba5f9fadc5e778010a924e00a13e21daeea2cd330f45536ef4f42c2e77be00bb53b3f9a93d3eb327dbf30baccee5d26849cfad654ff3ef2b035b78dd3ef42de3302e5514551a968a205b823dffb040ac9452ae3efb43219b02436d0761ca11470405510e534d56caeaacc40eaf9c47a39475adad266f5ddc813e71223800dd46fa7c02b078353f870049806ed7ba57b40b7c3c6272296667500c4b97dd2d7026698b6bc4985bc01be99e0097013a2632c71740888ffaf902a02bf644b38cf9a42528880d9dd142de967cc2ad3e1f1737f0cb8dc5c59c252496e8cfe4e53c82f4a28d9ba2bfa62b6415ba3e5e09040d7f3e3abfeba53e46575e8817ac5eca806ec8a84c7cf77c9fa86c9dd2940f5b96b25a92d4a8f894d4717c8f80a62a35a51d8511f1e822fd79e6fc27cc3f3097d9e3272447de6f223971657ded9e660ee4f8836359742ce7616fd0ca2de6656c71b212b34b8edc71ff36bc84ac4af58eb1adcba4b2c0cb31468dbd2c2b7ee6752981ee1d152c4e4a9b25b2ce87796820def34b662381806d2e4fc77f0b69d7a87de43d94d62a6a6526a7f8c588392890e96f9c51bb58b4f438eb5d197477ce9b160d1c898c89ab408b3c1d648be93b531a5bb4988592c5a8999ae3acbe586d947fe6dd507cddb92dff4974ae17ab99aad5aec9d07b96bd29489876f51afa67570e86b69321d9e565d86001514638403f86666dbf93f18e0a62bf65db333bb85a3ae12d8411aa3c2a423a29bacbbfeebb8a5bafd90436bfded16f992232360211086a3084d9fd1980dd96631820a2cf25c3ac5c19d164cf5ab9a852399491962100ca4fd640146b7ea5460b4fb9e46bf8d23d508a4eeb8a3e9fad8249ece3648c2ec7705a7414eb8e8d602549204cb437f589161fe40de1447d14efa4d738b775d0333526c845cef5ffcbaf5c957df1d8022176b56eeb198e7ad2dfc3d7ea46b125ed432cd04c77efc011a2dad8573345080d7c3cdf5cc160fbc86c4ee1959ee1b8258056b0f3d9343c22dbb2f7858c5f162f08cffdca1acc866aa68e5f1c00b74f66544e8a61e429335adf6f73e32fa87e48e1adf15bb6c7aeacc93713dbc31cdccc9b0e52f922842679494039c395cc1d95eb97ae4df3bb8aba9a2584d97a236f87cb22f00c0a078b045044a5c456e22b2b94a76a559de2672c880660f9785b76bcc2aaed780e05212415c6e73880ca110654ed155a1004af45d5f15ae8e5bfd4817440c5d3d5589eea2c6c344ca0d85d91460638b37f877ea4cbbed35ea75678ef2335a5922cc8541987cc256c8f58045028d33a1c4899cc32265c619ac782ff998a478996be6a0c5b102a664831b395a884f18e77885d860d6b236c52a8066d2ced25432bce79a31b23117f405ef4ebdf3517de98d288f8c3baf04b63b6817c46c14b646308e9f97170b7dbbf9d1a36480338d8eb7466df56feb6baef42cba75512954fd7e33961d247b7393726e46c6e94e156d5776a89ad3e288554470ca0bc4cf4d2d2b0c01ae4fcafcb65ccd6ead03df1d4d6577bb", + }, + { + "228eabb5ad8b4ff13b10d13b27372bc2152dff149859ba47d9c89b741d4a5340d8fff5858a4576c55547007d7e2b3f94583ea8f0976237712bd2e5481c3988f5387e7ac2c3f18718388795b7b2d44b0a13f3faaa55311b800301c9203a511572cf8f349280bbabb9424070f415bbfe28aef8d20329ee842cef4d4c299e619b6ef1cf00718aab2accec9ac00155be2903b6fb07dfe98b0bd8d8580176b99ce4aa6be51cf59046c17ce1817d363fa63af5a241d48bcce064a438651af102ff9c6de4b86374fe24f1dfa66e16e51550dbb791af425d8fa601c70c1bb90e1a557bfe0dde730b0364eba9d2018ee751699ee219e13fa8874070935b29a1767e1d748bfbe796fe4b81a71e823605d39fa4b5b885f4610c34d1a090fa4106785e7a035a629958ad1b00cb9d36d171d575268efa1bef064fc0a6dfbae8e532466035a0c2cef96fe9f93b872f0cf804811e927b39818189412868fb104e2d56ae62f77031f0df1ae91aa11826991ca7b8af22f130a47a72cce36ddc319b32dffd294f2e192e490249ea1a6f8437173ce6392d16dda888a98bf685bc91b89b8ee1eabdfb1806fd61f018d1744fe8b03521de4bff86d4a811ca2ecd5be668e9c752a6c26aacc0cc9dd89d112785c25ca6a0a7a5267b4e37457c04a0626c8a29be30ec28ddacf47a84918bab164d07bdedae62132ab04a6f2c4e108eba9ab878caa4a1a7509521d427ad7f3dfa86fae8345dfb5e0d46ce3a94dec84f7880c7422468ea74fe0b4825b8c762b34d5d9b82ba96e0c7dcae01718ccac0044a87476ff031e3ee3c2c13f5f375a841d243c38cd9a354b6525527de1fe7e36a6e2ad95e5bbc4c97e85f8cdcd5341da777e03451838807d5dd2eb4fd15976783c140e21cfc2eb3e58e40c16374de0aecbe3e3d41c64417a472cba18762080a2348ec3f441bf229a932ea0ca7c816938655d0c81b14dfbf86aa600d0c68172fb0046ef51f601ec89309d43ad1eacd583f9d205bb1ff1a37a97b44b5e35be4945f52897eb2a74645b01a7f82054cda44e9fa9f9af9bad1a235155718713bacd08d354f3fdd95858db0040fb551e9f93ae399d5dc53a67e88bcd5a02d104dfd9d824cdd5fe262ed9266fc47b7e640f2c9d9c7a62c6d24b429fa55560aa254a824a0858482e771144d6d5b05539cf71d75bec3a22be75655e1ababec4dff9472a019f6220067374dd49252282e4945a407084633ef9c88d14833bd95335107d36afdf56a642cb739bf0a61ed53a6915baed78e9d74166ebc492b517c7c594fe6564550bb7108f43012551e65fbafc0a9874e46fb64b5b7aee0082a5d617a43b8bf9473309c6761aebc7f13b72ed460b522a6b0875b67353c705f99d1d9dc899870fcc90c632aba1fa9ced6d7a2368dc4dd3d4b38a5807415e00de6b9ea70525a6c1b67d04521efeeefc6c591fc5256d990a1123522864a029430bb7ea00dd80d283fdd6d61cc5b509221e28f73386803d97a38fb0182fd95b3b91353c6eb60ef2b3d5c8c0ab8dc9cd9be2b4cf69450d00e88cb0f0bc9a4be82b71148a37237ceaf945ab94c365625f58171eb15c1bb244a87335550d813d28f241a3296520046e65aff3291555786d7c871ec8a2d10d4b44429041c3cd6ab60f0def742de3d28393c5aca92b150697ac15504ee66d8a2aa01a6c63d7c719d6d4f94af2ed1d8670e3231a0e481095e425e6231c43ad36e3b7a3478f6a61563f5aa13237beb8a891dbb29013c325f7f91c1b055fb83c436fdf8aef49ec457946e6ab7e955427373fd9c743acfd4b9609569b591ec79c7ea7276de103a35a4a8a05c91f59e04689ba1ddd570b18ed046f785d7e4ff9fce7115ac814fe126f781828877208ddfbb2ebc919e6d1f6eb417f38bfbf22ac9633f75e58e560b85d88d0e4fad9b2e68c9ebf9675819d50c30c8982bbbc2f41e02690390bf0e16979b24e648bf15b18800aaef58c3c465f38cfd1e47bf1266c17b69523b7868d2138cb95c4bce0dd3ceb7c2267b868b6e12888d5a489fc0091b295b56a1c328b54fe1119aaf1e6d7dd52fa450b52fbfc8b84c2200ebe209060b655cad288562786673121691809366af37b76567762d1fc24f1fad3128b43c8d10e9b6954b2efcbe40124fc0a5b670dd6dd544e30263a551825282aa06be3817a8eeacf31ca8b25cba011d60b78d3d2462810764e4acb566ff371005f5481c9d36c991527143af2c44cc8cfc59c920bb4a281f2ed4d494d30ba4d900edf59e23be2f763072255cb6f1e8b24ab1d305fbfb2429cff8bda303617c034e71a17230d0e860420dbcf9fea4ab48557e4d50797179496936ec6c97686fe6d9115809e14069244d251d4bc9c8931e47e06ec051e709ba1df526b55d959b37a6f3408833aaac80cfc9cb99915eb7d83e26998f0da2492b986fe0f5047b2cab6e6d33a117df21e6a8ec7f394a3712885dab176a4d6095e5cf75dbd3f0077e5e74b1ff8b902072380cf172562884de852ff5f07c55856224fb3df8eb44764ab9284944b86ab6f176a863cdd0e7ab5616a14692f6cbf41bc63113b27689fc2fb145736aaf2a5b26d2bef3a2a59ef8bb3f3e4d360a4251d0736482e9ed7e189fc48c0973b6649988228c2ac72b23826a61cfa06b11f13c8555be6e433d87e20113eb74c94f0e51719a7b38c59eba300089d06b9bc2a72017668e5aa3153ca4282718f1762642e7c1be1f865cd9b65c6387c8fe496f1e60d5acbb78c2f71cea1f35dc955b1e7d1cdc9ca339765995d9e05dd729cdf58aa2a1451b633c374e5b6c2af1c8486ee4250a875e80e1f359c15130eb1e2575c0c7badb2af61378527fa24347ebb12c10bbb36e3c94619556b2c641d0ebb691b2706cdd667f55b8fff8fb46e3ac72f3682661a4bac2391075ff5145eb07d69d77437adec2d096c1c89208ab3e7a9ea6a0ff4a5bc1846b3683bd7c6ec4520c3c95861a5856b0191e4221c9819c67273c66729728f6035e79c0dae8842df4c0c27ada1ad18b34efcd55b94ef120762e87e8c5afdec80d5788e83f0d1533cdd7aea8f27f33266e007b274f6d48c59bcfad607e8b298be2b17322be88558c60033452826778f167f318b660607bfb2f285cadb385399636acb8f5350d819511b5e7931c5f8483529d3ab3fdb5ae2dde0ada918f1327c6c0dfbbf5ed3c8afef171910dd0169022b3cad5b08084dd5e8eb8ef1ecb17e48bf69f80e3db0ae1cc7b73d94b89696e3c3443ecb4c7ca12568201744d1858d90ff759f2d264d49edf47772bd0e0990c14dcf8c8a4c2dafa44dc6e92f4c66b03bdc4f68f28ca2d0811a433e184cced99a8e5614ca83c46ec18b47e0c7ae91037ae06c6d6d0f3dee19711c21cddafb5869416d23c5219296acda7774891877f3f8d46155d39f43ed10500ede3afa26943b83b800b54a9752250ec6ae173e920002f365d692a9b3a2f9b27124ac97b8e81b70e8c0bb7022d07ee97e962810962b03fc019695b5399f77aab414327cfc5dedd51e99453179c42ae85a42f8e06e0cec6f937224dd019c77c5a0ba32ad08107216a9c758138b730bd5b5f4b613f192839514a8621634d9dbd5840e728c1ef4a2c8bbfadc376dd80d13dcb327ce55ab536a43b570789f5c5e135ac0af79b54232613d0e989ae695aeb358c671ae71d508b58a793e19c58c3d204cdc9a021ecc634bcb0bd6a1917554ea3bd688adab8163260a914fc01d7ce05a497a5c5836cf9401cb6aa35cd008470bdecfb97a511c905badd01bbb4d0c05867661debd2162beeccd52399d5a70a929405293916f33ed0d03f8b850f4bdd77b1fb6283118d71de629577383c81cad086f4099ce7476cb787f73c96431a0df4156f7826fce9045f7e7c97bbfd618b845595203cdc8df4638430fac74a07bc5f773486731d8ad29c06695704cbe2882077a85d543551b7ba81b181ccb93d2b3071b1a38f3c762b42df8246aa64cecbdc772830ac79e766fa99e8c65225f28297a32526df9b51227bd368253737f013ae18435a912bc18cc4a95216ce449865e8bd8bc759dce9d4af52f9e789eafa37023e91946952202dfb7243cab7db2f9f98bb66f19750c547a2bf2e2ba92862ab66f33fcf465ffc41d23f0b891a3b28b3f68ea48dde6ad4802902abd22b0d7d9101bd61471c5d88ee9d9477b7cf9f6ac52e0f520c79278da22938745446f1e647ae478ecba416b941aa31f979d0633efe72910bebb8988de1d0013616f31c5da163eb6c07022649ac57422627a5642618f53103adc9918f9992c5b085e10d2744f9934bfbb994a710d6cd387c325e94278f97d5582864f1bb29a1400aaf674ea8fb99a3b42e4ac50418fd804a5b1471eaac4642d4aa338fd3d5d0dd84372b2c32c5cfe7f319acf731a9787b048cedee3833300dde639cb1386c8fbca4bae8d67fb7bd72d1696a0212e27e166e6b04a79e34b47c98502ed0bdbd8d61777537f72df569fe5ed30071b57e8724e98ccb88c07f0458cf32298cefb6ed672b255e581ac756789b57e950d57174bffd3f47bdbe4b168e7e3f1a6df508d4202d327947facfbf9526a9e5fc1a5abb179902d4584deae6cb2900391e080d3f3540b87c3a873ccfaee5b4aaff0e6516a867ea00b4d5e680fee6b91defc65c240614a1409bdd0f49c2c4f3c1d258d77abfc17a749660f49547adb236730e5a7a22fbbabdd8ca079a8efa5b605332db12f455868ab67a1ffd27d1339bdf8d150189cfbf6199c6fc27c05788138a63267eb8ac086e27286b4ef99ee9d92cfedab5ce9916675f128f206a1733f47a597232067aa12da20c7b9cab6575d7634f8c31e9a29948b528681f3f9c13b9f585ebfbff8c28a299a43e4409b31b6c02a79eeb493734fe5f9c1d9e3830572eb54229b5cf525768f695acff48c76b4a6e0936b7406ab69f06d33d3f04946db9d7966ea6e8c50ede5abadda28149edef5223a6938d5c32933070d234043feddbd65c81be218f9d7c497a1ecac30bb9162e60a9bbbcdb4fec4b212050610e2b376aadf58b3c9207860d2650d0310ae6606a8f1b266b6a13b68c3306ed413224abdf19371bac3ea1b964f28996fc70f666ff118c6a7c9f2108d327f5145919c03832f754de35f5979ae72130e39126499037d6fbb3751cbb4843b05d9dc91dd5fc1429da491f72e3069313ea243933b47109af247fcbe0c70f9024ac5a41815655ab309fcaa282d03596ba59cfee0e40f7bd657689453e98d562442fa4c585f970b6983a581b0b8eb1c5e780b3f5c1abb326213c6b5fd440c2187066ddf55f4eabf88804139392c45979440c6f05b7222bd95e963832d7fa4a4760273cc075e8b8feeccb917e8feaf7d3f766d9ae880487e69bc01872ba62b91b8af5dbffdd93fdc95e8f47ed793fc070a5991f2e9ea61439662dab218f643c1959171937aa160008a548f51f87b58f2c4fae5aed556f26bb9cd1dc2b3518458e2f5ec5d974c6e11a0ed639958cc8c1db771cc8cc8bee8727bf6452f47c9782acf548856a0e67841c3dbdb1c98572a4fc8e6cc8195a504019b4930d302a90dc20d8628ae6c90e0206cbb3d05025744db4e115cd3b650e5519a1624acbf226ebca8875b05183b2584e65289f8b9cec3f7d010cb9671a0e80bb70ca8763f1722d79e8decb6b9023baf64b5981e745c06546cc1e", + "ade72c2ea29cf829ffe99c2d63840b2eef9b51a9919c02128347d2e88e9f063b86326928cf6252ce4beefbae7206dc61a22d0b33c90d464d551835e3b73c1e3d6e88663deab80c35a607e4180ec079b0ee84e3b7922904e7423acaf976e837", + "43348cf32211d7daa300de8a4218543c8e3c7373ad10950765c39760f80b733c", + "e4709d225a552e90fb357413", + "562050bfb40451f27b1181c389508550a0f46b53d14ca73143da9dae3d3d2b466e9618db39e3219675d2b6eadded7dd9c741d7c9bf3c5619a521189607acbcf6b3964d469d966fa134444aa06d80749c873f0f976e0c5efc5be8d00a2729f03eda6a7b8630575df8b3a19388ff88daf0d00bb3e7c35a525ded90a4511ce815fe6c8904406cf72d7bfa14ca533566f7b54268835285c5402e22a63f98b5d90c86dae0a76d65eacc1ba85b3f5a1499d5f3432dd5455fab9e8bfbd266e99283c2bddf9b556410956b2f061603d1fc91194766f90da841699ba7da3d53ed5abdd8e98034f8fe734446d92b458a731aa4c578552ec1ac5d1baaccc4153a67b48a290602d5f955d61a08436b27cfb0786a80afef76e1266310a42d90feeb3bcc40ae5c4506432dcc92f7e5758ceaf277255401f5c5f4b10df93a249e38edd9effe7bacdf7fecc451d3b2cea77c9bab0403450c41929775b8c0ace46f6928f4d9cf3adf86832d298ea32b236d3201464e2ff506ef01da0e1e389e26e2b3ddc553b369b48d1aa5dd43edd5cab065e276aeff72a4c43206063fc7eea3bcc783ba2221f5b615a7a43a75cecda6bca5aa159e9208bf66af61e2e465c2daee630c4c62077ea6ef0e8b4b4e272d4e93a5f5284f9da463e1a60f815a8a31698ecdc09dff2b62f00e37aea5fd4b07a110cef27e12466c1814d3b10017cb9b8e12f2f38f10cbe31296de2570d5662b16639fcdc05db81e0d48178d055ef873501148d00903ec771400fa4873c5579dc3265028f531538f6dab1e5607a15c8b90cbfa4835107cba6f453bbdc71d08c7e423f58b44be38a9c8a610469f2551ee6177edf639cde35fe8e02f76b7ed106d691a876a4fda3b42d8ace3e0d3d4e026206c5d7d4d56fdda9dcd30fd7b74217fab3c617903f1aeffb8363443ed128af94c391810e327704d6f655e57dece97658d41e074029823850ddf7c5937af41c64465046d8544bba65c691ac69121bd272107f7eef8cfdb6a25da5da16d1033cede09129d51f6abfe63905a6fba9a64d7832fa35825447150595a60163af848eea878fb31a5fb97b1859efbfcc8586eebce8cfe64386461a9b88aa5efc1db43c64dfd5d4a45aa74803fd178f9e16a3f59acfb6e13a564d645cedd73890d0a82fb6dffeef527694a7cf2a89aed9750c3675a67505bff77de8d046087bd39a85c90aedb085e99baf04c7e3bf92e350b332da1b8af85550a00d68904ca426da61add864496d6ff442bb0b848e9aa463bb0c2085cff1a83a47d6f702bd184cfb5c139752754c8978d27b58d364bd88722b9097ee3a6ae28eabb14ca7c31e40461101e92448dbbc63b55cfe56efd078d0058c5e6146c73bcd949c4b3ec9f881b9a5f7b41ca83301261e0c674f2d35d96761baa00ce0675c082bf73dc52dc726a3e605067569a372d2bb47fc8fe1e74f00078ce6f352a6d9d97fd2834670ba3a45aa6751eafc7ed6694e1e07542860c8ea516f296ee901a3ee16b00b40419c74bf6db12c7230325e85a918f412bc2f6469c1a13a5aa77f028e327749efd05b91053f49d9f1edf49aa552c58c68257233a168db60ac55b4086ddaea275b078869cda7b69493c4b371b4e9c8361357a7ac7d3d3bbb464c960addfa8df2b208b21b090d540c440241598212d33273203d484e0930e22469c2a8e866579a4a2b3db8f8344dbf8baa1b97be0c4d976f6aaf14cc09ec52630139b894b2b6f4dad3a205a7b286253f1522b1d6e43bfa37beaf06f831c6f0945cefb2593b9b298da13b0d910582086c5d7e256ed4067bfb476dbe01bcddb437d46ba716d6ace2ff9912c8e460ad33ab3d8f97b7b08dd4ba9e01968d1949ff85b4b9d5b8da291fc0f90ab1eab1d246f67d76092b7a37528ceb388dd76f8a8f0aabb7490f02a2c8bc6498cb26350d859c466dd611bf0ceb81a8b7899c67742c22697ccee21c4963acb003d15c1a2078112bab05595917584e417db3872a0ff0a29138bbca7314449b19827525340370d7e48fdf9f7c6b4a280e78d00775a291081a5e78e7a00ff915015dd5af5f0a45690baba8b1b503bf85f326c23136f4424be4a559aed03fbc81400ac27a33dadb2155d1704950d98043dcd86df1eee78f3f266c4d14deb8126708f74b59aa15e8b497c6a52924a473f999aaf0abd3d148fee8503a1568efec7bfb0bd463402f563e4019cc9c9e1eb498aa54dcb659f43b86df0a34de4e51ec558bbbade3d69511d3fea2baf44f67e85ada7398d7f72ecadcd9e981f82b0743ed74bd33088ba4cbc85b0c99dc5382c599706dd2d51aa9f470c25a98e7e8248dec216a155495630662bf6ba0b7a4baa2cdad30e9ce3e1a65e3c23d69d5f946606ee8504dd70830aa5a8ddd84f10e064695469727d2efeb46186c9d3b7a170057636f05b9ec4c2de7d935fba504a1e7eddf7a5a95226b253b0b9eccec976ca3c57599850db40c27a51ae755c1f30d392467cb74e5c8235861d11d0f8461b0e1d84f5718d64ea92da62f4de184a6499dba473e82b3d197305de0e494f118a263237c7b4c0652327977edb427ccded35552c00a5804b9557ccf2bca2484d9da2c33f6c1bbf2c666ea10b4644a21e3905e5c4eb417ac3572e783428d23dd7222e75c356b99e8183d033034e29e618c90e66ec2f1e9fca47d82c1cffda8ad14c96045159d9437e91ecef41d24cff89009ff57e18c1a422860aa9cd31dd2a85b07422c72a5decc614a9742e62a4988f394421b6918e51c2412d749bb53b1e8fed7b2ef0873ffe14fa77bc366bbd5fa1432be465f5e25266c6c12b55df1f19b1a491acfc5c9019f122c422243d751d8eaa8ff721397915171556e999b34425f7d3ad6f6c3323b8133b4618c65ac16cb5941edc979472734bdccafc73c08939c0b1e306ae3015faa9cfa09ed6560269a1dc54c2c046a12a178144f4381f7b6fd3fd2d28f778d444d9f7a0dae00ea96c6969b78ef326a962d23275f1518f0e6a2469440612f3710b53538fe99a6179471be8c5b2d682ab3e9a5126e41ed6de000cd9e92fec3974e0f4cb2d2245d03d6ee80d6a793b16efa829d75c796f34d4e918250f457703559bb48ff78f0896be1bda403b7f1fd6a319d68478ff70d88238f2b8afc7d20e51757bb9db3bffb35a8040fc0db913c4f03d48619af7fd24cb8986b3e139058be3cc253b3de9b3bb3f8dab7b8818638279b2e6a0c29cfe16fa7250d3c74362ffa07e2977cf562140fe28afba8f61d81f7c73bdd4a2faddb00752bb049d0a57d05c6475c7387e6716ee31974169930c9fd830cef138659cf56f2212de185186c3d683fc6b7fd36e7821f69d0de041a569765066dc4a1934870a7b80f174e8f9e484942e62404a42b21658467873865ef94fc262c231527f39e82dfec91215947b99567daf75c6a28073ee4e67d4307e4b35b46f85433abd9812f35438b34598ff3b6dbd60b60747ad64565391df45ac80b272d0141702ab807fa27c6a6ba2f42c3facfae0c773940cb2943bb1353b41298258bc0d07542b69483e17ab9ce709e4160b80a0968dae9af8fc7c0324c753ca4a11a6df32dfa79a87b445c988154bb3c503e6884cf6d8f5e062a16b4ff230fbda109a6127d35e3bf2b29bfd3b18ba275af773b1981d603300035e046ef023d51874aa105d136bfcc9c7323bd0513a6b2b397ffea71afb7a8d4695411d86164917099eef504f6cff3c5cefb88f23f56c4ae3e2b09a3f353fa55630f45f06c29e8912e8c3c4f493f25eda781680585580595bba43dca9cfd400d9eaf5081d2c6697da59e012dfd0b875336b88fe16609c2e9876737b9afb868ed52417ed0c6b359d582d585ff82d98edd4e63c6b65cf43d4f69eee2af4819157b8a433966953862d1ff2c6d0cba382644a1b0033ddb7be3d1fa9a204042d7b821b293bd659dca980c108ad1db740800b9bd2fc1a163f9b4066f7604f160a7910bd947cb48ce6c81e680fc6571ff0cd12a3ded9c8cd560970ca5cb480a70a8322d5072edcd257604eba8dcf55f9ec97ea2b14fdcc72fbf615131836fb14e42b8d7171d0a06d2fb3caec2e0759e86b0d8f21e312d9211ed7fe0b48669934ffb892baf1db9aa457c07820723e5446420334bf6479f2099e01ef8adf273adfdd9ed0b741931284515d69c211cc2efead8339e450b13be71b35c36c1f00c2b8ed0cfa9792e422912e14b5b1455ef6abdbbec0035480c6cb69d21321d12ee19d528dd48f43b142cf0502eae5304ce52b7fb827552db9ab885b93e83d56a33346135aef11b7e48efca7cd52e2499a7edab0bd0562862187ff4599b2446bff11c37181092fbb05d0e05220ca6bc37f529d6599e8c29acb9f25616c27df291d4fb07430188e6470df7002f73cfe5fe6907dab0b4f90bb58130fe90241c29c6063a22c9f45d032b282eb92c93736692bd5cbde2a17552e942b595b08e6ba0c91a03b9079e9117fbba8f26ce6c5d0500c69bb6e22e3562a50baece49109c2d42b6714250665afd0f0a7e951182012f21aef4b917cd434d9ca22661437608e32666497516be34652500def6c28ef8f56f2273de5416142ce9606faf7df92ab779ed6aa74cb99bb1bfe758ffd344e1d31f479807326d1a7b98f6811e275545d69198707b0fbf027dc6a5e4815d62ef191535569a452c27c4e25ecf139df949d70dd5935bddc04f33b2f0bcf5073c51fc51c15067963a20569b5659f0e7413b347d6d5ee38a92b7e6e656c199149f07ebafe5281db6b1b2ecd9e0384b6f5a8e27ecea9a0249c61b16564964054f5f9621471a98de132e102f518c1419829e2ae2c8c5fffd1270f0a0b33a383437b0034783d50bce8bd7420c059d16364eecbd55b6ac8df8a70382734d8127f4f5895cc9e508b13c000ea053ab59b87ee639745418ffc566ceebad37a17b842d24d3423ac3f086142c622eceaadc4106f8c90c5dae1f52f407fa0bf1e6bf9385cbcbf3b61006ea3b1e66b693ce704577ca9598587f41e05d36d1de424e0e51290a5f2e2f99f1960c0253a046a49b19eef249ca2dda2af1e8dd78411088eff1e9c23c31bd20abd4fc9e7eab19500827d202f76270fe9f90e95309516343e0fca48e5a12182e91c78ebf2cdd4644629afdc90bbccb77546cd765135910ba1cd8a3e3c00fa77e585865e898bfecd06c01a0a4d7be483801099c61941c4967154af5620b171b426cf229df59d2944ba50754140c3f305c16956953be376fe6e7cf31a2e9c276bb09cc24c4b86b2b26f039b0d8511853adcb7feb8502e7641a34e3242bf2c538006bb1983345ec3cacbf219ef10efc1681d52e6e1b1c60bb556b6b8a63d1d1f6869077841d1b816f3165a35833e33d39a8c6e62a2f7c482c395768fc6a0e3cbfc7a1a6d64da53adad66c8016f76eaa73df1b8ef83012ecbe75c92a8e39b48169433f951a539b28a034d5fdd00639a5e3e17ef14dafe869064d130c90c68be4d5ceddabed1bc94e97e2cdf7313f780cd6e175a9e3eba3eaed896fe464073fcf07ae7b5bd41d58c3160f66ac95a76fdaa7a8cbaebb304fe3c8f03cef927a1182ac2281c3b32378813b24bb99e42cb0774331ad78b74d46b8ce48bbf4ef8431a82d4240edfd61b910c38570ba0bfbd4a41665117e6d5f5a97908462e62d0b76160d06aa56cc6e17aaf4607ba8263648f2a0077e306c25486f5f39a75", + }, + { + "2f6210063cb3071b3d49339185c2cef8357b08ca826d8d1acd852540c16540f1c850f70404fe1f414853d3cd15a1c64a1cce149e3ca1b80926de4ae8438ad90bdad010decf2f201782f3e49794aae1b079f54eb59607bebde508a528927e346d4e444b1d736b34f65e198df2c36fa23c64f1f1fbf8b0b8ddb85d054bdb39b8297d0347f16f7be7cd9474c058e36294485386434b36fb28ee582e393367f15ce5f5a3d6641fbd31b331f10b1554a05da726a0f35c9b1b4af3498426b17582966a266cce452900f85af1046f45a4ccedca6ce02607fb70fa45f420f66aa38cd4c9f8a30e21a3067b940aebdaaeb7c77824a79e2ba20f26e70346dd6de96942b261e5c08288c7fe1cd1e9f680a0bdf8c46497f007a616eea95ccc17463559f8973eb919c68017e25100d9d1a196ca65fb615502076bf0b0c8bcc70ef22006895ebfa2243fba0791bae0625b762cc1718d1673948264454a200c58122d5e9b8b1e3eb05df8b7eeb297510e0d7dcf7f0be5f29f6756e4b177f109891e6825a9866359e35b10d20da7231bb5a0ea34abd0264b377d2fe9f420f27d3e5aa2e8e00541c46052966ef9b989ae5974e2054409507b867f647aa057f7deb19ac6929f0856005aec6e53a5f702fe6be403afed532b73d38fed73e6e551987f182a1e20801e7a6c8ccd1184cf0fefb4139fa166ca15395902ac40e7fed8661602853682a3b0ee307dffb44d0ea3012142a2880cb7c166ba6ea6a16c7e0882808db8023068f060e5ef1432fdb8331ffad6a7078d686d47d613e94291f1c4117e7c13aee4030fcaf223fcefdb300ed606b5dd931e4adbf45dc437eeb5fbff337812e15c15f026071423f6ef5305c559baa2ecd8ecc7cd498b043740ff3673774855d45d45fa64591d5b4970600ec91ab1b6f39d7dc0e709c41e49c355bd3b9d120ffb57095fb127bafa971a086135b917285794e83e9dac5ce76fb1a4aa4fb6b94a0dc3a9beea64b8817ec1e2b37af9dbd18ec30f2b6f6c12df1db6896c6c43b67a066038f0c4f17142b254f62c4dd1fedb950d07047919e397d06d033cb0bab6b61aefa6dee01720926b16beb9e8bc947dca9b8143b565da85d2dec182987838b267de9047f5b0d961c7971aaf54ae2c1e4aad61ff123c84e41a4566b2bd9e64247cf46b72a444d36bdced1a309b464ee5f4afe406eb68eb05ae51b76bf01b906c0ffbdeb440b11f1c9e3a4c3a809a1f7449047b356c663a1ab7f286a70d16141d11f2d151a4f06d422ab97cab539c1f9da09ad20c000c27b8fead5f0cc37329d466fa260aea934c154dc9c0a065df3d057a0f117a1c38321ae59226a8054f7d6b49a3753436c249838b0924f0e861f5627106dd8d3f0fa724a1cecda71d4a1267ed889b234ae4a7d5edcbc5d52cba389dc0152aff24d224c6a0f16dbd3b7f242807bf4b51a3f22690bdeb66eaa59e8766b3b265d784899d247a0ae1b58a06dd91c529e3691b09f9d9f55fc39afd4a00b0fc668880ef25a46a30861fba8cfd4b51262eba4138b41a2d13ddc71128c8c1242e49a51d6f49879fcfa7595ba4a4adcad3670b0b1b26382f03ff402bc70150f54bf513ba3e9a590e41b269e55616af297ebb3499e16cc8e46c0810330a602955553c0f93d668a1181a0bfd7021ad9a9f68ce39493b012da70a3dda149d0369f23f788616e0272efa322b6a54d804f340d32c890e2eb7b538f48f4c9293b584d22d0ae80d321607644271b81a76ac5b49d8e457069b0c3e909b8a222e3fa6016cb1e979e300804742f2005c68acb7b1849c088b3714c9c7af54e9de9390df0041c87924c8fa6b0aec6b6754171e059cba0d27f221f0b9d044a3aed8338dd8745651981e4b0329376f908b86ae9022699d495bbe3a148f7eb73d56eacb2e5e2180f63fcbfa680369f88eefa71f1210bc5b6b7b957f0a1437476a2112998033197673e470dbe7d9d476c97b95db8b5136f6cccc75d6e0ac1e4ace30e34e64fcc4d7e135b2c80e863ed701d3b28c25e982f1b5f8c895a4e6df7216c3c07abf8551a0ba0469c88aa7a08c7b5218a03b9b91f0935985373f65aa56286ad0e7ef2288a926f172b098123c136455b3a0f04590839e16bade7b6434a3cf048abe2612684c03dafd9cec39af508e63f07ea881014697bc24122058b5ef5d3fae835216d055f0cdf1dc06a12c95041d13ac9e15f235d11747f16ffce1cc3b8f508da520e395edd471f3759d8879ba9c2558b1188d822fd4739ed0546b0ce3bb9988db7c1dc8518ebbc62c4440e6e0653f917dcc13aca1864b71dbb67dbe7117474c936414e4f3cfab1f13eb05f3504484ce11977ab21ec523f97ba1b7ecb8fe384b634c30561cdb752fc67a2316bfa7e4d03f5f825d24a556a0460d8cfe0cc54a6f117ac52d553a5d1bb48031732716436675c5c3996b1939b127c6b0338bfaa29c7467cac9a127e455a715c9ce2b0c35a0d2f83a3d1273ee39399e6cc4980e610c752bd51652b96bf9cf34c7fa41fc9b13f5d55007483e4082ddac4675baa7822fd257452411b01de0e5e5da26e17539d64a89dd93c71d15a4c95b1a83039cb2d5f3f7fa04a817e48dfcbfb3de34ecb47f7592123caf27e17982fbfc8597af5b8aa6558f4e6c73db69328e47677afbe6ef8df82c3d1f0db6a108b2279f61822908d7b856432c32ac5ec0f3c53befab2a7ca356b9c2636f646b228b0a830d348be4ece2271814d477d4c73c0fb6e83a338b90ec4ef45cb25f7e3d6a014a9e8d2e8a6f55a383291a57f15667a73ea1daca31c7182523ca85a107efa2518d2f7f179ed4ba21fed479ef2be09669817133b2384bd85b155dfc1c4c9e6dd9ceecf06cc1ab8ebf7f07aeaae7441468b5471aed93f248a84f44c59be33274b11f651de010ab9f8fb24d3a99914e0147951c34280e7dd15ec196f9a4c86e55e7d373c7e31e6672d1b3ac6a45fa6c8c9088c0b8963d89f4ff1feea3e85cf9cf2f6c97128afd845bb131c6f62b3282bbba42745080fd457f1d3322058f1bd4be876bd01269546d1a853310b165926c1fd4e07054deb5d3fbe8f6007711d435994005aba95918c3df4cd390b165fcd139dd418ebbf661b6de57b655698a8a02ca8fad73e8c536c7110957c36e5494a831d536eccb97a2a9ef58fe58e2885aad170720ffcc57c7de601ea1cf723577a30aad8fd544317e33897c8b6c04e5191bec391ab990e197f10038c0726d371677e4a54c28d7ca5c6046e7cc4acde565b91f7f72af6109a0614160d3ae97e9257b8f71a4663b00c681e793cbb478306e97b0e04711eae7722b4845dadf2fff5bbe71ff24acffea2ee67df99bf62a098ddae9d4ebd3bc5dff04a2d9e3d1d83e8f493db3f63c9e24231b1dbe1147c79f21b0730c842f6983330c5c17dd34556d7e932074cfbe98f2dab5b0ebfd778a1e28fe2bac2d942f61a08b787ebfcdeb3d600bb130ca4922a4ffd38ffc4a1a1a7218451e45da4da67ad81ef898ece3d54cef877cb9d09f5dcf72eccbbc06e62f1e2b4d64059b0a807329780b155ce1614b68de04387d6108ef4dd3ab54b9da72e528d6eac3e16a360ae3421f3f23808a8b5e8ec3dbefcbca3c9f76905850033d78d9283bba9272c475b4e3b4d7643e62c2cc259ebbf168f890de88e82f8b26a7654ee31fe055e45609c70ae02b4942ee15678cd158f4c9e8d351d102ddf7a942458c6125e1457bea0d86ca38cf0c26e474b2b5cca77eb57ad0867cad7d25efc2b250e79396637ea3e948dbb855029cc9b452955bd04ad5a0d0514d4d773c0f298df7bc235a3ac64383a1fbd8a397a158e936b3ba81895a51daa89f51e4ae7a71a53794ff715a42f4fc3dcc9fd56df7bea4ab782534d3760e7b15605fc4dad16911656983c0ab77bce9445bbeb1537c55fef57a32c8f1404306a0a2ca7b73348cd99d0f9948875531cbb0ef7c036cd201614c33293d746c44140e0e8f82421c5bdf2bf428b249597df949fafdb5ccfe1618323f56a6ab9abab9a84a3beb6696ca918af244d34cc1cd95bbca4a87c860a0fa9ff6a04a905b0338a53f230bd5ee9c60e0e0332ca200c15dca0be5936b858d0a7b2e540b8958432e9767396c55d5cc35b60062580023b5cb2f9a5e9a1feba59a19f9a5a251e9d0e8500955a5df21da95213ced2260a2ed8f3d4b295c36cef750c89cf21985c302d5cc577aab7855409a912dbcf1d0a9800df4aa692a78607a40fd6d5a82305c58fcb3d2a82b27e8c5b91681aae62a2bf31ed55c494dbdc38eba30e83c6044945df76705228eede8470369f2e9941ddcb2f239fb3ff6bfcdb0efb5ec50f981adf0e8b213769ffbbea364b08cf8cd69abbfa2a6fe9865cc48558134a57bb5526b9d047e14a379d246de82d3d64f3c810ede280c768dd8bee25af287d5a8d94045ddbf5981382bc716ad9aedfcd66e0ab496172a24efe80649db8e1e83675fc8451e22c6564d8d6dfb285af7fec802b35f19dd8308c68952a11770247fcfecc4ed0e8a445c17b1573f0b4e3ed350f13269ceb572943fc435563459d5044699f1542335b03be6077af156b8c5a6a9f71078ad820cec4642427a9b187ee1b17036d5a5e6108cee8a7d444342eaec3afa64e77c71d3c2b3153d4e2dbb30df2b66b4d14cc45d3a4eda7e911d697e5763e23ee05311a20626df55549b8533c6ebe79737abf472f9cff08bec590943bdeb819d3f923f45b81f9a0cba1f3f800a261842d10cb4cbdba456c7fe5f0abb4a8b58891d97cfd6b669e2708922f1934809d51a1589e5f12e3bb82c9ac3e7e44e3f6e6cd63d428da624fd2f46eec38ff798a90d228efe50c9b67c63796347c8a2b53478f27605999a03c8e1f18b70e92419f646a7f49670aa12d324751aec17d0208fc296955b3098241189af8172d39a6819415cafb107c1842b369f174d6f37dd31cd728dfd0ab10f93609006342b6e4d6ccbfd1ed2bea2fdf5411442b04b1fe218916f159b20242f80b535b4e0a3024c6eff6a40bd0d3db24e51f5ff9c14e1b4a650ca4170ee70f0a3a5a58349a7d0b7a63af86347351696870b95231f76d8c5c6a20736907726341dcbb76672871d18c2157c094b929fd29d34f5bcaacd82706f89a60000cd341d98eb830b73a12335b69f3e0131ded3ce12c98bbd960d2d0696d40696a13ab43925374498d868cd8f070c9039ea6407fc2d92b9c39fe7c935bbcfcc5c0980952fb7dac79042951f49a1af828b138a87401c4104bc28cdf1e39dbd3fa63dd4d5f5ae9d85f032a43ad353bc5e6746e5a76326ab1f4e79103116ce70bc0b459200f32f85e461291e347dda92e421778b849e37a3ecb0b31ec6818e828dd3148dc74313aba43cc9d8b9a36a9dc4e229488060eb6c109f8ad6201958adec6d3bb3b04e5e558a272d44cb98e18f7a0ad8fa6ac3667a62f150830aa930f6166baac6b9081b44304988fbe1698a5b746255de26bb5988aca90bb6523cad68a7572f615f4aa58f932d8a749615cf0a7724e99de042268ceb31433e6df0a61547d576a6201b36b348c028ded5f7e94d1cd2eafc141088ff42cb3dafbbe4c402b93aa9d955df8d9d9fb57c75ac65c2c837acc44bbd4d4aff1888aed46c73d625ad7fff035e8ca0fe411c73ed8135b6b8e17a039ec74e9de0d64cb442bf8a676c0a666f68f21066332cd921ae0ed766f0516a8e19b82cf98e78add0373737a3419e13aa902310c44feae5fdf8bc64e80dce772686a31f141bcce452041bf545b908ef4a2b000e7beaf378e2afdccbbcaa42e330e5024400cf2852d3444718", + "fd5008477b0855f6f2486fd4f74b9fb4f6e19726c6996bc66893183bd76054d5b05c1c2b64722256ba912ab2dcca66d2abfdf972966438fff7513acfb18ea461eac08c4e32aea4ed3fcf9f1c9905ee4402e7b6984bef974340d212f160b6524b76de99a98d3e96cc0d35e8a63ad7ea3cbea1d40a906c4dd03e5fc19e1513e9", + "390a5e75c9ff4ad38fb6205ff47f209294337c1f25ff54a3c01eee8e1e220257", + "8bf183347ec1ca4bceff3374", + "19fa2641519e21293094e9d767ee1237f9e0715dc57172794867c3bbe2cb647f9b28a8d3f85c0ff557b91bad66f5ea16e0107757b0277fdd3ca05bf47c19bcb92a958a57e8c142a51af29bddb20af84377b6db65f77494e0dc4d2634a776b3a5d777319873bc0dacbbd4b9ebccfae849fa7e9769cdf54660ecca0d5cf4fa5190713726d54d02b3a3f21857125b8a808c0ca2f99d11dc430ed5113ee49ff8f00bcc08f0370dd510e8100e1285659a7b2c7457a6049f2af7786c4db1471ce5bd164e11c7a2165e83e03a135ae2b3429f82f677de044a067e99e0bda2d65a7270d629c00e1d528212d3aeb2896e58ee5145a93ed06a9c00705ad5c5988d3a192304c1d17661d45257c5d16799ef70771964435b12e3b2ee9d5b467c3b1992f45b7a59871b40d8daa1c280747ecb3d170257b91df1f549ce6d66455b5b6f60b7c6e95c92a67e20cffe8599ceb183de53f1dedfe19bae836447af8e053ba419660e0912cad064d6125b9e978e8d0d5f28f8a4e43ca3cdf2d4c0e9a11221d8184e9eb6c90761b0beac82d0d22793279aedb1c7db3632adbee323bc3bbde4801152694831abf5676979af26af7dcbadfba1cad1306b635840cbca76c558b37db0803b4c12befa27d16f21506b07ade4a838d6beba1816eb29ed5e3c4f132a752fc747bd9ba879156e87e6c1584e911da9f796e1fa4a055e427272559e4bd6d0f54b8257100f8a55d84c27b702bb1fe2f995425c85fd48b0a0610db5b39f7a5031407a12dae9f508b21b1378f14952d1beb2dea81d016b2d9b7f1a67b814569b69c0e619adea02a8683242d63a11d3317d060e5b4d85df5ad73127541ba5314715d187990735aa81f438f8b94070ec506ba536274d98b766c1694e54367891a602b99e370425b47a70b819277a249fa429c5bbd0530267f987e6022f25030c30f3baeedc0d13c95f3d5e4b2b87465d179a3a23b9f9e76a42ceea55226ce072f9488392f40621289124d786109d2498e74fb37e2ef466fe8bf3016d96e34204c32978775765aa80461cac48518157f86d59f6187bad4ee62fba1ddbe166b29452f4a59af1e057300c353440644a8e40ae8171ea028be2fa315804abf518847c7945e8228b7766cfdb08d3a3116b59aab8e94b6d8c8c9ef442c2dc7f923bc2cd3e5c663baca7dded976bf191fe36da16948c89c385fe71434f4aa5dd15fe0e925d2459e3b068b9d82a9cc8b8f9786bd9f5fef9baaaf2d67027d9bfd58bb2c58ec7c746b747ab62f9242e4b53ed14d6fc75f5280eca0de23717c97a2293826e19cc8eb47f946421516c349dc4ba49225b91e4e868874bdebd373700df1f3792aaa140597e58b88f90e163397dbad3941705b53d754e3e0c9003df836a7fb8d23f40362fcb5f3947a4281b24240be4ee89aa8e917b194f94345eeca224df0adc15f22a617b6427f29410bc48ea3f92216163785723efc36301d23ed52780c6fd7924bcfaa03269b13582b7c7ea9c0e4a451f38a469fbdb585dcb7c81452da77945ebe27eb26ff6e8c7b2decea289aac5af74746dc257c9bea44a0847f02c4f586e1d76f39d5bf952355a0875f177a666d1d354ad86ce5ec0aba2c2b20cab050eaffd31095395132f5af80a2d2d53b77bda49f948bbb37bdf31c8a690476488e14e542ff6841e7fbfc2eb84795696562d079dc1612274b6dff362567084f793f0bc2dd8de23392d05aeeeeac6991c9f74387153a4b7da94790375e336a00c8293bad0fcef2dd1880e7094e2e53f738247c860780ebe308410ca02ae409ae720e841f48c9677acc6e7d4ccd18c219c400f8b7e1257f692e09eaef96802b17a1cb7d93eb81d3bfcbc7af4cdf05b98e22556b3d1a8b56d6d83bb5f5724696f8f329839dbe477483ec3c09fa2e0628faeba1bf285c224bea3f6cdc7bbd768133c6ef1da14f248cc3b819b196588811b073a7291817bd1e89c65760435d8d17cbf9423744a92143e0f956e2977b39c54fdead5a57f3a04a0facca01bbf44d3b1fb9c4fa83ae1046985e3f26aa0a437999004dd8adc04c5111759849f919b93558dbc559173a23b069b59f800096d9fcf077c7640f59170bb9a6fffe64778bac272365d27ea62aa956559e90edd3f6393cc8775597bcf7d91990ab9511973d948324a27261059e93f4b5dd2f70caf12e1a08e0493cb05588618764391f355379578cf94dd33e616136eea997ec11c0d4ff064ff51a767e5558433a2e3a9a74c232d8e187f47b8cca010709eb9fea0dac8f1ea53bf18822e154ecd929c83b0eac366e30fffbd5ba6a46d734f58d26e7f5df538e18b3d827884aa857a680823131bcf30a76f1a555bcabb17b02b53aefad96fe76f7312da69719434c580d3ff1bcdcd594e6375935003d5d732cc577e11ea2abb1d04259f50aed4c3af9866e8c4a52a09809046ee330f05c4403acbc297a9416c5208fadb31ed4eb7a3b01b87bf08c75cf44c2b0df84df30872d021d6567ea649859268e5e1b5b6405e1b41e350a32c1af13722959c17c01b52c42241313b26b25995a1c89a53e248488724d280647226195746901929501df36d1e94815d7fe6c4ca2731f3181293217f71b9d7f59c2474856972013924ae4796db4cbd22d8905a6043c959941ca6b556c53d1688c439036c715d33a47a7dfc2fe40e53424c5093020d2e85e4b04aa4c704ea5bfe5a2384878da38319c59d41d66b6add2a443d9ea11edd8d18fa41004251653857733b388b453943eb33df93dcd5d549757fa2967ef0f9a5105836c48826c47fcccb2d9bc349032b286962136b848632bdcf186a08cbeaa52d195efcfc3a440bac154971d11ff4994f293b14fb8c3214ebe7ab8b3d0f2fe0b03ed7b145fafd7730a173e3cc1847f0cdf2cf629f5ea81a07bef716b1a67dd9e3b7a52fea1aaa7a393f53b5bdb5988df78a57a9dad19a8253316835acab8a6b9a9fb42d97bf29b2443322f46de386fd82bd3453ed68e2370c6eac4497b1bde7b42d569c452f377bd38bd50fa5a6792ef5c9ec6c647001149b86fedb3e2f18d4271e9cc4801aa16ecddb31b6a795fecabc613bfbc8e4f5636d71e74595c841fd11b6a6bc7f169317c1added56b82a71fc36d774bb4d661685363e9da5fd2e1f357006dc5b5bbf8b42ee3f869e75a541586fba558a8f490d641b78c27368b9b4c2db046354e9358ae9140e91cd95ebeffc6c0d2676a3ff4ab10d463bf32bed97023a80a79df191ab9858c43537a03072a17c30b1bd99efbd361590ed6b7d5b0ec4e2326fa35904ab9a48596f44491cbbc0112890f9386ed04dec30126be359a05e99b2b77fa2c8f6b7460a6cd590d71c73b2a1b23312ff89306b6e41c76ddc0a099bfa79498e36ae5cf0c560b8854dff32d2b690ce0ac4aabfa723ac6f2e97ad1083235196b464ad67fdd649aec01695d55c8b4bb198f30630ca635aa5a1915f3718341bcfd8b522f764015fa5479004d28eceea7fe67df7ee24a97a9708d528b89589f1899f13242a0d00f7464c3cdfce213699340e754533b934f4a8410224e111f31cf8e54d7b5e90cd8c68bf96edbc8d183894deefdf4fcc1a83162a3f6341dcd9a9aecf171c0df28257a68b1af1b67c54c43c3cff27fed89cc64bc46e23a49ec74a9efbab7981d9f0a018247441e4f0f5b5f68ba9325582f92de4cca4a5f878a0c5c387581e64324e3246d8f3205c838a29f1abeea24446e496421f0e742d411adb55f70272ae4a992e825a3d327e44b8b3762b25aa451d07eb4eac0322b431fa676462632daba2aba7bdeee1b438f051d21d4b1897e2ac2f95ee7c23f9996a805de8fffb3b30b855cd6c5b84c011accf4bf94d304d944079f04b5cadf8fcd6751c22a0f9165ab98998b2d89e6514641f1f3b91b8c0bf057d69c3d893fc4e041e06a2229e2ee58082ffb58cb920972ede58483287d0ace94c1becef26a410b93e4ff402e61dcc574b790d49679f18f4e2004f8b7cc357faba34a80e56821bb5b883d1a8b49c6605002152f270bbc36bc79095644e29ab08cc988deda765d67e4fff12b726d5de135ff9d0cbd9d5f9d440e548836633b93a38330d638468b59a32642da3375cdf70b062d14b46a78569c24a706e179baa2058dcae5c61fb6cadd9e015b017f26e9dbe3e6366cf5f1ec839aa3bbb21dd6c9b8e910245fa95b09b7d6cbf08a4c6c84bef257a70389be962dad14d97a893c128b73bf6580689e540d004f21edf8403f36b1ad7c9a2e83ffceb141af59700c316c8c1e3347187f24819c2ff0c9f9a2360dce354f3374374eab1643d2d8831310a8e3ca6768200ea7759822b82f7027cd450479fcc7f6d04802b15735a137ad489f1e1ee78434a253a9dd16684ad58fc91960cde6754f82e8b38edd5e798fdbbbf8fc2e2380a4e21dd94f8c1c063b18f29d8cd8d89f65deac5640799d4ca2caa29c1e72ad8bc417490d11e4051d94956fbc74289857e5f8e9e87b9a2d83074a994de0b10bc7782f6650cfbdb8c835c81cd88bdce5f04ca939b3c5cd010d4dc5d51224fcacbca9851694b8bf55b22dead859d023eee5a7ad3436a912c3fc0284456d5d72ea5f1afa8545c856676ac2dd9a057028bd3ca0f50e7070fa74152f13997c95c1834c3e67504f1a4165d2b49a96919b88f72caed60f56ca7ab5a3204fb12ad3592c725fdebb048732fc189c7dfed185c6c184a626e07d7356860d00389862d5b9701eaa4e5f7889e6db0f54633369b8d26805c08471de8fc3f8fa1fb0b0711d9e015add5373f7f8b64abaddbac3399c756244b1b07c579d33e4967e5e0cf16de29cb8a7efad07ff9039ca305772a6e45c76bd9b77e24949556766a8b8425c5e595efb431bde4ee222f9eb3fc2d002a1e2d14db2b23135266c942eea33bffd30eb0218405373240e0cd3040436ca895093bf056fd001c00ba59d90502042e6e6c0167105051628895c8164c9ab959400898309cabafdef12be53604fa57df44e0a90a81bd63c331291a93bffefe809e80db0679568f6e94e0d8e2edec0087c35bcb3c4f4725e6013bcf197156cd9d90612423348123383e45c14d27d8833f56ddb04083c069fd6e282fe69c940840f5f747dfb72ad72fd8cf9f3ded15c9e2f4727fd60b4f40e95dbe77a89b47dde7d5326942600554905d9dade9d145ab6da802643f2081678392609c2fdd1b79dd8caec137cbed315374c6f05c0758070f3bb17e23d81ccc39c6aa89913897e487fde889c5aacd422278f8571641cc4f0a93d9768aef9e45d6bd187d1ba637ce0fbd3c573d6778cf7bf5188c00dcdf13be3fd599143952b376220283e34e014e83b214bd5f64eb0ecb098ae8bef883949907cc36e22ece60b893b963cfa73d120513e285aaf70ce5add34edbdac60b3aa7b385b90e339058fb9b3cf984b06f79788016035c5ce490f2de7995b98a8c1c9c80f29603ae2b7fc41886663163e604275cb085f8453b27f4d795b9bad19ade2f98a1c99b43a7581bd991e5d0e5e1a6e713acc522ba9fe8302658a9782558e35436e714ac6bc85ad1d3cd008f24106901fa954f5fefb61210d6f8dc9ff35c480f1d14e59c0e501917a31ee9d00c6bdb06a00af5a8b08c3928cc5f37476248223627cb77eaf0e96213cb0a13e97d3fe9b9814d462690e8d68d02655a32fc271ee73db4f88a33386ea88a5857e15a28d9b3e3a96f00c7cd85aa53f9282ab8c8ca6d6a8afed43aa87fe7fc1ad59b0f0db2dd25c20af96e8c282c19fc883ef01a4060398926a1c82f07bcd3bc314580d7636b623b7bad8ddba05850291a6344df0f346fa4a321a85ee3e9c", + }, + { + "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b", + "0942e506c433afcda3847f2dad", + "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", + "129039b5572e8a7a8131f76a", + "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff4b4086fbbd1b6cec23e45481eac5a25d", + }, + { + "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b0942e506c433afcda3847f2dadd47647de321cec4ac430f62023856cfbb20704f4ec0bb920ba86c33e05f1ecd96733b79950a3e314", + "d3d934f75ea0f210a8f6059401", + "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", + "129039b5572e8a7a8131f76a", + "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff7c59dfe246e4bb2d6a8afcebdc2beeaabf2a3f43f95a5ea639853f38719875ecdd2bbc0d81bb2a5ed59553b1e76b6365b74f618f685eb7731024bbf6794c3f4c7c5a1cf925", + }, + { + "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b0942e506c433afcda3847f2dadd47647de321cec4ac430f62023856cfbb20704f4ec0bb920ba86c33e05f1ecd96733b79950a3e314", + "d3d934f75ea0f210a8f6059401beb4bc4478fa4969e623d01ada696a7e4c7e5125b34884533a94fb319990325744ee9bbce9e525cf08f5e9e25e5360aad2b2d085fa54d835e8d466826498d9a8877565705a8a3f62802944de7ca5894e5759d351adac869580ec17e485f18c0c66f17cc07cbb", + "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", + "129039b5572e8a7a8131f76a", + "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff7c59dfe246e4bb2d6a8afcebdc2beeaabf2a3f43f95a5ea639853f38719875ecdd2bbc0d81bb2a5ed59553b1e76b6365b74f618f68a12d0f1cc99e132db9014100d9668c91", + }, + { + "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b0942e506c433afcda3847f2dadd47647de321cec4ac430f62023856cfbb20704f4ec0bb920ba86c33e05f1ecd96733b79950a3e314d3d934f75ea0f210a8f6059401beb4bc4478fa4969e623d01ada696a7e4c7e5125b34884533a94fb319990325744ee9b", + "bc", + "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", + "129039b5572e8a7a8131f76a", + "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff7c59dfe246e4bb2d6a8afcebdc2beeaabf2a3f43f95a5ea639853f38719875ecdd2bbc0d81bb2a5ed59553b1e76b6365b74f618f68d1f05b5662cd6e04de896d3ef5dae4149485a5a2093ff4ec74b20b5e5bf8e61b5c65515938c202beab3eea5a498d2f32d4d00a24b826b6efb16013ef54cbe170", + }, + { + "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b0942e506c433afcda3847f2dadd47647de321cec4ac430f62023856cfbb20704f4ec0bb920ba86c33e05f1ecd96733b79950a3e314d3d934f75ea0f210a8f6059401beb4bc4478fa4969e623d01ada696a7e4c7e5125b34884533a94fb319990325744ee9bbce9e525cf08f5e9e25e5360aad2b2d085fa54d835e8d466826498d9a8877565705a8a3f62802944de7ca5894e5759d351adac869580ec17e485f18c0c66f17cc0", + "7cbb22fce466da610b63af62bc83b4692f3affaf271693ac071fb86d11342d", + "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", + "129039b5572e8a7a8131f76a", + "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff7c59dfe246e4bb2d6a8afcebdc2beeaabf2a3f43f95a5ea639853f38719875ecdd2bbc0d81bb2a5ed59553b1e76b6365b74f618f68d1f05b5662cd6e04de896d3ef5dae4149485a5a2093ff4ec74b20b5e5bf8e61b5c65515938c202beab3eea5a498d2f32c38dbb37d04f8272e741da2802c54a9d9aaf8ecf38b36fc9ad0079523f6a4abd5281a22697a3180bc02662a7c13ee23599d18e5c48300dbb831509df4c172f53e524b3c15124a87ac73e5028cde6c94d8d", + }, + { + "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b0942e506c433afcda3847f2dadd47647de321cec4ac430f62023856cfbb20704f4ec0bb920ba86c33e05f1ecd96733b79950a3e314d3d934f75ea0f210a8f6059401beb4bc4478fa4969e623d01ada696a7e4c7e5125b34884533a94fb319990325744ee9bbce9e525", + "", + "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", + "129039b5572e8a7a8131f76a", + "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff7c59dfe246e4bb2d6a8afcebdc2beeaabf2a3f43f95a5ea639853f38719875ecdd2bbc0d81bb2a5ed59553b1e76b6365b74f618f68d1f05b5662cd6e04de896d3ef5dae4149485a5a2093ff4ec74b20b5e5bf8e61b5c65515938c202beab3eea5a498d2f32c38dbb370a9bbc3187cc260ddac991f94ce4f0d5", + }, + { + "0fb826ddb2eb5e708de203d0438be12cf708d635ebdbae56278be09077009586b9bc646ba7c2db35a5de05e86ae71461efea96dac64430edcf117d461113cccacf303576f310ab98efb180599894ba877e50614494923163a3afa9b4c2757f91a6b40799c5b331b464b10dfc45c783c317e408ab76390e19e8b7ceaa2c4d3bd201436bc6f69c7a5a4d8756924ed95665bd5e1034971e4d80d51b2a", + "026866d46aa940309fdcabf92a324fbc", + "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", + "129039b5572e8a7a8131f76a", + "30f05cf8189bb7b8b4f560e746e228c4cc7e86e8f2fa66e1afe212d1855db51070acd5eb34ce80b2e223957df50fde4c2531d97fc9e573725e7a5e47f0dfc4da1942620320bb2deaf8b17937bae4218d04db8e76f6efe84a117292159507c9f8a09fb2c17921d7762510dbf1dac7b62b1bd7572e3e2cf008d01c445c7fa78833235034281ae180e051451c6a64f22ca9708634bd0d604e4cfcd971b13742efa5b6363e662a875daccb2b00", + }, + { + "c7d4f8790e4c47d4daecbddf5939973521ddbf3b832e564afc66f03b5583c41c58bd956609dc3ae3c8f7c2213059575236168dba44e3044049f47c9e7840bbd0fd5036062d70e9f567ac1797056ee93c8476f6c959fa09a3ee854166c6fc36c34d6cca7adcb36f435f86db65f4c4a1793b974294914b377fd179e697751c5ac289243c65d8aca93732849c27483da083d4e218652d4fe5fec8cb953ee7f00070143dd6ece97f241b03c0424bfee2cfd2c4e738f2361df0ffe8863dcf763d408a7a167763959b7f985bc1e359a4b22c6899645ad0814bcf69d10c38474978d1c48e482723e3a6bb3f689f980c51c474eb28cfbba91a8a12eb964b32dfc303a3524ccb752f71316ed9d007e521cb5a0cf429c79d4351b02ee7fb60c7be636a10af3586dfa7b74d80875466a820c0b514e97cb12cce615ab55cba7c1b1de72bcd1cb1acc368f944ef4eaa986e6a4d8253c9337f9795d94df193c90cb0b0387dcde929905223d441717ed9dfe826613bf094ba872993d41b269e27d74e5f541b497eac9ba180dc12ffb6f1e7dc5223cce6dd541071282b97c6526e15b2c330fb41dc96e25d72f45c28e543053766d11d44252db54e584c14abbb295d7e5a58bf36eea1936095ef897a338eb1995fcedd85fc92d354dfe7ff9a115c186bb4d7a1a27835030d248c87571a38f17906cefe0261d15740b9", + "56", + "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", + "129039b5572e8a7a8131f76a", + "f89c825ca43cae1ce3fbdee85c505edd1aabefe69a0f9efd740f027aa7dee48a91ad24e69ad061648f0a52b4afb19d7ffccdc21f4b4247dfd89f5f9f998cb3c02b226173fedb6f8770aceef9271e7236fefd19fb3b87d08a5c587ac7918e80aa4b477f22602189811e270d686bc4949137a41d11d95ec96ee9d26c6126f6e923ab37638b34d1538d2e46d6df6216da4f193a3cecb731e632e109ced643056a1673059355d2d1314df35ded8364efed7de490201090a6f2d1751748585f64d26041637ba3723cbc4b60e226f10a19699d223075bc1f27d82e7f560c0db630ea670b3f8a70a8950894af4d1c7b3f674a3fa00d19ee4cc2b6174c1d259a297424bf2c3943a29a16a9830ce11abaa79cd2eb77b53a02b365b1838e7bfd5ae1bd044ffc885c61c6b2186a357e8b8f732b7ab96517969aeb70c7b493bbaca9462a61815a3c6135c748bf9c8487ac0631807aa69243fa09cd3b8efb63f8d4e090ad30b6c2f08bf4e82f191cedfa5cbe2b42268d67ecd105918181e44fc9879efd642d20be84e6f74717e03fb94fcbaa6ed3b307431d2a9384b8a2b3e5825ffce8d99af48f177e43bb4272226d8a5edd37d53807f768feb9e0733b437a1d0f84779ab68a1804e92a5eecca56364f0fa6dca152203b249fdc8fbd950fdc37c1887596308a90ba3a5751c7096bfbd1cb177bb17847b33c4379b43938a67674459cd9a06e3017ccac5b", + }, + { + "135a28170fe89066da7bcff3a9ccc1b27dfe942a6f47b23835ef746aaea63dc10066d90f4e697528e5451b8e11dd408fdbd4b94a1c6c82515bf7bc099df9cb9d5fa4acad0d22d5f267f18078cec107a995c1f3b12d7603886dbf910ab85ca7180053c50e759b00dc8c81555a425c03d71df6894a6c8cd2d94b64e303c08a1bc1dee1cf537ccf300850856292e1656aff5bf349c87f1ca1ca8085cd400fe901edcad04146a0714ef0f6b083d715edd670e020385f3cda29bc5ff6fc6edffe5ca9ce9def6e0e3d5f04ede2db02cfb2", + "73afd2ab0e0e8537cae42dc6530dc4afb6934ca6", + "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e", + "129039b5572e8a7a8131f76a", + "2c125232a59879aee36cacc4aca5085a4688c4f776667a8fbd86862b5cfb1d57c976688fdd652eafa2b88b1b8e358aa2110ff6ef13cdc1ceca9c9f087c35c38d89d6fbd8de89538070f17916ecb19ca3ef4a1c834f0bdaa1df62aaabef2e117106787056c909e61ecd208357dd5c363f11c5d6cf24992cc873cf69f59360a820fcf290bd90b2cab24c47286acb4e1033962b6d41e562a206a94796a8ab1c6b8bade804ff9bdf5ba6062d2c1f8fe0f4dfc05720bd9a612b92c26789f9f6a7ce43f5e8e3aee99a9cd7d6c11eaa611983c36935b0dda57d898a60a0ab7c4b54", + }, +} diff --git a/vendor/golang.org/x/crypto/codereview.cfg b/vendor/golang.org/x/crypto/codereview.cfg new file mode 100644 index 0000000000000000000000000000000000000000..3f8b14b64e83f940ab7b05e8c542fd821b376d3f --- /dev/null +++ b/vendor/golang.org/x/crypto/codereview.cfg @@ -0,0 +1 @@ +issuerepo: golang/go diff --git a/vendor/golang.org/x/crypto/cryptobyte/asn1.go b/vendor/golang.org/x/crypto/cryptobyte/asn1.go new file mode 100644 index 0000000000000000000000000000000000000000..88ec8b4fbf85680f54ba84e92899c87a7f9da49f --- /dev/null +++ b/vendor/golang.org/x/crypto/cryptobyte/asn1.go @@ -0,0 +1,732 @@ +// Copyright 2017 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 cryptobyte + +import ( + encoding_asn1 "encoding/asn1" + "fmt" + "math/big" + "reflect" + "time" + + "golang.org/x/crypto/cryptobyte/asn1" +) + +// This file contains ASN.1-related methods for String and Builder. + +// Builder + +// AddASN1Int64 appends a DER-encoded ASN.1 INTEGER. +func (b *Builder) AddASN1Int64(v int64) { + b.addASN1Signed(asn1.INTEGER, v) +} + +// AddASN1Enum appends a DER-encoded ASN.1 ENUMERATION. +func (b *Builder) AddASN1Enum(v int64) { + b.addASN1Signed(asn1.ENUM, v) +} + +func (b *Builder) addASN1Signed(tag asn1.Tag, v int64) { + b.AddASN1(tag, func(c *Builder) { + length := 1 + for i := v; i >= 0x80 || i < -0x80; i >>= 8 { + length++ + } + + for ; length > 0; length-- { + i := v >> uint((length-1)*8) & 0xff + c.AddUint8(uint8(i)) + } + }) +} + +// AddASN1Uint64 appends a DER-encoded ASN.1 INTEGER. +func (b *Builder) AddASN1Uint64(v uint64) { + b.AddASN1(asn1.INTEGER, func(c *Builder) { + length := 1 + for i := v; i >= 0x80; i >>= 8 { + length++ + } + + for ; length > 0; length-- { + i := v >> uint((length-1)*8) & 0xff + c.AddUint8(uint8(i)) + } + }) +} + +// AddASN1BigInt appends a DER-encoded ASN.1 INTEGER. +func (b *Builder) AddASN1BigInt(n *big.Int) { + if b.err != nil { + return + } + + b.AddASN1(asn1.INTEGER, func(c *Builder) { + if n.Sign() < 0 { + // A negative number has to be converted to two's-complement form. So we + // invert and subtract 1. If the most-significant-bit isn't set then + // we'll need to pad the beginning with 0xff in order to keep the number + // negative. + nMinus1 := new(big.Int).Neg(n) + nMinus1.Sub(nMinus1, bigOne) + bytes := nMinus1.Bytes() + for i := range bytes { + bytes[i] ^= 0xff + } + if bytes[0]&0x80 == 0 { + c.add(0xff) + } + c.add(bytes...) + } else if n.Sign() == 0 { + c.add(0) + } else { + bytes := n.Bytes() + if bytes[0]&0x80 != 0 { + c.add(0) + } + c.add(bytes...) + } + }) +} + +// AddASN1OctetString appends a DER-encoded ASN.1 OCTET STRING. +func (b *Builder) AddASN1OctetString(bytes []byte) { + b.AddASN1(asn1.OCTET_STRING, func(c *Builder) { + c.AddBytes(bytes) + }) +} + +const generalizedTimeFormatStr = "20060102150405Z0700" + +// AddASN1GeneralizedTime appends a DER-encoded ASN.1 GENERALIZEDTIME. +func (b *Builder) AddASN1GeneralizedTime(t time.Time) { + if t.Year() < 0 || t.Year() > 9999 { + b.err = fmt.Errorf("cryptobyte: cannot represent %v as a GeneralizedTime", t) + return + } + b.AddASN1(asn1.GeneralizedTime, func(c *Builder) { + c.AddBytes([]byte(t.Format(generalizedTimeFormatStr))) + }) +} + +// AddASN1BitString appends a DER-encoded ASN.1 BIT STRING. This does not +// support BIT STRINGs that are not a whole number of bytes. +func (b *Builder) AddASN1BitString(data []byte) { + b.AddASN1(asn1.BIT_STRING, func(b *Builder) { + b.AddUint8(0) + b.AddBytes(data) + }) +} + +func (b *Builder) addBase128Int(n int64) { + var length int + if n == 0 { + length = 1 + } else { + for i := n; i > 0; i >>= 7 { + length++ + } + } + + for i := length - 1; i >= 0; i-- { + o := byte(n >> uint(i*7)) + o &= 0x7f + if i != 0 { + o |= 0x80 + } + + b.add(o) + } +} + +func isValidOID(oid encoding_asn1.ObjectIdentifier) bool { + if len(oid) < 2 { + return false + } + + if oid[0] > 2 || (oid[0] <= 1 && oid[1] >= 40) { + return false + } + + for _, v := range oid { + if v < 0 { + return false + } + } + + return true +} + +func (b *Builder) AddASN1ObjectIdentifier(oid encoding_asn1.ObjectIdentifier) { + b.AddASN1(asn1.OBJECT_IDENTIFIER, func(b *Builder) { + if !isValidOID(oid) { + b.err = fmt.Errorf("cryptobyte: invalid OID: %v", oid) + return + } + + b.addBase128Int(int64(oid[0])*40 + int64(oid[1])) + for _, v := range oid[2:] { + b.addBase128Int(int64(v)) + } + }) +} + +func (b *Builder) AddASN1Boolean(v bool) { + b.AddASN1(asn1.BOOLEAN, func(b *Builder) { + if v { + b.AddUint8(0xff) + } else { + b.AddUint8(0) + } + }) +} + +func (b *Builder) AddASN1NULL() { + b.add(uint8(asn1.NULL), 0) +} + +// MarshalASN1 calls encoding_asn1.Marshal on its input and appends the result if +// successful or records an error if one occurred. +func (b *Builder) MarshalASN1(v interface{}) { + // NOTE(martinkr): This is somewhat of a hack to allow propagation of + // encoding_asn1.Marshal errors into Builder.err. N.B. if you call MarshalASN1 with a + // value embedded into a struct, its tag information is lost. + if b.err != nil { + return + } + bytes, err := encoding_asn1.Marshal(v) + if err != nil { + b.err = err + return + } + b.AddBytes(bytes) +} + +// AddASN1 appends an ASN.1 object. The object is prefixed with the given tag. +// Tags greater than 30 are not supported and result in an error (i.e. +// low-tag-number form only). The child builder passed to the +// BuilderContinuation can be used to build the content of the ASN.1 object. +func (b *Builder) AddASN1(tag asn1.Tag, f BuilderContinuation) { + if b.err != nil { + return + } + // Identifiers with the low five bits set indicate high-tag-number format + // (two or more octets), which we don't support. + if tag&0x1f == 0x1f { + b.err = fmt.Errorf("cryptobyte: high-tag number identifier octects not supported: 0x%x", tag) + return + } + b.AddUint8(uint8(tag)) + b.addLengthPrefixed(1, true, f) +} + +// String + +func (s *String) ReadASN1Boolean(out *bool) bool { + var bytes String + if !s.ReadASN1(&bytes, asn1.INTEGER) || len(bytes) != 1 { + return false + } + + switch bytes[0] { + case 0: + *out = false + case 0xff: + *out = true + default: + return false + } + + return true +} + +var bigIntType = reflect.TypeOf((*big.Int)(nil)).Elem() + +// ReadASN1Integer decodes an ASN.1 INTEGER into out and advances. If out does +// not point to an integer or to a big.Int, it panics. It returns true on +// success and false on error. +func (s *String) ReadASN1Integer(out interface{}) bool { + if reflect.TypeOf(out).Kind() != reflect.Ptr { + panic("out is not a pointer") + } + switch reflect.ValueOf(out).Elem().Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + var i int64 + if !s.readASN1Int64(&i) || reflect.ValueOf(out).Elem().OverflowInt(i) { + return false + } + reflect.ValueOf(out).Elem().SetInt(i) + return true + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + var u uint64 + if !s.readASN1Uint64(&u) || reflect.ValueOf(out).Elem().OverflowUint(u) { + return false + } + reflect.ValueOf(out).Elem().SetUint(u) + return true + case reflect.Struct: + if reflect.TypeOf(out).Elem() == bigIntType { + return s.readASN1BigInt(out.(*big.Int)) + } + } + panic("out does not point to an integer type") +} + +func checkASN1Integer(bytes []byte) bool { + if len(bytes) == 0 { + // An INTEGER is encoded with at least one octet. + return false + } + if len(bytes) == 1 { + return true + } + if bytes[0] == 0 && bytes[1]&0x80 == 0 || bytes[0] == 0xff && bytes[1]&0x80 == 0x80 { + // Value is not minimally encoded. + return false + } + return true +} + +var bigOne = big.NewInt(1) + +func (s *String) readASN1BigInt(out *big.Int) bool { + var bytes String + if !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) { + return false + } + if bytes[0]&0x80 == 0x80 { + // Negative number. + neg := make([]byte, len(bytes)) + for i, b := range bytes { + neg[i] = ^b + } + out.SetBytes(neg) + out.Add(out, bigOne) + out.Neg(out) + } else { + out.SetBytes(bytes) + } + return true +} + +func (s *String) readASN1Int64(out *int64) bool { + var bytes String + if !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) || !asn1Signed(out, bytes) { + return false + } + return true +} + +func asn1Signed(out *int64, n []byte) bool { + length := len(n) + if length > 8 { + return false + } + for i := 0; i < length; i++ { + *out <<= 8 + *out |= int64(n[i]) + } + // Shift up and down in order to sign extend the result. + *out <<= 64 - uint8(length)*8 + *out >>= 64 - uint8(length)*8 + return true +} + +func (s *String) readASN1Uint64(out *uint64) bool { + var bytes String + if !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) || !asn1Unsigned(out, bytes) { + return false + } + return true +} + +func asn1Unsigned(out *uint64, n []byte) bool { + length := len(n) + if length > 9 || length == 9 && n[0] != 0 { + // Too large for uint64. + return false + } + if n[0]&0x80 != 0 { + // Negative number. + return false + } + for i := 0; i < length; i++ { + *out <<= 8 + *out |= uint64(n[i]) + } + return true +} + +// ReadASN1Enum decodes an ASN.1 ENUMERATION into out and advances. It returns +// true on success and false on error. +func (s *String) ReadASN1Enum(out *int) bool { + var bytes String + var i int64 + if !s.ReadASN1(&bytes, asn1.ENUM) || !checkASN1Integer(bytes) || !asn1Signed(&i, bytes) { + return false + } + if int64(int(i)) != i { + return false + } + *out = int(i) + return true +} + +func (s *String) readBase128Int(out *int) bool { + ret := 0 + for i := 0; len(*s) > 0; i++ { + if i == 4 { + return false + } + ret <<= 7 + b := s.read(1)[0] + ret |= int(b & 0x7f) + if b&0x80 == 0 { + *out = ret + return true + } + } + return false // truncated +} + +// ReadASN1ObjectIdentifier decodes an ASN.1 OBJECT IDENTIFIER into out and +// advances. It returns true on success and false on error. +func (s *String) ReadASN1ObjectIdentifier(out *encoding_asn1.ObjectIdentifier) bool { + var bytes String + if !s.ReadASN1(&bytes, asn1.OBJECT_IDENTIFIER) || len(bytes) == 0 { + return false + } + + // In the worst case, we get two elements from the first byte (which is + // encoded differently) and then every varint is a single byte long. + components := make([]int, len(bytes)+1) + + // The first varint is 40*value1 + value2: + // According to this packing, value1 can take the values 0, 1 and 2 only. + // When value1 = 0 or value1 = 1, then value2 is <= 39. When value1 = 2, + // then there are no restrictions on value2. + var v int + if !bytes.readBase128Int(&v) { + return false + } + if v < 80 { + components[0] = v / 40 + components[1] = v % 40 + } else { + components[0] = 2 + components[1] = v - 80 + } + + i := 2 + for ; len(bytes) > 0; i++ { + if !bytes.readBase128Int(&v) { + return false + } + components[i] = v + } + *out = components[:i] + return true +} + +// ReadASN1GeneralizedTime decodes an ASN.1 GENERALIZEDTIME into out and +// advances. It returns true on success and false on error. +func (s *String) ReadASN1GeneralizedTime(out *time.Time) bool { + var bytes String + if !s.ReadASN1(&bytes, asn1.GeneralizedTime) { + return false + } + t := string(bytes) + res, err := time.Parse(generalizedTimeFormatStr, t) + if err != nil { + return false + } + if serialized := res.Format(generalizedTimeFormatStr); serialized != t { + return false + } + *out = res + return true +} + +// ReadASN1BitString decodes an ASN.1 BIT STRING into out and advances. It +// returns true on success and false on error. +func (s *String) ReadASN1BitString(out *encoding_asn1.BitString) bool { + var bytes String + if !s.ReadASN1(&bytes, asn1.BIT_STRING) || len(bytes) == 0 { + return false + } + + paddingBits := uint8(bytes[0]) + bytes = bytes[1:] + if paddingBits > 7 || + len(bytes) == 0 && paddingBits != 0 || + len(bytes) > 0 && bytes[len(bytes)-1]&(1< 4 || len(*s) < int(2+lenLen) { + return false + } + + lenBytes := String((*s)[2 : 2+lenLen]) + if !lenBytes.readUnsigned(&len32, int(lenLen)) { + return false + } + + // ITU-T X.690 section 10.1 (DER length forms) requires encoding the length + // with the minimum number of octets. + if len32 < 128 { + // Length should have used short-form encoding. + return false + } + if len32>>((lenLen-1)*8) == 0 { + // Leading octet is 0. Length should have been at least one byte shorter. + return false + } + + headerLen = 2 + uint32(lenLen) + if headerLen+len32 < len32 { + // Overflow. + return false + } + length = headerLen + len32 + } + + if uint32(int(length)) != length || !s.ReadBytes((*[]byte)(out), int(length)) { + return false + } + if skipHeader && !out.Skip(int(headerLen)) { + panic("cryptobyte: internal error") + } + + return true +} diff --git a/vendor/golang.org/x/crypto/cryptobyte/asn1/asn1.go b/vendor/golang.org/x/crypto/cryptobyte/asn1/asn1.go new file mode 100644 index 0000000000000000000000000000000000000000..cda8e3edfd5ea4322c93d3b92c06ab771b82bef4 --- /dev/null +++ b/vendor/golang.org/x/crypto/cryptobyte/asn1/asn1.go @@ -0,0 +1,46 @@ +// Copyright 2017 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 asn1 contains supporting types for parsing and building ASN.1 +// messages with the cryptobyte package. +package asn1 // import "golang.org/x/crypto/cryptobyte/asn1" + +// Tag represents an ASN.1 identifier octet, consisting of a tag number +// (indicating a type) and class (such as context-specific or constructed). +// +// Methods in the cryptobyte package only support the low-tag-number form, i.e. +// a single identifier octet with bits 7-8 encoding the class and bits 1-6 +// encoding the tag number. +type Tag uint8 + +const ( + classConstructed = 0x20 + classContextSpecific = 0x80 +) + +// Constructed returns t with the constructed class bit set. +func (t Tag) Constructed() Tag { return t | classConstructed } + +// ContextSpecific returns t with the context-specific class bit set. +func (t Tag) ContextSpecific() Tag { return t | classContextSpecific } + +// The following is a list of standard tag and class combinations. +const ( + BOOLEAN = Tag(1) + INTEGER = Tag(2) + BIT_STRING = Tag(3) + OCTET_STRING = Tag(4) + NULL = Tag(5) + OBJECT_IDENTIFIER = Tag(6) + ENUM = Tag(10) + UTF8String = Tag(12) + SEQUENCE = Tag(16 | classConstructed) + SET = Tag(17 | classConstructed) + PrintableString = Tag(19) + T61String = Tag(20) + IA5String = Tag(22) + UTCTime = Tag(23) + GeneralizedTime = Tag(24) + GeneralString = Tag(27) +) diff --git a/vendor/golang.org/x/crypto/cryptobyte/asn1_test.go b/vendor/golang.org/x/crypto/cryptobyte/asn1_test.go new file mode 100644 index 0000000000000000000000000000000000000000..ee6674a2ff2136b36fd2d3e05f35174706963627 --- /dev/null +++ b/vendor/golang.org/x/crypto/cryptobyte/asn1_test.go @@ -0,0 +1,300 @@ +// Copyright 2017 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 cryptobyte + +import ( + "bytes" + encoding_asn1 "encoding/asn1" + "math/big" + "reflect" + "testing" + "time" + + "golang.org/x/crypto/cryptobyte/asn1" +) + +type readASN1Test struct { + name string + in []byte + tag asn1.Tag + ok bool + out interface{} +} + +var readASN1TestData = []readASN1Test{ + {"valid", []byte{0x30, 2, 1, 2}, 0x30, true, []byte{1, 2}}, + {"truncated", []byte{0x30, 3, 1, 2}, 0x30, false, nil}, + {"zero length of length", []byte{0x30, 0x80}, 0x30, false, nil}, + {"invalid long form length", []byte{0x30, 0x81, 1, 1}, 0x30, false, nil}, + {"non-minimal length", append([]byte{0x30, 0x82, 0, 0x80}, make([]byte, 0x80)...), 0x30, false, nil}, + {"invalid tag", []byte{0xa1, 3, 0x4, 1, 1}, 31, false, nil}, + {"high tag", []byte{0x1f, 0x81, 0x80, 0x01, 2, 1, 2}, 0xff /* actually 0x4001, but tag is uint8 */, false, nil}, +} + +func TestReadASN1(t *testing.T) { + for _, test := range readASN1TestData { + t.Run(test.name, func(t *testing.T) { + var in, out String = test.in, nil + ok := in.ReadASN1(&out, test.tag) + if ok != test.ok || ok && !bytes.Equal(out, test.out.([]byte)) { + t.Errorf("in.ReadASN1() = %v, want %v; out = %v, want %v", ok, test.ok, out, test.out) + } + }) + } +} + +func TestReadASN1Optional(t *testing.T) { + var empty String + var present bool + ok := empty.ReadOptionalASN1(nil, &present, 0xa0) + if !ok || present { + t.Errorf("empty.ReadOptionalASN1() = %v, want true; present = %v want false", ok, present) + } + + var in, out String = []byte{0xa1, 3, 0x4, 1, 1}, nil + ok = in.ReadOptionalASN1(&out, &present, 0xa0) + if !ok || present { + t.Errorf("in.ReadOptionalASN1() = %v, want true, present = %v, want false", ok, present) + } + ok = in.ReadOptionalASN1(&out, &present, 0xa1) + wantBytes := []byte{4, 1, 1} + if !ok || !present || !bytes.Equal(out, wantBytes) { + t.Errorf("in.ReadOptionalASN1() = %v, want true; present = %v, want true; out = %v, want = %v", ok, present, out, wantBytes) + } +} + +var optionalOctetStringTestData = []struct { + readASN1Test + present bool +}{ + {readASN1Test{"empty", []byte{}, 0xa0, true, []byte{}}, false}, + {readASN1Test{"invalid", []byte{0xa1, 3, 0x4, 2, 1}, 0xa1, false, []byte{}}, true}, + {readASN1Test{"missing", []byte{0xa1, 3, 0x4, 1, 1}, 0xa0, true, []byte{}}, false}, + {readASN1Test{"present", []byte{0xa1, 3, 0x4, 1, 1}, 0xa1, true, []byte{1}}, true}, +} + +func TestReadASN1OptionalOctetString(t *testing.T) { + for _, test := range optionalOctetStringTestData { + t.Run(test.name, func(t *testing.T) { + in := String(test.in) + var out []byte + var present bool + ok := in.ReadOptionalASN1OctetString(&out, &present, test.tag) + if ok != test.ok || present != test.present || !bytes.Equal(out, test.out.([]byte)) { + t.Errorf("in.ReadOptionalASN1OctetString() = %v, want %v; present = %v want %v; out = %v, want %v", ok, test.ok, present, test.present, out, test.out) + } + }) + } +} + +const defaultInt = -1 + +var optionalIntTestData = []readASN1Test{ + {"empty", []byte{}, 0xa0, true, defaultInt}, + {"invalid", []byte{0xa1, 3, 0x2, 2, 127}, 0xa1, false, 0}, + {"missing", []byte{0xa1, 3, 0x2, 1, 127}, 0xa0, true, defaultInt}, + {"present", []byte{0xa1, 3, 0x2, 1, 42}, 0xa1, true, 42}, +} + +func TestReadASN1OptionalInteger(t *testing.T) { + for _, test := range optionalIntTestData { + t.Run(test.name, func(t *testing.T) { + in := String(test.in) + var out int + ok := in.ReadOptionalASN1Integer(&out, test.tag, defaultInt) + if ok != test.ok || ok && out != test.out.(int) { + t.Errorf("in.ReadOptionalASN1Integer() = %v, want %v; out = %v, want %v", ok, test.ok, out, test.out) + } + }) + } +} + +func TestReadASN1IntegerSigned(t *testing.T) { + testData64 := []struct { + in []byte + out int64 + }{ + {[]byte{2, 3, 128, 0, 0}, -0x800000}, + {[]byte{2, 2, 255, 0}, -256}, + {[]byte{2, 2, 255, 127}, -129}, + {[]byte{2, 1, 128}, -128}, + {[]byte{2, 1, 255}, -1}, + {[]byte{2, 1, 0}, 0}, + {[]byte{2, 1, 1}, 1}, + {[]byte{2, 1, 2}, 2}, + {[]byte{2, 1, 127}, 127}, + {[]byte{2, 2, 0, 128}, 128}, + {[]byte{2, 2, 1, 0}, 256}, + {[]byte{2, 4, 0, 128, 0, 0}, 0x800000}, + } + for i, test := range testData64 { + in := String(test.in) + var out int64 + ok := in.ReadASN1Integer(&out) + if !ok || out != test.out { + t.Errorf("#%d: in.ReadASN1Integer() = %v, want true; out = %d, want %d", i, ok, out, test.out) + } + } + + // Repeat the same cases, reading into a big.Int. + t.Run("big.Int", func(t *testing.T) { + for i, test := range testData64 { + in := String(test.in) + var out big.Int + ok := in.ReadASN1Integer(&out) + if !ok || out.Int64() != test.out { + t.Errorf("#%d: in.ReadASN1Integer() = %v, want true; out = %d, want %d", i, ok, out.Int64(), test.out) + } + } + }) +} + +func TestReadASN1IntegerUnsigned(t *testing.T) { + testData := []struct { + in []byte + out uint64 + }{ + {[]byte{2, 1, 0}, 0}, + {[]byte{2, 1, 1}, 1}, + {[]byte{2, 1, 2}, 2}, + {[]byte{2, 1, 127}, 127}, + {[]byte{2, 2, 0, 128}, 128}, + {[]byte{2, 2, 1, 0}, 256}, + {[]byte{2, 4, 0, 128, 0, 0}, 0x800000}, + {[]byte{2, 8, 127, 255, 255, 255, 255, 255, 255, 255}, 0x7fffffffffffffff}, + {[]byte{2, 9, 0, 128, 0, 0, 0, 0, 0, 0, 0}, 0x8000000000000000}, + {[]byte{2, 9, 0, 255, 255, 255, 255, 255, 255, 255, 255}, 0xffffffffffffffff}, + } + for i, test := range testData { + in := String(test.in) + var out uint64 + ok := in.ReadASN1Integer(&out) + if !ok || out != test.out { + t.Errorf("#%d: in.ReadASN1Integer() = %v, want true; out = %d, want %d", i, ok, out, test.out) + } + } +} + +func TestReadASN1IntegerInvalid(t *testing.T) { + testData := []String{ + []byte{3, 1, 0}, // invalid tag + // truncated + []byte{2, 1}, + []byte{2, 2, 0}, + // not minimally encoded + []byte{2, 2, 0, 1}, + []byte{2, 2, 0xff, 0xff}, + } + + for i, test := range testData { + var out int64 + if test.ReadASN1Integer(&out) { + t.Errorf("#%d: in.ReadASN1Integer() = true, want false (out = %d)", i, out) + } + } +} + +func TestASN1ObjectIdentifier(t *testing.T) { + testData := []struct { + in []byte + ok bool + out []int + }{ + {[]byte{}, false, []int{}}, + {[]byte{6, 0}, false, []int{}}, + {[]byte{5, 1, 85}, false, []int{2, 5}}, + {[]byte{6, 1, 85}, true, []int{2, 5}}, + {[]byte{6, 2, 85, 0x02}, true, []int{2, 5, 2}}, + {[]byte{6, 4, 85, 0x02, 0xc0, 0x00}, true, []int{2, 5, 2, 0x2000}}, + {[]byte{6, 3, 0x81, 0x34, 0x03}, true, []int{2, 100, 3}}, + {[]byte{6, 7, 85, 0x02, 0xc0, 0x80, 0x80, 0x80, 0x80}, false, []int{}}, + } + + for i, test := range testData { + in := String(test.in) + var out encoding_asn1.ObjectIdentifier + ok := in.ReadASN1ObjectIdentifier(&out) + if ok != test.ok || ok && !out.Equal(test.out) { + t.Errorf("#%d: in.ReadASN1ObjectIdentifier() = %v, want %v; out = %v, want %v", i, ok, test.ok, out, test.out) + continue + } + + var b Builder + b.AddASN1ObjectIdentifier(out) + result, err := b.Bytes() + if builderOk := err == nil; test.ok != builderOk { + t.Errorf("#%d: error from Builder.Bytes: %s", i, err) + continue + } + if test.ok && !bytes.Equal(result, test.in) { + t.Errorf("#%d: reserialisation didn't match, got %x, want %x", i, result, test.in) + continue + } + } +} + +func TestReadASN1GeneralizedTime(t *testing.T) { + testData := []struct { + in string + ok bool + out time.Time + }{ + {"20100102030405Z", true, time.Date(2010, 01, 02, 03, 04, 05, 0, time.UTC)}, + {"20100102030405", false, time.Time{}}, + {"20100102030405+0607", true, time.Date(2010, 01, 02, 03, 04, 05, 0, time.FixedZone("", 6*60*60+7*60))}, + {"20100102030405-0607", true, time.Date(2010, 01, 02, 03, 04, 05, 0, time.FixedZone("", -6*60*60-7*60))}, + /* These are invalid times. However, the time package normalises times + * and they were accepted in some versions. See #11134. */ + {"00000100000000Z", false, time.Time{}}, + {"20101302030405Z", false, time.Time{}}, + {"20100002030405Z", false, time.Time{}}, + {"20100100030405Z", false, time.Time{}}, + {"20100132030405Z", false, time.Time{}}, + {"20100231030405Z", false, time.Time{}}, + {"20100102240405Z", false, time.Time{}}, + {"20100102036005Z", false, time.Time{}}, + {"20100102030460Z", false, time.Time{}}, + {"-20100102030410Z", false, time.Time{}}, + {"2010-0102030410Z", false, time.Time{}}, + {"2010-0002030410Z", false, time.Time{}}, + {"201001-02030410Z", false, time.Time{}}, + {"20100102-030410Z", false, time.Time{}}, + {"2010010203-0410Z", false, time.Time{}}, + {"201001020304-10Z", false, time.Time{}}, + } + for i, test := range testData { + in := String(append([]byte{byte(asn1.GeneralizedTime), byte(len(test.in))}, test.in...)) + var out time.Time + ok := in.ReadASN1GeneralizedTime(&out) + if ok != test.ok || ok && !reflect.DeepEqual(out, test.out) { + t.Errorf("#%d: in.ReadASN1GeneralizedTime() = %v, want %v; out = %q, want %q", i, ok, test.ok, out, test.out) + } + } +} + +func TestReadASN1BitString(t *testing.T) { + testData := []struct { + in []byte + ok bool + out encoding_asn1.BitString + }{ + {[]byte{}, false, encoding_asn1.BitString{}}, + {[]byte{0x00}, true, encoding_asn1.BitString{}}, + {[]byte{0x07, 0x00}, true, encoding_asn1.BitString{Bytes: []byte{0}, BitLength: 1}}, + {[]byte{0x07, 0x01}, false, encoding_asn1.BitString{}}, + {[]byte{0x07, 0x40}, false, encoding_asn1.BitString{}}, + {[]byte{0x08, 0x00}, false, encoding_asn1.BitString{}}, + {[]byte{0xff}, false, encoding_asn1.BitString{}}, + {[]byte{0xfe, 0x00}, false, encoding_asn1.BitString{}}, + } + for i, test := range testData { + in := String(append([]byte{3, byte(len(test.in))}, test.in...)) + var out encoding_asn1.BitString + ok := in.ReadASN1BitString(&out) + if ok != test.ok || ok && (!bytes.Equal(out.Bytes, test.out.Bytes) || out.BitLength != test.out.BitLength) { + t.Errorf("#%d: in.ReadASN1BitString() = %v, want %v; out = %v, want %v", i, ok, test.ok, out, test.out) + } + } +} diff --git a/vendor/golang.org/x/crypto/cryptobyte/builder.go b/vendor/golang.org/x/crypto/cryptobyte/builder.go new file mode 100644 index 0000000000000000000000000000000000000000..29b4c7641279c463f1ffd06bc8bbdb87cc9c32ed --- /dev/null +++ b/vendor/golang.org/x/crypto/cryptobyte/builder.go @@ -0,0 +1,309 @@ +// Copyright 2017 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 cryptobyte + +import ( + "errors" + "fmt" +) + +// A Builder builds byte strings from fixed-length and length-prefixed values. +// Builders either allocate space as needed, or are ‘fixed’, which means that +// they write into a given buffer and produce an error if it's exhausted. +// +// The zero value is a usable Builder that allocates space as needed. +// +// Simple values are marshaled and appended to a Builder using methods on the +// Builder. Length-prefixed values are marshaled by providing a +// BuilderContinuation, which is a function that writes the inner contents of +// the value to a given Builder. See the documentation for BuilderContinuation +// for details. +type Builder struct { + err error + result []byte + fixedSize bool + child *Builder + offset int + pendingLenLen int + pendingIsASN1 bool + inContinuation *bool +} + +// NewBuilder creates a Builder that appends its output to the given buffer. +// Like append(), the slice will be reallocated if its capacity is exceeded. +// Use Bytes to get the final buffer. +func NewBuilder(buffer []byte) *Builder { + return &Builder{ + result: buffer, + } +} + +// NewFixedBuilder creates a Builder that appends its output into the given +// buffer. This builder does not reallocate the output buffer. Writes that +// would exceed the buffer's capacity are treated as an error. +func NewFixedBuilder(buffer []byte) *Builder { + return &Builder{ + result: buffer, + fixedSize: true, + } +} + +// Bytes returns the bytes written by the builder or an error if one has +// occurred during during building. +func (b *Builder) Bytes() ([]byte, error) { + if b.err != nil { + return nil, b.err + } + return b.result[b.offset:], nil +} + +// BytesOrPanic returns the bytes written by the builder or panics if an error +// has occurred during building. +func (b *Builder) BytesOrPanic() []byte { + if b.err != nil { + panic(b.err) + } + return b.result[b.offset:] +} + +// AddUint8 appends an 8-bit value to the byte string. +func (b *Builder) AddUint8(v uint8) { + b.add(byte(v)) +} + +// AddUint16 appends a big-endian, 16-bit value to the byte string. +func (b *Builder) AddUint16(v uint16) { + b.add(byte(v>>8), byte(v)) +} + +// AddUint24 appends a big-endian, 24-bit value to the byte string. The highest +// byte of the 32-bit input value is silently truncated. +func (b *Builder) AddUint24(v uint32) { + b.add(byte(v>>16), byte(v>>8), byte(v)) +} + +// AddUint32 appends a big-endian, 32-bit value to the byte string. +func (b *Builder) AddUint32(v uint32) { + b.add(byte(v>>24), byte(v>>16), byte(v>>8), byte(v)) +} + +// AddBytes appends a sequence of bytes to the byte string. +func (b *Builder) AddBytes(v []byte) { + b.add(v...) +} + +// BuilderContinuation is continuation-passing interface for building +// length-prefixed byte sequences. Builder methods for length-prefixed +// sequences (AddUint8LengthPrefixed etc) will invoke the BuilderContinuation +// supplied to them. The child builder passed to the continuation can be used +// to build the content of the length-prefixed sequence. For example: +// +// parent := cryptobyte.NewBuilder() +// parent.AddUint8LengthPrefixed(func (child *Builder) { +// child.AddUint8(42) +// child.AddUint8LengthPrefixed(func (grandchild *Builder) { +// grandchild.AddUint8(5) +// }) +// }) +// +// It is an error to write more bytes to the child than allowed by the reserved +// length prefix. After the continuation returns, the child must be considered +// invalid, i.e. users must not store any copies or references of the child +// that outlive the continuation. +// +// If the continuation panics with a value of type BuildError then the inner +// error will be returned as the error from Bytes. If the child panics +// otherwise then Bytes will repanic with the same value. +type BuilderContinuation func(child *Builder) + +// BuildError wraps an error. If a BuilderContinuation panics with this value, +// the panic will be recovered and the inner error will be returned from +// Builder.Bytes. +type BuildError struct { + Err error +} + +// AddUint8LengthPrefixed adds a 8-bit length-prefixed byte sequence. +func (b *Builder) AddUint8LengthPrefixed(f BuilderContinuation) { + b.addLengthPrefixed(1, false, f) +} + +// AddUint16LengthPrefixed adds a big-endian, 16-bit length-prefixed byte sequence. +func (b *Builder) AddUint16LengthPrefixed(f BuilderContinuation) { + b.addLengthPrefixed(2, false, f) +} + +// AddUint24LengthPrefixed adds a big-endian, 24-bit length-prefixed byte sequence. +func (b *Builder) AddUint24LengthPrefixed(f BuilderContinuation) { + b.addLengthPrefixed(3, false, f) +} + +// AddUint32LengthPrefixed adds a big-endian, 32-bit length-prefixed byte sequence. +func (b *Builder) AddUint32LengthPrefixed(f BuilderContinuation) { + b.addLengthPrefixed(4, false, f) +} + +func (b *Builder) callContinuation(f BuilderContinuation, arg *Builder) { + if !*b.inContinuation { + *b.inContinuation = true + + defer func() { + *b.inContinuation = false + + r := recover() + if r == nil { + return + } + + if buildError, ok := r.(BuildError); ok { + b.err = buildError.Err + } else { + panic(r) + } + }() + } + + f(arg) +} + +func (b *Builder) addLengthPrefixed(lenLen int, isASN1 bool, f BuilderContinuation) { + // Subsequent writes can be ignored if the builder has encountered an error. + if b.err != nil { + return + } + + offset := len(b.result) + b.add(make([]byte, lenLen)...) + + if b.inContinuation == nil { + b.inContinuation = new(bool) + } + + b.child = &Builder{ + result: b.result, + fixedSize: b.fixedSize, + offset: offset, + pendingLenLen: lenLen, + pendingIsASN1: isASN1, + inContinuation: b.inContinuation, + } + + b.callContinuation(f, b.child) + b.flushChild() + if b.child != nil { + panic("cryptobyte: internal error") + } +} + +func (b *Builder) flushChild() { + if b.child == nil { + return + } + b.child.flushChild() + child := b.child + b.child = nil + + if child.err != nil { + b.err = child.err + return + } + + length := len(child.result) - child.pendingLenLen - child.offset + + if length < 0 { + panic("cryptobyte: internal error") // result unexpectedly shrunk + } + + if child.pendingIsASN1 { + // For ASN.1, we reserved a single byte for the length. If that turned out + // to be incorrect, we have to move the contents along in order to make + // space. + if child.pendingLenLen != 1 { + panic("cryptobyte: internal error") + } + var lenLen, lenByte uint8 + if int64(length) > 0xfffffffe { + b.err = errors.New("pending ASN.1 child too long") + return + } else if length > 0xffffff { + lenLen = 5 + lenByte = 0x80 | 4 + } else if length > 0xffff { + lenLen = 4 + lenByte = 0x80 | 3 + } else if length > 0xff { + lenLen = 3 + lenByte = 0x80 | 2 + } else if length > 0x7f { + lenLen = 2 + lenByte = 0x80 | 1 + } else { + lenLen = 1 + lenByte = uint8(length) + length = 0 + } + + // Insert the initial length byte, make space for successive length bytes, + // and adjust the offset. + child.result[child.offset] = lenByte + extraBytes := int(lenLen - 1) + if extraBytes != 0 { + child.add(make([]byte, extraBytes)...) + childStart := child.offset + child.pendingLenLen + copy(child.result[childStart+extraBytes:], child.result[childStart:]) + } + child.offset++ + child.pendingLenLen = extraBytes + } + + l := length + for i := child.pendingLenLen - 1; i >= 0; i-- { + child.result[child.offset+i] = uint8(l) + l >>= 8 + } + if l != 0 { + b.err = fmt.Errorf("cryptobyte: pending child length %d exceeds %d-byte length prefix", length, child.pendingLenLen) + return + } + + if !b.fixedSize { + b.result = child.result // In case child reallocated result. + } +} + +func (b *Builder) add(bytes ...byte) { + if b.err != nil { + return + } + if b.child != nil { + panic("attempted write while child is pending") + } + if len(b.result)+len(bytes) < len(bytes) { + b.err = errors.New("cryptobyte: length overflow") + } + if b.fixedSize && len(b.result)+len(bytes) > cap(b.result) { + b.err = errors.New("cryptobyte: Builder is exceeding its fixed-size buffer") + return + } + b.result = append(b.result, bytes...) +} + +// A MarshalingValue marshals itself into a Builder. +type MarshalingValue interface { + // Marshal is called by Builder.AddValue. It receives a pointer to a builder + // to marshal itself into. It may return an error that occurred during + // marshaling, such as unset or invalid values. + Marshal(b *Builder) error +} + +// AddValue calls Marshal on v, passing a pointer to the builder to append to. +// If Marshal returns an error, it is set on the Builder so that subsequent +// appends don't have an effect. +func (b *Builder) AddValue(v MarshalingValue) { + err := v.Marshal(b) + if err != nil { + b.err = err + } +} diff --git a/vendor/golang.org/x/crypto/cryptobyte/cryptobyte_test.go b/vendor/golang.org/x/crypto/cryptobyte/cryptobyte_test.go new file mode 100644 index 0000000000000000000000000000000000000000..f294dd552b753ba45f694000f5e07d69bd8bc472 --- /dev/null +++ b/vendor/golang.org/x/crypto/cryptobyte/cryptobyte_test.go @@ -0,0 +1,428 @@ +// Copyright 2017 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 cryptobyte + +import ( + "bytes" + "errors" + "fmt" + "testing" +) + +func builderBytesEq(b *Builder, want ...byte) error { + got := b.BytesOrPanic() + if !bytes.Equal(got, want) { + return fmt.Errorf("Bytes() = %v, want %v", got, want) + } + return nil +} + +func TestContinuationError(t *testing.T) { + const errorStr = "TestContinuationError" + var b Builder + b.AddUint8LengthPrefixed(func(b *Builder) { + b.AddUint8(1) + panic(BuildError{Err: errors.New(errorStr)}) + }) + + ret, err := b.Bytes() + if ret != nil { + t.Error("expected nil result") + } + if err == nil { + t.Fatal("unexpected nil error") + } + if s := err.Error(); s != errorStr { + t.Errorf("expected error %q, got %v", errorStr, s) + } +} + +func TestContinuationNonError(t *testing.T) { + defer func() { + recover() + }() + + var b Builder + b.AddUint8LengthPrefixed(func(b *Builder) { + b.AddUint8(1) + panic(1) + }) + + t.Error("Builder did not panic") +} + +func TestGeneratedPanic(t *testing.T) { + defer func() { + recover() + }() + + var b Builder + b.AddUint8LengthPrefixed(func(b *Builder) { + var p *byte + *p = 0 + }) + + t.Error("Builder did not panic") +} + +func TestBytes(t *testing.T) { + var b Builder + v := []byte("foobarbaz") + b.AddBytes(v[0:3]) + b.AddBytes(v[3:4]) + b.AddBytes(v[4:9]) + if err := builderBytesEq(&b, v...); err != nil { + t.Error(err) + } + s := String(b.BytesOrPanic()) + for _, w := range []string{"foo", "bar", "baz"} { + var got []byte + if !s.ReadBytes(&got, 3) { + t.Errorf("ReadBytes() = false, want true (w = %v)", w) + } + want := []byte(w) + if !bytes.Equal(got, want) { + t.Errorf("ReadBytes(): got = %v, want %v", got, want) + } + } + if len(s) != 0 { + t.Errorf("len(s) = %d, want 0", len(s)) + } +} + +func TestUint8(t *testing.T) { + var b Builder + b.AddUint8(42) + if err := builderBytesEq(&b, 42); err != nil { + t.Error(err) + } + + var s String = b.BytesOrPanic() + var v uint8 + if !s.ReadUint8(&v) { + t.Error("ReadUint8() = false, want true") + } + if v != 42 { + t.Errorf("v = %d, want 42", v) + } + if len(s) != 0 { + t.Errorf("len(s) = %d, want 0", len(s)) + } +} + +func TestUint16(t *testing.T) { + var b Builder + b.AddUint16(65534) + if err := builderBytesEq(&b, 255, 254); err != nil { + t.Error(err) + } + var s String = b.BytesOrPanic() + var v uint16 + if !s.ReadUint16(&v) { + t.Error("ReadUint16() == false, want true") + } + if v != 65534 { + t.Errorf("v = %d, want 65534", v) + } + if len(s) != 0 { + t.Errorf("len(s) = %d, want 0", len(s)) + } +} + +func TestUint24(t *testing.T) { + var b Builder + b.AddUint24(0xfffefd) + if err := builderBytesEq(&b, 255, 254, 253); err != nil { + t.Error(err) + } + + var s String = b.BytesOrPanic() + var v uint32 + if !s.ReadUint24(&v) { + t.Error("ReadUint8() = false, want true") + } + if v != 0xfffefd { + t.Errorf("v = %d, want fffefd", v) + } + if len(s) != 0 { + t.Errorf("len(s) = %d, want 0", len(s)) + } +} + +func TestUint24Truncation(t *testing.T) { + var b Builder + b.AddUint24(0x10111213) + if err := builderBytesEq(&b, 0x11, 0x12, 0x13); err != nil { + t.Error(err) + } +} + +func TestUint32(t *testing.T) { + var b Builder + b.AddUint32(0xfffefdfc) + if err := builderBytesEq(&b, 255, 254, 253, 252); err != nil { + t.Error(err) + } + + var s String = b.BytesOrPanic() + var v uint32 + if !s.ReadUint32(&v) { + t.Error("ReadUint8() = false, want true") + } + if v != 0xfffefdfc { + t.Errorf("v = %x, want fffefdfc", v) + } + if len(s) != 0 { + t.Errorf("len(s) = %d, want 0", len(s)) + } +} + +func TestUMultiple(t *testing.T) { + var b Builder + b.AddUint8(23) + b.AddUint32(0xfffefdfc) + b.AddUint16(42) + if err := builderBytesEq(&b, 23, 255, 254, 253, 252, 0, 42); err != nil { + t.Error(err) + } + + var s String = b.BytesOrPanic() + var ( + x uint8 + y uint32 + z uint16 + ) + if !s.ReadUint8(&x) || !s.ReadUint32(&y) || !s.ReadUint16(&z) { + t.Error("ReadUint8() = false, want true") + } + if x != 23 || y != 0xfffefdfc || z != 42 { + t.Errorf("x, y, z = %d, %d, %d; want 23, 4294901244, 5", x, y, z) + } + if len(s) != 0 { + t.Errorf("len(s) = %d, want 0", len(s)) + } +} + +func TestUint8LengthPrefixedSimple(t *testing.T) { + var b Builder + b.AddUint8LengthPrefixed(func(c *Builder) { + c.AddUint8(23) + c.AddUint8(42) + }) + if err := builderBytesEq(&b, 2, 23, 42); err != nil { + t.Error(err) + } + + var base, child String = b.BytesOrPanic(), nil + var x, y uint8 + if !base.ReadUint8LengthPrefixed(&child) || !child.ReadUint8(&x) || + !child.ReadUint8(&y) { + t.Error("parsing failed") + } + if x != 23 || y != 42 { + t.Errorf("want x, y == 23, 42; got %d, %d", x, y) + } + if len(base) != 0 { + t.Errorf("len(base) = %d, want 0", len(base)) + } + if len(child) != 0 { + t.Errorf("len(child) = %d, want 0", len(child)) + } +} + +func TestUint8LengthPrefixedMulti(t *testing.T) { + var b Builder + b.AddUint8LengthPrefixed(func(c *Builder) { + c.AddUint8(23) + c.AddUint8(42) + }) + b.AddUint8(5) + b.AddUint8LengthPrefixed(func(c *Builder) { + c.AddUint8(123) + c.AddUint8(234) + }) + if err := builderBytesEq(&b, 2, 23, 42, 5, 2, 123, 234); err != nil { + t.Error(err) + } + + var s, child String = b.BytesOrPanic(), nil + var u, v, w, x, y uint8 + if !s.ReadUint8LengthPrefixed(&child) || !child.ReadUint8(&u) || !child.ReadUint8(&v) || + !s.ReadUint8(&w) || !s.ReadUint8LengthPrefixed(&child) || !child.ReadUint8(&x) || !child.ReadUint8(&y) { + t.Error("parsing failed") + } + if u != 23 || v != 42 || w != 5 || x != 123 || y != 234 { + t.Errorf("u, v, w, x, y = %d, %d, %d, %d, %d; want 23, 42, 5, 123, 234", + u, v, w, x, y) + } + if len(s) != 0 { + t.Errorf("len(s) = %d, want 0", len(s)) + } + if len(child) != 0 { + t.Errorf("len(child) = %d, want 0", len(child)) + } +} + +func TestUint8LengthPrefixedNested(t *testing.T) { + var b Builder + b.AddUint8LengthPrefixed(func(c *Builder) { + c.AddUint8(5) + c.AddUint8LengthPrefixed(func(d *Builder) { + d.AddUint8(23) + d.AddUint8(42) + }) + c.AddUint8(123) + }) + if err := builderBytesEq(&b, 5, 5, 2, 23, 42, 123); err != nil { + t.Error(err) + } + + var base, child1, child2 String = b.BytesOrPanic(), nil, nil + var u, v, w, x uint8 + if !base.ReadUint8LengthPrefixed(&child1) { + t.Error("parsing base failed") + } + if !child1.ReadUint8(&u) || !child1.ReadUint8LengthPrefixed(&child2) || !child1.ReadUint8(&x) { + t.Error("parsing child1 failed") + } + if !child2.ReadUint8(&v) || !child2.ReadUint8(&w) { + t.Error("parsing child2 failed") + } + if u != 5 || v != 23 || w != 42 || x != 123 { + t.Errorf("u, v, w, x = %d, %d, %d, %d, want 5, 23, 42, 123", + u, v, w, x) + } + if len(base) != 0 { + t.Errorf("len(base) = %d, want 0", len(base)) + } + if len(child1) != 0 { + t.Errorf("len(child1) = %d, want 0", len(child1)) + } + if len(base) != 0 { + t.Errorf("len(child2) = %d, want 0", len(child2)) + } +} + +func TestPreallocatedBuffer(t *testing.T) { + var buf [5]byte + b := NewBuilder(buf[0:0]) + b.AddUint8(1) + b.AddUint8LengthPrefixed(func(c *Builder) { + c.AddUint8(3) + c.AddUint8(4) + }) + b.AddUint16(1286) // Outgrow buf by one byte. + want := []byte{1, 2, 3, 4, 0} + if !bytes.Equal(buf[:], want) { + t.Errorf("buf = %v want %v", buf, want) + } + if err := builderBytesEq(b, 1, 2, 3, 4, 5, 6); err != nil { + t.Error(err) + } +} + +func TestWriteWithPendingChild(t *testing.T) { + var b Builder + b.AddUint8LengthPrefixed(func(c *Builder) { + c.AddUint8LengthPrefixed(func(d *Builder) { + defer func() { + if recover() == nil { + t.Errorf("recover() = nil, want error; c.AddUint8() did not panic") + } + }() + c.AddUint8(2) // panics + + defer func() { + if recover() == nil { + t.Errorf("recover() = nil, want error; b.AddUint8() did not panic") + } + }() + b.AddUint8(2) // panics + }) + + defer func() { + if recover() == nil { + t.Errorf("recover() = nil, want error; b.AddUint8() did not panic") + } + }() + b.AddUint8(2) // panics + }) +} + +// ASN.1 + +func TestASN1Int64(t *testing.T) { + tests := []struct { + in int64 + want []byte + }{ + {-0x800000, []byte{2, 3, 128, 0, 0}}, + {-256, []byte{2, 2, 255, 0}}, + {-129, []byte{2, 2, 255, 127}}, + {-128, []byte{2, 1, 128}}, + {-1, []byte{2, 1, 255}}, + {0, []byte{2, 1, 0}}, + {1, []byte{2, 1, 1}}, + {2, []byte{2, 1, 2}}, + {127, []byte{2, 1, 127}}, + {128, []byte{2, 2, 0, 128}}, + {256, []byte{2, 2, 1, 0}}, + {0x800000, []byte{2, 4, 0, 128, 0, 0}}, + } + for i, tt := range tests { + var b Builder + b.AddASN1Int64(tt.in) + if err := builderBytesEq(&b, tt.want...); err != nil { + t.Errorf("%v, (i = %d; in = %v)", err, i, tt.in) + } + + var n int64 + s := String(b.BytesOrPanic()) + ok := s.ReadASN1Integer(&n) + if !ok || n != tt.in { + t.Errorf("s.ReadASN1Integer(&n) = %v, n = %d; want true, n = %d (i = %d)", + ok, n, tt.in, i) + } + if len(s) != 0 { + t.Errorf("len(s) = %d, want 0", len(s)) + } + } +} + +func TestASN1Uint64(t *testing.T) { + tests := []struct { + in uint64 + want []byte + }{ + {0, []byte{2, 1, 0}}, + {1, []byte{2, 1, 1}}, + {2, []byte{2, 1, 2}}, + {127, []byte{2, 1, 127}}, + {128, []byte{2, 2, 0, 128}}, + {256, []byte{2, 2, 1, 0}}, + {0x800000, []byte{2, 4, 0, 128, 0, 0}}, + {0x7fffffffffffffff, []byte{2, 8, 127, 255, 255, 255, 255, 255, 255, 255}}, + {0x8000000000000000, []byte{2, 9, 0, 128, 0, 0, 0, 0, 0, 0, 0}}, + {0xffffffffffffffff, []byte{2, 9, 0, 255, 255, 255, 255, 255, 255, 255, 255}}, + } + for i, tt := range tests { + var b Builder + b.AddASN1Uint64(tt.in) + if err := builderBytesEq(&b, tt.want...); err != nil { + t.Errorf("%v, (i = %d; in = %v)", err, i, tt.in) + } + + var n uint64 + s := String(b.BytesOrPanic()) + ok := s.ReadASN1Integer(&n) + if !ok || n != tt.in { + t.Errorf("s.ReadASN1Integer(&n) = %v, n = %d; want true, n = %d (i = %d)", + ok, n, tt.in, i) + } + if len(s) != 0 { + t.Errorf("len(s) = %d, want 0", len(s)) + } + } +} diff --git a/vendor/golang.org/x/crypto/cryptobyte/example_test.go b/vendor/golang.org/x/crypto/cryptobyte/example_test.go new file mode 100644 index 0000000000000000000000000000000000000000..86c098adf6141ef675fc324fda37bf11813a6030 --- /dev/null +++ b/vendor/golang.org/x/crypto/cryptobyte/example_test.go @@ -0,0 +1,154 @@ +// Copyright 2017 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 cryptobyte_test + +import ( + "errors" + "fmt" + + "golang.org/x/crypto/cryptobyte" + "golang.org/x/crypto/cryptobyte/asn1" +) + +func ExampleString_lengthPrefixed() { + // This is an example of parsing length-prefixed data (as found in, for + // example, TLS). Imagine a 16-bit prefixed series of 8-bit prefixed + // strings. + + input := cryptobyte.String([]byte{0, 12, 5, 'h', 'e', 'l', 'l', 'o', 5, 'w', 'o', 'r', 'l', 'd'}) + var result []string + + var values cryptobyte.String + if !input.ReadUint16LengthPrefixed(&values) || + !input.Empty() { + panic("bad format") + } + + for !values.Empty() { + var value cryptobyte.String + if !values.ReadUint8LengthPrefixed(&value) { + panic("bad format") + } + + result = append(result, string(value)) + } + + // Output: []string{"hello", "world"} + fmt.Printf("%#v\n", result) +} + +func ExampleString_aSN1() { + // This is an example of parsing ASN.1 data that looks like: + // Foo ::= SEQUENCE { + // version [6] INTEGER DEFAULT 0 + // data OCTET STRING + // } + + input := cryptobyte.String([]byte{0x30, 12, 0xa6, 3, 2, 1, 2, 4, 5, 'h', 'e', 'l', 'l', 'o'}) + + var ( + version int64 + data, inner, versionBytes cryptobyte.String + haveVersion bool + ) + if !input.ReadASN1(&inner, asn1.SEQUENCE) || + !input.Empty() || + !inner.ReadOptionalASN1(&versionBytes, &haveVersion, asn1.Tag(6).Constructed().ContextSpecific()) || + (haveVersion && !versionBytes.ReadASN1Integer(&version)) || + (haveVersion && !versionBytes.Empty()) || + !inner.ReadASN1(&data, asn1.OCTET_STRING) || + !inner.Empty() { + panic("bad format") + } + + // Output: haveVersion: true, version: 2, data: hello + fmt.Printf("haveVersion: %t, version: %d, data: %s\n", haveVersion, version, string(data)) +} + +func ExampleBuilder_aSN1() { + // This is an example of building ASN.1 data that looks like: + // Foo ::= SEQUENCE { + // version [6] INTEGER DEFAULT 0 + // data OCTET STRING + // } + + version := int64(2) + data := []byte("hello") + const defaultVersion = 0 + + var b cryptobyte.Builder + b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) { + if version != defaultVersion { + b.AddASN1(asn1.Tag(6).Constructed().ContextSpecific(), func(b *cryptobyte.Builder) { + b.AddASN1Int64(version) + }) + } + b.AddASN1OctetString(data) + }) + + result, err := b.Bytes() + if err != nil { + panic(err) + } + + // Output: 300ca603020102040568656c6c6f + fmt.Printf("%x\n", result) +} + +func ExampleBuilder_lengthPrefixed() { + // This is an example of building length-prefixed data (as found in, + // for example, TLS). Imagine a 16-bit prefixed series of 8-bit + // prefixed strings. + input := []string{"hello", "world"} + + var b cryptobyte.Builder + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + for _, value := range input { + b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes([]byte(value)) + }) + } + }) + + result, err := b.Bytes() + if err != nil { + panic(err) + } + + // Output: 000c0568656c6c6f05776f726c64 + fmt.Printf("%x\n", result) +} + +func ExampleBuilder_lengthPrefixOverflow() { + // Writing more data that can be expressed by the length prefix results + // in an error from Bytes(). + + tooLarge := make([]byte, 256) + + var b cryptobyte.Builder + b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(tooLarge) + }) + + result, err := b.Bytes() + fmt.Printf("len=%d err=%s\n", len(result), err) + + // Output: len=0 err=cryptobyte: pending child length 256 exceeds 1-byte length prefix +} + +func ExampleBuilderContinuation_errorHandling() { + var b cryptobyte.Builder + // Continuations that panic with a BuildError will cause Bytes to + // return the inner error. + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint32(0) + panic(cryptobyte.BuildError{Err: errors.New("example error")}) + }) + + result, err := b.Bytes() + fmt.Printf("len=%d err=%s\n", len(result), err) + + // Output: len=0 err=example error +} diff --git a/vendor/golang.org/x/crypto/cryptobyte/string.go b/vendor/golang.org/x/crypto/cryptobyte/string.go new file mode 100644 index 0000000000000000000000000000000000000000..7636fb9c8a8749605320adaf90c08c121e2720d1 --- /dev/null +++ b/vendor/golang.org/x/crypto/cryptobyte/string.go @@ -0,0 +1,167 @@ +// Copyright 2017 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 cryptobyte contains types that help with parsing and constructing +// length-prefixed, binary messages, including ASN.1 DER. (The asn1 subpackage +// contains useful ASN.1 constants.) +// +// The String type is for parsing. It wraps a []byte slice and provides helper +// functions for consuming structures, value by value. +// +// The Builder type is for constructing messages. It providers helper functions +// for appending values and also for appending length-prefixed submessages – +// without having to worry about calculating the length prefix ahead of time. +// +// See the documentation and examples for the Builder and String types to get +// started. +package cryptobyte // import "golang.org/x/crypto/cryptobyte" + +// String represents a string of bytes. It provides methods for parsing +// fixed-length and length-prefixed values from it. +type String []byte + +// read advances a String by n bytes and returns them. If less than n bytes +// remain, it returns nil. +func (s *String) read(n int) []byte { + if len(*s) < n { + return nil + } + v := (*s)[:n] + *s = (*s)[n:] + return v +} + +// Skip advances the String by n byte and reports whether it was successful. +func (s *String) Skip(n int) bool { + return s.read(n) != nil +} + +// ReadUint8 decodes an 8-bit value into out and advances over it. It +// returns true on success and false on error. +func (s *String) ReadUint8(out *uint8) bool { + v := s.read(1) + if v == nil { + return false + } + *out = uint8(v[0]) + return true +} + +// ReadUint16 decodes a big-endian, 16-bit value into out and advances over it. +// It returns true on success and false on error. +func (s *String) ReadUint16(out *uint16) bool { + v := s.read(2) + if v == nil { + return false + } + *out = uint16(v[0])<<8 | uint16(v[1]) + return true +} + +// ReadUint24 decodes a big-endian, 24-bit value into out and advances over it. +// It returns true on success and false on error. +func (s *String) ReadUint24(out *uint32) bool { + v := s.read(3) + if v == nil { + return false + } + *out = uint32(v[0])<<16 | uint32(v[1])<<8 | uint32(v[2]) + return true +} + +// ReadUint32 decodes a big-endian, 32-bit value into out and advances over it. +// It returns true on success and false on error. +func (s *String) ReadUint32(out *uint32) bool { + v := s.read(4) + if v == nil { + return false + } + *out = uint32(v[0])<<24 | uint32(v[1])<<16 | uint32(v[2])<<8 | uint32(v[3]) + return true +} + +func (s *String) readUnsigned(out *uint32, length int) bool { + v := s.read(length) + if v == nil { + return false + } + var result uint32 + for i := 0; i < length; i++ { + result <<= 8 + result |= uint32(v[i]) + } + *out = result + return true +} + +func (s *String) readLengthPrefixed(lenLen int, outChild *String) bool { + lenBytes := s.read(lenLen) + if lenBytes == nil { + return false + } + var length uint32 + for _, b := range lenBytes { + length = length << 8 + length = length | uint32(b) + } + if int(length) < 0 { + // This currently cannot overflow because we read uint24 at most, but check + // anyway in case that changes in the future. + return false + } + v := s.read(int(length)) + if v == nil { + return false + } + *outChild = v + return true +} + +// ReadUint8LengthPrefixed reads the content of an 8-bit length-prefixed value +// into out and advances over it. It returns true on success and false on +// error. +func (s *String) ReadUint8LengthPrefixed(out *String) bool { + return s.readLengthPrefixed(1, out) +} + +// ReadUint16LengthPrefixed reads the content of a big-endian, 16-bit +// length-prefixed value into out and advances over it. It returns true on +// success and false on error. +func (s *String) ReadUint16LengthPrefixed(out *String) bool { + return s.readLengthPrefixed(2, out) +} + +// ReadUint24LengthPrefixed reads the content of a big-endian, 24-bit +// length-prefixed value into out and advances over it. It returns true on +// success and false on error. +func (s *String) ReadUint24LengthPrefixed(out *String) bool { + return s.readLengthPrefixed(3, out) +} + +// ReadBytes reads n bytes into out and advances over them. It returns true on +// success and false and error. +func (s *String) ReadBytes(out *[]byte, n int) bool { + v := s.read(n) + if v == nil { + return false + } + *out = v + return true +} + +// CopyBytes copies len(out) bytes into out and advances over them. It returns +// true on success and false on error. +func (s *String) CopyBytes(out []byte) bool { + n := len(out) + v := s.read(n) + if v == nil { + return false + } + return copy(out, v) == n +} + +// Empty reports whether the string does not contain any bytes. +func (s String) Empty() bool { + return len(s) == 0 +} diff --git a/vendor/golang.org/x/crypto/curve25519/const_amd64.h b/vendor/golang.org/x/crypto/curve25519/const_amd64.h new file mode 100644 index 0000000000000000000000000000000000000000..b3f74162f60921060ab7522fcd30bb1db2507586 --- /dev/null +++ b/vendor/golang.org/x/crypto/curve25519/const_amd64.h @@ -0,0 +1,8 @@ +// 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: https://bench.cr.yp.to/supercop.html + +#define REDMASK51 0x0007FFFFFFFFFFFF diff --git a/vendor/golang.org/x/crypto/curve25519/const_amd64.s b/vendor/golang.org/x/crypto/curve25519/const_amd64.s new file mode 100644 index 0000000000000000000000000000000000000000..ee7b4bd5f8e3303e829cd909f02cf30de1877acd --- /dev/null +++ b/vendor/golang.org/x/crypto/curve25519/const_amd64.s @@ -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: https://bench.cr.yp.to/supercop.html + +// +build amd64,!gccgo,!appengine + +// These constants cannot be encoded in non-MOVQ immediates. +// We access them directly from memory instead. + +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 diff --git a/vendor/golang.org/x/crypto/curve25519/cswap_amd64.s b/vendor/golang.org/x/crypto/curve25519/cswap_amd64.s new file mode 100644 index 0000000000000000000000000000000000000000..cd793a5b5f2eb00a97e3a9374c03a5f71c879e19 --- /dev/null +++ b/vendor/golang.org/x/crypto/curve25519/cswap_amd64.s @@ -0,0 +1,65 @@ +// 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,!appengine + +// func cswap(inout *[4][5]uint64, v uint64) +TEXT ·cswap(SB),7,$0 + MOVQ inout+0(FP),DI + MOVQ v+8(FP),SI + + SUBQ $1, SI + NOTQ SI + MOVQ SI, X15 + PSHUFD $0x44, X15, X15 + + MOVOU 0(DI), X0 + MOVOU 16(DI), X2 + MOVOU 32(DI), X4 + MOVOU 48(DI), X6 + MOVOU 64(DI), X8 + MOVOU 80(DI), X1 + MOVOU 96(DI), X3 + MOVOU 112(DI), X5 + MOVOU 128(DI), X7 + MOVOU 144(DI), X9 + + MOVO X1, X10 + MOVO X3, X11 + MOVO X5, X12 + MOVO X7, X13 + MOVO X9, X14 + + PXOR X0, X10 + PXOR X2, X11 + PXOR X4, X12 + PXOR X6, X13 + PXOR X8, X14 + PAND X15, X10 + PAND X15, X11 + PAND X15, X12 + PAND X15, X13 + PAND X15, X14 + PXOR X10, X0 + PXOR X10, X1 + PXOR X11, X2 + PXOR X11, X3 + PXOR X12, X4 + PXOR X12, X5 + PXOR X13, X6 + PXOR X13, X7 + PXOR X14, X8 + PXOR X14, X9 + + MOVOU X0, 0(DI) + MOVOU X2, 16(DI) + MOVOU X4, 32(DI) + MOVOU X6, 48(DI) + MOVOU X8, 64(DI) + MOVOU X1, 80(DI) + MOVOU X3, 96(DI) + MOVOU X5, 112(DI) + MOVOU X7, 128(DI) + MOVOU X9, 144(DI) + RET diff --git a/vendor/golang.org/x/crypto/curve25519/curve25519.go b/vendor/golang.org/x/crypto/curve25519/curve25519.go new file mode 100644 index 0000000000000000000000000000000000000000..cb8fbc57b97a6ce068dd45e58a4c5c1b72209bae --- /dev/null +++ b/vendor/golang.org/x/crypto/curve25519/curve25519.go @@ -0,0 +1,834 @@ +// 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 an implementation in amd64 assembly so this code is only run on +// non-amd64 platforms. The amd64 assembly does not support gccgo. +// +build !amd64 gccgo appengine + +package curve25519 + +import ( + "encoding/binary" +) + +// 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) { + b = -b + for i := range f { + t := b & (f[i] ^ g[i]) + f[i] ^= t + g[i] ^= t + } +} + +// 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 { + return int64(binary.LittleEndian.Uint32(in)) +} + +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> 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) +} diff --git a/vendor/golang.org/x/crypto/curve25519/curve25519_test.go b/vendor/golang.org/x/crypto/curve25519/curve25519_test.go new file mode 100644 index 0000000000000000000000000000000000000000..051a8301f080ffe95e1645eae968a746395745ee --- /dev/null +++ b/vendor/golang.org/x/crypto/curve25519/curve25519_test.go @@ -0,0 +1,39 @@ +// 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) + } +} + +func BenchmarkScalarBaseMult(b *testing.B) { + var in, out [32]byte + in[0] = 1 + + b.SetBytes(32) + for i := 0; i < b.N; i++ { + ScalarBaseMult(&out, &in) + } +} diff --git a/vendor/golang.org/x/crypto/curve25519/doc.go b/vendor/golang.org/x/crypto/curve25519/doc.go new file mode 100644 index 0000000000000000000000000000000000000000..da9b10d9c1ffd204d7d4ccd683b196c6b5fb5e67 --- /dev/null +++ b/vendor/golang.org/x/crypto/curve25519/doc.go @@ -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 https://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) +} diff --git a/vendor/golang.org/x/crypto/curve25519/freeze_amd64.s b/vendor/golang.org/x/crypto/curve25519/freeze_amd64.s new file mode 100644 index 0000000000000000000000000000000000000000..390816106ee99879f7e0effb7cbb5f2b65931ae9 --- /dev/null +++ b/vendor/golang.org/x/crypto/curve25519/freeze_amd64.s @@ -0,0 +1,73 @@ +// 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: https://bench.cr.yp.to/supercop.html + +// +build amd64,!gccgo,!appengine + +#include "const_amd64.h" + +// func freeze(inout *[5]uint64) +TEXT ·freeze(SB),7,$0-8 + MOVQ inout+0(FP), DI + + MOVQ 0(DI),SI + MOVQ 8(DI),DX + MOVQ 16(DI),CX + MOVQ 24(DI),R8 + MOVQ 32(DI),R9 + MOVQ $REDMASK51,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) + RET diff --git a/vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s b/vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s new file mode 100644 index 0000000000000000000000000000000000000000..9e9040b2502f8e6bf156531a1cbe7feead9eee10 --- /dev/null +++ b/vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s @@ -0,0 +1,1377 @@ +// 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: https://bench.cr.yp.to/supercop.html + +// +build amd64,!gccgo,!appengine + +#include "const_amd64.h" + +// func ladderstep(inout *[5][5]uint64) +TEXT ·ladderstep(SB),0,$296-8 + MOVQ inout+0(FP),DI + + MOVQ 40(DI),SI + MOVQ 48(DI),DX + MOVQ 56(DI),CX + MOVQ 64(DI),R8 + MOVQ 72(DI),R9 + MOVQ SI,AX + MOVQ DX,R10 + MOVQ CX,R11 + MOVQ R8,R12 + MOVQ R9,R13 + ADDQ ·_2P0(SB),AX + ADDQ ·_2P1234(SB),R10 + ADDQ ·_2P1234(SB),R11 + ADDQ ·_2P1234(SB),R12 + ADDQ ·_2P1234(SB),R13 + ADDQ 80(DI),SI + ADDQ 88(DI),DX + ADDQ 96(DI),CX + ADDQ 104(DI),R8 + ADDQ 112(DI),R9 + SUBQ 80(DI),AX + SUBQ 88(DI),R10 + SUBQ 96(DI),R11 + SUBQ 104(DI),R12 + SUBQ 112(DI),R13 + MOVQ SI,0(SP) + MOVQ DX,8(SP) + MOVQ CX,16(SP) + MOVQ R8,24(SP) + MOVQ R9,32(SP) + MOVQ AX,40(SP) + MOVQ R10,48(SP) + MOVQ R11,56(SP) + MOVQ R12,64(SP) + MOVQ R13,72(SP) + MOVQ 40(SP),AX + MULQ 40(SP) + MOVQ AX,SI + MOVQ DX,CX + MOVQ 40(SP),AX + SHLQ $1,AX + MULQ 48(SP) + MOVQ AX,R8 + MOVQ DX,R9 + MOVQ 40(SP),AX + SHLQ $1,AX + MULQ 56(SP) + MOVQ AX,R10 + MOVQ DX,R11 + MOVQ 40(SP),AX + SHLQ $1,AX + MULQ 64(SP) + MOVQ AX,R12 + MOVQ DX,R13 + MOVQ 40(SP),AX + SHLQ $1,AX + MULQ 72(SP) + MOVQ AX,R14 + MOVQ DX,R15 + MOVQ 48(SP),AX + MULQ 48(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 48(SP),AX + SHLQ $1,AX + MULQ 56(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 48(SP),AX + SHLQ $1,AX + MULQ 64(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 48(SP),DX + IMUL3Q $38,DX,AX + MULQ 72(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 56(SP),AX + MULQ 56(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 56(SP),DX + IMUL3Q $38,DX,AX + MULQ 64(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 56(SP),DX + IMUL3Q $38,DX,AX + MULQ 72(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 64(SP),DX + IMUL3Q $19,DX,AX + MULQ 64(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 64(SP),DX + IMUL3Q $38,DX,AX + MULQ 72(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 72(SP),DX + IMUL3Q $19,DX,AX + MULQ 72(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ $REDMASK51,DX + SHLQ $13,CX:SI + ANDQ DX,SI + SHLQ $13,R9:R8 + ANDQ DX,R8 + ADDQ CX,R8 + SHLQ $13,R11:R10 + ANDQ DX,R10 + ADDQ R9,R10 + SHLQ $13,R13:R12 + ANDQ DX,R12 + ADDQ R11,R12 + SHLQ $13,R15:R14 + ANDQ DX,R14 + ADDQ R13,R14 + IMUL3Q $19,R15,CX + ADDQ CX,SI + MOVQ SI,CX + SHRQ $51,CX + ADDQ R8,CX + ANDQ DX,SI + MOVQ CX,R8 + SHRQ $51,CX + ADDQ R10,CX + ANDQ DX,R8 + MOVQ CX,R9 + SHRQ $51,CX + ADDQ R12,CX + ANDQ DX,R9 + MOVQ CX,AX + SHRQ $51,CX + ADDQ R14,CX + ANDQ DX,AX + MOVQ CX,R10 + SHRQ $51,CX + IMUL3Q $19,CX,CX + ADDQ CX,SI + ANDQ DX,R10 + MOVQ SI,80(SP) + MOVQ R8,88(SP) + MOVQ R9,96(SP) + MOVQ AX,104(SP) + MOVQ R10,112(SP) + MOVQ 0(SP),AX + MULQ 0(SP) + MOVQ AX,SI + MOVQ DX,CX + MOVQ 0(SP),AX + SHLQ $1,AX + MULQ 8(SP) + MOVQ AX,R8 + MOVQ DX,R9 + MOVQ 0(SP),AX + SHLQ $1,AX + MULQ 16(SP) + MOVQ AX,R10 + MOVQ DX,R11 + MOVQ 0(SP),AX + SHLQ $1,AX + MULQ 24(SP) + MOVQ AX,R12 + MOVQ DX,R13 + MOVQ 0(SP),AX + SHLQ $1,AX + MULQ 32(SP) + MOVQ AX,R14 + MOVQ DX,R15 + MOVQ 8(SP),AX + MULQ 8(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 8(SP),AX + SHLQ $1,AX + MULQ 16(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 8(SP),AX + SHLQ $1,AX + MULQ 24(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 8(SP),DX + IMUL3Q $38,DX,AX + MULQ 32(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 16(SP),AX + MULQ 16(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 16(SP),DX + IMUL3Q $38,DX,AX + MULQ 24(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 16(SP),DX + IMUL3Q $38,DX,AX + MULQ 32(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 24(SP),DX + IMUL3Q $19,DX,AX + MULQ 24(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 24(SP),DX + IMUL3Q $38,DX,AX + MULQ 32(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 32(SP),DX + IMUL3Q $19,DX,AX + MULQ 32(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ $REDMASK51,DX + SHLQ $13,CX:SI + ANDQ DX,SI + SHLQ $13,R9:R8 + ANDQ DX,R8 + ADDQ CX,R8 + SHLQ $13,R11:R10 + ANDQ DX,R10 + ADDQ R9,R10 + SHLQ $13,R13:R12 + ANDQ DX,R12 + ADDQ R11,R12 + SHLQ $13,R15:R14 + ANDQ DX,R14 + ADDQ R13,R14 + IMUL3Q $19,R15,CX + ADDQ CX,SI + MOVQ SI,CX + SHRQ $51,CX + ADDQ R8,CX + ANDQ DX,SI + MOVQ CX,R8 + SHRQ $51,CX + ADDQ R10,CX + ANDQ DX,R8 + MOVQ CX,R9 + SHRQ $51,CX + ADDQ R12,CX + ANDQ DX,R9 + MOVQ CX,AX + SHRQ $51,CX + ADDQ R14,CX + ANDQ DX,AX + MOVQ CX,R10 + SHRQ $51,CX + IMUL3Q $19,CX,CX + ADDQ CX,SI + ANDQ DX,R10 + MOVQ SI,120(SP) + MOVQ R8,128(SP) + MOVQ R9,136(SP) + MOVQ AX,144(SP) + MOVQ R10,152(SP) + MOVQ SI,SI + MOVQ R8,DX + MOVQ R9,CX + MOVQ AX,R8 + MOVQ R10,R9 + ADDQ ·_2P0(SB),SI + ADDQ ·_2P1234(SB),DX + ADDQ ·_2P1234(SB),CX + ADDQ ·_2P1234(SB),R8 + ADDQ ·_2P1234(SB),R9 + SUBQ 80(SP),SI + SUBQ 88(SP),DX + SUBQ 96(SP),CX + SUBQ 104(SP),R8 + SUBQ 112(SP),R9 + MOVQ SI,160(SP) + MOVQ DX,168(SP) + MOVQ CX,176(SP) + MOVQ R8,184(SP) + MOVQ R9,192(SP) + MOVQ 120(DI),SI + MOVQ 128(DI),DX + MOVQ 136(DI),CX + MOVQ 144(DI),R8 + MOVQ 152(DI),R9 + MOVQ SI,AX + MOVQ DX,R10 + MOVQ CX,R11 + MOVQ R8,R12 + MOVQ R9,R13 + ADDQ ·_2P0(SB),AX + ADDQ ·_2P1234(SB),R10 + ADDQ ·_2P1234(SB),R11 + ADDQ ·_2P1234(SB),R12 + ADDQ ·_2P1234(SB),R13 + ADDQ 160(DI),SI + ADDQ 168(DI),DX + ADDQ 176(DI),CX + ADDQ 184(DI),R8 + ADDQ 192(DI),R9 + SUBQ 160(DI),AX + SUBQ 168(DI),R10 + SUBQ 176(DI),R11 + SUBQ 184(DI),R12 + SUBQ 192(DI),R13 + MOVQ SI,200(SP) + MOVQ DX,208(SP) + MOVQ CX,216(SP) + MOVQ R8,224(SP) + MOVQ R9,232(SP) + MOVQ AX,240(SP) + MOVQ R10,248(SP) + MOVQ R11,256(SP) + MOVQ R12,264(SP) + MOVQ R13,272(SP) + MOVQ 224(SP),SI + IMUL3Q $19,SI,AX + MOVQ AX,280(SP) + MULQ 56(SP) + MOVQ AX,SI + MOVQ DX,CX + MOVQ 232(SP),DX + IMUL3Q $19,DX,AX + MOVQ AX,288(SP) + MULQ 48(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 200(SP),AX + MULQ 40(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 200(SP),AX + MULQ 48(SP) + MOVQ AX,R8 + MOVQ DX,R9 + MOVQ 200(SP),AX + MULQ 56(SP) + MOVQ AX,R10 + MOVQ DX,R11 + MOVQ 200(SP),AX + MULQ 64(SP) + MOVQ AX,R12 + MOVQ DX,R13 + MOVQ 200(SP),AX + MULQ 72(SP) + MOVQ AX,R14 + MOVQ DX,R15 + MOVQ 208(SP),AX + MULQ 40(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 208(SP),AX + MULQ 48(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 208(SP),AX + MULQ 56(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 208(SP),AX + MULQ 64(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 208(SP),DX + IMUL3Q $19,DX,AX + MULQ 72(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 216(SP),AX + MULQ 40(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 216(SP),AX + MULQ 48(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 216(SP),AX + MULQ 56(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 216(SP),DX + IMUL3Q $19,DX,AX + MULQ 64(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 216(SP),DX + IMUL3Q $19,DX,AX + MULQ 72(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 224(SP),AX + MULQ 40(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 224(SP),AX + MULQ 48(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 280(SP),AX + MULQ 64(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 280(SP),AX + MULQ 72(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 232(SP),AX + MULQ 40(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 288(SP),AX + MULQ 56(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 288(SP),AX + MULQ 64(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 288(SP),AX + MULQ 72(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ $REDMASK51,DX + SHLQ $13,CX:SI + ANDQ DX,SI + SHLQ $13,R9:R8 + ANDQ DX,R8 + ADDQ CX,R8 + SHLQ $13,R11:R10 + ANDQ DX,R10 + ADDQ R9,R10 + SHLQ $13,R13:R12 + ANDQ DX,R12 + ADDQ R11,R12 + SHLQ $13,R15:R14 + ANDQ DX,R14 + ADDQ R13,R14 + IMUL3Q $19,R15,CX + ADDQ CX,SI + MOVQ SI,CX + SHRQ $51,CX + ADDQ R8,CX + MOVQ CX,R8 + SHRQ $51,CX + ANDQ DX,SI + ADDQ R10,CX + MOVQ CX,R9 + SHRQ $51,CX + ANDQ DX,R8 + ADDQ R12,CX + MOVQ CX,AX + SHRQ $51,CX + ANDQ DX,R9 + ADDQ R14,CX + MOVQ CX,R10 + SHRQ $51,CX + ANDQ DX,AX + IMUL3Q $19,CX,CX + ADDQ CX,SI + ANDQ DX,R10 + MOVQ SI,40(SP) + MOVQ R8,48(SP) + MOVQ R9,56(SP) + MOVQ AX,64(SP) + MOVQ R10,72(SP) + MOVQ 264(SP),SI + IMUL3Q $19,SI,AX + MOVQ AX,200(SP) + MULQ 16(SP) + MOVQ AX,SI + MOVQ DX,CX + MOVQ 272(SP),DX + IMUL3Q $19,DX,AX + MOVQ AX,208(SP) + MULQ 8(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 240(SP),AX + MULQ 0(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 240(SP),AX + MULQ 8(SP) + MOVQ AX,R8 + MOVQ DX,R9 + MOVQ 240(SP),AX + MULQ 16(SP) + MOVQ AX,R10 + MOVQ DX,R11 + MOVQ 240(SP),AX + MULQ 24(SP) + MOVQ AX,R12 + MOVQ DX,R13 + MOVQ 240(SP),AX + MULQ 32(SP) + MOVQ AX,R14 + MOVQ DX,R15 + MOVQ 248(SP),AX + MULQ 0(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 248(SP),AX + MULQ 8(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 248(SP),AX + MULQ 16(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 248(SP),AX + MULQ 24(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 248(SP),DX + IMUL3Q $19,DX,AX + MULQ 32(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 256(SP),AX + MULQ 0(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 256(SP),AX + MULQ 8(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 256(SP),AX + MULQ 16(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 256(SP),DX + IMUL3Q $19,DX,AX + MULQ 24(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 256(SP),DX + IMUL3Q $19,DX,AX + MULQ 32(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 264(SP),AX + MULQ 0(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 264(SP),AX + MULQ 8(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 200(SP),AX + MULQ 24(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 200(SP),AX + MULQ 32(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 272(SP),AX + MULQ 0(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 208(SP),AX + MULQ 16(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 208(SP),AX + MULQ 24(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 208(SP),AX + MULQ 32(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ $REDMASK51,DX + SHLQ $13,CX:SI + ANDQ DX,SI + SHLQ $13,R9:R8 + ANDQ DX,R8 + ADDQ CX,R8 + SHLQ $13,R11:R10 + ANDQ DX,R10 + ADDQ R9,R10 + SHLQ $13,R13:R12 + ANDQ DX,R12 + ADDQ R11,R12 + SHLQ $13,R15:R14 + ANDQ DX,R14 + ADDQ R13,R14 + IMUL3Q $19,R15,CX + ADDQ CX,SI + MOVQ SI,CX + SHRQ $51,CX + ADDQ R8,CX + MOVQ CX,R8 + SHRQ $51,CX + ANDQ DX,SI + ADDQ R10,CX + MOVQ CX,R9 + SHRQ $51,CX + ANDQ DX,R8 + ADDQ R12,CX + MOVQ CX,AX + SHRQ $51,CX + ANDQ DX,R9 + ADDQ R14,CX + MOVQ CX,R10 + SHRQ $51,CX + ANDQ DX,AX + IMUL3Q $19,CX,CX + ADDQ CX,SI + ANDQ DX,R10 + MOVQ SI,DX + MOVQ R8,CX + MOVQ R9,R11 + MOVQ AX,R12 + MOVQ R10,R13 + ADDQ ·_2P0(SB),DX + ADDQ ·_2P1234(SB),CX + ADDQ ·_2P1234(SB),R11 + ADDQ ·_2P1234(SB),R12 + ADDQ ·_2P1234(SB),R13 + ADDQ 40(SP),SI + ADDQ 48(SP),R8 + ADDQ 56(SP),R9 + ADDQ 64(SP),AX + ADDQ 72(SP),R10 + SUBQ 40(SP),DX + SUBQ 48(SP),CX + SUBQ 56(SP),R11 + SUBQ 64(SP),R12 + SUBQ 72(SP),R13 + MOVQ SI,120(DI) + MOVQ R8,128(DI) + MOVQ R9,136(DI) + MOVQ AX,144(DI) + MOVQ R10,152(DI) + MOVQ DX,160(DI) + MOVQ CX,168(DI) + MOVQ R11,176(DI) + MOVQ R12,184(DI) + MOVQ R13,192(DI) + MOVQ 120(DI),AX + MULQ 120(DI) + MOVQ AX,SI + MOVQ DX,CX + MOVQ 120(DI),AX + SHLQ $1,AX + MULQ 128(DI) + MOVQ AX,R8 + MOVQ DX,R9 + MOVQ 120(DI),AX + SHLQ $1,AX + MULQ 136(DI) + MOVQ AX,R10 + MOVQ DX,R11 + MOVQ 120(DI),AX + SHLQ $1,AX + MULQ 144(DI) + MOVQ AX,R12 + MOVQ DX,R13 + MOVQ 120(DI),AX + SHLQ $1,AX + MULQ 152(DI) + MOVQ AX,R14 + MOVQ DX,R15 + MOVQ 128(DI),AX + MULQ 128(DI) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 128(DI),AX + SHLQ $1,AX + MULQ 136(DI) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 128(DI),AX + SHLQ $1,AX + MULQ 144(DI) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 128(DI),DX + IMUL3Q $38,DX,AX + MULQ 152(DI) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 136(DI),AX + MULQ 136(DI) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 136(DI),DX + IMUL3Q $38,DX,AX + MULQ 144(DI) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 136(DI),DX + IMUL3Q $38,DX,AX + MULQ 152(DI) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 144(DI),DX + IMUL3Q $19,DX,AX + MULQ 144(DI) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 144(DI),DX + IMUL3Q $38,DX,AX + MULQ 152(DI) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 152(DI),DX + IMUL3Q $19,DX,AX + MULQ 152(DI) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ $REDMASK51,DX + SHLQ $13,CX:SI + ANDQ DX,SI + SHLQ $13,R9:R8 + ANDQ DX,R8 + ADDQ CX,R8 + SHLQ $13,R11:R10 + ANDQ DX,R10 + ADDQ R9,R10 + SHLQ $13,R13:R12 + ANDQ DX,R12 + ADDQ R11,R12 + SHLQ $13,R15:R14 + ANDQ DX,R14 + ADDQ R13,R14 + IMUL3Q $19,R15,CX + ADDQ CX,SI + MOVQ SI,CX + SHRQ $51,CX + ADDQ R8,CX + ANDQ DX,SI + MOVQ CX,R8 + SHRQ $51,CX + ADDQ R10,CX + ANDQ DX,R8 + MOVQ CX,R9 + SHRQ $51,CX + ADDQ R12,CX + ANDQ DX,R9 + MOVQ CX,AX + SHRQ $51,CX + ADDQ R14,CX + ANDQ DX,AX + MOVQ CX,R10 + SHRQ $51,CX + IMUL3Q $19,CX,CX + ADDQ CX,SI + ANDQ DX,R10 + MOVQ SI,120(DI) + MOVQ R8,128(DI) + MOVQ R9,136(DI) + MOVQ AX,144(DI) + MOVQ R10,152(DI) + MOVQ 160(DI),AX + MULQ 160(DI) + MOVQ AX,SI + MOVQ DX,CX + MOVQ 160(DI),AX + SHLQ $1,AX + MULQ 168(DI) + MOVQ AX,R8 + MOVQ DX,R9 + MOVQ 160(DI),AX + SHLQ $1,AX + MULQ 176(DI) + MOVQ AX,R10 + MOVQ DX,R11 + MOVQ 160(DI),AX + SHLQ $1,AX + MULQ 184(DI) + MOVQ AX,R12 + MOVQ DX,R13 + MOVQ 160(DI),AX + SHLQ $1,AX + MULQ 192(DI) + MOVQ AX,R14 + MOVQ DX,R15 + MOVQ 168(DI),AX + MULQ 168(DI) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 168(DI),AX + SHLQ $1,AX + MULQ 176(DI) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 168(DI),AX + SHLQ $1,AX + MULQ 184(DI) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 168(DI),DX + IMUL3Q $38,DX,AX + MULQ 192(DI) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 176(DI),AX + MULQ 176(DI) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 176(DI),DX + IMUL3Q $38,DX,AX + MULQ 184(DI) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 176(DI),DX + IMUL3Q $38,DX,AX + MULQ 192(DI) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 184(DI),DX + IMUL3Q $19,DX,AX + MULQ 184(DI) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 184(DI),DX + IMUL3Q $38,DX,AX + MULQ 192(DI) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 192(DI),DX + IMUL3Q $19,DX,AX + MULQ 192(DI) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ $REDMASK51,DX + SHLQ $13,CX:SI + ANDQ DX,SI + SHLQ $13,R9:R8 + ANDQ DX,R8 + ADDQ CX,R8 + SHLQ $13,R11:R10 + ANDQ DX,R10 + ADDQ R9,R10 + SHLQ $13,R13:R12 + ANDQ DX,R12 + ADDQ R11,R12 + SHLQ $13,R15:R14 + ANDQ DX,R14 + ADDQ R13,R14 + IMUL3Q $19,R15,CX + ADDQ CX,SI + MOVQ SI,CX + SHRQ $51,CX + ADDQ R8,CX + ANDQ DX,SI + MOVQ CX,R8 + SHRQ $51,CX + ADDQ R10,CX + ANDQ DX,R8 + MOVQ CX,R9 + SHRQ $51,CX + ADDQ R12,CX + ANDQ DX,R9 + MOVQ CX,AX + SHRQ $51,CX + ADDQ R14,CX + ANDQ DX,AX + MOVQ CX,R10 + SHRQ $51,CX + IMUL3Q $19,CX,CX + ADDQ CX,SI + ANDQ DX,R10 + MOVQ SI,160(DI) + MOVQ R8,168(DI) + MOVQ R9,176(DI) + MOVQ AX,184(DI) + MOVQ R10,192(DI) + MOVQ 184(DI),SI + IMUL3Q $19,SI,AX + MOVQ AX,0(SP) + MULQ 16(DI) + MOVQ AX,SI + MOVQ DX,CX + MOVQ 192(DI),DX + IMUL3Q $19,DX,AX + MOVQ AX,8(SP) + MULQ 8(DI) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 160(DI),AX + MULQ 0(DI) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 160(DI),AX + MULQ 8(DI) + MOVQ AX,R8 + MOVQ DX,R9 + MOVQ 160(DI),AX + MULQ 16(DI) + MOVQ AX,R10 + MOVQ DX,R11 + MOVQ 160(DI),AX + MULQ 24(DI) + MOVQ AX,R12 + MOVQ DX,R13 + MOVQ 160(DI),AX + MULQ 32(DI) + MOVQ AX,R14 + MOVQ DX,R15 + MOVQ 168(DI),AX + MULQ 0(DI) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 168(DI),AX + MULQ 8(DI) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 168(DI),AX + MULQ 16(DI) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 168(DI),AX + MULQ 24(DI) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 168(DI),DX + IMUL3Q $19,DX,AX + MULQ 32(DI) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 176(DI),AX + MULQ 0(DI) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 176(DI),AX + MULQ 8(DI) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 176(DI),AX + MULQ 16(DI) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 176(DI),DX + IMUL3Q $19,DX,AX + MULQ 24(DI) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 176(DI),DX + IMUL3Q $19,DX,AX + MULQ 32(DI) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 184(DI),AX + MULQ 0(DI) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 184(DI),AX + MULQ 8(DI) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 0(SP),AX + MULQ 24(DI) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 0(SP),AX + MULQ 32(DI) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 192(DI),AX + MULQ 0(DI) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 8(SP),AX + MULQ 16(DI) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 8(SP),AX + MULQ 24(DI) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 8(SP),AX + MULQ 32(DI) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ $REDMASK51,DX + SHLQ $13,CX:SI + ANDQ DX,SI + SHLQ $13,R9:R8 + ANDQ DX,R8 + ADDQ CX,R8 + SHLQ $13,R11:R10 + ANDQ DX,R10 + ADDQ R9,R10 + SHLQ $13,R13:R12 + ANDQ DX,R12 + ADDQ R11,R12 + SHLQ $13,R15:R14 + ANDQ DX,R14 + ADDQ R13,R14 + IMUL3Q $19,R15,CX + ADDQ CX,SI + MOVQ SI,CX + SHRQ $51,CX + ADDQ R8,CX + MOVQ CX,R8 + SHRQ $51,CX + ANDQ DX,SI + ADDQ R10,CX + MOVQ CX,R9 + SHRQ $51,CX + ANDQ DX,R8 + ADDQ R12,CX + MOVQ CX,AX + SHRQ $51,CX + ANDQ DX,R9 + ADDQ R14,CX + MOVQ CX,R10 + SHRQ $51,CX + ANDQ DX,AX + IMUL3Q $19,CX,CX + ADDQ CX,SI + ANDQ DX,R10 + MOVQ SI,160(DI) + MOVQ R8,168(DI) + MOVQ R9,176(DI) + MOVQ AX,184(DI) + MOVQ R10,192(DI) + MOVQ 144(SP),SI + IMUL3Q $19,SI,AX + MOVQ AX,0(SP) + MULQ 96(SP) + MOVQ AX,SI + MOVQ DX,CX + MOVQ 152(SP),DX + IMUL3Q $19,DX,AX + MOVQ AX,8(SP) + MULQ 88(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 120(SP),AX + MULQ 80(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 120(SP),AX + MULQ 88(SP) + MOVQ AX,R8 + MOVQ DX,R9 + MOVQ 120(SP),AX + MULQ 96(SP) + MOVQ AX,R10 + MOVQ DX,R11 + MOVQ 120(SP),AX + MULQ 104(SP) + MOVQ AX,R12 + MOVQ DX,R13 + MOVQ 120(SP),AX + MULQ 112(SP) + MOVQ AX,R14 + MOVQ DX,R15 + MOVQ 128(SP),AX + MULQ 80(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 128(SP),AX + MULQ 88(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 128(SP),AX + MULQ 96(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 128(SP),AX + MULQ 104(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 128(SP),DX + IMUL3Q $19,DX,AX + MULQ 112(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 136(SP),AX + MULQ 80(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 136(SP),AX + MULQ 88(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 136(SP),AX + MULQ 96(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 136(SP),DX + IMUL3Q $19,DX,AX + MULQ 104(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 136(SP),DX + IMUL3Q $19,DX,AX + MULQ 112(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 144(SP),AX + MULQ 80(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 144(SP),AX + MULQ 88(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 0(SP),AX + MULQ 104(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 0(SP),AX + MULQ 112(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 152(SP),AX + MULQ 80(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 8(SP),AX + MULQ 96(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 8(SP),AX + MULQ 104(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 8(SP),AX + MULQ 112(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ $REDMASK51,DX + SHLQ $13,CX:SI + ANDQ DX,SI + SHLQ $13,R9:R8 + ANDQ DX,R8 + ADDQ CX,R8 + SHLQ $13,R11:R10 + ANDQ DX,R10 + ADDQ R9,R10 + SHLQ $13,R13:R12 + ANDQ DX,R12 + ADDQ R11,R12 + SHLQ $13,R15:R14 + ANDQ DX,R14 + ADDQ R13,R14 + IMUL3Q $19,R15,CX + ADDQ CX,SI + MOVQ SI,CX + SHRQ $51,CX + ADDQ R8,CX + MOVQ CX,R8 + SHRQ $51,CX + ANDQ DX,SI + ADDQ R10,CX + MOVQ CX,R9 + SHRQ $51,CX + ANDQ DX,R8 + ADDQ R12,CX + MOVQ CX,AX + SHRQ $51,CX + ANDQ DX,R9 + ADDQ R14,CX + MOVQ CX,R10 + SHRQ $51,CX + ANDQ DX,AX + IMUL3Q $19,CX,CX + ADDQ CX,SI + ANDQ DX,R10 + MOVQ SI,40(DI) + MOVQ R8,48(DI) + MOVQ R9,56(DI) + MOVQ AX,64(DI) + MOVQ R10,72(DI) + MOVQ 160(SP),AX + MULQ ·_121666_213(SB) + SHRQ $13,AX + MOVQ AX,SI + MOVQ DX,CX + MOVQ 168(SP),AX + MULQ ·_121666_213(SB) + SHRQ $13,AX + ADDQ AX,CX + MOVQ DX,R8 + MOVQ 176(SP),AX + MULQ ·_121666_213(SB) + SHRQ $13,AX + ADDQ AX,R8 + MOVQ DX,R9 + MOVQ 184(SP),AX + MULQ ·_121666_213(SB) + SHRQ $13,AX + ADDQ AX,R9 + MOVQ DX,R10 + MOVQ 192(SP),AX + MULQ ·_121666_213(SB) + SHRQ $13,AX + ADDQ AX,R10 + IMUL3Q $19,DX,DX + ADDQ DX,SI + ADDQ 80(SP),SI + ADDQ 88(SP),CX + ADDQ 96(SP),R8 + ADDQ 104(SP),R9 + ADDQ 112(SP),R10 + MOVQ SI,80(DI) + MOVQ CX,88(DI) + MOVQ R8,96(DI) + MOVQ R9,104(DI) + MOVQ R10,112(DI) + MOVQ 104(DI),SI + IMUL3Q $19,SI,AX + MOVQ AX,0(SP) + MULQ 176(SP) + MOVQ AX,SI + MOVQ DX,CX + MOVQ 112(DI),DX + IMUL3Q $19,DX,AX + MOVQ AX,8(SP) + MULQ 168(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 80(DI),AX + MULQ 160(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 80(DI),AX + MULQ 168(SP) + MOVQ AX,R8 + MOVQ DX,R9 + MOVQ 80(DI),AX + MULQ 176(SP) + MOVQ AX,R10 + MOVQ DX,R11 + MOVQ 80(DI),AX + MULQ 184(SP) + MOVQ AX,R12 + MOVQ DX,R13 + MOVQ 80(DI),AX + MULQ 192(SP) + MOVQ AX,R14 + MOVQ DX,R15 + MOVQ 88(DI),AX + MULQ 160(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 88(DI),AX + MULQ 168(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 88(DI),AX + MULQ 176(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 88(DI),AX + MULQ 184(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 88(DI),DX + IMUL3Q $19,DX,AX + MULQ 192(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 96(DI),AX + MULQ 160(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 96(DI),AX + MULQ 168(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 96(DI),AX + MULQ 176(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 96(DI),DX + IMUL3Q $19,DX,AX + MULQ 184(SP) + ADDQ AX,SI + ADCQ DX,CX + MOVQ 96(DI),DX + IMUL3Q $19,DX,AX + MULQ 192(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 104(DI),AX + MULQ 160(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 104(DI),AX + MULQ 168(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 0(SP),AX + MULQ 184(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 0(SP),AX + MULQ 192(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 112(DI),AX + MULQ 160(SP) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ 8(SP),AX + MULQ 176(SP) + ADDQ AX,R8 + ADCQ DX,R9 + MOVQ 8(SP),AX + MULQ 184(SP) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 8(SP),AX + MULQ 192(SP) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ $REDMASK51,DX + SHLQ $13,CX:SI + ANDQ DX,SI + SHLQ $13,R9:R8 + ANDQ DX,R8 + ADDQ CX,R8 + SHLQ $13,R11:R10 + ANDQ DX,R10 + ADDQ R9,R10 + SHLQ $13,R13:R12 + ANDQ DX,R12 + ADDQ R11,R12 + SHLQ $13,R15:R14 + ANDQ DX,R14 + ADDQ R13,R14 + IMUL3Q $19,R15,CX + ADDQ CX,SI + MOVQ SI,CX + SHRQ $51,CX + ADDQ R8,CX + MOVQ CX,R8 + SHRQ $51,CX + ANDQ DX,SI + ADDQ R10,CX + MOVQ CX,R9 + SHRQ $51,CX + ANDQ DX,R8 + ADDQ R12,CX + MOVQ CX,AX + SHRQ $51,CX + ANDQ DX,R9 + ADDQ R14,CX + MOVQ CX,R10 + SHRQ $51,CX + ANDQ DX,AX + IMUL3Q $19,CX,CX + ADDQ CX,SI + ANDQ DX,R10 + MOVQ SI,80(DI) + MOVQ R8,88(DI) + MOVQ R9,96(DI) + MOVQ AX,104(DI) + MOVQ R10,112(DI) + RET diff --git a/vendor/golang.org/x/crypto/curve25519/mont25519_amd64.go b/vendor/golang.org/x/crypto/curve25519/mont25519_amd64.go new file mode 100644 index 0000000000000000000000000000000000000000..5822bd53383495f484075e14cdc5c18dc658101a --- /dev/null +++ b/vendor/golang.org/x/crypto/curve25519/mont25519_amd64.go @@ -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,!appengine + +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 */ +} diff --git a/vendor/golang.org/x/crypto/curve25519/mul_amd64.s b/vendor/golang.org/x/crypto/curve25519/mul_amd64.s new file mode 100644 index 0000000000000000000000000000000000000000..5ce80a2e56b975ca0297dfd3cfae522b15f4c1b9 --- /dev/null +++ b/vendor/golang.org/x/crypto/curve25519/mul_amd64.s @@ -0,0 +1,169 @@ +// 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: https://bench.cr.yp.to/supercop.html + +// +build amd64,!gccgo,!appengine + +#include "const_amd64.h" + +// func mul(dest, a, b *[5]uint64) +TEXT ·mul(SB),0,$16-24 + MOVQ dest+0(FP), DI + MOVQ a+8(FP), SI + MOVQ b+16(FP), DX + + MOVQ DX,CX + MOVQ 24(SI),DX + IMUL3Q $19,DX,AX + MOVQ AX,0(SP) + MULQ 16(CX) + MOVQ AX,R8 + MOVQ DX,R9 + MOVQ 32(SI),DX + IMUL3Q $19,DX,AX + MOVQ AX,8(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 0(SP),AX + MULQ 24(CX) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 0(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 8(SP),AX + MULQ 16(CX) + ADDQ AX,R10 + ADCQ DX,R11 + MOVQ 8(SP),AX + MULQ 24(CX) + ADDQ AX,R12 + ADCQ DX,R13 + MOVQ 8(SP),AX + MULQ 32(CX) + ADDQ AX,R14 + ADCQ DX,R15 + MOVQ $REDMASK51,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) + RET diff --git a/vendor/golang.org/x/crypto/curve25519/square_amd64.s b/vendor/golang.org/x/crypto/curve25519/square_amd64.s new file mode 100644 index 0000000000000000000000000000000000000000..12f73734ff5aede956c2098faf473b862c72afe5 --- /dev/null +++ b/vendor/golang.org/x/crypto/curve25519/square_amd64.s @@ -0,0 +1,132 @@ +// 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: https://bench.cr.yp.to/supercop.html + +// +build amd64,!gccgo,!appengine + +#include "const_amd64.h" + +// func square(out, in *[5]uint64) +TEXT ·square(SB),7,$0-16 + MOVQ out+0(FP), DI + MOVQ in+8(FP), SI + + 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,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) + RET diff --git a/vendor/golang.org/x/crypto/ed25519/ed25519.go b/vendor/golang.org/x/crypto/ed25519/ed25519.go new file mode 100644 index 0000000000000000000000000000000000000000..4f26b49b6a872c50d55eaae07368024c0b8f50bc --- /dev/null +++ b/vendor/golang.org/x/crypto/ed25519/ed25519.go @@ -0,0 +1,181 @@ +// Copyright 2016 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 ed25519 implements the Ed25519 signature algorithm. See +// https://ed25519.cr.yp.to/. +// +// These functions are also compatible with the “Ed25519†function defined in +// RFC 8032. +package ed25519 + +// This code is a port of the public domain, “ref10†implementation of ed25519 +// from SUPERCOP. + +import ( + "bytes" + "crypto" + cryptorand "crypto/rand" + "crypto/sha512" + "errors" + "io" + "strconv" + + "golang.org/x/crypto/ed25519/internal/edwards25519" +) + +const ( + // PublicKeySize is the size, in bytes, of public keys as used in this package. + PublicKeySize = 32 + // PrivateKeySize is the size, in bytes, of private keys as used in this package. + PrivateKeySize = 64 + // SignatureSize is the size, in bytes, of signatures generated and verified by this package. + SignatureSize = 64 +) + +// PublicKey is the type of Ed25519 public keys. +type PublicKey []byte + +// PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer. +type PrivateKey []byte + +// Public returns the PublicKey corresponding to priv. +func (priv PrivateKey) Public() crypto.PublicKey { + publicKey := make([]byte, PublicKeySize) + copy(publicKey, priv[32:]) + return PublicKey(publicKey) +} + +// Sign signs the given message with priv. +// Ed25519 performs two passes over messages to be signed and therefore cannot +// handle pre-hashed messages. Thus opts.HashFunc() must return zero to +// indicate the message hasn't been hashed. This can be achieved by passing +// crypto.Hash(0) as the value for opts. +func (priv PrivateKey) Sign(rand io.Reader, message []byte, opts crypto.SignerOpts) (signature []byte, err error) { + if opts.HashFunc() != crypto.Hash(0) { + return nil, errors.New("ed25519: cannot sign hashed message") + } + + return Sign(priv, message), nil +} + +// GenerateKey generates a public/private key pair using entropy from rand. +// If rand is nil, crypto/rand.Reader will be used. +func GenerateKey(rand io.Reader) (publicKey PublicKey, privateKey PrivateKey, err error) { + if rand == nil { + rand = cryptorand.Reader + } + + privateKey = make([]byte, PrivateKeySize) + publicKey = make([]byte, PublicKeySize) + _, err = io.ReadFull(rand, privateKey[:32]) + if err != nil { + return nil, nil, err + } + + digest := sha512.Sum512(privateKey[:32]) + digest[0] &= 248 + digest[31] &= 127 + digest[31] |= 64 + + var A edwards25519.ExtendedGroupElement + var hBytes [32]byte + copy(hBytes[:], digest[:]) + edwards25519.GeScalarMultBase(&A, &hBytes) + var publicKeyBytes [32]byte + A.ToBytes(&publicKeyBytes) + + copy(privateKey[32:], publicKeyBytes[:]) + copy(publicKey, publicKeyBytes[:]) + + return publicKey, privateKey, nil +} + +// Sign signs the message with privateKey and returns a signature. It will +// panic if len(privateKey) is not PrivateKeySize. +func Sign(privateKey PrivateKey, message []byte) []byte { + if l := len(privateKey); l != PrivateKeySize { + panic("ed25519: bad private key length: " + strconv.Itoa(l)) + } + + h := sha512.New() + h.Write(privateKey[:32]) + + var digest1, messageDigest, hramDigest [64]byte + var expandedSecretKey [32]byte + h.Sum(digest1[:0]) + copy(expandedSecretKey[:], digest1[:]) + expandedSecretKey[0] &= 248 + expandedSecretKey[31] &= 63 + expandedSecretKey[31] |= 64 + + h.Reset() + h.Write(digest1[32:]) + h.Write(message) + h.Sum(messageDigest[:0]) + + var messageDigestReduced [32]byte + edwards25519.ScReduce(&messageDigestReduced, &messageDigest) + var R edwards25519.ExtendedGroupElement + edwards25519.GeScalarMultBase(&R, &messageDigestReduced) + + var encodedR [32]byte + R.ToBytes(&encodedR) + + h.Reset() + h.Write(encodedR[:]) + h.Write(privateKey[32:]) + h.Write(message) + h.Sum(hramDigest[:0]) + var hramDigestReduced [32]byte + edwards25519.ScReduce(&hramDigestReduced, &hramDigest) + + var s [32]byte + edwards25519.ScMulAdd(&s, &hramDigestReduced, &expandedSecretKey, &messageDigestReduced) + + signature := make([]byte, SignatureSize) + copy(signature[:], encodedR[:]) + copy(signature[32:], s[:]) + + return signature +} + +// Verify reports whether sig is a valid signature of message by publicKey. It +// will panic if len(publicKey) is not PublicKeySize. +func Verify(publicKey PublicKey, message, sig []byte) bool { + if l := len(publicKey); l != PublicKeySize { + panic("ed25519: bad public key length: " + strconv.Itoa(l)) + } + + if len(sig) != SignatureSize || sig[63]&224 != 0 { + return false + } + + var A edwards25519.ExtendedGroupElement + var publicKeyBytes [32]byte + copy(publicKeyBytes[:], publicKey) + if !A.FromBytes(&publicKeyBytes) { + return false + } + edwards25519.FeNeg(&A.X, &A.X) + edwards25519.FeNeg(&A.T, &A.T) + + h := sha512.New() + h.Write(sig[:32]) + h.Write(publicKey[:]) + h.Write(message) + var digest [64]byte + h.Sum(digest[:0]) + + var hReduced [32]byte + edwards25519.ScReduce(&hReduced, &digest) + + var R edwards25519.ProjectiveGroupElement + var b [32]byte + copy(b[:], sig[32:]) + edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &b) + + var checkR [32]byte + R.ToBytes(&checkR) + return bytes.Equal(sig[:32], checkR[:]) +} diff --git a/vendor/golang.org/x/crypto/ed25519/ed25519_test.go b/vendor/golang.org/x/crypto/ed25519/ed25519_test.go new file mode 100644 index 0000000000000000000000000000000000000000..e272f8a557f9a8546ef3cecd12cb5f8d2d010e6a --- /dev/null +++ b/vendor/golang.org/x/crypto/ed25519/ed25519_test.go @@ -0,0 +1,183 @@ +// Copyright 2016 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 ed25519 + +import ( + "bufio" + "bytes" + "compress/gzip" + "crypto" + "crypto/rand" + "encoding/hex" + "os" + "strings" + "testing" + + "golang.org/x/crypto/ed25519/internal/edwards25519" +) + +type zeroReader struct{} + +func (zeroReader) Read(buf []byte) (int, error) { + for i := range buf { + buf[i] = 0 + } + return len(buf), nil +} + +func TestUnmarshalMarshal(t *testing.T) { + pub, _, _ := GenerateKey(rand.Reader) + + var A edwards25519.ExtendedGroupElement + var pubBytes [32]byte + copy(pubBytes[:], pub) + if !A.FromBytes(&pubBytes) { + t.Fatalf("ExtendedGroupElement.FromBytes failed") + } + + var pub2 [32]byte + A.ToBytes(&pub2) + + if pubBytes != pub2 { + t.Errorf("FromBytes(%v)->ToBytes does not round-trip, got %x\n", pubBytes, pub2) + } +} + +func TestSignVerify(t *testing.T) { + var zero zeroReader + public, private, _ := GenerateKey(zero) + + message := []byte("test message") + sig := Sign(private, message) + if !Verify(public, message, sig) { + t.Errorf("valid signature rejected") + } + + wrongMessage := []byte("wrong message") + if Verify(public, wrongMessage, sig) { + t.Errorf("signature of different message accepted") + } +} + +func TestCryptoSigner(t *testing.T) { + var zero zeroReader + public, private, _ := GenerateKey(zero) + + signer := crypto.Signer(private) + + publicInterface := signer.Public() + public2, ok := publicInterface.(PublicKey) + if !ok { + t.Fatalf("expected PublicKey from Public() but got %T", publicInterface) + } + + if !bytes.Equal(public, public2) { + t.Errorf("public keys do not match: original:%x vs Public():%x", public, public2) + } + + message := []byte("message") + var noHash crypto.Hash + signature, err := signer.Sign(zero, message, noHash) + if err != nil { + t.Fatalf("error from Sign(): %s", err) + } + + if !Verify(public, message, signature) { + t.Errorf("Verify failed on signature from Sign()") + } +} + +func TestGolden(t *testing.T) { + // sign.input.gz is a selection of test cases from + // https://ed25519.cr.yp.to/python/sign.input + testDataZ, err := os.Open("testdata/sign.input.gz") + if err != nil { + t.Fatal(err) + } + defer testDataZ.Close() + testData, err := gzip.NewReader(testDataZ) + if err != nil { + t.Fatal(err) + } + defer testData.Close() + + scanner := bufio.NewScanner(testData) + lineNo := 0 + + for scanner.Scan() { + lineNo++ + + line := scanner.Text() + parts := strings.Split(line, ":") + if len(parts) != 5 { + t.Fatalf("bad number of parts on line %d", lineNo) + } + + privBytes, _ := hex.DecodeString(parts[0]) + pubKey, _ := hex.DecodeString(parts[1]) + msg, _ := hex.DecodeString(parts[2]) + sig, _ := hex.DecodeString(parts[3]) + // The signatures in the test vectors also include the message + // at the end, but we just want R and S. + sig = sig[:SignatureSize] + + if l := len(pubKey); l != PublicKeySize { + t.Fatalf("bad public key length on line %d: got %d bytes", lineNo, l) + } + + var priv [PrivateKeySize]byte + copy(priv[:], privBytes) + copy(priv[32:], pubKey) + + sig2 := Sign(priv[:], msg) + if !bytes.Equal(sig, sig2[:]) { + t.Errorf("different signature result on line %d: %x vs %x", lineNo, sig, sig2) + } + + if !Verify(pubKey, msg, sig2) { + t.Errorf("signature failed to verify on line %d", lineNo) + } + } + + if err := scanner.Err(); err != nil { + t.Fatalf("error reading test data: %s", err) + } +} + +func BenchmarkKeyGeneration(b *testing.B) { + var zero zeroReader + for i := 0; i < b.N; i++ { + if _, _, err := GenerateKey(zero); err != nil { + b.Fatal(err) + } + } +} + +func BenchmarkSigning(b *testing.B) { + var zero zeroReader + _, priv, err := GenerateKey(zero) + if err != nil { + b.Fatal(err) + } + message := []byte("Hello, world!") + b.ResetTimer() + for i := 0; i < b.N; i++ { + Sign(priv, message) + } +} + +func BenchmarkVerification(b *testing.B) { + var zero zeroReader + pub, priv, err := GenerateKey(zero) + if err != nil { + b.Fatal(err) + } + message := []byte("Hello, world!") + signature := Sign(priv, message) + b.ResetTimer() + for i := 0; i < b.N; i++ { + Verify(pub, message, signature) + } +} diff --git a/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/const.go b/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/const.go new file mode 100644 index 0000000000000000000000000000000000000000..e39f086c1d87dbedcb0cd0ccb4d302bae2c04dbc --- /dev/null +++ b/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/const.go @@ -0,0 +1,1422 @@ +// Copyright 2016 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 edwards25519 + +// These values are from the public domain, “ref10†implementation of ed25519 +// from SUPERCOP. + +// d is a constant in the Edwards curve equation. +var d = FieldElement{ + -10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116, +} + +// d2 is 2*d. +var d2 = FieldElement{ + -21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199, +} + +// SqrtM1 is the square-root of -1 in the field. +var SqrtM1 = FieldElement{ + -32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482, +} + +// A is a constant in the Montgomery-form of curve25519. +var A = FieldElement{ + 486662, 0, 0, 0, 0, 0, 0, 0, 0, 0, +} + +// bi contains precomputed multiples of the base-point. See the Ed25519 paper +// for a discussion about how these values are used. +var bi = [8]PreComputedGroupElement{ + { + FieldElement{25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605}, + FieldElement{-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378}, + FieldElement{-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546}, + }, + { + FieldElement{15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024}, + FieldElement{16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574}, + FieldElement{30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357}, + }, + { + FieldElement{10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380}, + FieldElement{4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306}, + FieldElement{19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942}, + }, + { + FieldElement{5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766}, + FieldElement{-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701}, + FieldElement{28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300}, + }, + { + FieldElement{-22518993, -6692182, 14201702, -8745502, -23510406, 8844726, 18474211, -1361450, -13062696, 13821877}, + FieldElement{-6455177, -7839871, 3374702, -4740862, -27098617, -10571707, 31655028, -7212327, 18853322, -14220951}, + FieldElement{4566830, -12963868, -28974889, -12240689, -7602672, -2830569, -8514358, -10431137, 2207753, -3209784}, + }, + { + FieldElement{-25154831, -4185821, 29681144, 7868801, -6854661, -9423865, -12437364, -663000, -31111463, -16132436}, + FieldElement{25576264, -2703214, 7349804, -11814844, 16472782, 9300885, 3844789, 15725684, 171356, 6466918}, + FieldElement{23103977, 13316479, 9739013, -16149481, 817875, -15038942, 8965339, -14088058, -30714912, 16193877}, + }, + { + FieldElement{-33521811, 3180713, -2394130, 14003687, -16903474, -16270840, 17238398, 4729455, -18074513, 9256800}, + FieldElement{-25182317, -4174131, 32336398, 5036987, -21236817, 11360617, 22616405, 9761698, -19827198, 630305}, + FieldElement{-13720693, 2639453, -24237460, -7406481, 9494427, -5774029, -6554551, -15960994, -2449256, -14291300}, + }, + { + FieldElement{-3151181, -5046075, 9282714, 6866145, -31907062, -863023, -18940575, 15033784, 25105118, -7894876}, + FieldElement{-24326370, 15950226, -31801215, -14592823, -11662737, -5090925, 1573892, -2625887, 2198790, -15804619}, + FieldElement{-3099351, 10324967, -2241613, 7453183, -5446979, -2735503, -13812022, -16236442, -32461234, -12290683}, + }, +} + +// base contains precomputed multiples of the base-point. See the Ed25519 paper +// for a discussion about how these values are used. +var base = [32][8]PreComputedGroupElement{ + { + { + FieldElement{25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605}, + FieldElement{-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378}, + FieldElement{-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546}, + }, + { + FieldElement{-12815894, -12976347, -21581243, 11784320, -25355658, -2750717, -11717903, -3814571, -358445, -10211303}, + FieldElement{-21703237, 6903825, 27185491, 6451973, -29577724, -9554005, -15616551, 11189268, -26829678, -5319081}, + FieldElement{26966642, 11152617, 32442495, 15396054, 14353839, -12752335, -3128826, -9541118, -15472047, -4166697}, + }, + { + FieldElement{15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024}, + FieldElement{16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574}, + FieldElement{30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357}, + }, + { + FieldElement{-17036878, 13921892, 10945806, -6033431, 27105052, -16084379, -28926210, 15006023, 3284568, -6276540}, + FieldElement{23599295, -8306047, -11193664, -7687416, 13236774, 10506355, 7464579, 9656445, 13059162, 10374397}, + FieldElement{7798556, 16710257, 3033922, 2874086, 28997861, 2835604, 32406664, -3839045, -641708, -101325}, + }, + { + FieldElement{10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380}, + FieldElement{4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306}, + FieldElement{19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942}, + }, + { + FieldElement{-15371964, -12862754, 32573250, 4720197, -26436522, 5875511, -19188627, -15224819, -9818940, -12085777}, + FieldElement{-8549212, 109983, 15149363, 2178705, 22900618, 4543417, 3044240, -15689887, 1762328, 14866737}, + FieldElement{-18199695, -15951423, -10473290, 1707278, -17185920, 3916101, -28236412, 3959421, 27914454, 4383652}, + }, + { + FieldElement{5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766}, + FieldElement{-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701}, + FieldElement{28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300}, + }, + { + FieldElement{14499471, -2729599, -33191113, -4254652, 28494862, 14271267, 30290735, 10876454, -33154098, 2381726}, + FieldElement{-7195431, -2655363, -14730155, 462251, -27724326, 3941372, -6236617, 3696005, -32300832, 15351955}, + FieldElement{27431194, 8222322, 16448760, -3907995, -18707002, 11938355, -32961401, -2970515, 29551813, 10109425}, + }, + }, + { + { + FieldElement{-13657040, -13155431, -31283750, 11777098, 21447386, 6519384, -2378284, -1627556, 10092783, -4764171}, + FieldElement{27939166, 14210322, 4677035, 16277044, -22964462, -12398139, -32508754, 12005538, -17810127, 12803510}, + FieldElement{17228999, -15661624, -1233527, 300140, -1224870, -11714777, 30364213, -9038194, 18016357, 4397660}, + }, + { + FieldElement{-10958843, -7690207, 4776341, -14954238, 27850028, -15602212, -26619106, 14544525, -17477504, 982639}, + FieldElement{29253598, 15796703, -2863982, -9908884, 10057023, 3163536, 7332899, -4120128, -21047696, 9934963}, + FieldElement{5793303, 16271923, -24131614, -10116404, 29188560, 1206517, -14747930, 4559895, -30123922, -10897950}, + }, + { + FieldElement{-27643952, -11493006, 16282657, -11036493, 28414021, -15012264, 24191034, 4541697, -13338309, 5500568}, + FieldElement{12650548, -1497113, 9052871, 11355358, -17680037, -8400164, -17430592, 12264343, 10874051, 13524335}, + FieldElement{25556948, -3045990, 714651, 2510400, 23394682, -10415330, 33119038, 5080568, -22528059, 5376628}, + }, + { + FieldElement{-26088264, -4011052, -17013699, -3537628, -6726793, 1920897, -22321305, -9447443, 4535768, 1569007}, + FieldElement{-2255422, 14606630, -21692440, -8039818, 28430649, 8775819, -30494562, 3044290, 31848280, 12543772}, + FieldElement{-22028579, 2943893, -31857513, 6777306, 13784462, -4292203, -27377195, -2062731, 7718482, 14474653}, + }, + { + FieldElement{2385315, 2454213, -22631320, 46603, -4437935, -15680415, 656965, -7236665, 24316168, -5253567}, + FieldElement{13741529, 10911568, -33233417, -8603737, -20177830, -1033297, 33040651, -13424532, -20729456, 8321686}, + FieldElement{21060490, -2212744, 15712757, -4336099, 1639040, 10656336, 23845965, -11874838, -9984458, 608372}, + }, + { + FieldElement{-13672732, -15087586, -10889693, -7557059, -6036909, 11305547, 1123968, -6780577, 27229399, 23887}, + FieldElement{-23244140, -294205, -11744728, 14712571, -29465699, -2029617, 12797024, -6440308, -1633405, 16678954}, + FieldElement{-29500620, 4770662, -16054387, 14001338, 7830047, 9564805, -1508144, -4795045, -17169265, 4904953}, + }, + { + FieldElement{24059557, 14617003, 19037157, -15039908, 19766093, -14906429, 5169211, 16191880, 2128236, -4326833}, + FieldElement{-16981152, 4124966, -8540610, -10653797, 30336522, -14105247, -29806336, 916033, -6882542, -2986532}, + FieldElement{-22630907, 12419372, -7134229, -7473371, -16478904, 16739175, 285431, 2763829, 15736322, 4143876}, + }, + { + FieldElement{2379352, 11839345, -4110402, -5988665, 11274298, 794957, 212801, -14594663, 23527084, -16458268}, + FieldElement{33431127, -11130478, -17838966, -15626900, 8909499, 8376530, -32625340, 4087881, -15188911, -14416214}, + FieldElement{1767683, 7197987, -13205226, -2022635, -13091350, 448826, 5799055, 4357868, -4774191, -16323038}, + }, + }, + { + { + FieldElement{6721966, 13833823, -23523388, -1551314, 26354293, -11863321, 23365147, -3949732, 7390890, 2759800}, + FieldElement{4409041, 2052381, 23373853, 10530217, 7676779, -12885954, 21302353, -4264057, 1244380, -12919645}, + FieldElement{-4421239, 7169619, 4982368, -2957590, 30256825, -2777540, 14086413, 9208236, 15886429, 16489664}, + }, + { + FieldElement{1996075, 10375649, 14346367, 13311202, -6874135, -16438411, -13693198, 398369, -30606455, -712933}, + FieldElement{-25307465, 9795880, -2777414, 14878809, -33531835, 14780363, 13348553, 12076947, -30836462, 5113182}, + FieldElement{-17770784, 11797796, 31950843, 13929123, -25888302, 12288344, -30341101, -7336386, 13847711, 5387222}, + }, + { + FieldElement{-18582163, -3416217, 17824843, -2340966, 22744343, -10442611, 8763061, 3617786, -19600662, 10370991}, + FieldElement{20246567, -14369378, 22358229, -543712, 18507283, -10413996, 14554437, -8746092, 32232924, 16763880}, + FieldElement{9648505, 10094563, 26416693, 14745928, -30374318, -6472621, 11094161, 15689506, 3140038, -16510092}, + }, + { + FieldElement{-16160072, 5472695, 31895588, 4744994, 8823515, 10365685, -27224800, 9448613, -28774454, 366295}, + FieldElement{19153450, 11523972, -11096490, -6503142, -24647631, 5420647, 28344573, 8041113, 719605, 11671788}, + FieldElement{8678025, 2694440, -6808014, 2517372, 4964326, 11152271, -15432916, -15266516, 27000813, -10195553}, + }, + { + FieldElement{-15157904, 7134312, 8639287, -2814877, -7235688, 10421742, 564065, 5336097, 6750977, -14521026}, + FieldElement{11836410, -3979488, 26297894, 16080799, 23455045, 15735944, 1695823, -8819122, 8169720, 16220347}, + FieldElement{-18115838, 8653647, 17578566, -6092619, -8025777, -16012763, -11144307, -2627664, -5990708, -14166033}, + }, + { + FieldElement{-23308498, -10968312, 15213228, -10081214, -30853605, -11050004, 27884329, 2847284, 2655861, 1738395}, + FieldElement{-27537433, -14253021, -25336301, -8002780, -9370762, 8129821, 21651608, -3239336, -19087449, -11005278}, + FieldElement{1533110, 3437855, 23735889, 459276, 29970501, 11335377, 26030092, 5821408, 10478196, 8544890}, + }, + { + FieldElement{32173121, -16129311, 24896207, 3921497, 22579056, -3410854, 19270449, 12217473, 17789017, -3395995}, + FieldElement{-30552961, -2228401, -15578829, -10147201, 13243889, 517024, 15479401, -3853233, 30460520, 1052596}, + FieldElement{-11614875, 13323618, 32618793, 8175907, -15230173, 12596687, 27491595, -4612359, 3179268, -9478891}, + }, + { + FieldElement{31947069, -14366651, -4640583, -15339921, -15125977, -6039709, -14756777, -16411740, 19072640, -9511060}, + FieldElement{11685058, 11822410, 3158003, -13952594, 33402194, -4165066, 5977896, -5215017, 473099, 5040608}, + FieldElement{-20290863, 8198642, -27410132, 11602123, 1290375, -2799760, 28326862, 1721092, -19558642, -3131606}, + }, + }, + { + { + FieldElement{7881532, 10687937, 7578723, 7738378, -18951012, -2553952, 21820786, 8076149, -27868496, 11538389}, + FieldElement{-19935666, 3899861, 18283497, -6801568, -15728660, -11249211, 8754525, 7446702, -5676054, 5797016}, + FieldElement{-11295600, -3793569, -15782110, -7964573, 12708869, -8456199, 2014099, -9050574, -2369172, -5877341}, + }, + { + FieldElement{-22472376, -11568741, -27682020, 1146375, 18956691, 16640559, 1192730, -3714199, 15123619, 10811505}, + FieldElement{14352098, -3419715, -18942044, 10822655, 32750596, 4699007, -70363, 15776356, -28886779, -11974553}, + FieldElement{-28241164, -8072475, -4978962, -5315317, 29416931, 1847569, -20654173, -16484855, 4714547, -9600655}, + }, + { + FieldElement{15200332, 8368572, 19679101, 15970074, -31872674, 1959451, 24611599, -4543832, -11745876, 12340220}, + FieldElement{12876937, -10480056, 33134381, 6590940, -6307776, 14872440, 9613953, 8241152, 15370987, 9608631}, + FieldElement{-4143277, -12014408, 8446281, -391603, 4407738, 13629032, -7724868, 15866074, -28210621, -8814099}, + }, + { + FieldElement{26660628, -15677655, 8393734, 358047, -7401291, 992988, -23904233, 858697, 20571223, 8420556}, + FieldElement{14620715, 13067227, -15447274, 8264467, 14106269, 15080814, 33531827, 12516406, -21574435, -12476749}, + FieldElement{236881, 10476226, 57258, -14677024, 6472998, 2466984, 17258519, 7256740, 8791136, 15069930}, + }, + { + FieldElement{1276410, -9371918, 22949635, -16322807, -23493039, -5702186, 14711875, 4874229, -30663140, -2331391}, + FieldElement{5855666, 4990204, -13711848, 7294284, -7804282, 1924647, -1423175, -7912378, -33069337, 9234253}, + FieldElement{20590503, -9018988, 31529744, -7352666, -2706834, 10650548, 31559055, -11609587, 18979186, 13396066}, + }, + { + FieldElement{24474287, 4968103, 22267082, 4407354, 24063882, -8325180, -18816887, 13594782, 33514650, 7021958}, + FieldElement{-11566906, -6565505, -21365085, 15928892, -26158305, 4315421, -25948728, -3916677, -21480480, 12868082}, + FieldElement{-28635013, 13504661, 19988037, -2132761, 21078225, 6443208, -21446107, 2244500, -12455797, -8089383}, + }, + { + FieldElement{-30595528, 13793479, -5852820, 319136, -25723172, -6263899, 33086546, 8957937, -15233648, 5540521}, + FieldElement{-11630176, -11503902, -8119500, -7643073, 2620056, 1022908, -23710744, -1568984, -16128528, -14962807}, + FieldElement{23152971, 775386, 27395463, 14006635, -9701118, 4649512, 1689819, 892185, -11513277, -15205948}, + }, + { + FieldElement{9770129, 9586738, 26496094, 4324120, 1556511, -3550024, 27453819, 4763127, -19179614, 5867134}, + FieldElement{-32765025, 1927590, 31726409, -4753295, 23962434, -16019500, 27846559, 5931263, -29749703, -16108455}, + FieldElement{27461885, -2977536, 22380810, 1815854, -23033753, -3031938, 7283490, -15148073, -19526700, 7734629}, + }, + }, + { + { + FieldElement{-8010264, -9590817, -11120403, 6196038, 29344158, -13430885, 7585295, -3176626, 18549497, 15302069}, + FieldElement{-32658337, -6171222, -7672793, -11051681, 6258878, 13504381, 10458790, -6418461, -8872242, 8424746}, + FieldElement{24687205, 8613276, -30667046, -3233545, 1863892, -1830544, 19206234, 7134917, -11284482, -828919}, + }, + { + FieldElement{11334899, -9218022, 8025293, 12707519, 17523892, -10476071, 10243738, -14685461, -5066034, 16498837}, + FieldElement{8911542, 6887158, -9584260, -6958590, 11145641, -9543680, 17303925, -14124238, 6536641, 10543906}, + FieldElement{-28946384, 15479763, -17466835, 568876, -1497683, 11223454, -2669190, -16625574, -27235709, 8876771}, + }, + { + FieldElement{-25742899, -12566864, -15649966, -846607, -33026686, -796288, -33481822, 15824474, -604426, -9039817}, + FieldElement{10330056, 70051, 7957388, -9002667, 9764902, 15609756, 27698697, -4890037, 1657394, 3084098}, + FieldElement{10477963, -7470260, 12119566, -13250805, 29016247, -5365589, 31280319, 14396151, -30233575, 15272409}, + }, + { + FieldElement{-12288309, 3169463, 28813183, 16658753, 25116432, -5630466, -25173957, -12636138, -25014757, 1950504}, + FieldElement{-26180358, 9489187, 11053416, -14746161, -31053720, 5825630, -8384306, -8767532, 15341279, 8373727}, + FieldElement{28685821, 7759505, -14378516, -12002860, -31971820, 4079242, 298136, -10232602, -2878207, 15190420}, + }, + { + FieldElement{-32932876, 13806336, -14337485, -15794431, -24004620, 10940928, 8669718, 2742393, -26033313, -6875003}, + FieldElement{-1580388, -11729417, -25979658, -11445023, -17411874, -10912854, 9291594, -16247779, -12154742, 6048605}, + FieldElement{-30305315, 14843444, 1539301, 11864366, 20201677, 1900163, 13934231, 5128323, 11213262, 9168384}, + }, + { + FieldElement{-26280513, 11007847, 19408960, -940758, -18592965, -4328580, -5088060, -11105150, 20470157, -16398701}, + FieldElement{-23136053, 9282192, 14855179, -15390078, -7362815, -14408560, -22783952, 14461608, 14042978, 5230683}, + FieldElement{29969567, -2741594, -16711867, -8552442, 9175486, -2468974, 21556951, 3506042, -5933891, -12449708}, + }, + { + FieldElement{-3144746, 8744661, 19704003, 4581278, -20430686, 6830683, -21284170, 8971513, -28539189, 15326563}, + FieldElement{-19464629, 10110288, -17262528, -3503892, -23500387, 1355669, -15523050, 15300988, -20514118, 9168260}, + FieldElement{-5353335, 4488613, -23803248, 16314347, 7780487, -15638939, -28948358, 9601605, 33087103, -9011387}, + }, + { + FieldElement{-19443170, -15512900, -20797467, -12445323, -29824447, 10229461, -27444329, -15000531, -5996870, 15664672}, + FieldElement{23294591, -16632613, -22650781, -8470978, 27844204, 11461195, 13099750, -2460356, 18151676, 13417686}, + FieldElement{-24722913, -4176517, -31150679, 5988919, -26858785, 6685065, 1661597, -12551441, 15271676, -15452665}, + }, + }, + { + { + FieldElement{11433042, -13228665, 8239631, -5279517, -1985436, -725718, -18698764, 2167544, -6921301, -13440182}, + FieldElement{-31436171, 15575146, 30436815, 12192228, -22463353, 9395379, -9917708, -8638997, 12215110, 12028277}, + FieldElement{14098400, 6555944, 23007258, 5757252, -15427832, -12950502, 30123440, 4617780, -16900089, -655628}, + }, + { + FieldElement{-4026201, -15240835, 11893168, 13718664, -14809462, 1847385, -15819999, 10154009, 23973261, -12684474}, + FieldElement{-26531820, -3695990, -1908898, 2534301, -31870557, -16550355, 18341390, -11419951, 32013174, -10103539}, + FieldElement{-25479301, 10876443, -11771086, -14625140, -12369567, 1838104, 21911214, 6354752, 4425632, -837822}, + }, + { + FieldElement{-10433389, -14612966, 22229858, -3091047, -13191166, 776729, -17415375, -12020462, 4725005, 14044970}, + FieldElement{19268650, -7304421, 1555349, 8692754, -21474059, -9910664, 6347390, -1411784, -19522291, -16109756}, + FieldElement{-24864089, 12986008, -10898878, -5558584, -11312371, -148526, 19541418, 8180106, 9282262, 10282508}, + }, + { + FieldElement{-26205082, 4428547, -8661196, -13194263, 4098402, -14165257, 15522535, 8372215, 5542595, -10702683}, + FieldElement{-10562541, 14895633, 26814552, -16673850, -17480754, -2489360, -2781891, 6993761, -18093885, 10114655}, + FieldElement{-20107055, -929418, 31422704, 10427861, -7110749, 6150669, -29091755, -11529146, 25953725, -106158}, + }, + { + FieldElement{-4234397, -8039292, -9119125, 3046000, 2101609, -12607294, 19390020, 6094296, -3315279, 12831125}, + FieldElement{-15998678, 7578152, 5310217, 14408357, -33548620, -224739, 31575954, 6326196, 7381791, -2421839}, + FieldElement{-20902779, 3296811, 24736065, -16328389, 18374254, 7318640, 6295303, 8082724, -15362489, 12339664}, + }, + { + FieldElement{27724736, 2291157, 6088201, -14184798, 1792727, 5857634, 13848414, 15768922, 25091167, 14856294}, + FieldElement{-18866652, 8331043, 24373479, 8541013, -701998, -9269457, 12927300, -12695493, -22182473, -9012899}, + FieldElement{-11423429, -5421590, 11632845, 3405020, 30536730, -11674039, -27260765, 13866390, 30146206, 9142070}, + }, + { + FieldElement{3924129, -15307516, -13817122, -10054960, 12291820, -668366, -27702774, 9326384, -8237858, 4171294}, + FieldElement{-15921940, 16037937, 6713787, 16606682, -21612135, 2790944, 26396185, 3731949, 345228, -5462949}, + FieldElement{-21327538, 13448259, 25284571, 1143661, 20614966, -8849387, 2031539, -12391231, -16253183, -13582083}, + }, + { + FieldElement{31016211, -16722429, 26371392, -14451233, -5027349, 14854137, 17477601, 3842657, 28012650, -16405420}, + FieldElement{-5075835, 9368966, -8562079, -4600902, -15249953, 6970560, -9189873, 16292057, -8867157, 3507940}, + FieldElement{29439664, 3537914, 23333589, 6997794, -17555561, -11018068, -15209202, -15051267, -9164929, 6580396}, + }, + }, + { + { + FieldElement{-12185861, -7679788, 16438269, 10826160, -8696817, -6235611, 17860444, -9273846, -2095802, 9304567}, + FieldElement{20714564, -4336911, 29088195, 7406487, 11426967, -5095705, 14792667, -14608617, 5289421, -477127}, + FieldElement{-16665533, -10650790, -6160345, -13305760, 9192020, -1802462, 17271490, 12349094, 26939669, -3752294}, + }, + { + FieldElement{-12889898, 9373458, 31595848, 16374215, 21471720, 13221525, -27283495, -12348559, -3698806, 117887}, + FieldElement{22263325, -6560050, 3984570, -11174646, -15114008, -566785, 28311253, 5358056, -23319780, 541964}, + FieldElement{16259219, 3261970, 2309254, -15534474, -16885711, -4581916, 24134070, -16705829, -13337066, -13552195}, + }, + { + FieldElement{9378160, -13140186, -22845982, -12745264, 28198281, -7244098, -2399684, -717351, 690426, 14876244}, + FieldElement{24977353, -314384, -8223969, -13465086, 28432343, -1176353, -13068804, -12297348, -22380984, 6618999}, + FieldElement{-1538174, 11685646, 12944378, 13682314, -24389511, -14413193, 8044829, -13817328, 32239829, -5652762}, + }, + { + FieldElement{-18603066, 4762990, -926250, 8885304, -28412480, -3187315, 9781647, -10350059, 32779359, 5095274}, + FieldElement{-33008130, -5214506, -32264887, -3685216, 9460461, -9327423, -24601656, 14506724, 21639561, -2630236}, + FieldElement{-16400943, -13112215, 25239338, 15531969, 3987758, -4499318, -1289502, -6863535, 17874574, 558605}, + }, + { + FieldElement{-13600129, 10240081, 9171883, 16131053, -20869254, 9599700, 33499487, 5080151, 2085892, 5119761}, + FieldElement{-22205145, -2519528, -16381601, 414691, -25019550, 2170430, 30634760, -8363614, -31999993, -5759884}, + FieldElement{-6845704, 15791202, 8550074, -1312654, 29928809, -12092256, 27534430, -7192145, -22351378, 12961482}, + }, + { + FieldElement{-24492060, -9570771, 10368194, 11582341, -23397293, -2245287, 16533930, 8206996, -30194652, -5159638}, + FieldElement{-11121496, -3382234, 2307366, 6362031, -135455, 8868177, -16835630, 7031275, 7589640, 8945490}, + FieldElement{-32152748, 8917967, 6661220, -11677616, -1192060, -15793393, 7251489, -11182180, 24099109, -14456170}, + }, + { + FieldElement{5019558, -7907470, 4244127, -14714356, -26933272, 6453165, -19118182, -13289025, -6231896, -10280736}, + FieldElement{10853594, 10721687, 26480089, 5861829, -22995819, 1972175, -1866647, -10557898, -3363451, -6441124}, + FieldElement{-17002408, 5906790, 221599, -6563147, 7828208, -13248918, 24362661, -2008168, -13866408, 7421392}, + }, + { + FieldElement{8139927, -6546497, 32257646, -5890546, 30375719, 1886181, -21175108, 15441252, 28826358, -4123029}, + FieldElement{6267086, 9695052, 7709135, -16603597, -32869068, -1886135, 14795160, -7840124, 13746021, -1742048}, + FieldElement{28584902, 7787108, -6732942, -15050729, 22846041, -7571236, -3181936, -363524, 4771362, -8419958}, + }, + }, + { + { + FieldElement{24949256, 6376279, -27466481, -8174608, -18646154, -9930606, 33543569, -12141695, 3569627, 11342593}, + FieldElement{26514989, 4740088, 27912651, 3697550, 19331575, -11472339, 6809886, 4608608, 7325975, -14801071}, + FieldElement{-11618399, -14554430, -24321212, 7655128, -1369274, 5214312, -27400540, 10258390, -17646694, -8186692}, + }, + { + FieldElement{11431204, 15823007, 26570245, 14329124, 18029990, 4796082, -31446179, 15580664, 9280358, -3973687}, + FieldElement{-160783, -10326257, -22855316, -4304997, -20861367, -13621002, -32810901, -11181622, -15545091, 4387441}, + FieldElement{-20799378, 12194512, 3937617, -5805892, -27154820, 9340370, -24513992, 8548137, 20617071, -7482001}, + }, + { + FieldElement{-938825, -3930586, -8714311, 16124718, 24603125, -6225393, -13775352, -11875822, 24345683, 10325460}, + FieldElement{-19855277, -1568885, -22202708, 8714034, 14007766, 6928528, 16318175, -1010689, 4766743, 3552007}, + FieldElement{-21751364, -16730916, 1351763, -803421, -4009670, 3950935, 3217514, 14481909, 10988822, -3994762}, + }, + { + FieldElement{15564307, -14311570, 3101243, 5684148, 30446780, -8051356, 12677127, -6505343, -8295852, 13296005}, + FieldElement{-9442290, 6624296, -30298964, -11913677, -4670981, -2057379, 31521204, 9614054, -30000824, 12074674}, + FieldElement{4771191, -135239, 14290749, -13089852, 27992298, 14998318, -1413936, -1556716, 29832613, -16391035}, + }, + { + FieldElement{7064884, -7541174, -19161962, -5067537, -18891269, -2912736, 25825242, 5293297, -27122660, 13101590}, + FieldElement{-2298563, 2439670, -7466610, 1719965, -27267541, -16328445, 32512469, -5317593, -30356070, -4190957}, + FieldElement{-30006540, 10162316, -33180176, 3981723, -16482138, -13070044, 14413974, 9515896, 19568978, 9628812}, + }, + { + FieldElement{33053803, 199357, 15894591, 1583059, 27380243, -4580435, -17838894, -6106839, -6291786, 3437740}, + FieldElement{-18978877, 3884493, 19469877, 12726490, 15913552, 13614290, -22961733, 70104, 7463304, 4176122}, + FieldElement{-27124001, 10659917, 11482427, -16070381, 12771467, -6635117, -32719404, -5322751, 24216882, 5944158}, + }, + { + FieldElement{8894125, 7450974, -2664149, -9765752, -28080517, -12389115, 19345746, 14680796, 11632993, 5847885}, + FieldElement{26942781, -2315317, 9129564, -4906607, 26024105, 11769399, -11518837, 6367194, -9727230, 4782140}, + FieldElement{19916461, -4828410, -22910704, -11414391, 25606324, -5972441, 33253853, 8220911, 6358847, -1873857}, + }, + { + FieldElement{801428, -2081702, 16569428, 11065167, 29875704, 96627, 7908388, -4480480, -13538503, 1387155}, + FieldElement{19646058, 5720633, -11416706, 12814209, 11607948, 12749789, 14147075, 15156355, -21866831, 11835260}, + FieldElement{19299512, 1155910, 28703737, 14890794, 2925026, 7269399, 26121523, 15467869, -26560550, 5052483}, + }, + }, + { + { + FieldElement{-3017432, 10058206, 1980837, 3964243, 22160966, 12322533, -6431123, -12618185, 12228557, -7003677}, + FieldElement{32944382, 14922211, -22844894, 5188528, 21913450, -8719943, 4001465, 13238564, -6114803, 8653815}, + FieldElement{22865569, -4652735, 27603668, -12545395, 14348958, 8234005, 24808405, 5719875, 28483275, 2841751}, + }, + { + FieldElement{-16420968, -1113305, -327719, -12107856, 21886282, -15552774, -1887966, -315658, 19932058, -12739203}, + FieldElement{-11656086, 10087521, -8864888, -5536143, -19278573, -3055912, 3999228, 13239134, -4777469, -13910208}, + FieldElement{1382174, -11694719, 17266790, 9194690, -13324356, 9720081, 20403944, 11284705, -14013818, 3093230}, + }, + { + FieldElement{16650921, -11037932, -1064178, 1570629, -8329746, 7352753, -302424, 16271225, -24049421, -6691850}, + FieldElement{-21911077, -5927941, -4611316, -5560156, -31744103, -10785293, 24123614, 15193618, -21652117, -16739389}, + FieldElement{-9935934, -4289447, -25279823, 4372842, 2087473, 10399484, 31870908, 14690798, 17361620, 11864968}, + }, + { + FieldElement{-11307610, 6210372, 13206574, 5806320, -29017692, -13967200, -12331205, -7486601, -25578460, -16240689}, + FieldElement{14668462, -12270235, 26039039, 15305210, 25515617, 4542480, 10453892, 6577524, 9145645, -6443880}, + FieldElement{5974874, 3053895, -9433049, -10385191, -31865124, 3225009, -7972642, 3936128, -5652273, -3050304}, + }, + { + FieldElement{30625386, -4729400, -25555961, -12792866, -20484575, 7695099, 17097188, -16303496, -27999779, 1803632}, + FieldElement{-3553091, 9865099, -5228566, 4272701, -5673832, -16689700, 14911344, 12196514, -21405489, 7047412}, + FieldElement{20093277, 9920966, -11138194, -5343857, 13161587, 12044805, -32856851, 4124601, -32343828, -10257566}, + }, + { + FieldElement{-20788824, 14084654, -13531713, 7842147, 19119038, -13822605, 4752377, -8714640, -21679658, 2288038}, + FieldElement{-26819236, -3283715, 29965059, 3039786, -14473765, 2540457, 29457502, 14625692, -24819617, 12570232}, + FieldElement{-1063558, -11551823, 16920318, 12494842, 1278292, -5869109, -21159943, -3498680, -11974704, 4724943}, + }, + { + FieldElement{17960970, -11775534, -4140968, -9702530, -8876562, -1410617, -12907383, -8659932, -29576300, 1903856}, + FieldElement{23134274, -14279132, -10681997, -1611936, 20684485, 15770816, -12989750, 3190296, 26955097, 14109738}, + FieldElement{15308788, 5320727, -30113809, -14318877, 22902008, 7767164, 29425325, -11277562, 31960942, 11934971}, + }, + { + FieldElement{-27395711, 8435796, 4109644, 12222639, -24627868, 14818669, 20638173, 4875028, 10491392, 1379718}, + FieldElement{-13159415, 9197841, 3875503, -8936108, -1383712, -5879801, 33518459, 16176658, 21432314, 12180697}, + FieldElement{-11787308, 11500838, 13787581, -13832590, -22430679, 10140205, 1465425, 12689540, -10301319, -13872883}, + }, + }, + { + { + FieldElement{5414091, -15386041, -21007664, 9643570, 12834970, 1186149, -2622916, -1342231, 26128231, 6032912}, + FieldElement{-26337395, -13766162, 32496025, -13653919, 17847801, -12669156, 3604025, 8316894, -25875034, -10437358}, + FieldElement{3296484, 6223048, 24680646, -12246460, -23052020, 5903205, -8862297, -4639164, 12376617, 3188849}, + }, + { + FieldElement{29190488, -14659046, 27549113, -1183516, 3520066, -10697301, 32049515, -7309113, -16109234, -9852307}, + FieldElement{-14744486, -9309156, 735818, -598978, -20407687, -5057904, 25246078, -15795669, 18640741, -960977}, + FieldElement{-6928835, -16430795, 10361374, 5642961, 4910474, 12345252, -31638386, -494430, 10530747, 1053335}, + }, + { + FieldElement{-29265967, -14186805, -13538216, -12117373, -19457059, -10655384, -31462369, -2948985, 24018831, 15026644}, + FieldElement{-22592535, -3145277, -2289276, 5953843, -13440189, 9425631, 25310643, 13003497, -2314791, -15145616}, + FieldElement{-27419985, -603321, -8043984, -1669117, -26092265, 13987819, -27297622, 187899, -23166419, -2531735}, + }, + { + FieldElement{-21744398, -13810475, 1844840, 5021428, -10434399, -15911473, 9716667, 16266922, -5070217, 726099}, + FieldElement{29370922, -6053998, 7334071, -15342259, 9385287, 2247707, -13661962, -4839461, 30007388, -15823341}, + FieldElement{-936379, 16086691, 23751945, -543318, -1167538, -5189036, 9137109, 730663, 9835848, 4555336}, + }, + { + FieldElement{-23376435, 1410446, -22253753, -12899614, 30867635, 15826977, 17693930, 544696, -11985298, 12422646}, + FieldElement{31117226, -12215734, -13502838, 6561947, -9876867, -12757670, -5118685, -4096706, 29120153, 13924425}, + FieldElement{-17400879, -14233209, 19675799, -2734756, -11006962, -5858820, -9383939, -11317700, 7240931, -237388}, + }, + { + FieldElement{-31361739, -11346780, -15007447, -5856218, -22453340, -12152771, 1222336, 4389483, 3293637, -15551743}, + FieldElement{-16684801, -14444245, 11038544, 11054958, -13801175, -3338533, -24319580, 7733547, 12796905, -6335822}, + FieldElement{-8759414, -10817836, -25418864, 10783769, -30615557, -9746811, -28253339, 3647836, 3222231, -11160462}, + }, + { + FieldElement{18606113, 1693100, -25448386, -15170272, 4112353, 10045021, 23603893, -2048234, -7550776, 2484985}, + FieldElement{9255317, -3131197, -12156162, -1004256, 13098013, -9214866, 16377220, -2102812, -19802075, -3034702}, + FieldElement{-22729289, 7496160, -5742199, 11329249, 19991973, -3347502, -31718148, 9936966, -30097688, -10618797}, + }, + { + FieldElement{21878590, -5001297, 4338336, 13643897, -3036865, 13160960, 19708896, 5415497, -7360503, -4109293}, + FieldElement{27736861, 10103576, 12500508, 8502413, -3413016, -9633558, 10436918, -1550276, -23659143, -8132100}, + FieldElement{19492550, -12104365, -29681976, -852630, -3208171, 12403437, 30066266, 8367329, 13243957, 8709688}, + }, + }, + { + { + FieldElement{12015105, 2801261, 28198131, 10151021, 24818120, -4743133, -11194191, -5645734, 5150968, 7274186}, + FieldElement{2831366, -12492146, 1478975, 6122054, 23825128, -12733586, 31097299, 6083058, 31021603, -9793610}, + FieldElement{-2529932, -2229646, 445613, 10720828, -13849527, -11505937, -23507731, 16354465, 15067285, -14147707}, + }, + { + FieldElement{7840942, 14037873, -33364863, 15934016, -728213, -3642706, 21403988, 1057586, -19379462, -12403220}, + FieldElement{915865, -16469274, 15608285, -8789130, -24357026, 6060030, -17371319, 8410997, -7220461, 16527025}, + FieldElement{32922597, -556987, 20336074, -16184568, 10903705, -5384487, 16957574, 52992, 23834301, 6588044}, + }, + { + FieldElement{32752030, 11232950, 3381995, -8714866, 22652988, -10744103, 17159699, 16689107, -20314580, -1305992}, + FieldElement{-4689649, 9166776, -25710296, -10847306, 11576752, 12733943, 7924251, -2752281, 1976123, -7249027}, + FieldElement{21251222, 16309901, -2983015, -6783122, 30810597, 12967303, 156041, -3371252, 12331345, -8237197}, + }, + { + FieldElement{8651614, -4477032, -16085636, -4996994, 13002507, 2950805, 29054427, -5106970, 10008136, -4667901}, + FieldElement{31486080, 15114593, -14261250, 12951354, 14369431, -7387845, 16347321, -13662089, 8684155, -10532952}, + FieldElement{19443825, 11385320, 24468943, -9659068, -23919258, 2187569, -26263207, -6086921, 31316348, 14219878}, + }, + { + FieldElement{-28594490, 1193785, 32245219, 11392485, 31092169, 15722801, 27146014, 6992409, 29126555, 9207390}, + FieldElement{32382935, 1110093, 18477781, 11028262, -27411763, -7548111, -4980517, 10843782, -7957600, -14435730}, + FieldElement{2814918, 7836403, 27519878, -7868156, -20894015, -11553689, -21494559, 8550130, 28346258, 1994730}, + }, + { + FieldElement{-19578299, 8085545, -14000519, -3948622, 2785838, -16231307, -19516951, 7174894, 22628102, 8115180}, + FieldElement{-30405132, 955511, -11133838, -15078069, -32447087, -13278079, -25651578, 3317160, -9943017, 930272}, + FieldElement{-15303681, -6833769, 28856490, 1357446, 23421993, 1057177, 24091212, -1388970, -22765376, -10650715}, + }, + { + FieldElement{-22751231, -5303997, -12907607, -12768866, -15811511, -7797053, -14839018, -16554220, -1867018, 8398970}, + FieldElement{-31969310, 2106403, -4736360, 1362501, 12813763, 16200670, 22981545, -6291273, 18009408, -15772772}, + FieldElement{-17220923, -9545221, -27784654, 14166835, 29815394, 7444469, 29551787, -3727419, 19288549, 1325865}, + }, + { + FieldElement{15100157, -15835752, -23923978, -1005098, -26450192, 15509408, 12376730, -3479146, 33166107, -8042750}, + FieldElement{20909231, 13023121, -9209752, 16251778, -5778415, -8094914, 12412151, 10018715, 2213263, -13878373}, + FieldElement{32529814, -11074689, 30361439, -16689753, -9135940, 1513226, 22922121, 6382134, -5766928, 8371348}, + }, + }, + { + { + FieldElement{9923462, 11271500, 12616794, 3544722, -29998368, -1721626, 12891687, -8193132, -26442943, 10486144}, + FieldElement{-22597207, -7012665, 8587003, -8257861, 4084309, -12970062, 361726, 2610596, -23921530, -11455195}, + FieldElement{5408411, -1136691, -4969122, 10561668, 24145918, 14240566, 31319731, -4235541, 19985175, -3436086}, + }, + { + FieldElement{-13994457, 16616821, 14549246, 3341099, 32155958, 13648976, -17577068, 8849297, 65030, 8370684}, + FieldElement{-8320926, -12049626, 31204563, 5839400, -20627288, -1057277, -19442942, 6922164, 12743482, -9800518}, + FieldElement{-2361371, 12678785, 28815050, 4759974, -23893047, 4884717, 23783145, 11038569, 18800704, 255233}, + }, + { + FieldElement{-5269658, -1773886, 13957886, 7990715, 23132995, 728773, 13393847, 9066957, 19258688, -14753793}, + FieldElement{-2936654, -10827535, -10432089, 14516793, -3640786, 4372541, -31934921, 2209390, -1524053, 2055794}, + FieldElement{580882, 16705327, 5468415, -2683018, -30926419, -14696000, -7203346, -8994389, -30021019, 7394435}, + }, + { + FieldElement{23838809, 1822728, -15738443, 15242727, 8318092, -3733104, -21672180, -3492205, -4821741, 14799921}, + FieldElement{13345610, 9759151, 3371034, -16137791, 16353039, 8577942, 31129804, 13496856, -9056018, 7402518}, + FieldElement{2286874, -4435931, -20042458, -2008336, -13696227, 5038122, 11006906, -15760352, 8205061, 1607563}, + }, + { + FieldElement{14414086, -8002132, 3331830, -3208217, 22249151, -5594188, 18364661, -2906958, 30019587, -9029278}, + FieldElement{-27688051, 1585953, -10775053, 931069, -29120221, -11002319, -14410829, 12029093, 9944378, 8024}, + FieldElement{4368715, -3709630, 29874200, -15022983, -20230386, -11410704, -16114594, -999085, -8142388, 5640030}, + }, + { + FieldElement{10299610, 13746483, 11661824, 16234854, 7630238, 5998374, 9809887, -16694564, 15219798, -14327783}, + FieldElement{27425505, -5719081, 3055006, 10660664, 23458024, 595578, -15398605, -1173195, -18342183, 9742717}, + FieldElement{6744077, 2427284, 26042789, 2720740, -847906, 1118974, 32324614, 7406442, 12420155, 1994844}, + }, + { + FieldElement{14012521, -5024720, -18384453, -9578469, -26485342, -3936439, -13033478, -10909803, 24319929, -6446333}, + FieldElement{16412690, -4507367, 10772641, 15929391, -17068788, -4658621, 10555945, -10484049, -30102368, -4739048}, + FieldElement{22397382, -7767684, -9293161, -12792868, 17166287, -9755136, -27333065, 6199366, 21880021, -12250760}, + }, + { + FieldElement{-4283307, 5368523, -31117018, 8163389, -30323063, 3209128, 16557151, 8890729, 8840445, 4957760}, + FieldElement{-15447727, 709327, -6919446, -10870178, -29777922, 6522332, -21720181, 12130072, -14796503, 5005757}, + FieldElement{-2114751, -14308128, 23019042, 15765735, -25269683, 6002752, 10183197, -13239326, -16395286, -2176112}, + }, + }, + { + { + FieldElement{-19025756, 1632005, 13466291, -7995100, -23640451, 16573537, -32013908, -3057104, 22208662, 2000468}, + FieldElement{3065073, -1412761, -25598674, -361432, -17683065, -5703415, -8164212, 11248527, -3691214, -7414184}, + FieldElement{10379208, -6045554, 8877319, 1473647, -29291284, -12507580, 16690915, 2553332, -3132688, 16400289}, + }, + { + FieldElement{15716668, 1254266, -18472690, 7446274, -8448918, 6344164, -22097271, -7285580, 26894937, 9132066}, + FieldElement{24158887, 12938817, 11085297, -8177598, -28063478, -4457083, -30576463, 64452, -6817084, -2692882}, + FieldElement{13488534, 7794716, 22236231, 5989356, 25426474, -12578208, 2350710, -3418511, -4688006, 2364226}, + }, + { + FieldElement{16335052, 9132434, 25640582, 6678888, 1725628, 8517937, -11807024, -11697457, 15445875, -7798101}, + FieldElement{29004207, -7867081, 28661402, -640412, -12794003, -7943086, 31863255, -4135540, -278050, -15759279}, + FieldElement{-6122061, -14866665, -28614905, 14569919, -10857999, -3591829, 10343412, -6976290, -29828287, -10815811}, + }, + { + FieldElement{27081650, 3463984, 14099042, -4517604, 1616303, -6205604, 29542636, 15372179, 17293797, 960709}, + FieldElement{20263915, 11434237, -5765435, 11236810, 13505955, -10857102, -16111345, 6493122, -19384511, 7639714}, + FieldElement{-2830798, -14839232, 25403038, -8215196, -8317012, -16173699, 18006287, -16043750, 29994677, -15808121}, + }, + { + FieldElement{9769828, 5202651, -24157398, -13631392, -28051003, -11561624, -24613141, -13860782, -31184575, 709464}, + FieldElement{12286395, 13076066, -21775189, -1176622, -25003198, 4057652, -32018128, -8890874, 16102007, 13205847}, + FieldElement{13733362, 5599946, 10557076, 3195751, -5557991, 8536970, -25540170, 8525972, 10151379, 10394400}, + }, + { + FieldElement{4024660, -16137551, 22436262, 12276534, -9099015, -2686099, 19698229, 11743039, -33302334, 8934414}, + FieldElement{-15879800, -4525240, -8580747, -2934061, 14634845, -698278, -9449077, 3137094, -11536886, 11721158}, + FieldElement{17555939, -5013938, 8268606, 2331751, -22738815, 9761013, 9319229, 8835153, -9205489, -1280045}, + }, + { + FieldElement{-461409, -7830014, 20614118, 16688288, -7514766, -4807119, 22300304, 505429, 6108462, -6183415}, + FieldElement{-5070281, 12367917, -30663534, 3234473, 32617080, -8422642, 29880583, -13483331, -26898490, -7867459}, + FieldElement{-31975283, 5726539, 26934134, 10237677, -3173717, -605053, 24199304, 3795095, 7592688, -14992079}, + }, + { + FieldElement{21594432, -14964228, 17466408, -4077222, 32537084, 2739898, 6407723, 12018833, -28256052, 4298412}, + FieldElement{-20650503, -11961496, -27236275, 570498, 3767144, -1717540, 13891942, -1569194, 13717174, 10805743}, + FieldElement{-14676630, -15644296, 15287174, 11927123, 24177847, -8175568, -796431, 14860609, -26938930, -5863836}, + }, + }, + { + { + FieldElement{12962541, 5311799, -10060768, 11658280, 18855286, -7954201, 13286263, -12808704, -4381056, 9882022}, + FieldElement{18512079, 11319350, -20123124, 15090309, 18818594, 5271736, -22727904, 3666879, -23967430, -3299429}, + FieldElement{-6789020, -3146043, 16192429, 13241070, 15898607, -14206114, -10084880, -6661110, -2403099, 5276065}, + }, + { + FieldElement{30169808, -5317648, 26306206, -11750859, 27814964, 7069267, 7152851, 3684982, 1449224, 13082861}, + FieldElement{10342826, 3098505, 2119311, 193222, 25702612, 12233820, 23697382, 15056736, -21016438, -8202000}, + FieldElement{-33150110, 3261608, 22745853, 7948688, 19370557, -15177665, -26171976, 6482814, -10300080, -11060101}, + }, + { + FieldElement{32869458, -5408545, 25609743, 15678670, -10687769, -15471071, 26112421, 2521008, -22664288, 6904815}, + FieldElement{29506923, 4457497, 3377935, -9796444, -30510046, 12935080, 1561737, 3841096, -29003639, -6657642}, + FieldElement{10340844, -6630377, -18656632, -2278430, 12621151, -13339055, 30878497, -11824370, -25584551, 5181966}, + }, + { + FieldElement{25940115, -12658025, 17324188, -10307374, -8671468, 15029094, 24396252, -16450922, -2322852, -12388574}, + FieldElement{-21765684, 9916823, -1300409, 4079498, -1028346, 11909559, 1782390, 12641087, 20603771, -6561742}, + FieldElement{-18882287, -11673380, 24849422, 11501709, 13161720, -4768874, 1925523, 11914390, 4662781, 7820689}, + }, + { + FieldElement{12241050, -425982, 8132691, 9393934, 32846760, -1599620, 29749456, 12172924, 16136752, 15264020}, + FieldElement{-10349955, -14680563, -8211979, 2330220, -17662549, -14545780, 10658213, 6671822, 19012087, 3772772}, + FieldElement{3753511, -3421066, 10617074, 2028709, 14841030, -6721664, 28718732, -15762884, 20527771, 12988982}, + }, + { + FieldElement{-14822485, -5797269, -3707987, 12689773, -898983, -10914866, -24183046, -10564943, 3299665, -12424953}, + FieldElement{-16777703, -15253301, -9642417, 4978983, 3308785, 8755439, 6943197, 6461331, -25583147, 8991218}, + FieldElement{-17226263, 1816362, -1673288, -6086439, 31783888, -8175991, -32948145, 7417950, -30242287, 1507265}, + }, + { + FieldElement{29692663, 6829891, -10498800, 4334896, 20945975, -11906496, -28887608, 8209391, 14606362, -10647073}, + FieldElement{-3481570, 8707081, 32188102, 5672294, 22096700, 1711240, -33020695, 9761487, 4170404, -2085325}, + FieldElement{-11587470, 14855945, -4127778, -1531857, -26649089, 15084046, 22186522, 16002000, -14276837, -8400798}, + }, + { + FieldElement{-4811456, 13761029, -31703877, -2483919, -3312471, 7869047, -7113572, -9620092, 13240845, 10965870}, + FieldElement{-7742563, -8256762, -14768334, -13656260, -23232383, 12387166, 4498947, 14147411, 29514390, 4302863}, + FieldElement{-13413405, -12407859, 20757302, -13801832, 14785143, 8976368, -5061276, -2144373, 17846988, -13971927}, + }, + }, + { + { + FieldElement{-2244452, -754728, -4597030, -1066309, -6247172, 1455299, -21647728, -9214789, -5222701, 12650267}, + FieldElement{-9906797, -16070310, 21134160, 12198166, -27064575, 708126, 387813, 13770293, -19134326, 10958663}, + FieldElement{22470984, 12369526, 23446014, -5441109, -21520802, -9698723, -11772496, -11574455, -25083830, 4271862}, + }, + { + FieldElement{-25169565, -10053642, -19909332, 15361595, -5984358, 2159192, 75375, -4278529, -32526221, 8469673}, + FieldElement{15854970, 4148314, -8893890, 7259002, 11666551, 13824734, -30531198, 2697372, 24154791, -9460943}, + FieldElement{15446137, -15806644, 29759747, 14019369, 30811221, -9610191, -31582008, 12840104, 24913809, 9815020}, + }, + { + FieldElement{-4709286, -5614269, -31841498, -12288893, -14443537, 10799414, -9103676, 13438769, 18735128, 9466238}, + FieldElement{11933045, 9281483, 5081055, -5183824, -2628162, -4905629, -7727821, -10896103, -22728655, 16199064}, + FieldElement{14576810, 379472, -26786533, -8317236, -29426508, -10812974, -102766, 1876699, 30801119, 2164795}, + }, + { + FieldElement{15995086, 3199873, 13672555, 13712240, -19378835, -4647646, -13081610, -15496269, -13492807, 1268052}, + FieldElement{-10290614, -3659039, -3286592, 10948818, 23037027, 3794475, -3470338, -12600221, -17055369, 3565904}, + FieldElement{29210088, -9419337, -5919792, -4952785, 10834811, -13327726, -16512102, -10820713, -27162222, -14030531}, + }, + { + FieldElement{-13161890, 15508588, 16663704, -8156150, -28349942, 9019123, -29183421, -3769423, 2244111, -14001979}, + FieldElement{-5152875, -3800936, -9306475, -6071583, 16243069, 14684434, -25673088, -16180800, 13491506, 4641841}, + FieldElement{10813417, 643330, -19188515, -728916, 30292062, -16600078, 27548447, -7721242, 14476989, -12767431}, + }, + { + FieldElement{10292079, 9984945, 6481436, 8279905, -7251514, 7032743, 27282937, -1644259, -27912810, 12651324}, + FieldElement{-31185513, -813383, 22271204, 11835308, 10201545, 15351028, 17099662, 3988035, 21721536, -3148940}, + FieldElement{10202177, -6545839, -31373232, -9574638, -32150642, -8119683, -12906320, 3852694, 13216206, 14842320}, + }, + { + FieldElement{-15815640, -10601066, -6538952, -7258995, -6984659, -6581778, -31500847, 13765824, -27434397, 9900184}, + FieldElement{14465505, -13833331, -32133984, -14738873, -27443187, 12990492, 33046193, 15796406, -7051866, -8040114}, + FieldElement{30924417, -8279620, 6359016, -12816335, 16508377, 9071735, -25488601, 15413635, 9524356, -7018878}, + }, + { + FieldElement{12274201, -13175547, 32627641, -1785326, 6736625, 13267305, 5237659, -5109483, 15663516, 4035784}, + FieldElement{-2951309, 8903985, 17349946, 601635, -16432815, -4612556, -13732739, -15889334, -22258478, 4659091}, + FieldElement{-16916263, -4952973, -30393711, -15158821, 20774812, 15897498, 5736189, 15026997, -2178256, -13455585}, + }, + }, + { + { + FieldElement{-8858980, -2219056, 28571666, -10155518, -474467, -10105698, -3801496, 278095, 23440562, -290208}, + FieldElement{10226241, -5928702, 15139956, 120818, -14867693, 5218603, 32937275, 11551483, -16571960, -7442864}, + FieldElement{17932739, -12437276, -24039557, 10749060, 11316803, 7535897, 22503767, 5561594, -3646624, 3898661}, + }, + { + FieldElement{7749907, -969567, -16339731, -16464, -25018111, 15122143, -1573531, 7152530, 21831162, 1245233}, + FieldElement{26958459, -14658026, 4314586, 8346991, -5677764, 11960072, -32589295, -620035, -30402091, -16716212}, + FieldElement{-12165896, 9166947, 33491384, 13673479, 29787085, 13096535, 6280834, 14587357, -22338025, 13987525}, + }, + { + FieldElement{-24349909, 7778775, 21116000, 15572597, -4833266, -5357778, -4300898, -5124639, -7469781, -2858068}, + FieldElement{9681908, -6737123, -31951644, 13591838, -6883821, 386950, 31622781, 6439245, -14581012, 4091397}, + FieldElement{-8426427, 1470727, -28109679, -1596990, 3978627, -5123623, -19622683, 12092163, 29077877, -14741988}, + }, + { + FieldElement{5269168, -6859726, -13230211, -8020715, 25932563, 1763552, -5606110, -5505881, -20017847, 2357889}, + FieldElement{32264008, -15407652, -5387735, -1160093, -2091322, -3946900, 23104804, -12869908, 5727338, 189038}, + FieldElement{14609123, -8954470, -6000566, -16622781, -14577387, -7743898, -26745169, 10942115, -25888931, -14884697}, + }, + { + FieldElement{20513500, 5557931, -15604613, 7829531, 26413943, -2019404, -21378968, 7471781, 13913677, -5137875}, + FieldElement{-25574376, 11967826, 29233242, 12948236, -6754465, 4713227, -8940970, 14059180, 12878652, 8511905}, + FieldElement{-25656801, 3393631, -2955415, -7075526, -2250709, 9366908, -30223418, 6812974, 5568676, -3127656}, + }, + { + FieldElement{11630004, 12144454, 2116339, 13606037, 27378885, 15676917, -17408753, -13504373, -14395196, 8070818}, + FieldElement{27117696, -10007378, -31282771, -5570088, 1127282, 12772488, -29845906, 10483306, -11552749, -1028714}, + FieldElement{10637467, -5688064, 5674781, 1072708, -26343588, -6982302, -1683975, 9177853, -27493162, 15431203}, + }, + { + FieldElement{20525145, 10892566, -12742472, 12779443, -29493034, 16150075, -28240519, 14943142, -15056790, -7935931}, + FieldElement{-30024462, 5626926, -551567, -9981087, 753598, 11981191, 25244767, -3239766, -3356550, 9594024}, + FieldElement{-23752644, 2636870, -5163910, -10103818, 585134, 7877383, 11345683, -6492290, 13352335, -10977084}, + }, + { + FieldElement{-1931799, -5407458, 3304649, -12884869, 17015806, -4877091, -29783850, -7752482, -13215537, -319204}, + FieldElement{20239939, 6607058, 6203985, 3483793, -18386976, -779229, -20723742, 15077870, -22750759, 14523817}, + FieldElement{27406042, -6041657, 27423596, -4497394, 4996214, 10002360, -28842031, -4545494, -30172742, -4805667}, + }, + }, + { + { + FieldElement{11374242, 12660715, 17861383, -12540833, 10935568, 1099227, -13886076, -9091740, -27727044, 11358504}, + FieldElement{-12730809, 10311867, 1510375, 10778093, -2119455, -9145702, 32676003, 11149336, -26123651, 4985768}, + FieldElement{-19096303, 341147, -6197485, -239033, 15756973, -8796662, -983043, 13794114, -19414307, -15621255}, + }, + { + FieldElement{6490081, 11940286, 25495923, -7726360, 8668373, -8751316, 3367603, 6970005, -1691065, -9004790}, + FieldElement{1656497, 13457317, 15370807, 6364910, 13605745, 8362338, -19174622, -5475723, -16796596, -5031438}, + FieldElement{-22273315, -13524424, -64685, -4334223, -18605636, -10921968, -20571065, -7007978, -99853, -10237333}, + }, + { + FieldElement{17747465, 10039260, 19368299, -4050591, -20630635, -16041286, 31992683, -15857976, -29260363, -5511971}, + FieldElement{31932027, -4986141, -19612382, 16366580, 22023614, 88450, 11371999, -3744247, 4882242, -10626905}, + FieldElement{29796507, 37186, 19818052, 10115756, -11829032, 3352736, 18551198, 3272828, -5190932, -4162409}, + }, + { + FieldElement{12501286, 4044383, -8612957, -13392385, -32430052, 5136599, -19230378, -3529697, 330070, -3659409}, + FieldElement{6384877, 2899513, 17807477, 7663917, -2358888, 12363165, 25366522, -8573892, -271295, 12071499}, + FieldElement{-8365515, -4042521, 25133448, -4517355, -6211027, 2265927, -32769618, 1936675, -5159697, 3829363}, + }, + { + FieldElement{28425966, -5835433, -577090, -4697198, -14217555, 6870930, 7921550, -6567787, 26333140, 14267664}, + FieldElement{-11067219, 11871231, 27385719, -10559544, -4585914, -11189312, 10004786, -8709488, -21761224, 8930324}, + FieldElement{-21197785, -16396035, 25654216, -1725397, 12282012, 11008919, 1541940, 4757911, -26491501, -16408940}, + }, + { + FieldElement{13537262, -7759490, -20604840, 10961927, -5922820, -13218065, -13156584, 6217254, -15943699, 13814990}, + FieldElement{-17422573, 15157790, 18705543, 29619, 24409717, -260476, 27361681, 9257833, -1956526, -1776914}, + FieldElement{-25045300, -10191966, 15366585, 15166509, -13105086, 8423556, -29171540, 12361135, -18685978, 4578290}, + }, + { + FieldElement{24579768, 3711570, 1342322, -11180126, -27005135, 14124956, -22544529, 14074919, 21964432, 8235257}, + FieldElement{-6528613, -2411497, 9442966, -5925588, 12025640, -1487420, -2981514, -1669206, 13006806, 2355433}, + FieldElement{-16304899, -13605259, -6632427, -5142349, 16974359, -10911083, 27202044, 1719366, 1141648, -12796236}, + }, + { + FieldElement{-12863944, -13219986, -8318266, -11018091, -6810145, -4843894, 13475066, -3133972, 32674895, 13715045}, + FieldElement{11423335, -5468059, 32344216, 8962751, 24989809, 9241752, -13265253, 16086212, -28740881, -15642093}, + FieldElement{-1409668, 12530728, -6368726, 10847387, 19531186, -14132160, -11709148, 7791794, -27245943, 4383347}, + }, + }, + { + { + FieldElement{-28970898, 5271447, -1266009, -9736989, -12455236, 16732599, -4862407, -4906449, 27193557, 6245191}, + FieldElement{-15193956, 5362278, -1783893, 2695834, 4960227, 12840725, 23061898, 3260492, 22510453, 8577507}, + FieldElement{-12632451, 11257346, -32692994, 13548177, -721004, 10879011, 31168030, 13952092, -29571492, -3635906}, + }, + { + FieldElement{3877321, -9572739, 32416692, 5405324, -11004407, -13656635, 3759769, 11935320, 5611860, 8164018}, + FieldElement{-16275802, 14667797, 15906460, 12155291, -22111149, -9039718, 32003002, -8832289, 5773085, -8422109}, + FieldElement{-23788118, -8254300, 1950875, 8937633, 18686727, 16459170, -905725, 12376320, 31632953, 190926}, + }, + { + FieldElement{-24593607, -16138885, -8423991, 13378746, 14162407, 6901328, -8288749, 4508564, -25341555, -3627528}, + FieldElement{8884438, -5884009, 6023974, 10104341, -6881569, -4941533, 18722941, -14786005, -1672488, 827625}, + FieldElement{-32720583, -16289296, -32503547, 7101210, 13354605, 2659080, -1800575, -14108036, -24878478, 1541286}, + }, + { + FieldElement{2901347, -1117687, 3880376, -10059388, -17620940, -3612781, -21802117, -3567481, 20456845, -1885033}, + FieldElement{27019610, 12299467, -13658288, -1603234, -12861660, -4861471, -19540150, -5016058, 29439641, 15138866}, + FieldElement{21536104, -6626420, -32447818, -10690208, -22408077, 5175814, -5420040, -16361163, 7779328, 109896}, + }, + { + FieldElement{30279744, 14648750, -8044871, 6425558, 13639621, -743509, 28698390, 12180118, 23177719, -554075}, + FieldElement{26572847, 3405927, -31701700, 12890905, -19265668, 5335866, -6493768, 2378492, 4439158, -13279347}, + FieldElement{-22716706, 3489070, -9225266, -332753, 18875722, -1140095, 14819434, -12731527, -17717757, -5461437}, + }, + { + FieldElement{-5056483, 16566551, 15953661, 3767752, -10436499, 15627060, -820954, 2177225, 8550082, -15114165}, + FieldElement{-18473302, 16596775, -381660, 15663611, 22860960, 15585581, -27844109, -3582739, -23260460, -8428588}, + FieldElement{-32480551, 15707275, -8205912, -5652081, 29464558, 2713815, -22725137, 15860482, -21902570, 1494193}, + }, + { + FieldElement{-19562091, -14087393, -25583872, -9299552, 13127842, 759709, 21923482, 16529112, 8742704, 12967017}, + FieldElement{-28464899, 1553205, 32536856, -10473729, -24691605, -406174, -8914625, -2933896, -29903758, 15553883}, + FieldElement{21877909, 3230008, 9881174, 10539357, -4797115, 2841332, 11543572, 14513274, 19375923, -12647961}, + }, + { + FieldElement{8832269, -14495485, 13253511, 5137575, 5037871, 4078777, 24880818, -6222716, 2862653, 9455043}, + FieldElement{29306751, 5123106, 20245049, -14149889, 9592566, 8447059, -2077124, -2990080, 15511449, 4789663}, + FieldElement{-20679756, 7004547, 8824831, -9434977, -4045704, -3750736, -5754762, 108893, 23513200, 16652362}, + }, + }, + { + { + FieldElement{-33256173, 4144782, -4476029, -6579123, 10770039, -7155542, -6650416, -12936300, -18319198, 10212860}, + FieldElement{2756081, 8598110, 7383731, -6859892, 22312759, -1105012, 21179801, 2600940, -9988298, -12506466}, + FieldElement{-24645692, 13317462, -30449259, -15653928, 21365574, -10869657, 11344424, 864440, -2499677, -16710063}, + }, + { + FieldElement{-26432803, 6148329, -17184412, -14474154, 18782929, -275997, -22561534, 211300, 2719757, 4940997}, + FieldElement{-1323882, 3911313, -6948744, 14759765, -30027150, 7851207, 21690126, 8518463, 26699843, 5276295}, + FieldElement{-13149873, -6429067, 9396249, 365013, 24703301, -10488939, 1321586, 149635, -15452774, 7159369}, + }, + { + FieldElement{9987780, -3404759, 17507962, 9505530, 9731535, -2165514, 22356009, 8312176, 22477218, -8403385}, + FieldElement{18155857, -16504990, 19744716, 9006923, 15154154, -10538976, 24256460, -4864995, -22548173, 9334109}, + FieldElement{2986088, -4911893, 10776628, -3473844, 10620590, -7083203, -21413845, 14253545, -22587149, 536906}, + }, + { + FieldElement{4377756, 8115836, 24567078, 15495314, 11625074, 13064599, 7390551, 10589625, 10838060, -15420424}, + FieldElement{-19342404, 867880, 9277171, -3218459, -14431572, -1986443, 19295826, -15796950, 6378260, 699185}, + FieldElement{7895026, 4057113, -7081772, -13077756, -17886831, -323126, -716039, 15693155, -5045064, -13373962}, + }, + { + FieldElement{-7737563, -5869402, -14566319, -7406919, 11385654, 13201616, 31730678, -10962840, -3918636, -9669325}, + FieldElement{10188286, -15770834, -7336361, 13427543, 22223443, 14896287, 30743455, 7116568, -21786507, 5427593}, + FieldElement{696102, 13206899, 27047647, -10632082, 15285305, -9853179, 10798490, -4578720, 19236243, 12477404}, + }, + { + FieldElement{-11229439, 11243796, -17054270, -8040865, -788228, -8167967, -3897669, 11180504, -23169516, 7733644}, + FieldElement{17800790, -14036179, -27000429, -11766671, 23887827, 3149671, 23466177, -10538171, 10322027, 15313801}, + FieldElement{26246234, 11968874, 32263343, -5468728, 6830755, -13323031, -15794704, -101982, -24449242, 10890804}, + }, + { + FieldElement{-31365647, 10271363, -12660625, -6267268, 16690207, -13062544, -14982212, 16484931, 25180797, -5334884}, + FieldElement{-586574, 10376444, -32586414, -11286356, 19801893, 10997610, 2276632, 9482883, 316878, 13820577}, + FieldElement{-9882808, -4510367, -2115506, 16457136, -11100081, 11674996, 30756178, -7515054, 30696930, -3712849}, + }, + { + FieldElement{32988917, -9603412, 12499366, 7910787, -10617257, -11931514, -7342816, -9985397, -32349517, 7392473}, + FieldElement{-8855661, 15927861, 9866406, -3649411, -2396914, -16655781, -30409476, -9134995, 25112947, -2926644}, + FieldElement{-2504044, -436966, 25621774, -5678772, 15085042, -5479877, -24884878, -13526194, 5537438, -13914319}, + }, + }, + { + { + FieldElement{-11225584, 2320285, -9584280, 10149187, -33444663, 5808648, -14876251, -1729667, 31234590, 6090599}, + FieldElement{-9633316, 116426, 26083934, 2897444, -6364437, -2688086, 609721, 15878753, -6970405, -9034768}, + FieldElement{-27757857, 247744, -15194774, -9002551, 23288161, -10011936, -23869595, 6503646, 20650474, 1804084}, + }, + { + FieldElement{-27589786, 15456424, 8972517, 8469608, 15640622, 4439847, 3121995, -10329713, 27842616, -202328}, + FieldElement{-15306973, 2839644, 22530074, 10026331, 4602058, 5048462, 28248656, 5031932, -11375082, 12714369}, + FieldElement{20807691, -7270825, 29286141, 11421711, -27876523, -13868230, -21227475, 1035546, -19733229, 12796920}, + }, + { + FieldElement{12076899, -14301286, -8785001, -11848922, -25012791, 16400684, -17591495, -12899438, 3480665, -15182815}, + FieldElement{-32361549, 5457597, 28548107, 7833186, 7303070, -11953545, -24363064, -15921875, -33374054, 2771025}, + FieldElement{-21389266, 421932, 26597266, 6860826, 22486084, -6737172, -17137485, -4210226, -24552282, 15673397}, + }, + { + FieldElement{-20184622, 2338216, 19788685, -9620956, -4001265, -8740893, -20271184, 4733254, 3727144, -12934448}, + FieldElement{6120119, 814863, -11794402, -622716, 6812205, -15747771, 2019594, 7975683, 31123697, -10958981}, + FieldElement{30069250, -11435332, 30434654, 2958439, 18399564, -976289, 12296869, 9204260, -16432438, 9648165}, + }, + { + FieldElement{32705432, -1550977, 30705658, 7451065, -11805606, 9631813, 3305266, 5248604, -26008332, -11377501}, + FieldElement{17219865, 2375039, -31570947, -5575615, -19459679, 9219903, 294711, 15298639, 2662509, -16297073}, + FieldElement{-1172927, -7558695, -4366770, -4287744, -21346413, -8434326, 32087529, -1222777, 32247248, -14389861}, + }, + { + FieldElement{14312628, 1221556, 17395390, -8700143, -4945741, -8684635, -28197744, -9637817, -16027623, -13378845}, + FieldElement{-1428825, -9678990, -9235681, 6549687, -7383069, -468664, 23046502, 9803137, 17597934, 2346211}, + FieldElement{18510800, 15337574, 26171504, 981392, -22241552, 7827556, -23491134, -11323352, 3059833, -11782870}, + }, + { + FieldElement{10141598, 6082907, 17829293, -1947643, 9830092, 13613136, -25556636, -5544586, -33502212, 3592096}, + FieldElement{33114168, -15889352, -26525686, -13343397, 33076705, 8716171, 1151462, 1521897, -982665, -6837803}, + FieldElement{-32939165, -4255815, 23947181, -324178, -33072974, -12305637, -16637686, 3891704, 26353178, 693168}, + }, + { + FieldElement{30374239, 1595580, -16884039, 13186931, 4600344, 406904, 9585294, -400668, 31375464, 14369965}, + FieldElement{-14370654, -7772529, 1510301, 6434173, -18784789, -6262728, 32732230, -13108839, 17901441, 16011505}, + FieldElement{18171223, -11934626, -12500402, 15197122, -11038147, -15230035, -19172240, -16046376, 8764035, 12309598}, + }, + }, + { + { + FieldElement{5975908, -5243188, -19459362, -9681747, -11541277, 14015782, -23665757, 1228319, 17544096, -10593782}, + FieldElement{5811932, -1715293, 3442887, -2269310, -18367348, -8359541, -18044043, -15410127, -5565381, 12348900}, + FieldElement{-31399660, 11407555, 25755363, 6891399, -3256938, 14872274, -24849353, 8141295, -10632534, -585479}, + }, + { + FieldElement{-12675304, 694026, -5076145, 13300344, 14015258, -14451394, -9698672, -11329050, 30944593, 1130208}, + FieldElement{8247766, -6710942, -26562381, -7709309, -14401939, -14648910, 4652152, 2488540, 23550156, -271232}, + FieldElement{17294316, -3788438, 7026748, 15626851, 22990044, 113481, 2267737, -5908146, -408818, -137719}, + }, + { + FieldElement{16091085, -16253926, 18599252, 7340678, 2137637, -1221657, -3364161, 14550936, 3260525, -7166271}, + FieldElement{-4910104, -13332887, 18550887, 10864893, -16459325, -7291596, -23028869, -13204905, -12748722, 2701326}, + FieldElement{-8574695, 16099415, 4629974, -16340524, -20786213, -6005432, -10018363, 9276971, 11329923, 1862132}, + }, + { + FieldElement{14763076, -15903608, -30918270, 3689867, 3511892, 10313526, -21951088, 12219231, -9037963, -940300}, + FieldElement{8894987, -3446094, 6150753, 3013931, 301220, 15693451, -31981216, -2909717, -15438168, 11595570}, + FieldElement{15214962, 3537601, -26238722, -14058872, 4418657, -15230761, 13947276, 10730794, -13489462, -4363670}, + }, + { + FieldElement{-2538306, 7682793, 32759013, 263109, -29984731, -7955452, -22332124, -10188635, 977108, 699994}, + FieldElement{-12466472, 4195084, -9211532, 550904, -15565337, 12917920, 19118110, -439841, -30534533, -14337913}, + FieldElement{31788461, -14507657, 4799989, 7372237, 8808585, -14747943, 9408237, -10051775, 12493932, -5409317}, + }, + { + FieldElement{-25680606, 5260744, -19235809, -6284470, -3695942, 16566087, 27218280, 2607121, 29375955, 6024730}, + FieldElement{842132, -2794693, -4763381, -8722815, 26332018, -12405641, 11831880, 6985184, -9940361, 2854096}, + FieldElement{-4847262, -7969331, 2516242, -5847713, 9695691, -7221186, 16512645, 960770, 12121869, 16648078}, + }, + { + FieldElement{-15218652, 14667096, -13336229, 2013717, 30598287, -464137, -31504922, -7882064, 20237806, 2838411}, + FieldElement{-19288047, 4453152, 15298546, -16178388, 22115043, -15972604, 12544294, -13470457, 1068881, -12499905}, + FieldElement{-9558883, -16518835, 33238498, 13506958, 30505848, -1114596, -8486907, -2630053, 12521378, 4845654}, + }, + { + FieldElement{-28198521, 10744108, -2958380, 10199664, 7759311, -13088600, 3409348, -873400, -6482306, -12885870}, + FieldElement{-23561822, 6230156, -20382013, 10655314, -24040585, -11621172, 10477734, -1240216, -3113227, 13974498}, + FieldElement{12966261, 15550616, -32038948, -1615346, 21025980, -629444, 5642325, 7188737, 18895762, 12629579}, + }, + }, + { + { + FieldElement{14741879, -14946887, 22177208, -11721237, 1279741, 8058600, 11758140, 789443, 32195181, 3895677}, + FieldElement{10758205, 15755439, -4509950, 9243698, -4879422, 6879879, -2204575, -3566119, -8982069, 4429647}, + FieldElement{-2453894, 15725973, -20436342, -10410672, -5803908, -11040220, -7135870, -11642895, 18047436, -15281743}, + }, + { + FieldElement{-25173001, -11307165, 29759956, 11776784, -22262383, -15820455, 10993114, -12850837, -17620701, -9408468}, + FieldElement{21987233, 700364, -24505048, 14972008, -7774265, -5718395, 32155026, 2581431, -29958985, 8773375}, + FieldElement{-25568350, 454463, -13211935, 16126715, 25240068, 8594567, 20656846, 12017935, -7874389, -13920155}, + }, + { + FieldElement{6028182, 6263078, -31011806, -11301710, -818919, 2461772, -31841174, -5468042, -1721788, -2776725}, + FieldElement{-12278994, 16624277, 987579, -5922598, 32908203, 1248608, 7719845, -4166698, 28408820, 6816612}, + FieldElement{-10358094, -8237829, 19549651, -12169222, 22082623, 16147817, 20613181, 13982702, -10339570, 5067943}, + }, + { + FieldElement{-30505967, -3821767, 12074681, 13582412, -19877972, 2443951, -19719286, 12746132, 5331210, -10105944}, + FieldElement{30528811, 3601899, -1957090, 4619785, -27361822, -15436388, 24180793, -12570394, 27679908, -1648928}, + FieldElement{9402404, -13957065, 32834043, 10838634, -26580150, -13237195, 26653274, -8685565, 22611444, -12715406}, + }, + { + FieldElement{22190590, 1118029, 22736441, 15130463, -30460692, -5991321, 19189625, -4648942, 4854859, 6622139}, + FieldElement{-8310738, -2953450, -8262579, -3388049, -10401731, -271929, 13424426, -3567227, 26404409, 13001963}, + FieldElement{-31241838, -15415700, -2994250, 8939346, 11562230, -12840670, -26064365, -11621720, -15405155, 11020693}, + }, + { + FieldElement{1866042, -7949489, -7898649, -10301010, 12483315, 13477547, 3175636, -12424163, 28761762, 1406734}, + FieldElement{-448555, -1777666, 13018551, 3194501, -9580420, -11161737, 24760585, -4347088, 25577411, -13378680}, + FieldElement{-24290378, 4759345, -690653, -1852816, 2066747, 10693769, -29595790, 9884936, -9368926, 4745410}, + }, + { + FieldElement{-9141284, 6049714, -19531061, -4341411, -31260798, 9944276, -15462008, -11311852, 10931924, -11931931}, + FieldElement{-16561513, 14112680, -8012645, 4817318, -8040464, -11414606, -22853429, 10856641, -20470770, 13434654}, + FieldElement{22759489, -10073434, -16766264, -1871422, 13637442, -10168091, 1765144, -12654326, 28445307, -5364710}, + }, + { + FieldElement{29875063, 12493613, 2795536, -3786330, 1710620, 15181182, -10195717, -8788675, 9074234, 1167180}, + FieldElement{-26205683, 11014233, -9842651, -2635485, -26908120, 7532294, -18716888, -9535498, 3843903, 9367684}, + FieldElement{-10969595, -6403711, 9591134, 9582310, 11349256, 108879, 16235123, 8601684, -139197, 4242895}, + }, + }, + { + { + FieldElement{22092954, -13191123, -2042793, -11968512, 32186753, -11517388, -6574341, 2470660, -27417366, 16625501}, + FieldElement{-11057722, 3042016, 13770083, -9257922, 584236, -544855, -7770857, 2602725, -27351616, 14247413}, + FieldElement{6314175, -10264892, -32772502, 15957557, -10157730, 168750, -8618807, 14290061, 27108877, -1180880}, + }, + { + FieldElement{-8586597, -7170966, 13241782, 10960156, -32991015, -13794596, 33547976, -11058889, -27148451, 981874}, + FieldElement{22833440, 9293594, -32649448, -13618667, -9136966, 14756819, -22928859, -13970780, -10479804, -16197962}, + FieldElement{-7768587, 3326786, -28111797, 10783824, 19178761, 14905060, 22680049, 13906969, -15933690, 3797899}, + }, + { + FieldElement{21721356, -4212746, -12206123, 9310182, -3882239, -13653110, 23740224, -2709232, 20491983, -8042152}, + FieldElement{9209270, -15135055, -13256557, -6167798, -731016, 15289673, 25947805, 15286587, 30997318, -6703063}, + FieldElement{7392032, 16618386, 23946583, -8039892, -13265164, -1533858, -14197445, -2321576, 17649998, -250080}, + }, + { + FieldElement{-9301088, -14193827, 30609526, -3049543, -25175069, -1283752, -15241566, -9525724, -2233253, 7662146}, + FieldElement{-17558673, 1763594, -33114336, 15908610, -30040870, -12174295, 7335080, -8472199, -3174674, 3440183}, + FieldElement{-19889700, -5977008, -24111293, -9688870, 10799743, -16571957, 40450, -4431835, 4862400, 1133}, + }, + { + FieldElement{-32856209, -7873957, -5422389, 14860950, -16319031, 7956142, 7258061, 311861, -30594991, -7379421}, + FieldElement{-3773428, -1565936, 28985340, 7499440, 24445838, 9325937, 29727763, 16527196, 18278453, 15405622}, + FieldElement{-4381906, 8508652, -19898366, -3674424, -5984453, 15149970, -13313598, 843523, -21875062, 13626197}, + }, + { + FieldElement{2281448, -13487055, -10915418, -2609910, 1879358, 16164207, -10783882, 3953792, 13340839, 15928663}, + FieldElement{31727126, -7179855, -18437503, -8283652, 2875793, -16390330, -25269894, -7014826, -23452306, 5964753}, + FieldElement{4100420, -5959452, -17179337, 6017714, -18705837, 12227141, -26684835, 11344144, 2538215, -7570755}, + }, + { + FieldElement{-9433605, 6123113, 11159803, -2156608, 30016280, 14966241, -20474983, 1485421, -629256, -15958862}, + FieldElement{-26804558, 4260919, 11851389, 9658551, -32017107, 16367492, -20205425, -13191288, 11659922, -11115118}, + FieldElement{26180396, 10015009, -30844224, -8581293, 5418197, 9480663, 2231568, -10170080, 33100372, -1306171}, + }, + { + FieldElement{15121113, -5201871, -10389905, 15427821, -27509937, -15992507, 21670947, 4486675, -5931810, -14466380}, + FieldElement{16166486, -9483733, -11104130, 6023908, -31926798, -1364923, 2340060, -16254968, -10735770, -10039824}, + FieldElement{28042865, -3557089, -12126526, 12259706, -3717498, -6945899, 6766453, -8689599, 18036436, 5803270}, + }, + }, + { + { + FieldElement{-817581, 6763912, 11803561, 1585585, 10958447, -2671165, 23855391, 4598332, -6159431, -14117438}, + FieldElement{-31031306, -14256194, 17332029, -2383520, 31312682, -5967183, 696309, 50292, -20095739, 11763584}, + FieldElement{-594563, -2514283, -32234153, 12643980, 12650761, 14811489, 665117, -12613632, -19773211, -10713562}, + }, + { + FieldElement{30464590, -11262872, -4127476, -12734478, 19835327, -7105613, -24396175, 2075773, -17020157, 992471}, + FieldElement{18357185, -6994433, 7766382, 16342475, -29324918, 411174, 14578841, 8080033, -11574335, -10601610}, + FieldElement{19598397, 10334610, 12555054, 2555664, 18821899, -10339780, 21873263, 16014234, 26224780, 16452269}, + }, + { + FieldElement{-30223925, 5145196, 5944548, 16385966, 3976735, 2009897, -11377804, -7618186, -20533829, 3698650}, + FieldElement{14187449, 3448569, -10636236, -10810935, -22663880, -3433596, 7268410, -10890444, 27394301, 12015369}, + FieldElement{19695761, 16087646, 28032085, 12999827, 6817792, 11427614, 20244189, -1312777, -13259127, -3402461}, + }, + { + FieldElement{30860103, 12735208, -1888245, -4699734, -16974906, 2256940, -8166013, 12298312, -8550524, -10393462}, + FieldElement{-5719826, -11245325, -1910649, 15569035, 26642876, -7587760, -5789354, -15118654, -4976164, 12651793}, + FieldElement{-2848395, 9953421, 11531313, -5282879, 26895123, -12697089, -13118820, -16517902, 9768698, -2533218}, + }, + { + FieldElement{-24719459, 1894651, -287698, -4704085, 15348719, -8156530, 32767513, 12765450, 4940095, 10678226}, + FieldElement{18860224, 15980149, -18987240, -1562570, -26233012, -11071856, -7843882, 13944024, -24372348, 16582019}, + FieldElement{-15504260, 4970268, -29893044, 4175593, -20993212, -2199756, -11704054, 15444560, -11003761, 7989037}, + }, + { + FieldElement{31490452, 5568061, -2412803, 2182383, -32336847, 4531686, -32078269, 6200206, -19686113, -14800171}, + FieldElement{-17308668, -15879940, -31522777, -2831, -32887382, 16375549, 8680158, -16371713, 28550068, -6857132}, + FieldElement{-28126887, -5688091, 16837845, -1820458, -6850681, 12700016, -30039981, 4364038, 1155602, 5988841}, + }, + { + FieldElement{21890435, -13272907, -12624011, 12154349, -7831873, 15300496, 23148983, -4470481, 24618407, 8283181}, + FieldElement{-33136107, -10512751, 9975416, 6841041, -31559793, 16356536, 3070187, -7025928, 1466169, 10740210}, + FieldElement{-1509399, -15488185, -13503385, -10655916, 32799044, 909394, -13938903, -5779719, -32164649, -15327040}, + }, + { + FieldElement{3960823, -14267803, -28026090, -15918051, -19404858, 13146868, 15567327, 951507, -3260321, -573935}, + FieldElement{24740841, 5052253, -30094131, 8961361, 25877428, 6165135, -24368180, 14397372, -7380369, -6144105}, + FieldElement{-28888365, 3510803, -28103278, -1158478, -11238128, -10631454, -15441463, -14453128, -1625486, -6494814}, + }, + }, + { + { + FieldElement{793299, -9230478, 8836302, -6235707, -27360908, -2369593, 33152843, -4885251, -9906200, -621852}, + FieldElement{5666233, 525582, 20782575, -8038419, -24538499, 14657740, 16099374, 1468826, -6171428, -15186581}, + FieldElement{-4859255, -3779343, -2917758, -6748019, 7778750, 11688288, -30404353, -9871238, -1558923, -9863646}, + }, + { + FieldElement{10896332, -7719704, 824275, 472601, -19460308, 3009587, 25248958, 14783338, -30581476, -15757844}, + FieldElement{10566929, 12612572, -31944212, 11118703, -12633376, 12362879, 21752402, 8822496, 24003793, 14264025}, + FieldElement{27713862, -7355973, -11008240, 9227530, 27050101, 2504721, 23886875, -13117525, 13958495, -5732453}, + }, + { + FieldElement{-23481610, 4867226, -27247128, 3900521, 29838369, -8212291, -31889399, -10041781, 7340521, -15410068}, + FieldElement{4646514, -8011124, -22766023, -11532654, 23184553, 8566613, 31366726, -1381061, -15066784, -10375192}, + FieldElement{-17270517, 12723032, -16993061, 14878794, 21619651, -6197576, 27584817, 3093888, -8843694, 3849921}, + }, + { + FieldElement{-9064912, 2103172, 25561640, -15125738, -5239824, 9582958, 32477045, -9017955, 5002294, -15550259}, + FieldElement{-12057553, -11177906, 21115585, -13365155, 8808712, -12030708, 16489530, 13378448, -25845716, 12741426}, + FieldElement{-5946367, 10645103, -30911586, 15390284, -3286982, -7118677, 24306472, 15852464, 28834118, -7646072}, + }, + { + FieldElement{-17335748, -9107057, -24531279, 9434953, -8472084, -583362, -13090771, 455841, 20461858, 5491305}, + FieldElement{13669248, -16095482, -12481974, -10203039, -14569770, -11893198, -24995986, 11293807, -28588204, -9421832}, + FieldElement{28497928, 6272777, -33022994, 14470570, 8906179, -1225630, 18504674, -14165166, 29867745, -8795943}, + }, + { + FieldElement{-16207023, 13517196, -27799630, -13697798, 24009064, -6373891, -6367600, -13175392, 22853429, -4012011}, + FieldElement{24191378, 16712145, -13931797, 15217831, 14542237, 1646131, 18603514, -11037887, 12876623, -2112447}, + FieldElement{17902668, 4518229, -411702, -2829247, 26878217, 5258055, -12860753, 608397, 16031844, 3723494}, + }, + { + FieldElement{-28632773, 12763728, -20446446, 7577504, 33001348, -13017745, 17558842, -7872890, 23896954, -4314245}, + FieldElement{-20005381, -12011952, 31520464, 605201, 2543521, 5991821, -2945064, 7229064, -9919646, -8826859}, + FieldElement{28816045, 298879, -28165016, -15920938, 19000928, -1665890, -12680833, -2949325, -18051778, -2082915}, + }, + { + FieldElement{16000882, -344896, 3493092, -11447198, -29504595, -13159789, 12577740, 16041268, -19715240, 7847707}, + FieldElement{10151868, 10572098, 27312476, 7922682, 14825339, 4723128, -32855931, -6519018, -10020567, 3852848}, + FieldElement{-11430470, 15697596, -21121557, -4420647, 5386314, 15063598, 16514493, -15932110, 29330899, -15076224}, + }, + }, + { + { + FieldElement{-25499735, -4378794, -15222908, -6901211, 16615731, 2051784, 3303702, 15490, -27548796, 12314391}, + FieldElement{15683520, -6003043, 18109120, -9980648, 15337968, -5997823, -16717435, 15921866, 16103996, -3731215}, + FieldElement{-23169824, -10781249, 13588192, -1628807, -3798557, -1074929, -19273607, 5402699, -29815713, -9841101}, + }, + { + FieldElement{23190676, 2384583, -32714340, 3462154, -29903655, -1529132, -11266856, 8911517, -25205859, 2739713}, + FieldElement{21374101, -3554250, -33524649, 9874411, 15377179, 11831242, -33529904, 6134907, 4931255, 11987849}, + FieldElement{-7732, -2978858, -16223486, 7277597, 105524, -322051, -31480539, 13861388, -30076310, 10117930}, + }, + { + FieldElement{-29501170, -10744872, -26163768, 13051539, -25625564, 5089643, -6325503, 6704079, 12890019, 15728940}, + FieldElement{-21972360, -11771379, -951059, -4418840, 14704840, 2695116, 903376, -10428139, 12885167, 8311031}, + FieldElement{-17516482, 5352194, 10384213, -13811658, 7506451, 13453191, 26423267, 4384730, 1888765, -5435404}, + }, + { + FieldElement{-25817338, -3107312, -13494599, -3182506, 30896459, -13921729, -32251644, -12707869, -19464434, -3340243}, + FieldElement{-23607977, -2665774, -526091, 4651136, 5765089, 4618330, 6092245, 14845197, 17151279, -9854116}, + FieldElement{-24830458, -12733720, -15165978, 10367250, -29530908, -265356, 22825805, -7087279, -16866484, 16176525}, + }, + { + FieldElement{-23583256, 6564961, 20063689, 3798228, -4740178, 7359225, 2006182, -10363426, -28746253, -10197509}, + FieldElement{-10626600, -4486402, -13320562, -5125317, 3432136, -6393229, 23632037, -1940610, 32808310, 1099883}, + FieldElement{15030977, 5768825, -27451236, -2887299, -6427378, -15361371, -15277896, -6809350, 2051441, -15225865}, + }, + { + FieldElement{-3362323, -7239372, 7517890, 9824992, 23555850, 295369, 5148398, -14154188, -22686354, 16633660}, + FieldElement{4577086, -16752288, 13249841, -15304328, 19958763, -14537274, 18559670, -10759549, 8402478, -9864273}, + FieldElement{-28406330, -1051581, -26790155, -907698, -17212414, -11030789, 9453451, -14980072, 17983010, 9967138}, + }, + { + FieldElement{-25762494, 6524722, 26585488, 9969270, 24709298, 1220360, -1677990, 7806337, 17507396, 3651560}, + FieldElement{-10420457, -4118111, 14584639, 15971087, -15768321, 8861010, 26556809, -5574557, -18553322, -11357135}, + FieldElement{2839101, 14284142, 4029895, 3472686, 14402957, 12689363, -26642121, 8459447, -5605463, -7621941}, + }, + { + FieldElement{-4839289, -3535444, 9744961, 2871048, 25113978, 3187018, -25110813, -849066, 17258084, -7977739}, + FieldElement{18164541, -10595176, -17154882, -1542417, 19237078, -9745295, 23357533, -15217008, 26908270, 12150756}, + FieldElement{-30264870, -7647865, 5112249, -7036672, -1499807, -6974257, 43168, -5537701, -32302074, 16215819}, + }, + }, + { + { + FieldElement{-6898905, 9824394, -12304779, -4401089, -31397141, -6276835, 32574489, 12532905, -7503072, -8675347}, + FieldElement{-27343522, -16515468, -27151524, -10722951, 946346, 16291093, 254968, 7168080, 21676107, -1943028}, + FieldElement{21260961, -8424752, -16831886, -11920822, -23677961, 3968121, -3651949, -6215466, -3556191, -7913075}, + }, + { + FieldElement{16544754, 13250366, -16804428, 15546242, -4583003, 12757258, -2462308, -8680336, -18907032, -9662799}, + FieldElement{-2415239, -15577728, 18312303, 4964443, -15272530, -12653564, 26820651, 16690659, 25459437, -4564609}, + FieldElement{-25144690, 11425020, 28423002, -11020557, -6144921, -15826224, 9142795, -2391602, -6432418, -1644817}, + }, + { + FieldElement{-23104652, 6253476, 16964147, -3768872, -25113972, -12296437, -27457225, -16344658, 6335692, 7249989}, + FieldElement{-30333227, 13979675, 7503222, -12368314, -11956721, -4621693, -30272269, 2682242, 25993170, -12478523}, + FieldElement{4364628, 5930691, 32304656, -10044554, -8054781, 15091131, 22857016, -10598955, 31820368, 15075278}, + }, + { + FieldElement{31879134, -8918693, 17258761, 90626, -8041836, -4917709, 24162788, -9650886, -17970238, 12833045}, + FieldElement{19073683, 14851414, -24403169, -11860168, 7625278, 11091125, -19619190, 2074449, -9413939, 14905377}, + FieldElement{24483667, -11935567, -2518866, -11547418, -1553130, 15355506, -25282080, 9253129, 27628530, -7555480}, + }, + { + FieldElement{17597607, 8340603, 19355617, 552187, 26198470, -3176583, 4593324, -9157582, -14110875, 15297016}, + FieldElement{510886, 14337390, -31785257, 16638632, 6328095, 2713355, -20217417, -11864220, 8683221, 2921426}, + FieldElement{18606791, 11874196, 27155355, -5281482, -24031742, 6265446, -25178240, -1278924, 4674690, 13890525}, + }, + { + FieldElement{13609624, 13069022, -27372361, -13055908, 24360586, 9592974, 14977157, 9835105, 4389687, 288396}, + FieldElement{9922506, -519394, 13613107, 5883594, -18758345, -434263, -12304062, 8317628, 23388070, 16052080}, + FieldElement{12720016, 11937594, -31970060, -5028689, 26900120, 8561328, -20155687, -11632979, -14754271, -10812892}, + }, + { + FieldElement{15961858, 14150409, 26716931, -665832, -22794328, 13603569, 11829573, 7467844, -28822128, 929275}, + FieldElement{11038231, -11582396, -27310482, -7316562, -10498527, -16307831, -23479533, -9371869, -21393143, 2465074}, + FieldElement{20017163, -4323226, 27915242, 1529148, 12396362, 15675764, 13817261, -9658066, 2463391, -4622140}, + }, + { + FieldElement{-16358878, -12663911, -12065183, 4996454, -1256422, 1073572, 9583558, 12851107, 4003896, 12673717}, + FieldElement{-1731589, -15155870, -3262930, 16143082, 19294135, 13385325, 14741514, -9103726, 7903886, 2348101}, + FieldElement{24536016, -16515207, 12715592, -3862155, 1511293, 10047386, -3842346, -7129159, -28377538, 10048127}, + }, + }, + { + { + FieldElement{-12622226, -6204820, 30718825, 2591312, -10617028, 12192840, 18873298, -7297090, -32297756, 15221632}, + FieldElement{-26478122, -11103864, 11546244, -1852483, 9180880, 7656409, -21343950, 2095755, 29769758, 6593415}, + FieldElement{-31994208, -2907461, 4176912, 3264766, 12538965, -868111, 26312345, -6118678, 30958054, 8292160}, + }, + { + FieldElement{31429822, -13959116, 29173532, 15632448, 12174511, -2760094, 32808831, 3977186, 26143136, -3148876}, + FieldElement{22648901, 1402143, -22799984, 13746059, 7936347, 365344, -8668633, -1674433, -3758243, -2304625}, + FieldElement{-15491917, 8012313, -2514730, -12702462, -23965846, -10254029, -1612713, -1535569, -16664475, 8194478}, + }, + { + FieldElement{27338066, -7507420, -7414224, 10140405, -19026427, -6589889, 27277191, 8855376, 28572286, 3005164}, + FieldElement{26287124, 4821776, 25476601, -4145903, -3764513, -15788984, -18008582, 1182479, -26094821, -13079595}, + FieldElement{-7171154, 3178080, 23970071, 6201893, -17195577, -4489192, -21876275, -13982627, 32208683, -1198248}, + }, + { + FieldElement{-16657702, 2817643, -10286362, 14811298, 6024667, 13349505, -27315504, -10497842, -27672585, -11539858}, + FieldElement{15941029, -9405932, -21367050, 8062055, 31876073, -238629, -15278393, -1444429, 15397331, -4130193}, + FieldElement{8934485, -13485467, -23286397, -13423241, -32446090, 14047986, 31170398, -1441021, -27505566, 15087184}, + }, + { + FieldElement{-18357243, -2156491, 24524913, -16677868, 15520427, -6360776, -15502406, 11461896, 16788528, -5868942}, + FieldElement{-1947386, 16013773, 21750665, 3714552, -17401782, -16055433, -3770287, -10323320, 31322514, -11615635}, + FieldElement{21426655, -5650218, -13648287, -5347537, -28812189, -4920970, -18275391, -14621414, 13040862, -12112948}, + }, + { + FieldElement{11293895, 12478086, -27136401, 15083750, -29307421, 14748872, 14555558, -13417103, 1613711, 4896935}, + FieldElement{-25894883, 15323294, -8489791, -8057900, 25967126, -13425460, 2825960, -4897045, -23971776, -11267415}, + FieldElement{-15924766, -5229880, -17443532, 6410664, 3622847, 10243618, 20615400, 12405433, -23753030, -8436416}, + }, + { + FieldElement{-7091295, 12556208, -20191352, 9025187, -17072479, 4333801, 4378436, 2432030, 23097949, -566018}, + FieldElement{4565804, -16025654, 20084412, -7842817, 1724999, 189254, 24767264, 10103221, -18512313, 2424778}, + FieldElement{366633, -11976806, 8173090, -6890119, 30788634, 5745705, -7168678, 1344109, -3642553, 12412659}, + }, + { + FieldElement{-24001791, 7690286, 14929416, -168257, -32210835, -13412986, 24162697, -15326504, -3141501, 11179385}, + FieldElement{18289522, -14724954, 8056945, 16430056, -21729724, 7842514, -6001441, -1486897, -18684645, -11443503}, + FieldElement{476239, 6601091, -6152790, -9723375, 17503545, -4863900, 27672959, 13403813, 11052904, 5219329}, + }, + }, + { + { + FieldElement{20678546, -8375738, -32671898, 8849123, -5009758, 14574752, 31186971, -3973730, 9014762, -8579056}, + FieldElement{-13644050, -10350239, -15962508, 5075808, -1514661, -11534600, -33102500, 9160280, 8473550, -3256838}, + FieldElement{24900749, 14435722, 17209120, -15292541, -22592275, 9878983, -7689309, -16335821, -24568481, 11788948}, + }, + { + FieldElement{-3118155, -11395194, -13802089, 14797441, 9652448, -6845904, -20037437, 10410733, -24568470, -1458691}, + FieldElement{-15659161, 16736706, -22467150, 10215878, -9097177, 7563911, 11871841, -12505194, -18513325, 8464118}, + FieldElement{-23400612, 8348507, -14585951, -861714, -3950205, -6373419, 14325289, 8628612, 33313881, -8370517}, + }, + { + FieldElement{-20186973, -4967935, 22367356, 5271547, -1097117, -4788838, -24805667, -10236854, -8940735, -5818269}, + FieldElement{-6948785, -1795212, -32625683, -16021179, 32635414, -7374245, 15989197, -12838188, 28358192, -4253904}, + FieldElement{-23561781, -2799059, -32351682, -1661963, -9147719, 10429267, -16637684, 4072016, -5351664, 5596589}, + }, + { + FieldElement{-28236598, -3390048, 12312896, 6213178, 3117142, 16078565, 29266239, 2557221, 1768301, 15373193}, + FieldElement{-7243358, -3246960, -4593467, -7553353, -127927, -912245, -1090902, -4504991, -24660491, 3442910}, + FieldElement{-30210571, 5124043, 14181784, 8197961, 18964734, -11939093, 22597931, 7176455, -18585478, 13365930}, + }, + { + FieldElement{-7877390, -1499958, 8324673, 4690079, 6261860, 890446, 24538107, -8570186, -9689599, -3031667}, + FieldElement{25008904, -10771599, -4305031, -9638010, 16265036, 15721635, 683793, -11823784, 15723479, -15163481}, + FieldElement{-9660625, 12374379, -27006999, -7026148, -7724114, -12314514, 11879682, 5400171, 519526, -1235876}, + }, + { + FieldElement{22258397, -16332233, -7869817, 14613016, -22520255, -2950923, -20353881, 7315967, 16648397, 7605640}, + FieldElement{-8081308, -8464597, -8223311, 9719710, 19259459, -15348212, 23994942, -5281555, -9468848, 4763278}, + FieldElement{-21699244, 9220969, -15730624, 1084137, -25476107, -2852390, 31088447, -7764523, -11356529, 728112}, + }, + { + FieldElement{26047220, -11751471, -6900323, -16521798, 24092068, 9158119, -4273545, -12555558, -29365436, -5498272}, + FieldElement{17510331, -322857, 5854289, 8403524, 17133918, -3112612, -28111007, 12327945, 10750447, 10014012}, + FieldElement{-10312768, 3936952, 9156313, -8897683, 16498692, -994647, -27481051, -666732, 3424691, 7540221}, + }, + { + FieldElement{30322361, -6964110, 11361005, -4143317, 7433304, 4989748, -7071422, -16317219, -9244265, 15258046}, + FieldElement{13054562, -2779497, 19155474, 469045, -12482797, 4566042, 5631406, 2711395, 1062915, -5136345}, + FieldElement{-19240248, -11254599, -29509029, -7499965, -5835763, 13005411, -6066489, 12194497, 32960380, 1459310}, + }, + }, + { + { + FieldElement{19852034, 7027924, 23669353, 10020366, 8586503, -6657907, 394197, -6101885, 18638003, -11174937}, + FieldElement{31395534, 15098109, 26581030, 8030562, -16527914, -5007134, 9012486, -7584354, -6643087, -5442636}, + FieldElement{-9192165, -2347377, -1997099, 4529534, 25766844, 607986, -13222, 9677543, -32294889, -6456008}, + }, + { + FieldElement{-2444496, -149937, 29348902, 8186665, 1873760, 12489863, -30934579, -7839692, -7852844, -8138429}, + FieldElement{-15236356, -15433509, 7766470, 746860, 26346930, -10221762, -27333451, 10754588, -9431476, 5203576}, + FieldElement{31834314, 14135496, -770007, 5159118, 20917671, -16768096, -7467973, -7337524, 31809243, 7347066}, + }, + { + FieldElement{-9606723, -11874240, 20414459, 13033986, 13716524, -11691881, 19797970, -12211255, 15192876, -2087490}, + FieldElement{-12663563, -2181719, 1168162, -3804809, 26747877, -14138091, 10609330, 12694420, 33473243, -13382104}, + FieldElement{33184999, 11180355, 15832085, -11385430, -1633671, 225884, 15089336, -11023903, -6135662, 14480053}, + }, + { + FieldElement{31308717, -5619998, 31030840, -1897099, 15674547, -6582883, 5496208, 13685227, 27595050, 8737275}, + FieldElement{-20318852, -15150239, 10933843, -16178022, 8335352, -7546022, -31008351, -12610604, 26498114, 66511}, + FieldElement{22644454, -8761729, -16671776, 4884562, -3105614, -13559366, 30540766, -4286747, -13327787, -7515095}, + }, + { + FieldElement{-28017847, 9834845, 18617207, -2681312, -3401956, -13307506, 8205540, 13585437, -17127465, 15115439}, + FieldElement{23711543, -672915, 31206561, -8362711, 6164647, -9709987, -33535882, -1426096, 8236921, 16492939}, + FieldElement{-23910559, -13515526, -26299483, -4503841, 25005590, -7687270, 19574902, 10071562, 6708380, -6222424}, + }, + { + FieldElement{2101391, -4930054, 19702731, 2367575, -15427167, 1047675, 5301017, 9328700, 29955601, -11678310}, + FieldElement{3096359, 9271816, -21620864, -15521844, -14847996, -7592937, -25892142, -12635595, -9917575, 6216608}, + FieldElement{-32615849, 338663, -25195611, 2510422, -29213566, -13820213, 24822830, -6146567, -26767480, 7525079}, + }, + { + FieldElement{-23066649, -13985623, 16133487, -7896178, -3389565, 778788, -910336, -2782495, -19386633, 11994101}, + FieldElement{21691500, -13624626, -641331, -14367021, 3285881, -3483596, -25064666, 9718258, -7477437, 13381418}, + FieldElement{18445390, -4202236, 14979846, 11622458, -1727110, -3582980, 23111648, -6375247, 28535282, 15779576}, + }, + { + FieldElement{30098053, 3089662, -9234387, 16662135, -21306940, 11308411, -14068454, 12021730, 9955285, -16303356}, + FieldElement{9734894, -14576830, -7473633, -9138735, 2060392, 11313496, -18426029, 9924399, 20194861, 13380996}, + FieldElement{-26378102, -7965207, -22167821, 15789297, -18055342, -6168792, -1984914, 15707771, 26342023, 10146099}, + }, + }, + { + { + FieldElement{-26016874, -219943, 21339191, -41388, 19745256, -2878700, -29637280, 2227040, 21612326, -545728}, + FieldElement{-13077387, 1184228, 23562814, -5970442, -20351244, -6348714, 25764461, 12243797, -20856566, 11649658}, + FieldElement{-10031494, 11262626, 27384172, 2271902, 26947504, -15997771, 39944, 6114064, 33514190, 2333242}, + }, + { + FieldElement{-21433588, -12421821, 8119782, 7219913, -21830522, -9016134, -6679750, -12670638, 24350578, -13450001}, + FieldElement{-4116307, -11271533, -23886186, 4843615, -30088339, 690623, -31536088, -10406836, 8317860, 12352766}, + FieldElement{18200138, -14475911, -33087759, -2696619, -23702521, -9102511, -23552096, -2287550, 20712163, 6719373}, + }, + { + FieldElement{26656208, 6075253, -7858556, 1886072, -28344043, 4262326, 11117530, -3763210, 26224235, -3297458}, + FieldElement{-17168938, -14854097, -3395676, -16369877, -19954045, 14050420, 21728352, 9493610, 18620611, -16428628}, + FieldElement{-13323321, 13325349, 11432106, 5964811, 18609221, 6062965, -5269471, -9725556, -30701573, -16479657}, + }, + { + FieldElement{-23860538, -11233159, 26961357, 1640861, -32413112, -16737940, 12248509, -5240639, 13735342, 1934062}, + FieldElement{25089769, 6742589, 17081145, -13406266, 21909293, -16067981, -15136294, -3765346, -21277997, 5473616}, + FieldElement{31883677, -7961101, 1083432, -11572403, 22828471, 13290673, -7125085, 12469656, 29111212, -5451014}, + }, + { + FieldElement{24244947, -15050407, -26262976, 2791540, -14997599, 16666678, 24367466, 6388839, -10295587, 452383}, + FieldElement{-25640782, -3417841, 5217916, 16224624, 19987036, -4082269, -24236251, -5915248, 15766062, 8407814}, + FieldElement{-20406999, 13990231, 15495425, 16395525, 5377168, 15166495, -8917023, -4388953, -8067909, 2276718}, + }, + { + FieldElement{30157918, 12924066, -17712050, 9245753, 19895028, 3368142, -23827587, 5096219, 22740376, -7303417}, + FieldElement{2041139, -14256350, 7783687, 13876377, -25946985, -13352459, 24051124, 13742383, -15637599, 13295222}, + FieldElement{33338237, -8505733, 12532113, 7977527, 9106186, -1715251, -17720195, -4612972, -4451357, -14669444}, + }, + { + FieldElement{-20045281, 5454097, -14346548, 6447146, 28862071, 1883651, -2469266, -4141880, 7770569, 9620597}, + FieldElement{23208068, 7979712, 33071466, 8149229, 1758231, -10834995, 30945528, -1694323, -33502340, -14767970}, + FieldElement{1439958, -16270480, -1079989, -793782, 4625402, 10647766, -5043801, 1220118, 30494170, -11440799}, + }, + { + FieldElement{-5037580, -13028295, -2970559, -3061767, 15640974, -6701666, -26739026, 926050, -1684339, -13333647}, + FieldElement{13908495, -3549272, 30919928, -6273825, -21521863, 7989039, 9021034, 9078865, 3353509, 4033511}, + FieldElement{-29663431, -15113610, 32259991, -344482, 24295849, -12912123, 23161163, 8839127, 27485041, 7356032}, + }, + }, + { + { + FieldElement{9661027, 705443, 11980065, -5370154, -1628543, 14661173, -6346142, 2625015, 28431036, -16771834}, + FieldElement{-23839233, -8311415, -25945511, 7480958, -17681669, -8354183, -22545972, 14150565, 15970762, 4099461}, + FieldElement{29262576, 16756590, 26350592, -8793563, 8529671, -11208050, 13617293, -9937143, 11465739, 8317062}, + }, + { + FieldElement{-25493081, -6962928, 32500200, -9419051, -23038724, -2302222, 14898637, 3848455, 20969334, -5157516}, + FieldElement{-20384450, -14347713, -18336405, 13884722, -33039454, 2842114, -21610826, -3649888, 11177095, 14989547}, + FieldElement{-24496721, -11716016, 16959896, 2278463, 12066309, 10137771, 13515641, 2581286, -28487508, 9930240}, + }, + { + FieldElement{-17751622, -2097826, 16544300, -13009300, -15914807, -14949081, 18345767, -13403753, 16291481, -5314038}, + FieldElement{-33229194, 2553288, 32678213, 9875984, 8534129, 6889387, -9676774, 6957617, 4368891, 9788741}, + FieldElement{16660756, 7281060, -10830758, 12911820, 20108584, -8101676, -21722536, -8613148, 16250552, -11111103}, + }, + { + FieldElement{-19765507, 2390526, -16551031, 14161980, 1905286, 6414907, 4689584, 10604807, -30190403, 4782747}, + FieldElement{-1354539, 14736941, -7367442, -13292886, 7710542, -14155590, -9981571, 4383045, 22546403, 437323}, + FieldElement{31665577, -12180464, -16186830, 1491339, -18368625, 3294682, 27343084, 2786261, -30633590, -14097016}, + }, + { + FieldElement{-14467279, -683715, -33374107, 7448552, 19294360, 14334329, -19690631, 2355319, -19284671, -6114373}, + FieldElement{15121312, -15796162, 6377020, -6031361, -10798111, -12957845, 18952177, 15496498, -29380133, 11754228}, + FieldElement{-2637277, -13483075, 8488727, -14303896, 12728761, -1622493, 7141596, 11724556, 22761615, -10134141}, + }, + { + FieldElement{16918416, 11729663, -18083579, 3022987, -31015732, -13339659, -28741185, -12227393, 32851222, 11717399}, + FieldElement{11166634, 7338049, -6722523, 4531520, -29468672, -7302055, 31474879, 3483633, -1193175, -4030831}, + FieldElement{-185635, 9921305, 31456609, -13536438, -12013818, 13348923, 33142652, 6546660, -19985279, -3948376}, + }, + { + FieldElement{-32460596, 11266712, -11197107, -7899103, 31703694, 3855903, -8537131, -12833048, -30772034, -15486313}, + FieldElement{-18006477, 12709068, 3991746, -6479188, -21491523, -10550425, -31135347, -16049879, 10928917, 3011958}, + FieldElement{-6957757, -15594337, 31696059, 334240, 29576716, 14796075, -30831056, -12805180, 18008031, 10258577}, + }, + { + FieldElement{-22448644, 15655569, 7018479, -4410003, -30314266, -1201591, -1853465, 1367120, 25127874, 6671743}, + FieldElement{29701166, -14373934, -10878120, 9279288, -17568, 13127210, 21382910, 11042292, 25838796, 4642684}, + FieldElement{-20430234, 14955537, -24126347, 8124619, -5369288, -5990470, 30468147, -13900640, 18423289, 4177476}, + }, + }, +} diff --git a/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go b/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go new file mode 100644 index 0000000000000000000000000000000000000000..5f8b9947872716c50edb0392432670240973ce3b --- /dev/null +++ b/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go @@ -0,0 +1,1771 @@ +// Copyright 2016 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 edwards25519 + +// This code is a port of the public domain, “ref10†implementation of ed25519 +// from SUPERCOP. + +// 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 + +var zero FieldElement + +func FeZero(fe *FieldElement) { + copy(fe[:], zero[:]) +} + +func FeOne(fe *FieldElement) { + FeZero(fe) + fe[0] = 1 +} + +func FeAdd(dst, a, b *FieldElement) { + dst[0] = a[0] + b[0] + dst[1] = a[1] + b[1] + dst[2] = a[2] + b[2] + dst[3] = a[3] + b[3] + dst[4] = a[4] + b[4] + dst[5] = a[5] + b[5] + dst[6] = a[6] + b[6] + dst[7] = a[7] + b[7] + dst[8] = a[8] + b[8] + dst[9] = a[9] + b[9] +} + +func FeSub(dst, a, b *FieldElement) { + dst[0] = a[0] - b[0] + dst[1] = a[1] - b[1] + dst[2] = a[2] - b[2] + dst[3] = a[3] - b[3] + dst[4] = a[4] - b[4] + dst[5] = a[5] - b[5] + dst[6] = a[6] - b[6] + dst[7] = a[7] - b[7] + dst[8] = a[8] - b[8] + dst[9] = a[9] - b[9] +} + +func FeCopy(dst, src *FieldElement) { + copy(dst[:], src[:]) +} + +// Replace (f,g) with (g,g) if b == 1; +// replace (f,g) with (f,g) if b == 0. +// +// Preconditions: b in {0,1}. +func FeCMove(f, g *FieldElement, b int32) { + b = -b + f[0] ^= b & (f[0] ^ g[0]) + f[1] ^= b & (f[1] ^ g[1]) + f[2] ^= b & (f[2] ^ g[2]) + f[3] ^= b & (f[3] ^ g[3]) + f[4] ^= b & (f[4] ^ g[4]) + f[5] ^= b & (f[5] ^ g[5]) + f[6] ^= b & (f[6] ^ g[6]) + f[7] ^= b & (f[7] ^ g[7]) + f[8] ^= b & (f[8] ^ g[8]) + f[9] ^= b & (f[9] ^ g[9]) +} + +func load3(in []byte) int64 { + var r int64 + r = int64(in[0]) + r |= int64(in[1]) << 8 + r |= int64(in[2]) << 16 + return r +} + +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:]) & 8388607) << 2 + + FeCombine(dst, h0, h1, h2, h3, h4, h5, h6, h7, h8, 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> 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) +} + +func FeIsNegative(f *FieldElement) byte { + var s [32]byte + FeToBytes(&s, f) + return s[0] & 1 +} + +func FeIsNonZero(f *FieldElement) int32 { + var s [32]byte + FeToBytes(&s, f) + var x uint8 + for _, b := range s { + x |= b + } + x |= x >> 4 + x |= x >> 2 + x |= x >> 1 + return int32(x & 1) +} + +// FeNeg sets h = -f +// +// Preconditions: +// |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. +// +// Postconditions: +// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. +func FeNeg(h, f *FieldElement) { + h[0] = -f[0] + h[1] = -f[1] + h[2] = -f[2] + h[3] = -f[3] + h[4] = -f[4] + h[5] = -f[5] + h[6] = -f[6] + h[7] = -f[7] + h[8] = -f[8] + h[9] = -f[9] +} + +func FeCombine(h *FieldElement, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 int64) { + var c0, c1, c2, c3, c4, c5, c6, c7, c8, c9 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 + */ + + c0 = (h0 + (1 << 25)) >> 26 + h1 += c0 + h0 -= c0 << 26 + c4 = (h4 + (1 << 25)) >> 26 + h5 += c4 + h4 -= c4 << 26 + /* |h0| <= 2^25 */ + /* |h4| <= 2^25 */ + /* |h1| <= 1.51*2^58 */ + /* |h5| <= 1.51*2^58 */ + + c1 = (h1 + (1 << 24)) >> 25 + h2 += c1 + h1 -= c1 << 25 + c5 = (h5 + (1 << 24)) >> 25 + h6 += c5 + h5 -= c5 << 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 */ + + c2 = (h2 + (1 << 25)) >> 26 + h3 += c2 + h2 -= c2 << 26 + c6 = (h6 + (1 << 25)) >> 26 + h7 += c6 + h6 -= c6 << 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 */ + + c3 = (h3 + (1 << 24)) >> 25 + h4 += c3 + h3 -= c3 << 25 + c7 = (h7 + (1 << 24)) >> 25 + h8 += c7 + h7 -= c7 << 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 */ + + c4 = (h4 + (1 << 25)) >> 26 + h5 += c4 + h4 -= c4 << 26 + c8 = (h8 + (1 << 25)) >> 26 + h9 += c8 + h8 -= c8 << 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 */ + + c9 = (h9 + (1 << 24)) >> 25 + h0 += c9 * 19 + h9 -= c9 << 25 + /* |h9| <= 2^24; from now on fits into int32 unchanged */ + /* |h0| <= 1.8*2^37 */ + + c0 = (h0 + (1 << 25)) >> 26 + h1 += c0 + h0 -= c0 << 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) +} + +// 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 := int64(f[0]) + f1 := int64(f[1]) + f2 := int64(f[2]) + f3 := int64(f[3]) + f4 := int64(f[4]) + f5 := int64(f[5]) + f6 := int64(f[6]) + f7 := int64(f[7]) + f8 := int64(f[8]) + f9 := int64(f[9]) + + f1_2 := int64(2 * f[1]) + f3_2 := int64(2 * f[3]) + f5_2 := int64(2 * f[5]) + f7_2 := int64(2 * f[7]) + f9_2 := int64(2 * f[9]) + + g0 := int64(g[0]) + g1 := int64(g[1]) + g2 := int64(g[2]) + g3 := int64(g[3]) + g4 := int64(g[4]) + g5 := int64(g[5]) + g6 := int64(g[6]) + g7 := int64(g[7]) + g8 := int64(g[8]) + g9 := int64(g[9]) + + g1_19 := int64(19 * g[1]) /* 1.4*2^29 */ + g2_19 := int64(19 * g[2]) /* 1.4*2^30; still ok */ + g3_19 := int64(19 * g[3]) + g4_19 := int64(19 * g[4]) + g5_19 := int64(19 * g[5]) + g6_19 := int64(19 * g[6]) + g7_19 := int64(19 * g[7]) + g8_19 := int64(19 * g[8]) + g9_19 := int64(19 * g[9]) + + h0 := f0*g0 + f1_2*g9_19 + f2*g8_19 + f3_2*g7_19 + f4*g6_19 + f5_2*g5_19 + f6*g4_19 + f7_2*g3_19 + f8*g2_19 + f9_2*g1_19 + h1 := f0*g1 + f1*g0 + f2*g9_19 + f3*g8_19 + f4*g7_19 + f5*g6_19 + f6*g5_19 + f7*g4_19 + f8*g3_19 + f9*g2_19 + h2 := f0*g2 + f1_2*g1 + f2*g0 + f3_2*g9_19 + f4*g8_19 + f5_2*g7_19 + f6*g6_19 + f7_2*g5_19 + f8*g4_19 + f9_2*g3_19 + h3 := f0*g3 + f1*g2 + f2*g1 + f3*g0 + f4*g9_19 + f5*g8_19 + f6*g7_19 + f7*g6_19 + f8*g5_19 + f9*g4_19 + h4 := f0*g4 + f1_2*g3 + f2*g2 + f3_2*g1 + f4*g0 + f5_2*g9_19 + f6*g8_19 + f7_2*g7_19 + f8*g6_19 + f9_2*g5_19 + h5 := f0*g5 + f1*g4 + f2*g3 + f3*g2 + f4*g1 + f5*g0 + f6*g9_19 + f7*g8_19 + f8*g7_19 + f9*g6_19 + h6 := f0*g6 + f1_2*g5 + f2*g4 + f3_2*g3 + f4*g2 + f5_2*g1 + f6*g0 + f7_2*g9_19 + f8*g8_19 + f9_2*g7_19 + h7 := f0*g7 + f1*g6 + f2*g5 + f3*g4 + f4*g3 + f5*g2 + f6*g1 + f7*g0 + f8*g9_19 + f9*g8_19 + h8 := f0*g8 + f1_2*g7 + f2*g6 + f3_2*g5 + f4*g4 + f5_2*g3 + f6*g2 + f7_2*g1 + f8*g0 + f9_2*g9_19 + h9 := f0*g9 + f1*g8 + f2*g7 + f3*g6 + f4*g5 + f5*g4 + f6*g3 + f7*g2 + f8*g1 + f9*g0 + + FeCombine(h, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9) +} + +func feSquare(f *FieldElement) (h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 int64) { + f0 := int64(f[0]) + f1 := int64(f[1]) + f2 := int64(f[2]) + f3 := int64(f[3]) + f4 := int64(f[4]) + f5 := int64(f[5]) + f6 := int64(f[6]) + f7 := int64(f[7]) + f8 := int64(f[8]) + f9 := int64(f[9]) + f0_2 := int64(2 * f[0]) + f1_2 := int64(2 * f[1]) + f2_2 := int64(2 * f[2]) + f3_2 := int64(2 * f[3]) + f4_2 := int64(2 * f[4]) + f5_2 := int64(2 * f[5]) + f6_2 := int64(2 * f[6]) + f7_2 := int64(2 * f[7]) + 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 + + h0 = f0*f0 + f1_2*f9_38 + f2_2*f8_19 + f3_2*f7_38 + f4_2*f6_19 + f5*f5_38 + h1 = f0_2*f1 + f2*f9_38 + f3_2*f8_19 + f4*f7_38 + f5_2*f6_19 + h2 = f0_2*f2 + f1_2*f1 + f3_2*f9_38 + f4_2*f8_19 + f5_2*f7_38 + f6*f6_19 + h3 = f0_2*f3 + f1_2*f2 + f4*f9_38 + f5_2*f8_19 + f6*f7_38 + h4 = f0_2*f4 + f1_2*f3_2 + f2*f2 + f5_2*f9_38 + f6_2*f8_19 + f7*f7_38 + h5 = f0_2*f5 + f1_2*f4 + f2_2*f3 + f6*f9_38 + f7_2*f8_19 + h6 = f0_2*f6 + f1_2*f5_2 + f2_2*f4 + f3_2*f3 + f7_2*f9_38 + f8*f8_19 + h7 = f0_2*f7 + f1_2*f6 + f2_2*f5 + f3_2*f4 + f8*f9_38 + h8 = f0_2*f8 + f1_2*f7_2 + f2_2*f6 + f3_2*f5_2 + f4*f4 + f9*f9_38 + h9 = f0_2*f9 + f1_2*f8 + f2_2*f7 + f3_2*f6 + f4_2*f5 + + return +} + +// 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) { + h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 := feSquare(f) + FeCombine(h, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9) +} + +// FeSquare2 sets h = 2 * f * f +// +// Can overlap h with f. +// +// Preconditions: +// |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. +// +// Postconditions: +// |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. +// See fe_mul.c for discussion of implementation strategy. +func FeSquare2(h, f *FieldElement) { + h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 := feSquare(f) + + h0 += h0 + h1 += h1 + h2 += h2 + h3 += h3 + h4 += h4 + h5 += h5 + h6 += h6 + h7 += h7 + h8 += h8 + h9 += h9 + + FeCombine(h, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9) +} + +func FeInvert(out, z *FieldElement) { + var t0, t1, t2, t3 FieldElement + var i int + + FeSquare(&t0, z) // 2^1 + FeSquare(&t1, &t0) // 2^2 + for i = 1; i < 2; i++ { // 2^3 + FeSquare(&t1, &t1) + } + FeMul(&t1, z, &t1) // 2^3 + 2^0 + FeMul(&t0, &t0, &t1) // 2^3 + 2^1 + 2^0 + FeSquare(&t2, &t0) // 2^4 + 2^2 + 2^1 + FeMul(&t1, &t1, &t2) // 2^4 + 2^3 + 2^2 + 2^1 + 2^0 + FeSquare(&t2, &t1) // 5,4,3,2,1 + for i = 1; i < 5; i++ { // 9,8,7,6,5 + FeSquare(&t2, &t2) + } + FeMul(&t1, &t2, &t1) // 9,8,7,6,5,4,3,2,1,0 + FeSquare(&t2, &t1) // 10..1 + for i = 1; i < 10; i++ { // 19..10 + FeSquare(&t2, &t2) + } + FeMul(&t2, &t2, &t1) // 19..0 + FeSquare(&t3, &t2) // 20..1 + for i = 1; i < 20; i++ { // 39..20 + FeSquare(&t3, &t3) + } + FeMul(&t2, &t3, &t2) // 39..0 + FeSquare(&t2, &t2) // 40..1 + for i = 1; i < 10; i++ { // 49..10 + FeSquare(&t2, &t2) + } + FeMul(&t1, &t2, &t1) // 49..0 + FeSquare(&t2, &t1) // 50..1 + for i = 1; i < 50; i++ { // 99..50 + FeSquare(&t2, &t2) + } + FeMul(&t2, &t2, &t1) // 99..0 + FeSquare(&t3, &t2) // 100..1 + for i = 1; i < 100; i++ { // 199..100 + FeSquare(&t3, &t3) + } + FeMul(&t2, &t3, &t2) // 199..0 + FeSquare(&t2, &t2) // 200..1 + for i = 1; i < 50; i++ { // 249..50 + FeSquare(&t2, &t2) + } + FeMul(&t1, &t2, &t1) // 249..0 + FeSquare(&t1, &t1) // 250..1 + for i = 1; i < 5; i++ { // 254..5 + FeSquare(&t1, &t1) + } + FeMul(out, &t1, &t0) // 254..5,3,1,0 +} + +func fePow22523(out, z *FieldElement) { + var t0, t1, t2 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(&t0, &t0) + for i = 1; i < 1; i++ { + FeSquare(&t0, &t0) + } + FeMul(&t0, &t1, &t0) + FeSquare(&t1, &t0) + for i = 1; i < 5; i++ { + FeSquare(&t1, &t1) + } + FeMul(&t0, &t1, &t0) + FeSquare(&t1, &t0) + for i = 1; i < 10; i++ { + FeSquare(&t1, &t1) + } + FeMul(&t1, &t1, &t0) + FeSquare(&t2, &t1) + for i = 1; i < 20; i++ { + FeSquare(&t2, &t2) + } + FeMul(&t1, &t2, &t1) + FeSquare(&t1, &t1) + for i = 1; i < 10; i++ { + FeSquare(&t1, &t1) + } + FeMul(&t0, &t1, &t0) + FeSquare(&t1, &t0) + for i = 1; i < 50; i++ { + FeSquare(&t1, &t1) + } + FeMul(&t1, &t1, &t0) + FeSquare(&t2, &t1) + for i = 1; i < 100; i++ { + FeSquare(&t2, &t2) + } + FeMul(&t1, &t2, &t1) + FeSquare(&t1, &t1) + for i = 1; i < 50; i++ { + FeSquare(&t1, &t1) + } + FeMul(&t0, &t1, &t0) + FeSquare(&t0, &t0) + for i = 1; i < 2; i++ { + FeSquare(&t0, &t0) + } + FeMul(out, &t0, z) +} + +// Group elements are members of the elliptic curve -x^2 + y^2 = 1 + d * x^2 * +// y^2 where d = -121665/121666. +// +// Several representations are used: +// ProjectiveGroupElement: (X:Y:Z) satisfying x=X/Z, y=Y/Z +// ExtendedGroupElement: (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT +// CompletedGroupElement: ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T +// PreComputedGroupElement: (y+x,y-x,2dxy) + +type ProjectiveGroupElement struct { + X, Y, Z FieldElement +} + +type ExtendedGroupElement struct { + X, Y, Z, T FieldElement +} + +type CompletedGroupElement struct { + X, Y, Z, T FieldElement +} + +type PreComputedGroupElement struct { + yPlusX, yMinusX, xy2d FieldElement +} + +type CachedGroupElement struct { + yPlusX, yMinusX, Z, T2d FieldElement +} + +func (p *ProjectiveGroupElement) Zero() { + FeZero(&p.X) + FeOne(&p.Y) + FeOne(&p.Z) +} + +func (p *ProjectiveGroupElement) Double(r *CompletedGroupElement) { + var t0 FieldElement + + FeSquare(&r.X, &p.X) + FeSquare(&r.Z, &p.Y) + FeSquare2(&r.T, &p.Z) + FeAdd(&r.Y, &p.X, &p.Y) + FeSquare(&t0, &r.Y) + FeAdd(&r.Y, &r.Z, &r.X) + FeSub(&r.Z, &r.Z, &r.X) + FeSub(&r.X, &t0, &r.Y) + FeSub(&r.T, &r.T, &r.Z) +} + +func (p *ProjectiveGroupElement) ToBytes(s *[32]byte) { + var recip, x, y FieldElement + + FeInvert(&recip, &p.Z) + FeMul(&x, &p.X, &recip) + FeMul(&y, &p.Y, &recip) + FeToBytes(s, &y) + s[31] ^= FeIsNegative(&x) << 7 +} + +func (p *ExtendedGroupElement) Zero() { + FeZero(&p.X) + FeOne(&p.Y) + FeOne(&p.Z) + FeZero(&p.T) +} + +func (p *ExtendedGroupElement) Double(r *CompletedGroupElement) { + var q ProjectiveGroupElement + p.ToProjective(&q) + q.Double(r) +} + +func (p *ExtendedGroupElement) ToCached(r *CachedGroupElement) { + FeAdd(&r.yPlusX, &p.Y, &p.X) + FeSub(&r.yMinusX, &p.Y, &p.X) + FeCopy(&r.Z, &p.Z) + FeMul(&r.T2d, &p.T, &d2) +} + +func (p *ExtendedGroupElement) ToProjective(r *ProjectiveGroupElement) { + FeCopy(&r.X, &p.X) + FeCopy(&r.Y, &p.Y) + FeCopy(&r.Z, &p.Z) +} + +func (p *ExtendedGroupElement) ToBytes(s *[32]byte) { + var recip, x, y FieldElement + + FeInvert(&recip, &p.Z) + FeMul(&x, &p.X, &recip) + FeMul(&y, &p.Y, &recip) + FeToBytes(s, &y) + s[31] ^= FeIsNegative(&x) << 7 +} + +func (p *ExtendedGroupElement) FromBytes(s *[32]byte) bool { + var u, v, v3, vxx, check FieldElement + + FeFromBytes(&p.Y, s) + FeOne(&p.Z) + FeSquare(&u, &p.Y) + FeMul(&v, &u, &d) + FeSub(&u, &u, &p.Z) // y = y^2-1 + FeAdd(&v, &v, &p.Z) // v = dy^2+1 + + FeSquare(&v3, &v) + FeMul(&v3, &v3, &v) // v3 = v^3 + FeSquare(&p.X, &v3) + FeMul(&p.X, &p.X, &v) + FeMul(&p.X, &p.X, &u) // x = uv^7 + + fePow22523(&p.X, &p.X) // x = (uv^7)^((q-5)/8) + FeMul(&p.X, &p.X, &v3) + FeMul(&p.X, &p.X, &u) // x = uv^3(uv^7)^((q-5)/8) + + var tmpX, tmp2 [32]byte + + FeSquare(&vxx, &p.X) + FeMul(&vxx, &vxx, &v) + FeSub(&check, &vxx, &u) // vx^2-u + if FeIsNonZero(&check) == 1 { + FeAdd(&check, &vxx, &u) // vx^2+u + if FeIsNonZero(&check) == 1 { + return false + } + FeMul(&p.X, &p.X, &SqrtM1) + + FeToBytes(&tmpX, &p.X) + for i, v := range tmpX { + tmp2[31-i] = v + } + } + + if FeIsNegative(&p.X) != (s[31] >> 7) { + FeNeg(&p.X, &p.X) + } + + FeMul(&p.T, &p.X, &p.Y) + return true +} + +func (p *CompletedGroupElement) ToProjective(r *ProjectiveGroupElement) { + FeMul(&r.X, &p.X, &p.T) + FeMul(&r.Y, &p.Y, &p.Z) + FeMul(&r.Z, &p.Z, &p.T) +} + +func (p *CompletedGroupElement) ToExtended(r *ExtendedGroupElement) { + FeMul(&r.X, &p.X, &p.T) + FeMul(&r.Y, &p.Y, &p.Z) + FeMul(&r.Z, &p.Z, &p.T) + FeMul(&r.T, &p.X, &p.Y) +} + +func (p *PreComputedGroupElement) Zero() { + FeOne(&p.yPlusX) + FeOne(&p.yMinusX) + FeZero(&p.xy2d) +} + +func geAdd(r *CompletedGroupElement, p *ExtendedGroupElement, q *CachedGroupElement) { + var t0 FieldElement + + FeAdd(&r.X, &p.Y, &p.X) + FeSub(&r.Y, &p.Y, &p.X) + FeMul(&r.Z, &r.X, &q.yPlusX) + FeMul(&r.Y, &r.Y, &q.yMinusX) + FeMul(&r.T, &q.T2d, &p.T) + FeMul(&r.X, &p.Z, &q.Z) + FeAdd(&t0, &r.X, &r.X) + FeSub(&r.X, &r.Z, &r.Y) + FeAdd(&r.Y, &r.Z, &r.Y) + FeAdd(&r.Z, &t0, &r.T) + FeSub(&r.T, &t0, &r.T) +} + +func geSub(r *CompletedGroupElement, p *ExtendedGroupElement, q *CachedGroupElement) { + var t0 FieldElement + + FeAdd(&r.X, &p.Y, &p.X) + FeSub(&r.Y, &p.Y, &p.X) + FeMul(&r.Z, &r.X, &q.yMinusX) + FeMul(&r.Y, &r.Y, &q.yPlusX) + FeMul(&r.T, &q.T2d, &p.T) + FeMul(&r.X, &p.Z, &q.Z) + FeAdd(&t0, &r.X, &r.X) + FeSub(&r.X, &r.Z, &r.Y) + FeAdd(&r.Y, &r.Z, &r.Y) + FeSub(&r.Z, &t0, &r.T) + FeAdd(&r.T, &t0, &r.T) +} + +func geMixedAdd(r *CompletedGroupElement, p *ExtendedGroupElement, q *PreComputedGroupElement) { + var t0 FieldElement + + FeAdd(&r.X, &p.Y, &p.X) + FeSub(&r.Y, &p.Y, &p.X) + FeMul(&r.Z, &r.X, &q.yPlusX) + FeMul(&r.Y, &r.Y, &q.yMinusX) + FeMul(&r.T, &q.xy2d, &p.T) + FeAdd(&t0, &p.Z, &p.Z) + FeSub(&r.X, &r.Z, &r.Y) + FeAdd(&r.Y, &r.Z, &r.Y) + FeAdd(&r.Z, &t0, &r.T) + FeSub(&r.T, &t0, &r.T) +} + +func geMixedSub(r *CompletedGroupElement, p *ExtendedGroupElement, q *PreComputedGroupElement) { + var t0 FieldElement + + FeAdd(&r.X, &p.Y, &p.X) + FeSub(&r.Y, &p.Y, &p.X) + FeMul(&r.Z, &r.X, &q.yMinusX) + FeMul(&r.Y, &r.Y, &q.yPlusX) + FeMul(&r.T, &q.xy2d, &p.T) + FeAdd(&t0, &p.Z, &p.Z) + FeSub(&r.X, &r.Z, &r.Y) + FeAdd(&r.Y, &r.Z, &r.Y) + FeSub(&r.Z, &t0, &r.T) + FeAdd(&r.T, &t0, &r.T) +} + +func slide(r *[256]int8, a *[32]byte) { + for i := range r { + r[i] = int8(1 & (a[i>>3] >> uint(i&7))) + } + + for i := range r { + if r[i] != 0 { + for b := 1; b <= 6 && i+b < 256; b++ { + if r[i+b] != 0 { + if r[i]+(r[i+b]<= -15 { + r[i] -= r[i+b] << uint(b) + for k := i + b; k < 256; k++ { + if r[k] == 0 { + r[k] = 1 + break + } + r[k] = 0 + } + } else { + break + } + } + } + } + } +} + +// GeDoubleScalarMultVartime sets r = a*A + b*B +// where a = a[0]+256*a[1]+...+256^31 a[31]. +// and b = b[0]+256*b[1]+...+256^31 b[31]. +// B is the Ed25519 base point (x,4/5) with x positive. +func GeDoubleScalarMultVartime(r *ProjectiveGroupElement, a *[32]byte, A *ExtendedGroupElement, b *[32]byte) { + var aSlide, bSlide [256]int8 + var Ai [8]CachedGroupElement // A,3A,5A,7A,9A,11A,13A,15A + var t CompletedGroupElement + var u, A2 ExtendedGroupElement + var i int + + slide(&aSlide, a) + slide(&bSlide, b) + + A.ToCached(&Ai[0]) + A.Double(&t) + t.ToExtended(&A2) + + for i := 0; i < 7; i++ { + geAdd(&t, &A2, &Ai[i]) + t.ToExtended(&u) + u.ToCached(&Ai[i+1]) + } + + r.Zero() + + for i = 255; i >= 0; i-- { + if aSlide[i] != 0 || bSlide[i] != 0 { + break + } + } + + for ; i >= 0; i-- { + r.Double(&t) + + if aSlide[i] > 0 { + t.ToExtended(&u) + geAdd(&t, &u, &Ai[aSlide[i]/2]) + } else if aSlide[i] < 0 { + t.ToExtended(&u) + geSub(&t, &u, &Ai[(-aSlide[i])/2]) + } + + if bSlide[i] > 0 { + t.ToExtended(&u) + geMixedAdd(&t, &u, &bi[bSlide[i]/2]) + } else if bSlide[i] < 0 { + t.ToExtended(&u) + geMixedSub(&t, &u, &bi[(-bSlide[i])/2]) + } + + t.ToProjective(r) + } +} + +// equal returns 1 if b == c and 0 otherwise, assuming that b and c are +// non-negative. +func equal(b, c int32) int32 { + x := uint32(b ^ c) + x-- + return int32(x >> 31) +} + +// negative returns 1 if b < 0 and 0 otherwise. +func negative(b int32) int32 { + return (b >> 31) & 1 +} + +func PreComputedGroupElementCMove(t, u *PreComputedGroupElement, b int32) { + FeCMove(&t.yPlusX, &u.yPlusX, b) + FeCMove(&t.yMinusX, &u.yMinusX, b) + FeCMove(&t.xy2d, &u.xy2d, b) +} + +func selectPoint(t *PreComputedGroupElement, pos int32, b int32) { + var minusT PreComputedGroupElement + bNegative := negative(b) + bAbs := b - (((-bNegative) & b) << 1) + + t.Zero() + for i := int32(0); i < 8; i++ { + PreComputedGroupElementCMove(t, &base[pos][i], equal(bAbs, i+1)) + } + FeCopy(&minusT.yPlusX, &t.yMinusX) + FeCopy(&minusT.yMinusX, &t.yPlusX) + FeNeg(&minusT.xy2d, &t.xy2d) + PreComputedGroupElementCMove(t, &minusT, bNegative) +} + +// GeScalarMultBase computes h = a*B, where +// a = a[0]+256*a[1]+...+256^31 a[31] +// B is the Ed25519 base point (x,4/5) with x positive. +// +// Preconditions: +// a[31] <= 127 +func GeScalarMultBase(h *ExtendedGroupElement, a *[32]byte) { + var e [64]int8 + + for i, v := range a { + e[2*i] = int8(v & 15) + e[2*i+1] = int8((v >> 4) & 15) + } + + // each e[i] is between 0 and 15 and e[63] is between 0 and 7. + + carry := int8(0) + for i := 0; i < 63; i++ { + e[i] += carry + carry = (e[i] + 8) >> 4 + e[i] -= carry << 4 + } + e[63] += carry + // each e[i] is between -8 and 8. + + h.Zero() + var t PreComputedGroupElement + var r CompletedGroupElement + for i := int32(1); i < 64; i += 2 { + selectPoint(&t, i/2, int32(e[i])) + geMixedAdd(&r, h, &t) + r.ToExtended(h) + } + + var s ProjectiveGroupElement + + h.Double(&r) + r.ToProjective(&s) + s.Double(&r) + r.ToProjective(&s) + s.Double(&r) + r.ToProjective(&s) + s.Double(&r) + r.ToExtended(h) + + for i := int32(0); i < 64; i += 2 { + selectPoint(&t, i/2, int32(e[i])) + geMixedAdd(&r, h, &t) + r.ToExtended(h) + } +} + +// The scalars are GF(2^252 + 27742317777372353535851937790883648493). + +// Input: +// a[0]+256*a[1]+...+256^31*a[31] = a +// b[0]+256*b[1]+...+256^31*b[31] = b +// c[0]+256*c[1]+...+256^31*c[31] = c +// +// Output: +// s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l +// where l = 2^252 + 27742317777372353535851937790883648493. +func ScMulAdd(s, a, b, c *[32]byte) { + a0 := 2097151 & load3(a[:]) + a1 := 2097151 & (load4(a[2:]) >> 5) + a2 := 2097151 & (load3(a[5:]) >> 2) + a3 := 2097151 & (load4(a[7:]) >> 7) + a4 := 2097151 & (load4(a[10:]) >> 4) + a5 := 2097151 & (load3(a[13:]) >> 1) + a6 := 2097151 & (load4(a[15:]) >> 6) + a7 := 2097151 & (load3(a[18:]) >> 3) + a8 := 2097151 & load3(a[21:]) + a9 := 2097151 & (load4(a[23:]) >> 5) + a10 := 2097151 & (load3(a[26:]) >> 2) + a11 := (load4(a[28:]) >> 7) + b0 := 2097151 & load3(b[:]) + b1 := 2097151 & (load4(b[2:]) >> 5) + b2 := 2097151 & (load3(b[5:]) >> 2) + b3 := 2097151 & (load4(b[7:]) >> 7) + b4 := 2097151 & (load4(b[10:]) >> 4) + b5 := 2097151 & (load3(b[13:]) >> 1) + b6 := 2097151 & (load4(b[15:]) >> 6) + b7 := 2097151 & (load3(b[18:]) >> 3) + b8 := 2097151 & load3(b[21:]) + b9 := 2097151 & (load4(b[23:]) >> 5) + b10 := 2097151 & (load3(b[26:]) >> 2) + b11 := (load4(b[28:]) >> 7) + c0 := 2097151 & load3(c[:]) + c1 := 2097151 & (load4(c[2:]) >> 5) + c2 := 2097151 & (load3(c[5:]) >> 2) + c3 := 2097151 & (load4(c[7:]) >> 7) + c4 := 2097151 & (load4(c[10:]) >> 4) + c5 := 2097151 & (load3(c[13:]) >> 1) + c6 := 2097151 & (load4(c[15:]) >> 6) + c7 := 2097151 & (load3(c[18:]) >> 3) + c8 := 2097151 & load3(c[21:]) + c9 := 2097151 & (load4(c[23:]) >> 5) + c10 := 2097151 & (load3(c[26:]) >> 2) + c11 := (load4(c[28:]) >> 7) + var carry [23]int64 + + s0 := c0 + a0*b0 + s1 := c1 + a0*b1 + a1*b0 + s2 := c2 + a0*b2 + a1*b1 + a2*b0 + s3 := c3 + a0*b3 + a1*b2 + a2*b1 + a3*b0 + s4 := c4 + a0*b4 + a1*b3 + a2*b2 + a3*b1 + a4*b0 + s5 := c5 + a0*b5 + a1*b4 + a2*b3 + a3*b2 + a4*b1 + a5*b0 + s6 := c6 + a0*b6 + a1*b5 + a2*b4 + a3*b3 + a4*b2 + a5*b1 + a6*b0 + s7 := c7 + a0*b7 + a1*b6 + a2*b5 + a3*b4 + a4*b3 + a5*b2 + a6*b1 + a7*b0 + s8 := c8 + a0*b8 + a1*b7 + a2*b6 + a3*b5 + a4*b4 + a5*b3 + a6*b2 + a7*b1 + a8*b0 + s9 := c9 + a0*b9 + a1*b8 + a2*b7 + a3*b6 + a4*b5 + a5*b4 + a6*b3 + a7*b2 + a8*b1 + a9*b0 + s10 := c10 + a0*b10 + a1*b9 + a2*b8 + a3*b7 + a4*b6 + a5*b5 + a6*b4 + a7*b3 + a8*b2 + a9*b1 + a10*b0 + s11 := c11 + a0*b11 + a1*b10 + a2*b9 + a3*b8 + a4*b7 + a5*b6 + a6*b5 + a7*b4 + a8*b3 + a9*b2 + a10*b1 + a11*b0 + s12 := a1*b11 + a2*b10 + a3*b9 + a4*b8 + a5*b7 + a6*b6 + a7*b5 + a8*b4 + a9*b3 + a10*b2 + a11*b1 + s13 := a2*b11 + a3*b10 + a4*b9 + a5*b8 + a6*b7 + a7*b6 + a8*b5 + a9*b4 + a10*b3 + a11*b2 + s14 := a3*b11 + a4*b10 + a5*b9 + a6*b8 + a7*b7 + a8*b6 + a9*b5 + a10*b4 + a11*b3 + s15 := a4*b11 + a5*b10 + a6*b9 + a7*b8 + a8*b7 + a9*b6 + a10*b5 + a11*b4 + s16 := a5*b11 + a6*b10 + a7*b9 + a8*b8 + a9*b7 + a10*b6 + a11*b5 + s17 := a6*b11 + a7*b10 + a8*b9 + a9*b8 + a10*b7 + a11*b6 + s18 := a7*b11 + a8*b10 + a9*b9 + a10*b8 + a11*b7 + s19 := a8*b11 + a9*b10 + a10*b9 + a11*b8 + s20 := a9*b11 + a10*b10 + a11*b9 + s21 := a10*b11 + a11*b10 + s22 := a11 * b11 + s23 := int64(0) + + carry[0] = (s0 + (1 << 20)) >> 21 + s1 += carry[0] + s0 -= carry[0] << 21 + carry[2] = (s2 + (1 << 20)) >> 21 + s3 += carry[2] + s2 -= carry[2] << 21 + carry[4] = (s4 + (1 << 20)) >> 21 + s5 += carry[4] + s4 -= carry[4] << 21 + carry[6] = (s6 + (1 << 20)) >> 21 + s7 += carry[6] + s6 -= carry[6] << 21 + carry[8] = (s8 + (1 << 20)) >> 21 + s9 += carry[8] + s8 -= carry[8] << 21 + carry[10] = (s10 + (1 << 20)) >> 21 + s11 += carry[10] + s10 -= carry[10] << 21 + carry[12] = (s12 + (1 << 20)) >> 21 + s13 += carry[12] + s12 -= carry[12] << 21 + carry[14] = (s14 + (1 << 20)) >> 21 + s15 += carry[14] + s14 -= carry[14] << 21 + carry[16] = (s16 + (1 << 20)) >> 21 + s17 += carry[16] + s16 -= carry[16] << 21 + carry[18] = (s18 + (1 << 20)) >> 21 + s19 += carry[18] + s18 -= carry[18] << 21 + carry[20] = (s20 + (1 << 20)) >> 21 + s21 += carry[20] + s20 -= carry[20] << 21 + carry[22] = (s22 + (1 << 20)) >> 21 + s23 += carry[22] + s22 -= carry[22] << 21 + + carry[1] = (s1 + (1 << 20)) >> 21 + s2 += carry[1] + s1 -= carry[1] << 21 + carry[3] = (s3 + (1 << 20)) >> 21 + s4 += carry[3] + s3 -= carry[3] << 21 + carry[5] = (s5 + (1 << 20)) >> 21 + s6 += carry[5] + s5 -= carry[5] << 21 + carry[7] = (s7 + (1 << 20)) >> 21 + s8 += carry[7] + s7 -= carry[7] << 21 + carry[9] = (s9 + (1 << 20)) >> 21 + s10 += carry[9] + s9 -= carry[9] << 21 + carry[11] = (s11 + (1 << 20)) >> 21 + s12 += carry[11] + s11 -= carry[11] << 21 + carry[13] = (s13 + (1 << 20)) >> 21 + s14 += carry[13] + s13 -= carry[13] << 21 + carry[15] = (s15 + (1 << 20)) >> 21 + s16 += carry[15] + s15 -= carry[15] << 21 + carry[17] = (s17 + (1 << 20)) >> 21 + s18 += carry[17] + s17 -= carry[17] << 21 + carry[19] = (s19 + (1 << 20)) >> 21 + s20 += carry[19] + s19 -= carry[19] << 21 + carry[21] = (s21 + (1 << 20)) >> 21 + s22 += carry[21] + s21 -= carry[21] << 21 + + s11 += s23 * 666643 + s12 += s23 * 470296 + s13 += s23 * 654183 + s14 -= s23 * 997805 + s15 += s23 * 136657 + s16 -= s23 * 683901 + s23 = 0 + + s10 += s22 * 666643 + s11 += s22 * 470296 + s12 += s22 * 654183 + s13 -= s22 * 997805 + s14 += s22 * 136657 + s15 -= s22 * 683901 + s22 = 0 + + s9 += s21 * 666643 + s10 += s21 * 470296 + s11 += s21 * 654183 + s12 -= s21 * 997805 + s13 += s21 * 136657 + s14 -= s21 * 683901 + s21 = 0 + + s8 += s20 * 666643 + s9 += s20 * 470296 + s10 += s20 * 654183 + s11 -= s20 * 997805 + s12 += s20 * 136657 + s13 -= s20 * 683901 + s20 = 0 + + s7 += s19 * 666643 + s8 += s19 * 470296 + s9 += s19 * 654183 + s10 -= s19 * 997805 + s11 += s19 * 136657 + s12 -= s19 * 683901 + s19 = 0 + + s6 += s18 * 666643 + s7 += s18 * 470296 + s8 += s18 * 654183 + s9 -= s18 * 997805 + s10 += s18 * 136657 + s11 -= s18 * 683901 + s18 = 0 + + carry[6] = (s6 + (1 << 20)) >> 21 + s7 += carry[6] + s6 -= carry[6] << 21 + carry[8] = (s8 + (1 << 20)) >> 21 + s9 += carry[8] + s8 -= carry[8] << 21 + carry[10] = (s10 + (1 << 20)) >> 21 + s11 += carry[10] + s10 -= carry[10] << 21 + carry[12] = (s12 + (1 << 20)) >> 21 + s13 += carry[12] + s12 -= carry[12] << 21 + carry[14] = (s14 + (1 << 20)) >> 21 + s15 += carry[14] + s14 -= carry[14] << 21 + carry[16] = (s16 + (1 << 20)) >> 21 + s17 += carry[16] + s16 -= carry[16] << 21 + + carry[7] = (s7 + (1 << 20)) >> 21 + s8 += carry[7] + s7 -= carry[7] << 21 + carry[9] = (s9 + (1 << 20)) >> 21 + s10 += carry[9] + s9 -= carry[9] << 21 + carry[11] = (s11 + (1 << 20)) >> 21 + s12 += carry[11] + s11 -= carry[11] << 21 + carry[13] = (s13 + (1 << 20)) >> 21 + s14 += carry[13] + s13 -= carry[13] << 21 + carry[15] = (s15 + (1 << 20)) >> 21 + s16 += carry[15] + s15 -= carry[15] << 21 + + s5 += s17 * 666643 + s6 += s17 * 470296 + s7 += s17 * 654183 + s8 -= s17 * 997805 + s9 += s17 * 136657 + s10 -= s17 * 683901 + s17 = 0 + + s4 += s16 * 666643 + s5 += s16 * 470296 + s6 += s16 * 654183 + s7 -= s16 * 997805 + s8 += s16 * 136657 + s9 -= s16 * 683901 + s16 = 0 + + s3 += s15 * 666643 + s4 += s15 * 470296 + s5 += s15 * 654183 + s6 -= s15 * 997805 + s7 += s15 * 136657 + s8 -= s15 * 683901 + s15 = 0 + + s2 += s14 * 666643 + s3 += s14 * 470296 + s4 += s14 * 654183 + s5 -= s14 * 997805 + s6 += s14 * 136657 + s7 -= s14 * 683901 + s14 = 0 + + s1 += s13 * 666643 + s2 += s13 * 470296 + s3 += s13 * 654183 + s4 -= s13 * 997805 + s5 += s13 * 136657 + s6 -= s13 * 683901 + s13 = 0 + + s0 += s12 * 666643 + s1 += s12 * 470296 + s2 += s12 * 654183 + s3 -= s12 * 997805 + s4 += s12 * 136657 + s5 -= s12 * 683901 + s12 = 0 + + carry[0] = (s0 + (1 << 20)) >> 21 + s1 += carry[0] + s0 -= carry[0] << 21 + carry[2] = (s2 + (1 << 20)) >> 21 + s3 += carry[2] + s2 -= carry[2] << 21 + carry[4] = (s4 + (1 << 20)) >> 21 + s5 += carry[4] + s4 -= carry[4] << 21 + carry[6] = (s6 + (1 << 20)) >> 21 + s7 += carry[6] + s6 -= carry[6] << 21 + carry[8] = (s8 + (1 << 20)) >> 21 + s9 += carry[8] + s8 -= carry[8] << 21 + carry[10] = (s10 + (1 << 20)) >> 21 + s11 += carry[10] + s10 -= carry[10] << 21 + + carry[1] = (s1 + (1 << 20)) >> 21 + s2 += carry[1] + s1 -= carry[1] << 21 + carry[3] = (s3 + (1 << 20)) >> 21 + s4 += carry[3] + s3 -= carry[3] << 21 + carry[5] = (s5 + (1 << 20)) >> 21 + s6 += carry[5] + s5 -= carry[5] << 21 + carry[7] = (s7 + (1 << 20)) >> 21 + s8 += carry[7] + s7 -= carry[7] << 21 + carry[9] = (s9 + (1 << 20)) >> 21 + s10 += carry[9] + s9 -= carry[9] << 21 + carry[11] = (s11 + (1 << 20)) >> 21 + s12 += carry[11] + s11 -= carry[11] << 21 + + s0 += s12 * 666643 + s1 += s12 * 470296 + s2 += s12 * 654183 + s3 -= s12 * 997805 + s4 += s12 * 136657 + s5 -= s12 * 683901 + s12 = 0 + + carry[0] = s0 >> 21 + s1 += carry[0] + s0 -= carry[0] << 21 + carry[1] = s1 >> 21 + s2 += carry[1] + s1 -= carry[1] << 21 + carry[2] = s2 >> 21 + s3 += carry[2] + s2 -= carry[2] << 21 + carry[3] = s3 >> 21 + s4 += carry[3] + s3 -= carry[3] << 21 + carry[4] = s4 >> 21 + s5 += carry[4] + s4 -= carry[4] << 21 + carry[5] = s5 >> 21 + s6 += carry[5] + s5 -= carry[5] << 21 + carry[6] = s6 >> 21 + s7 += carry[6] + s6 -= carry[6] << 21 + carry[7] = s7 >> 21 + s8 += carry[7] + s7 -= carry[7] << 21 + carry[8] = s8 >> 21 + s9 += carry[8] + s8 -= carry[8] << 21 + carry[9] = s9 >> 21 + s10 += carry[9] + s9 -= carry[9] << 21 + carry[10] = s10 >> 21 + s11 += carry[10] + s10 -= carry[10] << 21 + carry[11] = s11 >> 21 + s12 += carry[11] + s11 -= carry[11] << 21 + + s0 += s12 * 666643 + s1 += s12 * 470296 + s2 += s12 * 654183 + s3 -= s12 * 997805 + s4 += s12 * 136657 + s5 -= s12 * 683901 + s12 = 0 + + carry[0] = s0 >> 21 + s1 += carry[0] + s0 -= carry[0] << 21 + carry[1] = s1 >> 21 + s2 += carry[1] + s1 -= carry[1] << 21 + carry[2] = s2 >> 21 + s3 += carry[2] + s2 -= carry[2] << 21 + carry[3] = s3 >> 21 + s4 += carry[3] + s3 -= carry[3] << 21 + carry[4] = s4 >> 21 + s5 += carry[4] + s4 -= carry[4] << 21 + carry[5] = s5 >> 21 + s6 += carry[5] + s5 -= carry[5] << 21 + carry[6] = s6 >> 21 + s7 += carry[6] + s6 -= carry[6] << 21 + carry[7] = s7 >> 21 + s8 += carry[7] + s7 -= carry[7] << 21 + carry[8] = s8 >> 21 + s9 += carry[8] + s8 -= carry[8] << 21 + carry[9] = s9 >> 21 + s10 += carry[9] + s9 -= carry[9] << 21 + carry[10] = s10 >> 21 + s11 += carry[10] + s10 -= carry[10] << 21 + + s[0] = byte(s0 >> 0) + s[1] = byte(s0 >> 8) + s[2] = byte((s0 >> 16) | (s1 << 5)) + s[3] = byte(s1 >> 3) + s[4] = byte(s1 >> 11) + s[5] = byte((s1 >> 19) | (s2 << 2)) + s[6] = byte(s2 >> 6) + s[7] = byte((s2 >> 14) | (s3 << 7)) + s[8] = byte(s3 >> 1) + s[9] = byte(s3 >> 9) + s[10] = byte((s3 >> 17) | (s4 << 4)) + s[11] = byte(s4 >> 4) + s[12] = byte(s4 >> 12) + s[13] = byte((s4 >> 20) | (s5 << 1)) + s[14] = byte(s5 >> 7) + s[15] = byte((s5 >> 15) | (s6 << 6)) + s[16] = byte(s6 >> 2) + s[17] = byte(s6 >> 10) + s[18] = byte((s6 >> 18) | (s7 << 3)) + s[19] = byte(s7 >> 5) + s[20] = byte(s7 >> 13) + s[21] = byte(s8 >> 0) + s[22] = byte(s8 >> 8) + s[23] = byte((s8 >> 16) | (s9 << 5)) + s[24] = byte(s9 >> 3) + s[25] = byte(s9 >> 11) + s[26] = byte((s9 >> 19) | (s10 << 2)) + s[27] = byte(s10 >> 6) + s[28] = byte((s10 >> 14) | (s11 << 7)) + s[29] = byte(s11 >> 1) + s[30] = byte(s11 >> 9) + s[31] = byte(s11 >> 17) +} + +// Input: +// s[0]+256*s[1]+...+256^63*s[63] = s +// +// Output: +// s[0]+256*s[1]+...+256^31*s[31] = s mod l +// where l = 2^252 + 27742317777372353535851937790883648493. +func ScReduce(out *[32]byte, s *[64]byte) { + s0 := 2097151 & load3(s[:]) + s1 := 2097151 & (load4(s[2:]) >> 5) + s2 := 2097151 & (load3(s[5:]) >> 2) + s3 := 2097151 & (load4(s[7:]) >> 7) + s4 := 2097151 & (load4(s[10:]) >> 4) + s5 := 2097151 & (load3(s[13:]) >> 1) + s6 := 2097151 & (load4(s[15:]) >> 6) + s7 := 2097151 & (load3(s[18:]) >> 3) + s8 := 2097151 & load3(s[21:]) + s9 := 2097151 & (load4(s[23:]) >> 5) + s10 := 2097151 & (load3(s[26:]) >> 2) + s11 := 2097151 & (load4(s[28:]) >> 7) + s12 := 2097151 & (load4(s[31:]) >> 4) + s13 := 2097151 & (load3(s[34:]) >> 1) + s14 := 2097151 & (load4(s[36:]) >> 6) + s15 := 2097151 & (load3(s[39:]) >> 3) + s16 := 2097151 & load3(s[42:]) + s17 := 2097151 & (load4(s[44:]) >> 5) + s18 := 2097151 & (load3(s[47:]) >> 2) + s19 := 2097151 & (load4(s[49:]) >> 7) + s20 := 2097151 & (load4(s[52:]) >> 4) + s21 := 2097151 & (load3(s[55:]) >> 1) + s22 := 2097151 & (load4(s[57:]) >> 6) + s23 := (load4(s[60:]) >> 3) + + s11 += s23 * 666643 + s12 += s23 * 470296 + s13 += s23 * 654183 + s14 -= s23 * 997805 + s15 += s23 * 136657 + s16 -= s23 * 683901 + s23 = 0 + + s10 += s22 * 666643 + s11 += s22 * 470296 + s12 += s22 * 654183 + s13 -= s22 * 997805 + s14 += s22 * 136657 + s15 -= s22 * 683901 + s22 = 0 + + s9 += s21 * 666643 + s10 += s21 * 470296 + s11 += s21 * 654183 + s12 -= s21 * 997805 + s13 += s21 * 136657 + s14 -= s21 * 683901 + s21 = 0 + + s8 += s20 * 666643 + s9 += s20 * 470296 + s10 += s20 * 654183 + s11 -= s20 * 997805 + s12 += s20 * 136657 + s13 -= s20 * 683901 + s20 = 0 + + s7 += s19 * 666643 + s8 += s19 * 470296 + s9 += s19 * 654183 + s10 -= s19 * 997805 + s11 += s19 * 136657 + s12 -= s19 * 683901 + s19 = 0 + + s6 += s18 * 666643 + s7 += s18 * 470296 + s8 += s18 * 654183 + s9 -= s18 * 997805 + s10 += s18 * 136657 + s11 -= s18 * 683901 + s18 = 0 + + var carry [17]int64 + + carry[6] = (s6 + (1 << 20)) >> 21 + s7 += carry[6] + s6 -= carry[6] << 21 + carry[8] = (s8 + (1 << 20)) >> 21 + s9 += carry[8] + s8 -= carry[8] << 21 + carry[10] = (s10 + (1 << 20)) >> 21 + s11 += carry[10] + s10 -= carry[10] << 21 + carry[12] = (s12 + (1 << 20)) >> 21 + s13 += carry[12] + s12 -= carry[12] << 21 + carry[14] = (s14 + (1 << 20)) >> 21 + s15 += carry[14] + s14 -= carry[14] << 21 + carry[16] = (s16 + (1 << 20)) >> 21 + s17 += carry[16] + s16 -= carry[16] << 21 + + carry[7] = (s7 + (1 << 20)) >> 21 + s8 += carry[7] + s7 -= carry[7] << 21 + carry[9] = (s9 + (1 << 20)) >> 21 + s10 += carry[9] + s9 -= carry[9] << 21 + carry[11] = (s11 + (1 << 20)) >> 21 + s12 += carry[11] + s11 -= carry[11] << 21 + carry[13] = (s13 + (1 << 20)) >> 21 + s14 += carry[13] + s13 -= carry[13] << 21 + carry[15] = (s15 + (1 << 20)) >> 21 + s16 += carry[15] + s15 -= carry[15] << 21 + + s5 += s17 * 666643 + s6 += s17 * 470296 + s7 += s17 * 654183 + s8 -= s17 * 997805 + s9 += s17 * 136657 + s10 -= s17 * 683901 + s17 = 0 + + s4 += s16 * 666643 + s5 += s16 * 470296 + s6 += s16 * 654183 + s7 -= s16 * 997805 + s8 += s16 * 136657 + s9 -= s16 * 683901 + s16 = 0 + + s3 += s15 * 666643 + s4 += s15 * 470296 + s5 += s15 * 654183 + s6 -= s15 * 997805 + s7 += s15 * 136657 + s8 -= s15 * 683901 + s15 = 0 + + s2 += s14 * 666643 + s3 += s14 * 470296 + s4 += s14 * 654183 + s5 -= s14 * 997805 + s6 += s14 * 136657 + s7 -= s14 * 683901 + s14 = 0 + + s1 += s13 * 666643 + s2 += s13 * 470296 + s3 += s13 * 654183 + s4 -= s13 * 997805 + s5 += s13 * 136657 + s6 -= s13 * 683901 + s13 = 0 + + s0 += s12 * 666643 + s1 += s12 * 470296 + s2 += s12 * 654183 + s3 -= s12 * 997805 + s4 += s12 * 136657 + s5 -= s12 * 683901 + s12 = 0 + + carry[0] = (s0 + (1 << 20)) >> 21 + s1 += carry[0] + s0 -= carry[0] << 21 + carry[2] = (s2 + (1 << 20)) >> 21 + s3 += carry[2] + s2 -= carry[2] << 21 + carry[4] = (s4 + (1 << 20)) >> 21 + s5 += carry[4] + s4 -= carry[4] << 21 + carry[6] = (s6 + (1 << 20)) >> 21 + s7 += carry[6] + s6 -= carry[6] << 21 + carry[8] = (s8 + (1 << 20)) >> 21 + s9 += carry[8] + s8 -= carry[8] << 21 + carry[10] = (s10 + (1 << 20)) >> 21 + s11 += carry[10] + s10 -= carry[10] << 21 + + carry[1] = (s1 + (1 << 20)) >> 21 + s2 += carry[1] + s1 -= carry[1] << 21 + carry[3] = (s3 + (1 << 20)) >> 21 + s4 += carry[3] + s3 -= carry[3] << 21 + carry[5] = (s5 + (1 << 20)) >> 21 + s6 += carry[5] + s5 -= carry[5] << 21 + carry[7] = (s7 + (1 << 20)) >> 21 + s8 += carry[7] + s7 -= carry[7] << 21 + carry[9] = (s9 + (1 << 20)) >> 21 + s10 += carry[9] + s9 -= carry[9] << 21 + carry[11] = (s11 + (1 << 20)) >> 21 + s12 += carry[11] + s11 -= carry[11] << 21 + + s0 += s12 * 666643 + s1 += s12 * 470296 + s2 += s12 * 654183 + s3 -= s12 * 997805 + s4 += s12 * 136657 + s5 -= s12 * 683901 + s12 = 0 + + carry[0] = s0 >> 21 + s1 += carry[0] + s0 -= carry[0] << 21 + carry[1] = s1 >> 21 + s2 += carry[1] + s1 -= carry[1] << 21 + carry[2] = s2 >> 21 + s3 += carry[2] + s2 -= carry[2] << 21 + carry[3] = s3 >> 21 + s4 += carry[3] + s3 -= carry[3] << 21 + carry[4] = s4 >> 21 + s5 += carry[4] + s4 -= carry[4] << 21 + carry[5] = s5 >> 21 + s6 += carry[5] + s5 -= carry[5] << 21 + carry[6] = s6 >> 21 + s7 += carry[6] + s6 -= carry[6] << 21 + carry[7] = s7 >> 21 + s8 += carry[7] + s7 -= carry[7] << 21 + carry[8] = s8 >> 21 + s9 += carry[8] + s8 -= carry[8] << 21 + carry[9] = s9 >> 21 + s10 += carry[9] + s9 -= carry[9] << 21 + carry[10] = s10 >> 21 + s11 += carry[10] + s10 -= carry[10] << 21 + carry[11] = s11 >> 21 + s12 += carry[11] + s11 -= carry[11] << 21 + + s0 += s12 * 666643 + s1 += s12 * 470296 + s2 += s12 * 654183 + s3 -= s12 * 997805 + s4 += s12 * 136657 + s5 -= s12 * 683901 + s12 = 0 + + carry[0] = s0 >> 21 + s1 += carry[0] + s0 -= carry[0] << 21 + carry[1] = s1 >> 21 + s2 += carry[1] + s1 -= carry[1] << 21 + carry[2] = s2 >> 21 + s3 += carry[2] + s2 -= carry[2] << 21 + carry[3] = s3 >> 21 + s4 += carry[3] + s3 -= carry[3] << 21 + carry[4] = s4 >> 21 + s5 += carry[4] + s4 -= carry[4] << 21 + carry[5] = s5 >> 21 + s6 += carry[5] + s5 -= carry[5] << 21 + carry[6] = s6 >> 21 + s7 += carry[6] + s6 -= carry[6] << 21 + carry[7] = s7 >> 21 + s8 += carry[7] + s7 -= carry[7] << 21 + carry[8] = s8 >> 21 + s9 += carry[8] + s8 -= carry[8] << 21 + carry[9] = s9 >> 21 + s10 += carry[9] + s9 -= carry[9] << 21 + carry[10] = s10 >> 21 + s11 += carry[10] + s10 -= carry[10] << 21 + + out[0] = byte(s0 >> 0) + out[1] = byte(s0 >> 8) + out[2] = byte((s0 >> 16) | (s1 << 5)) + out[3] = byte(s1 >> 3) + out[4] = byte(s1 >> 11) + out[5] = byte((s1 >> 19) | (s2 << 2)) + out[6] = byte(s2 >> 6) + out[7] = byte((s2 >> 14) | (s3 << 7)) + out[8] = byte(s3 >> 1) + out[9] = byte(s3 >> 9) + out[10] = byte((s3 >> 17) | (s4 << 4)) + out[11] = byte(s4 >> 4) + out[12] = byte(s4 >> 12) + out[13] = byte((s4 >> 20) | (s5 << 1)) + out[14] = byte(s5 >> 7) + out[15] = byte((s5 >> 15) | (s6 << 6)) + out[16] = byte(s6 >> 2) + out[17] = byte(s6 >> 10) + out[18] = byte((s6 >> 18) | (s7 << 3)) + out[19] = byte(s7 >> 5) + out[20] = byte(s7 >> 13) + out[21] = byte(s8 >> 0) + out[22] = byte(s8 >> 8) + out[23] = byte((s8 >> 16) | (s9 << 5)) + out[24] = byte(s9 >> 3) + out[25] = byte(s9 >> 11) + out[26] = byte((s9 >> 19) | (s10 << 2)) + out[27] = byte(s10 >> 6) + out[28] = byte((s10 >> 14) | (s11 << 7)) + out[29] = byte(s11 >> 1) + out[30] = byte(s11 >> 9) + out[31] = byte(s11 >> 17) +} diff --git a/vendor/golang.org/x/crypto/ed25519/testdata/sign.input.gz b/vendor/golang.org/x/crypto/ed25519/testdata/sign.input.gz new file mode 100644 index 0000000000000000000000000000000000000000..41030690c0db39a0279304a46f002a625caa9080 Binary files /dev/null and b/vendor/golang.org/x/crypto/ed25519/testdata/sign.input.gz differ diff --git a/vendor/golang.org/x/crypto/hkdf/example_test.go b/vendor/golang.org/x/crypto/hkdf/example_test.go new file mode 100644 index 0000000000000000000000000000000000000000..df84395129115e3aa5c4c46a52597bf3d1d9a9c4 --- /dev/null +++ b/vendor/golang.org/x/crypto/hkdf/example_test.go @@ -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 +} diff --git a/vendor/golang.org/x/crypto/hkdf/hkdf.go b/vendor/golang.org/x/crypto/hkdf/hkdf.go new file mode 100644 index 0000000000000000000000000000000000000000..5bc246355a265a3359b491152779b0c35fa180a4 --- /dev/null +++ b/vendor/golang.org/x/crypto/hkdf/hkdf.go @@ -0,0 +1,75 @@ +// 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 implements the HMAC-based Extract-and-Expand Key Derivation +// Function (HKDF) as defined in RFC 5869. +// +// HKDF is a cryptographic key derivation function (KDF) with the goal of +// expanding limited input keying material into one or more cryptographically +// strong secret keys. +// +// RFC 5869: https://tools.ietf.org/html/rfc5869 +package hkdf // import "golang.org/x/crypto/hkdf" + +import ( + "crypto/hmac" + "errors" + "hash" + "io" +) + +type hkdf struct { + expander hash.Hash + size int + + info []byte + counter byte + + prev []byte + cache []byte +} + +func (f *hkdf) Read(p []byte) (int, error) { + // Check whether enough data can be generated + need := len(p) + remains := len(f.cache) + int(255-f.counter+1)*f.size + if remains < need { + return 0, errors.New("hkdf: entropy limit reached") + } + // Read from the cache, if enough data is present + n := copy(p, f.cache) + p = p[n:] + + // Fill the buffer + for len(p) > 0 { + f.expander.Reset() + f.expander.Write(f.prev) + f.expander.Write(f.info) + f.expander.Write([]byte{f.counter}) + f.prev = f.expander.Sum(f.prev[:0]) + f.counter++ + + // Copy the new batch into p + f.cache = f.prev + n = copy(p, f.cache) + p = p[n:] + } + // Save leftovers for next run + f.cache = f.cache[n:] + + return need, nil +} + +// New returns a new HKDF using the given hash, the secret keying material to expand +// and optional salt and info fields. +func New(hash func() hash.Hash, secret, salt, info []byte) io.Reader { + if salt == nil { + salt = make([]byte, hash().Size()) + } + extractor := hmac.New(hash, salt) + extractor.Write(secret) + prk := extractor.Sum(nil) + + return &hkdf{hmac.New(hash, prk), extractor.Size(), info, 1, nil, nil} +} diff --git a/vendor/golang.org/x/crypto/hkdf/hkdf_test.go b/vendor/golang.org/x/crypto/hkdf/hkdf_test.go new file mode 100644 index 0000000000000000000000000000000000000000..cee659bcdb97408ad84cf5bbdf9dcd7c6fb05117 --- /dev/null +++ b/vendor/golang.org/x/crypto/hkdf/hkdf_test.go @@ -0,0 +1,370 @@ +// 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 + +import ( + "bytes" + "crypto/md5" + "crypto/sha1" + "crypto/sha256" + "crypto/sha512" + "hash" + "io" + "testing" +) + +type hkdfTest struct { + hash func() hash.Hash + master []byte + salt []byte + info []byte + out []byte +} + +var hkdfTests = []hkdfTest{ + // Tests from RFC 5869 + { + sha256.New, + []byte{ + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + }, + []byte{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, + }, + []byte{ + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, + }, + []byte{ + 0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, + 0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36, 0x2f, 0x2a, + 0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c, + 0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf, + 0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18, + 0x58, 0x65, + }, + }, + { + sha256.New, + []byte{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + }, + []byte{ + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + }, + []byte{ + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, + }, + []byte{ + 0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1, + 0xc8, 0xe7, 0xf7, 0x8c, 0x59, 0x6a, 0x49, 0x34, + 0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8, + 0xa0, 0x50, 0xcc, 0x4c, 0x19, 0xaf, 0xa9, 0x7c, + 0x59, 0x04, 0x5a, 0x99, 0xca, 0xc7, 0x82, 0x72, + 0x71, 0xcb, 0x41, 0xc6, 0x5e, 0x59, 0x0e, 0x09, + 0xda, 0x32, 0x75, 0x60, 0x0c, 0x2f, 0x09, 0xb8, + 0x36, 0x77, 0x93, 0xa9, 0xac, 0xa3, 0xdb, 0x71, + 0xcc, 0x30, 0xc5, 0x81, 0x79, 0xec, 0x3e, 0x87, + 0xc1, 0x4c, 0x01, 0xd5, 0xc1, 0xf3, 0x43, 0x4f, + 0x1d, 0x87, + }, + }, + { + sha256.New, + []byte{ + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + }, + []byte{}, + []byte{}, + []byte{ + 0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f, + 0x71, 0x5f, 0x80, 0x2a, 0x06, 0x3c, 0x5a, 0x31, + 0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e, + 0xc3, 0x45, 0x4e, 0x5f, 0x3c, 0x73, 0x8d, 0x2d, + 0x9d, 0x20, 0x13, 0x95, 0xfa, 0xa4, 0xb6, 0x1a, + 0x96, 0xc8, + }, + }, + { + sha1.New, + []byte{ + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, + }, + []byte{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, + }, + []byte{ + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, + }, + []byte{ + 0x08, 0x5a, 0x01, 0xea, 0x1b, 0x10, 0xf3, 0x69, + 0x33, 0x06, 0x8b, 0x56, 0xef, 0xa5, 0xad, 0x81, + 0xa4, 0xf1, 0x4b, 0x82, 0x2f, 0x5b, 0x09, 0x15, + 0x68, 0xa9, 0xcd, 0xd4, 0xf1, 0x55, 0xfd, 0xa2, + 0xc2, 0x2e, 0x42, 0x24, 0x78, 0xd3, 0x05, 0xf3, + 0xf8, 0x96, + }, + }, + { + sha1.New, + []byte{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + }, + []byte{ + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + }, + []byte{ + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, + }, + []byte{ + 0x0b, 0xd7, 0x70, 0xa7, 0x4d, 0x11, 0x60, 0xf7, + 0xc9, 0xf1, 0x2c, 0xd5, 0x91, 0x2a, 0x06, 0xeb, + 0xff, 0x6a, 0xdc, 0xae, 0x89, 0x9d, 0x92, 0x19, + 0x1f, 0xe4, 0x30, 0x56, 0x73, 0xba, 0x2f, 0xfe, + 0x8f, 0xa3, 0xf1, 0xa4, 0xe5, 0xad, 0x79, 0xf3, + 0xf3, 0x34, 0xb3, 0xb2, 0x02, 0xb2, 0x17, 0x3c, + 0x48, 0x6e, 0xa3, 0x7c, 0xe3, 0xd3, 0x97, 0xed, + 0x03, 0x4c, 0x7f, 0x9d, 0xfe, 0xb1, 0x5c, 0x5e, + 0x92, 0x73, 0x36, 0xd0, 0x44, 0x1f, 0x4c, 0x43, + 0x00, 0xe2, 0xcf, 0xf0, 0xd0, 0x90, 0x0b, 0x52, + 0xd3, 0xb4, + }, + }, + { + sha1.New, + []byte{ + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + }, + []byte{}, + []byte{}, + []byte{ + 0x0a, 0xc1, 0xaf, 0x70, 0x02, 0xb3, 0xd7, 0x61, + 0xd1, 0xe5, 0x52, 0x98, 0xda, 0x9d, 0x05, 0x06, + 0xb9, 0xae, 0x52, 0x05, 0x72, 0x20, 0xa3, 0x06, + 0xe0, 0x7b, 0x6b, 0x87, 0xe8, 0xdf, 0x21, 0xd0, + 0xea, 0x00, 0x03, 0x3d, 0xe0, 0x39, 0x84, 0xd3, + 0x49, 0x18, + }, + }, + { + sha1.New, + []byte{ + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + }, + nil, + []byte{}, + []byte{ + 0x2c, 0x91, 0x11, 0x72, 0x04, 0xd7, 0x45, 0xf3, + 0x50, 0x0d, 0x63, 0x6a, 0x62, 0xf6, 0x4f, 0x0a, + 0xb3, 0xba, 0xe5, 0x48, 0xaa, 0x53, 0xd4, 0x23, + 0xb0, 0xd1, 0xf2, 0x7e, 0xbb, 0xa6, 0xf5, 0xe5, + 0x67, 0x3a, 0x08, 0x1d, 0x70, 0xcc, 0xe7, 0xac, + 0xfc, 0x48, + }, + }, +} + +func TestHKDF(t *testing.T) { + for i, tt := range hkdfTests { + hkdf := New(tt.hash, tt.master, tt.salt, tt.info) + out := make([]byte, len(tt.out)) + + n, err := io.ReadFull(hkdf, out) + if n != len(tt.out) || err != nil { + t.Errorf("test %d: not enough output bytes: %d.", i, n) + } + + if !bytes.Equal(out, tt.out) { + t.Errorf("test %d: incorrect output: have %v, need %v.", i, out, tt.out) + } + } +} + +func TestHKDFMultiRead(t *testing.T) { + for i, tt := range hkdfTests { + hkdf := New(tt.hash, tt.master, tt.salt, tt.info) + out := make([]byte, len(tt.out)) + + for b := 0; b < len(tt.out); b++ { + n, err := io.ReadFull(hkdf, out[b:b+1]) + if n != 1 || err != nil { + t.Errorf("test %d.%d: not enough output bytes: have %d, need %d .", i, b, n, len(tt.out)) + } + } + + if !bytes.Equal(out, tt.out) { + t.Errorf("test %d: incorrect output: have %v, need %v.", i, out, tt.out) + } + } +} + +func TestHKDFLimit(t *testing.T) { + hash := sha1.New + master := []byte{0x00, 0x01, 0x02, 0x03} + info := []byte{} + + hkdf := New(hash, master, nil, info) + limit := hash().Size() * 255 + out := make([]byte, limit) + + // The maximum output bytes should be extractable + n, err := io.ReadFull(hkdf, out) + if n != limit || err != nil { + t.Errorf("not enough output bytes: %d, %v.", n, err) + } + + // Reading one more should fail + n, err = io.ReadFull(hkdf, make([]byte, 1)) + if n > 0 || err == nil { + t.Errorf("key expansion overflowed: n = %d, err = %v", n, err) + } +} + +func Benchmark16ByteMD5Single(b *testing.B) { + benchmarkHKDFSingle(md5.New, 16, b) +} + +func Benchmark20ByteSHA1Single(b *testing.B) { + benchmarkHKDFSingle(sha1.New, 20, b) +} + +func Benchmark32ByteSHA256Single(b *testing.B) { + benchmarkHKDFSingle(sha256.New, 32, b) +} + +func Benchmark64ByteSHA512Single(b *testing.B) { + benchmarkHKDFSingle(sha512.New, 64, b) +} + +func Benchmark8ByteMD5Stream(b *testing.B) { + benchmarkHKDFStream(md5.New, 8, b) +} + +func Benchmark16ByteMD5Stream(b *testing.B) { + benchmarkHKDFStream(md5.New, 16, b) +} + +func Benchmark8ByteSHA1Stream(b *testing.B) { + benchmarkHKDFStream(sha1.New, 8, b) +} + +func Benchmark20ByteSHA1Stream(b *testing.B) { + benchmarkHKDFStream(sha1.New, 20, b) +} + +func Benchmark8ByteSHA256Stream(b *testing.B) { + benchmarkHKDFStream(sha256.New, 8, b) +} + +func Benchmark32ByteSHA256Stream(b *testing.B) { + benchmarkHKDFStream(sha256.New, 32, b) +} + +func Benchmark8ByteSHA512Stream(b *testing.B) { + benchmarkHKDFStream(sha512.New, 8, b) +} + +func Benchmark64ByteSHA512Stream(b *testing.B) { + benchmarkHKDFStream(sha512.New, 64, b) +} + +func benchmarkHKDFSingle(hasher func() hash.Hash, block int, b *testing.B) { + master := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07} + salt := []byte{0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17} + info := []byte{0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27} + out := make([]byte, block) + + b.SetBytes(int64(block)) + b.ResetTimer() + + for i := 0; i < b.N; i++ { + hkdf := New(hasher, master, salt, info) + io.ReadFull(hkdf, out) + } +} + +func benchmarkHKDFStream(hasher func() hash.Hash, block int, b *testing.B) { + master := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07} + salt := []byte{0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17} + info := []byte{0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27} + out := make([]byte, block) + + b.SetBytes(int64(block)) + b.ResetTimer() + + hkdf := New(hasher, master, salt, info) + for i := 0; i < b.N; i++ { + _, err := io.ReadFull(hkdf, out) + if err != nil { + hkdf = New(hasher, master, salt, info) + i-- + } + } +} diff --git a/vendor/golang.org/x/crypto/internal/chacha20/chacha_generic.go b/vendor/golang.org/x/crypto/internal/chacha20/chacha_generic.go new file mode 100644 index 0000000000000000000000000000000000000000..0f8efdbaa44f9da19aca5a14740e29ea5da07660 --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/chacha20/chacha_generic.go @@ -0,0 +1,198 @@ +// Copyright 2016 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 ChaCha20 implements the core ChaCha20 function as specified in https://tools.ietf.org/html/rfc7539#section-2.3. +package chacha20 + +import "encoding/binary" + +const rounds = 20 + +// core applies the ChaCha20 core function to 16-byte input in, 32-byte key k, +// and 16-byte constant c, and puts the result into 64-byte array out. +func core(out *[64]byte, in *[16]byte, k *[32]byte) { + j0 := uint32(0x61707865) + j1 := uint32(0x3320646e) + j2 := uint32(0x79622d32) + j3 := uint32(0x6b206574) + j4 := binary.LittleEndian.Uint32(k[0:4]) + j5 := binary.LittleEndian.Uint32(k[4:8]) + j6 := binary.LittleEndian.Uint32(k[8:12]) + j7 := binary.LittleEndian.Uint32(k[12:16]) + j8 := binary.LittleEndian.Uint32(k[16:20]) + j9 := binary.LittleEndian.Uint32(k[20:24]) + j10 := binary.LittleEndian.Uint32(k[24:28]) + j11 := binary.LittleEndian.Uint32(k[28:32]) + j12 := binary.LittleEndian.Uint32(in[0:4]) + j13 := binary.LittleEndian.Uint32(in[4:8]) + j14 := binary.LittleEndian.Uint32(in[8:12]) + j15 := binary.LittleEndian.Uint32(in[12:16]) + + x0, x1, x2, x3, x4, x5, x6, x7 := j0, j1, j2, j3, j4, j5, j6, j7 + x8, x9, x10, x11, x12, x13, x14, x15 := j8, j9, j10, j11, j12, j13, j14, j15 + + for i := 0; i < rounds; i += 2 { + x0 += x4 + x12 ^= x0 + x12 = (x12 << 16) | (x12 >> (16)) + x8 += x12 + x4 ^= x8 + x4 = (x4 << 12) | (x4 >> (20)) + x0 += x4 + x12 ^= x0 + x12 = (x12 << 8) | (x12 >> (24)) + x8 += x12 + x4 ^= x8 + x4 = (x4 << 7) | (x4 >> (25)) + x1 += x5 + x13 ^= x1 + x13 = (x13 << 16) | (x13 >> 16) + x9 += x13 + x5 ^= x9 + x5 = (x5 << 12) | (x5 >> 20) + x1 += x5 + x13 ^= x1 + x13 = (x13 << 8) | (x13 >> 24) + x9 += x13 + x5 ^= x9 + x5 = (x5 << 7) | (x5 >> 25) + x2 += x6 + x14 ^= x2 + x14 = (x14 << 16) | (x14 >> 16) + x10 += x14 + x6 ^= x10 + x6 = (x6 << 12) | (x6 >> 20) + x2 += x6 + x14 ^= x2 + x14 = (x14 << 8) | (x14 >> 24) + x10 += x14 + x6 ^= x10 + x6 = (x6 << 7) | (x6 >> 25) + x3 += x7 + x15 ^= x3 + x15 = (x15 << 16) | (x15 >> 16) + x11 += x15 + x7 ^= x11 + x7 = (x7 << 12) | (x7 >> 20) + x3 += x7 + x15 ^= x3 + x15 = (x15 << 8) | (x15 >> 24) + x11 += x15 + x7 ^= x11 + x7 = (x7 << 7) | (x7 >> 25) + x0 += x5 + x15 ^= x0 + x15 = (x15 << 16) | (x15 >> 16) + x10 += x15 + x5 ^= x10 + x5 = (x5 << 12) | (x5 >> 20) + x0 += x5 + x15 ^= x0 + x15 = (x15 << 8) | (x15 >> 24) + x10 += x15 + x5 ^= x10 + x5 = (x5 << 7) | (x5 >> 25) + x1 += x6 + x12 ^= x1 + x12 = (x12 << 16) | (x12 >> 16) + x11 += x12 + x6 ^= x11 + x6 = (x6 << 12) | (x6 >> 20) + x1 += x6 + x12 ^= x1 + x12 = (x12 << 8) | (x12 >> 24) + x11 += x12 + x6 ^= x11 + x6 = (x6 << 7) | (x6 >> 25) + x2 += x7 + x13 ^= x2 + x13 = (x13 << 16) | (x13 >> 16) + x8 += x13 + x7 ^= x8 + x7 = (x7 << 12) | (x7 >> 20) + x2 += x7 + x13 ^= x2 + x13 = (x13 << 8) | (x13 >> 24) + x8 += x13 + x7 ^= x8 + x7 = (x7 << 7) | (x7 >> 25) + x3 += x4 + x14 ^= x3 + x14 = (x14 << 16) | (x14 >> 16) + x9 += x14 + x4 ^= x9 + x4 = (x4 << 12) | (x4 >> 20) + x3 += x4 + x14 ^= x3 + x14 = (x14 << 8) | (x14 >> 24) + x9 += x14 + x4 ^= x9 + x4 = (x4 << 7) | (x4 >> 25) + } + + x0 += j0 + x1 += j1 + x2 += j2 + x3 += j3 + x4 += j4 + x5 += j5 + x6 += j6 + x7 += j7 + x8 += j8 + x9 += j9 + x10 += j10 + x11 += j11 + x12 += j12 + x13 += j13 + x14 += j14 + x15 += j15 + + binary.LittleEndian.PutUint32(out[0:4], x0) + binary.LittleEndian.PutUint32(out[4:8], x1) + binary.LittleEndian.PutUint32(out[8:12], x2) + binary.LittleEndian.PutUint32(out[12:16], x3) + binary.LittleEndian.PutUint32(out[16:20], x4) + binary.LittleEndian.PutUint32(out[20:24], x5) + binary.LittleEndian.PutUint32(out[24:28], x6) + binary.LittleEndian.PutUint32(out[28:32], x7) + binary.LittleEndian.PutUint32(out[32:36], x8) + binary.LittleEndian.PutUint32(out[36:40], x9) + binary.LittleEndian.PutUint32(out[40:44], x10) + binary.LittleEndian.PutUint32(out[44:48], x11) + binary.LittleEndian.PutUint32(out[48:52], x12) + binary.LittleEndian.PutUint32(out[52:56], x13) + binary.LittleEndian.PutUint32(out[56:60], x14) + binary.LittleEndian.PutUint32(out[60:64], x15) +} + +// XORKeyStream crypts bytes from in to out using the given key and counters. +// In and out must overlap entirely or not at all. Counter contains the raw +// ChaCha20 counter bytes (i.e. block counter followed by nonce). +func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) { + var block [64]byte + var counterCopy [16]byte + copy(counterCopy[:], counter[:]) + + for len(in) >= 64 { + core(&block, &counterCopy, key) + for i, x := range block { + out[i] = in[i] ^ x + } + u := uint32(1) + for i := 0; i < 4; i++ { + u += uint32(counterCopy[i]) + counterCopy[i] = byte(u) + u >>= 8 + } + in = in[64:] + out = out[64:] + } + + if len(in) > 0 { + core(&block, &counterCopy, key) + for i, v := range in { + out[i] = v ^ block[i] + } + } +} diff --git a/vendor/golang.org/x/crypto/internal/chacha20/chacha_test.go b/vendor/golang.org/x/crypto/internal/chacha20/chacha_test.go new file mode 100644 index 0000000000000000000000000000000000000000..b80d34cdd77061bc3c8b1864842f2c9ea7c50fd7 --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/chacha20/chacha_test.go @@ -0,0 +1,33 @@ +// Copyright 2016 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 chacha20 + +import ( + "encoding/hex" + "testing" +) + +func TestCore(t *testing.T) { + // This is just a smoke test that checks the example from + // https://tools.ietf.org/html/rfc7539#section-2.3.2. The + // chacha20poly1305 package contains much more extensive tests of this + // code. + var key [32]byte + for i := range key { + key[i] = byte(i) + } + + var input [16]byte + input[0] = 1 + input[7] = 9 + input[11] = 0x4a + + var out [64]byte + XORKeyStream(out[:], out[:], &input, &key) + const expected = "10f1e7e4d13b5915500fdd1fa32071c4c7d1f4c733c068030422aa9ac3d46c4ed2826446079faa0914c2d705d98b02a2b5129cd1de164eb9cbd083e8a2503c4e" + if result := hex.EncodeToString(out[:]); result != expected { + t.Errorf("wanted %x but got %x", expected, result) + } +} diff --git a/vendor/golang.org/x/crypto/md4/example_test.go b/vendor/golang.org/x/crypto/md4/example_test.go new file mode 100644 index 0000000000000000000000000000000000000000..db3f59b19bce5474e7f173cdd40fd3f6104deb36 --- /dev/null +++ b/vendor/golang.org/x/crypto/md4/example_test.go @@ -0,0 +1,20 @@ +// Copyright 2017 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 md4_test + +import ( + "fmt" + "io" + + "golang.org/x/crypto/md4" +) + +func ExampleNew() { + h := md4.New() + data := "These pretzels are making me thirsty." + io.WriteString(h, data) + fmt.Printf("%x", h.Sum(nil)) + // Output: 48c4e365090b30a32f084c4888deceaa +} diff --git a/vendor/golang.org/x/crypto/md4/md4.go b/vendor/golang.org/x/crypto/md4/md4.go new file mode 100644 index 0000000000000000000000000000000000000000..6d9ba9e5f330a7c82e37d424ee1247b1f43b05ad --- /dev/null +++ b/vendor/golang.org/x/crypto/md4/md4.go @@ -0,0 +1,118 @@ +// Copyright 2009 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 md4 implements the MD4 hash algorithm as defined in RFC 1320. +package md4 // import "golang.org/x/crypto/md4" + +import ( + "crypto" + "hash" +) + +func init() { + crypto.RegisterHash(crypto.MD4, New) +} + +// The size of an MD4 checksum in bytes. +const Size = 16 + +// The blocksize of MD4 in bytes. +const BlockSize = 64 + +const ( + _Chunk = 64 + _Init0 = 0x67452301 + _Init1 = 0xEFCDAB89 + _Init2 = 0x98BADCFE + _Init3 = 0x10325476 +) + +// digest represents the partial evaluation of a checksum. +type digest struct { + s [4]uint32 + x [_Chunk]byte + nx int + len uint64 +} + +func (d *digest) Reset() { + d.s[0] = _Init0 + d.s[1] = _Init1 + d.s[2] = _Init2 + d.s[3] = _Init3 + d.nx = 0 + d.len = 0 +} + +// New returns a new hash.Hash computing the MD4 checksum. +func New() hash.Hash { + d := new(digest) + d.Reset() + return d +} + +func (d *digest) Size() int { return Size } + +func (d *digest) BlockSize() int { return BlockSize } + +func (d *digest) Write(p []byte) (nn int, err error) { + nn = len(p) + d.len += uint64(nn) + if d.nx > 0 { + n := len(p) + if n > _Chunk-d.nx { + n = _Chunk - d.nx + } + for i := 0; i < n; i++ { + d.x[d.nx+i] = p[i] + } + d.nx += n + if d.nx == _Chunk { + _Block(d, d.x[0:]) + d.nx = 0 + } + p = p[n:] + } + n := _Block(d, p) + p = p[n:] + if len(p) > 0 { + d.nx = copy(d.x[:], p) + } + return +} + +func (d0 *digest) Sum(in []byte) []byte { + // Make a copy of d0, so that caller can keep writing and summing. + d := new(digest) + *d = *d0 + + // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. + len := d.len + var tmp [64]byte + tmp[0] = 0x80 + if len%64 < 56 { + d.Write(tmp[0 : 56-len%64]) + } else { + d.Write(tmp[0 : 64+56-len%64]) + } + + // Length in bits. + len <<= 3 + for i := uint(0); i < 8; i++ { + tmp[i] = byte(len >> (8 * i)) + } + d.Write(tmp[0:8]) + + if d.nx != 0 { + panic("d.nx != 0") + } + + for _, s := range d.s { + in = append(in, byte(s>>0)) + in = append(in, byte(s>>8)) + in = append(in, byte(s>>16)) + in = append(in, byte(s>>24)) + } + return in +} diff --git a/vendor/golang.org/x/crypto/md4/md4_test.go b/vendor/golang.org/x/crypto/md4/md4_test.go new file mode 100644 index 0000000000000000000000000000000000000000..b56edd7875d8b6655cc07ccec0f65d8171d74680 --- /dev/null +++ b/vendor/golang.org/x/crypto/md4/md4_test.go @@ -0,0 +1,71 @@ +// Copyright 2009 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 md4 + +import ( + "fmt" + "io" + "testing" +) + +type md4Test struct { + out string + in string +} + +var golden = []md4Test{ + {"31d6cfe0d16ae931b73c59d7e0c089c0", ""}, + {"bde52cb31de33e46245e05fbdbd6fb24", "a"}, + {"ec388dd78999dfc7cf4632465693b6bf", "ab"}, + {"a448017aaf21d8525fc10ae87aa6729d", "abc"}, + {"41decd8f579255c5200f86a4bb3ba740", "abcd"}, + {"9803f4a34e8eb14f96adba49064a0c41", "abcde"}, + {"804e7f1c2586e50b49ac65db5b645131", "abcdef"}, + {"752f4adfe53d1da0241b5bc216d098fc", "abcdefg"}, + {"ad9daf8d49d81988590a6f0e745d15dd", "abcdefgh"}, + {"1e4e28b05464316b56402b3815ed2dfd", "abcdefghi"}, + {"dc959c6f5d6f9e04e4380777cc964b3d", "abcdefghij"}, + {"1b5701e265778898ef7de5623bbe7cc0", "Discard medicine more than two years old."}, + {"d7f087e090fe7ad4a01cb59dacc9a572", "He who has a shady past knows that nice guys finish last."}, + {"a6f8fd6df617c72837592fc3570595c9", "I wouldn't marry him with a ten foot pole."}, + {"c92a84a9526da8abc240c05d6b1a1ce0", "Free! Free!/A trip/to Mars/for 900/empty jars/Burma Shave"}, + {"f6013160c4dcb00847069fee3bb09803", "The days of the digital watch are numbered. -Tom Stoppard"}, + {"2c3bb64f50b9107ed57640fe94bec09f", "Nepal premier won't resign."}, + {"45b7d8a32c7806f2f7f897332774d6e4", "For every action there is an equal and opposite government program."}, + {"b5b4f9026b175c62d7654bdc3a1cd438", "His money is twice tainted: 'taint yours and 'taint mine."}, + {"caf44e80f2c20ce19b5ba1cab766e7bd", "There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977"}, + {"191fae6707f496aa54a6bce9f2ecf74d", "It's a tiny change to the code and not completely disgusting. - Bob Manchek"}, + {"9ddc753e7a4ccee6081cd1b45b23a834", "size: a.out: bad magic"}, + {"8d050f55b1cadb9323474564be08a521", "The major problem is with sendmail. -Mark Horton"}, + {"ad6e2587f74c3e3cc19146f6127fa2e3", "Give me a rock, paper and scissors and I will move the world. CCFestoon"}, + {"1d616d60a5fabe85589c3f1566ca7fca", "If the enemy is within range, then so are you."}, + {"aec3326a4f496a2ced65a1963f84577f", "It's well we cannot hear the screams/That we create in others' dreams."}, + {"77b4fd762d6b9245e61c50bf6ebf118b", "You remind me of a TV show, but that's all right: I watch it anyway."}, + {"e8f48c726bae5e516f6ddb1a4fe62438", "C is as portable as Stonehedge!!"}, + {"a3a84366e7219e887423b01f9be7166e", "Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley"}, + {"a6b7aa35157e984ef5d9b7f32e5fbb52", "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction. Lewis-Randall Rule"}, + {"75661f0545955f8f9abeeb17845f3fd6", "How can you write a big system without C++? -Paul Glick"}, +} + +func TestGolden(t *testing.T) { + for i := 0; i < len(golden); i++ { + g := golden[i] + c := New() + for j := 0; j < 3; j++ { + if j < 2 { + io.WriteString(c, g.in) + } else { + io.WriteString(c, g.in[0:len(g.in)/2]) + c.Sum(nil) + io.WriteString(c, g.in[len(g.in)/2:]) + } + s := fmt.Sprintf("%x", c.Sum(nil)) + if s != g.out { + t.Fatalf("md4[%d](%s) = %s want %s", j, g.in, s, g.out) + } + c.Reset() + } + } +} diff --git a/vendor/golang.org/x/crypto/md4/md4block.go b/vendor/golang.org/x/crypto/md4/md4block.go new file mode 100644 index 0000000000000000000000000000000000000000..3fed475f3f600440f0e99b91dffbb9663ae0056c --- /dev/null +++ b/vendor/golang.org/x/crypto/md4/md4block.go @@ -0,0 +1,89 @@ +// Copyright 2009 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. + +// MD4 block step. +// In its own file so that a faster assembly or C version +// can be substituted easily. + +package md4 + +var shift1 = []uint{3, 7, 11, 19} +var shift2 = []uint{3, 5, 9, 13} +var shift3 = []uint{3, 9, 11, 15} + +var xIndex2 = []uint{0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15} +var xIndex3 = []uint{0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15} + +func _Block(dig *digest, p []byte) int { + a := dig.s[0] + b := dig.s[1] + c := dig.s[2] + d := dig.s[3] + n := 0 + var X [16]uint32 + for len(p) >= _Chunk { + aa, bb, cc, dd := a, b, c, d + + j := 0 + for i := 0; i < 16; i++ { + X[i] = uint32(p[j]) | uint32(p[j+1])<<8 | uint32(p[j+2])<<16 | uint32(p[j+3])<<24 + j += 4 + } + + // If this needs to be made faster in the future, + // the usual trick is to unroll each of these + // loops by a factor of 4; that lets you replace + // the shift[] lookups with constants and, + // with suitable variable renaming in each + // unrolled body, delete the a, b, c, d = d, a, b, c + // (or you can let the optimizer do the renaming). + // + // The index variables are uint so that % by a power + // of two can be optimized easily by a compiler. + + // Round 1. + for i := uint(0); i < 16; i++ { + x := i + s := shift1[i%4] + f := ((c ^ d) & b) ^ d + a += f + X[x] + a = a<>(32-s) + a, b, c, d = d, a, b, c + } + + // Round 2. + for i := uint(0); i < 16; i++ { + x := xIndex2[i] + s := shift2[i%4] + g := (b & c) | (b & d) | (c & d) + a += g + X[x] + 0x5a827999 + a = a<>(32-s) + a, b, c, d = d, a, b, c + } + + // Round 3. + for i := uint(0); i < 16; i++ { + x := xIndex3[i] + s := shift3[i%4] + h := b ^ c ^ d + a += h + X[x] + 0x6ed9eba1 + a = a<>(32-s) + a, b, c, d = d, a, b, c + } + + a += aa + b += bb + c += cc + d += dd + + p = p[_Chunk:] + n += _Chunk + } + + dig.s[0] = a + dig.s[1] = b + dig.s[2] = c + dig.s[3] = d + return n +} diff --git a/vendor/golang.org/x/crypto/nacl/auth/auth.go b/vendor/golang.org/x/crypto/nacl/auth/auth.go new file mode 100644 index 0000000000000000000000000000000000000000..ec1d6ebe4a421743056141527e456b6ec62cb0fe --- /dev/null +++ b/vendor/golang.org/x/crypto/nacl/auth/auth.go @@ -0,0 +1,58 @@ +// Copyright 2017 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 auth authenticates a message using a secret key. + +The Sum function, viewed as a function of the message for a uniform random +key, is designed to meet the standard notion of unforgeability. This means +that an attacker cannot find authenticators for any messages not authenticated +by the sender, even if the attacker has adaptively influenced the messages +authenticated by the sender. For a formal definition see, e.g., Section 2.4 +of Bellare, Kilian, and Rogaway, "The security of the cipher block chaining +message authentication code," Journal of Computer and System Sciences 61 (2000), +362–399; http://www-cse.ucsd.edu/~mihir/papers/cbc.html. + +auth does not make any promises regarding "strong" unforgeability; perhaps +one valid authenticator can be converted into another valid authenticator for +the same message. NaCl also does not make any promises regarding "truncated +unforgeability." + +This package is interoperable with NaCl: https://nacl.cr.yp.to/auth.html. +*/ +package auth + +import ( + "crypto/hmac" + "crypto/sha512" +) + +const ( + // Size is the size, in bytes, of an authenticated digest. + Size = 32 + // KeySize is the size, in bytes, of an authentication key. + KeySize = 32 +) + +// Sum generates an authenticator for m using a secret key and returns the +// 32-byte digest. +func Sum(m []byte, key *[KeySize]byte) *[Size]byte { + mac := hmac.New(sha512.New, key[:]) + mac.Write(m) + out := new([KeySize]byte) + copy(out[:], mac.Sum(nil)[:Size]) + return out +} + +// Verify checks that digest is a valid authenticator of message m under the +// given secret key. Verify does not leak timing information. +func Verify(digest []byte, m []byte, key *[KeySize]byte) bool { + if len(digest) != Size { + return false + } + mac := hmac.New(sha512.New, key[:]) + mac.Write(m) + expectedMAC := mac.Sum(nil) // first 256 bits of 512-bit sum + return hmac.Equal(digest, expectedMAC[:Size]) +} diff --git a/vendor/golang.org/x/crypto/nacl/auth/auth_test.go b/vendor/golang.org/x/crypto/nacl/auth/auth_test.go new file mode 100644 index 0000000000000000000000000000000000000000..92074b50b60e64a49aecf47a20cc3d46439c37bb --- /dev/null +++ b/vendor/golang.org/x/crypto/nacl/auth/auth_test.go @@ -0,0 +1,172 @@ +// Copyright 2017 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 auth + +import ( + "bytes" + rand "crypto/rand" + mrand "math/rand" + "testing" +) + +// Test cases are from RFC 4231, and match those present in the tests directory +// of the download here: https://nacl.cr.yp.to/install.html +var testCases = []struct { + key [32]byte + msg []byte + out [32]byte +}{ + { + key: [32]byte{ + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, + }, + msg: []byte("Hi There"), + out: [32]byte{ + 0x87, 0xaa, 0x7c, 0xde, 0xa5, 0xef, 0x61, 0x9d, + 0x4f, 0xf0, 0xb4, 0x24, 0x1a, 0x1d, 0x6c, 0xb0, + 0x23, 0x79, 0xf4, 0xe2, 0xce, 0x4e, 0xc2, 0x78, + 0x7a, 0xd0, 0xb3, 0x05, 0x45, 0xe1, 0x7c, 0xde, + }, + }, + { + key: [32]byte{'J', 'e', 'f', 'e'}, + msg: []byte("what do ya want for nothing?"), + out: [32]byte{ + 0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2, + 0xe3, 0x95, 0xfb, 0xe7, 0x3b, 0x56, 0xe0, 0xa3, + 0x87, 0xbd, 0x64, 0x22, 0x2e, 0x83, 0x1f, 0xd6, + 0x10, 0x27, 0x0c, 0xd7, 0xea, 0x25, 0x05, 0x54, + }, + }, + { + key: [32]byte{ + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, + }, + msg: []byte{ // 50 bytes of 0xdd + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, + }, + out: [32]byte{ + 0xfa, 0x73, 0xb0, 0x08, 0x9d, 0x56, 0xa2, 0x84, + 0xef, 0xb0, 0xf0, 0x75, 0x6c, 0x89, 0x0b, 0xe9, + 0xb1, 0xb5, 0xdb, 0xdd, 0x8e, 0xe8, 0x1a, 0x36, + 0x55, 0xf8, 0x3e, 0x33, 0xb2, 0x27, 0x9d, 0x39, + }, + }, + { + key: [32]byte{ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, + }, + msg: []byte{ + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, + }, + out: [32]byte{ + 0xb0, 0xba, 0x46, 0x56, 0x37, 0x45, 0x8c, 0x69, + 0x90, 0xe5, 0xa8, 0xc5, 0xf6, 0x1d, 0x4a, 0xf7, + 0xe5, 0x76, 0xd9, 0x7f, 0xf9, 0x4b, 0x87, 0x2d, + 0xe7, 0x6f, 0x80, 0x50, 0x36, 0x1e, 0xe3, 0xdb, + }, + }, +} + +func TestSum(t *testing.T) { + for i, test := range testCases { + tag := Sum(test.msg, &test.key) + if !bytes.Equal(tag[:], test.out[:]) { + t.Errorf("#%d: Sum: got\n%x\nwant\n%x", i, tag, test.out) + } + } +} + +func TestVerify(t *testing.T) { + wrongMsg := []byte("unknown msg") + + for i, test := range testCases { + if !Verify(test.out[:], test.msg, &test.key) { + t.Errorf("#%d: Verify(%x, %q, %x) failed", i, test.out, test.msg, test.key) + } + if Verify(test.out[:], wrongMsg, &test.key) { + t.Errorf("#%d: Verify(%x, %q, %x) unexpectedly passed", i, test.out, wrongMsg, test.key) + } + } +} + +func TestStress(t *testing.T) { + if testing.Short() { + t.Skip("exhaustiveness test") + } + + var key [32]byte + msg := make([]byte, 10000) + prng := mrand.New(mrand.NewSource(0)) + + // copied from tests/auth5.c in nacl + for i := 0; i < 10000; i++ { + if _, err := rand.Read(key[:]); err != nil { + t.Fatal(err) + } + if _, err := rand.Read(msg[:i]); err != nil { + t.Fatal(err) + } + tag := Sum(msg[:i], &key) + if !Verify(tag[:], msg[:i], &key) { + t.Errorf("#%d: unexpected failure from Verify", i) + } + if i > 0 { + msgIndex := prng.Intn(i) + oldMsgByte := msg[msgIndex] + msg[msgIndex] += byte(1 + prng.Intn(255)) + if Verify(tag[:], msg[:i], &key) { + t.Errorf("#%d: unexpected success from Verify after corrupting message", i) + } + msg[msgIndex] = oldMsgByte + + tag[prng.Intn(len(tag))] += byte(1 + prng.Intn(255)) + if Verify(tag[:], msg[:i], &key) { + t.Errorf("#%d: unexpected success from Verify after corrupting authenticator", i) + } + } + } +} + +func BenchmarkAuth(b *testing.B) { + var key [32]byte + if _, err := rand.Read(key[:]); err != nil { + b.Fatal(err) + } + buf := make([]byte, 1024) + if _, err := rand.Read(buf[:]); err != nil { + b.Fatal(err) + } + + b.SetBytes(int64(len(buf))) + b.ReportAllocs() + b.ResetTimer() + + for i := 0; i < b.N; i++ { + tag := Sum(buf, &key) + if Verify(tag[:], buf, &key) == false { + b.Fatal("unexpected failure from Verify") + } + } +} diff --git a/vendor/golang.org/x/crypto/nacl/auth/example_test.go b/vendor/golang.org/x/crypto/nacl/auth/example_test.go new file mode 100644 index 0000000000000000000000000000000000000000..02a2cd6c46a8f4ba0533646bb4c71cd13cba565c --- /dev/null +++ b/vendor/golang.org/x/crypto/nacl/auth/example_test.go @@ -0,0 +1,36 @@ +// Copyright 2017 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 auth_test + +import ( + "encoding/hex" + "fmt" + + "golang.org/x/crypto/nacl/auth" +) + +func Example() { + // Load your secret key from a safe place and reuse it across multiple + // Sum calls. (Obviously don't use this example key for anything + // real.) If you want to convert a passphrase to a key, use a suitable + // package like bcrypt or scrypt. + secretKeyBytes, err := hex.DecodeString("6368616e676520746869732070617373776f726420746f206120736563726574") + if err != nil { + panic(err) + } + + var secretKey [32]byte + copy(secretKey[:], secretKeyBytes) + + mac := auth.Sum([]byte("hello world"), &secretKey) + fmt.Printf("%x\n", *mac) + result := auth.Verify(mac[:], []byte("hello world"), &secretKey) + fmt.Println(result) + badResult := auth.Verify(mac[:], []byte("different message"), &secretKey) + fmt.Println(badResult) + // Output: eca5a521f3d77b63f567fb0cb6f5f2d200641bc8dada42f60c5f881260c30317 + // true + // false +} diff --git a/vendor/golang.org/x/crypto/nacl/box/box.go b/vendor/golang.org/x/crypto/nacl/box/box.go new file mode 100644 index 0000000000000000000000000000000000000000..31b697be44137be94a997ecc303bc071b8b4c9a6 --- /dev/null +++ b/vendor/golang.org/x/crypto/nacl/box/box.go @@ -0,0 +1,103 @@ +// 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 box authenticates and encrypts small messages using public-key cryptography. + +Box uses Curve25519, XSalsa20 and Poly1305 to encrypt and authenticate +messages. The length of messages is not hidden. + +It is the caller's responsibility to ensure the uniqueness of nonces—for +example, by using nonce 1 for the first message, nonce 2 for the second +message, etc. Nonces are long enough that randomly generated nonces have +negligible risk of collision. + +Messages should be small because: + +1. The whole message needs to be held in memory to be processed. + +2. Using large messages pressures implementations on small machines to decrypt +and process plaintext before authenticating it. This is very dangerous, and +this API does not allow it, but a protocol that uses excessive message sizes +might present some implementations with no other choice. + +3. Fixed overheads will be sufficiently amortised by messages as small as 8KB. + +4. Performance may be improved by working with messages that fit into data caches. + +Thus large amounts of data should be chunked so that each message is small. +(Each message still needs a unique nonce.) If in doubt, 16KB is a reasonable +chunk size. + +This package is interoperable with NaCl: https://nacl.cr.yp.to/box.html. +*/ +package box // import "golang.org/x/crypto/nacl/box" + +import ( + "io" + + "golang.org/x/crypto/curve25519" + "golang.org/x/crypto/nacl/secretbox" + "golang.org/x/crypto/salsa20/salsa" +) + +// Overhead is the number of bytes of overhead when boxing a message. +const Overhead = secretbox.Overhead + +// GenerateKey generates a new public/private key pair suitable for use with +// Seal and Open. +func GenerateKey(rand io.Reader) (publicKey, privateKey *[32]byte, err error) { + publicKey = new([32]byte) + privateKey = new([32]byte) + _, err = io.ReadFull(rand, privateKey[:]) + if err != nil { + publicKey = nil + privateKey = nil + return + } + + curve25519.ScalarBaseMult(publicKey, privateKey) + return +} + +var zeros [16]byte + +// Precompute calculates the shared key between peersPublicKey and privateKey +// and writes it to sharedKey. The shared key can be used with +// OpenAfterPrecomputation and SealAfterPrecomputation to speed up processing +// when using the same pair of keys repeatedly. +func Precompute(sharedKey, peersPublicKey, privateKey *[32]byte) { + curve25519.ScalarMult(sharedKey, privateKey, peersPublicKey) + salsa.HSalsa20(sharedKey, &zeros, sharedKey, &salsa.Sigma) +} + +// Seal appends an encrypted and authenticated copy of message to out, which +// will be Overhead bytes longer than the original and must not overlap it. The +// nonce must be unique for each distinct message for a given pair of keys. +func Seal(out, message []byte, nonce *[24]byte, peersPublicKey, privateKey *[32]byte) []byte { + var sharedKey [32]byte + Precompute(&sharedKey, peersPublicKey, privateKey) + return secretbox.Seal(out, message, nonce, &sharedKey) +} + +// SealAfterPrecomputation performs the same actions as Seal, but takes a +// shared key as generated by Precompute. +func SealAfterPrecomputation(out, message []byte, nonce *[24]byte, sharedKey *[32]byte) []byte { + return secretbox.Seal(out, message, nonce, sharedKey) +} + +// Open authenticates and decrypts a box produced by Seal and appends the +// message to out, which must not overlap box. The output will be Overhead +// bytes smaller than box. +func Open(out, box []byte, nonce *[24]byte, peersPublicKey, privateKey *[32]byte) ([]byte, bool) { + var sharedKey [32]byte + Precompute(&sharedKey, peersPublicKey, privateKey) + return secretbox.Open(out, box, nonce, &sharedKey) +} + +// OpenAfterPrecomputation performs the same actions as Open, but takes a +// shared key as generated by Precompute. +func OpenAfterPrecomputation(out, box []byte, nonce *[24]byte, sharedKey *[32]byte) ([]byte, bool) { + return secretbox.Open(out, box, nonce, sharedKey) +} diff --git a/vendor/golang.org/x/crypto/nacl/box/box_test.go b/vendor/golang.org/x/crypto/nacl/box/box_test.go new file mode 100644 index 0000000000000000000000000000000000000000..481ade28aecd4fa0badbf45db45a99da85604c2f --- /dev/null +++ b/vendor/golang.org/x/crypto/nacl/box/box_test.go @@ -0,0 +1,78 @@ +// 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 box + +import ( + "bytes" + "crypto/rand" + "encoding/hex" + "testing" + + "golang.org/x/crypto/curve25519" +) + +func TestSealOpen(t *testing.T) { + publicKey1, privateKey1, _ := GenerateKey(rand.Reader) + publicKey2, privateKey2, _ := GenerateKey(rand.Reader) + + if *privateKey1 == *privateKey2 { + t.Fatalf("private keys are equal!") + } + if *publicKey1 == *publicKey2 { + t.Fatalf("public keys are equal!") + } + message := []byte("test message") + var nonce [24]byte + + box := Seal(nil, message, &nonce, publicKey1, privateKey2) + opened, ok := Open(nil, box, &nonce, publicKey2, privateKey1) + if !ok { + t.Fatalf("failed to open box") + } + + if !bytes.Equal(opened, message) { + t.Fatalf("got %x, want %x", opened, message) + } + + for i := range box { + box[i] ^= 0x40 + _, ok := Open(nil, box, &nonce, publicKey2, privateKey1) + if ok { + t.Fatalf("opened box with byte %d corrupted", i) + } + box[i] ^= 0x40 + } +} + +func TestBox(t *testing.T) { + var privateKey1, privateKey2 [32]byte + for i := range privateKey1[:] { + privateKey1[i] = 1 + } + for i := range privateKey2[:] { + privateKey2[i] = 2 + } + + var publicKey1 [32]byte + curve25519.ScalarBaseMult(&publicKey1, &privateKey1) + var message [64]byte + for i := range message[:] { + message[i] = 3 + } + + var nonce [24]byte + for i := range nonce[:] { + nonce[i] = 4 + } + + box := Seal(nil, message[:], &nonce, &publicKey1, &privateKey2) + + // expected was generated using the C implementation of NaCl. + expected, _ := hex.DecodeString("78ea30b19d2341ebbdba54180f821eec265cf86312549bea8a37652a8bb94f07b78a73ed1708085e6ddd0e943bbdeb8755079a37eb31d86163ce241164a47629c0539f330b4914cd135b3855bc2a2dfc") + + if !bytes.Equal(box, expected) { + t.Fatalf("box didn't match, got\n%x\n, expected\n%x", box, expected) + } +} diff --git a/vendor/golang.org/x/crypto/nacl/box/example_test.go b/vendor/golang.org/x/crypto/nacl/box/example_test.go new file mode 100644 index 0000000000000000000000000000000000000000..25e42d2be9aa806fb2474dd8a1a8379abf548466 --- /dev/null +++ b/vendor/golang.org/x/crypto/nacl/box/example_test.go @@ -0,0 +1,95 @@ +package box_test + +import ( + crypto_rand "crypto/rand" // Custom so it's clear which rand we're using. + "fmt" + "io" + + "golang.org/x/crypto/nacl/box" +) + +func Example() { + senderPublicKey, senderPrivateKey, err := box.GenerateKey(crypto_rand.Reader) + if err != nil { + panic(err) + } + + recipientPublicKey, recipientPrivateKey, err := box.GenerateKey(crypto_rand.Reader) + if err != nil { + panic(err) + } + + // You must use a different nonce for each message you encrypt with the + // same key. Since the nonce here is 192 bits long, a random value + // provides a sufficiently small probability of repeats. + var nonce [24]byte + if _, err := io.ReadFull(crypto_rand.Reader, nonce[:]); err != nil { + panic(err) + } + + msg := []byte("Alas, poor Yorick! I knew him, Horatio") + // This encrypts msg and appends the result to the nonce. + encrypted := box.Seal(nonce[:], msg, &nonce, recipientPublicKey, senderPrivateKey) + + // The recipient can decrypt the message using their private key and the + // sender's public key. When you decrypt, you must use the same nonce you + // used to encrypt the message. One way to achieve this is to store the + // nonce alongside the encrypted message. Above, we stored the nonce in the + // first 24 bytes of the encrypted text. + var decryptNonce [24]byte + copy(decryptNonce[:], encrypted[:24]) + decrypted, ok := box.Open(nil, encrypted[24:], &decryptNonce, senderPublicKey, recipientPrivateKey) + if !ok { + panic("decryption error") + } + fmt.Println(string(decrypted)) + // Output: Alas, poor Yorick! I knew him, Horatio +} + +func Example_precompute() { + senderPublicKey, senderPrivateKey, err := box.GenerateKey(crypto_rand.Reader) + if err != nil { + panic(err) + } + + recipientPublicKey, recipientPrivateKey, err := box.GenerateKey(crypto_rand.Reader) + if err != nil { + panic(err) + } + + // The shared key can be used to speed up processing when using the same + // pair of keys repeatedly. + sharedEncryptKey := new([32]byte) + box.Precompute(sharedEncryptKey, recipientPublicKey, senderPrivateKey) + + // You must use a different nonce for each message you encrypt with the + // same key. Since the nonce here is 192 bits long, a random value + // provides a sufficiently small probability of repeats. + var nonce [24]byte + if _, err := io.ReadFull(crypto_rand.Reader, nonce[:]); err != nil { + panic(err) + } + + msg := []byte("A fellow of infinite jest, of most excellent fancy") + // This encrypts msg and appends the result to the nonce. + encrypted := box.SealAfterPrecomputation(nonce[:], msg, &nonce, sharedEncryptKey) + + // The shared key can be used to speed up processing when using the same + // pair of keys repeatedly. + var sharedDecryptKey [32]byte + box.Precompute(&sharedDecryptKey, senderPublicKey, recipientPrivateKey) + + // The recipient can decrypt the message using the shared key. When you + // decrypt, you must use the same nonce you used to encrypt the message. + // One way to achieve this is to store the nonce alongside the encrypted + // message. Above, we stored the nonce in the first 24 bytes of the + // encrypted text. + var decryptNonce [24]byte + copy(decryptNonce[:], encrypted[:24]) + decrypted, ok := box.OpenAfterPrecomputation(nil, encrypted[24:], &decryptNonce, &sharedDecryptKey) + if !ok { + panic("decryption error") + } + fmt.Println(string(decrypted)) + // Output: A fellow of infinite jest, of most excellent fancy +} diff --git a/vendor/golang.org/x/crypto/nacl/secretbox/example_test.go b/vendor/golang.org/x/crypto/nacl/secretbox/example_test.go new file mode 100644 index 0000000000000000000000000000000000000000..789f4ff03f2ff8ebbf55a20403864efb0c165c76 --- /dev/null +++ b/vendor/golang.org/x/crypto/nacl/secretbox/example_test.go @@ -0,0 +1,53 @@ +// Copyright 2016 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 secretbox_test + +import ( + "crypto/rand" + "encoding/hex" + "fmt" + "io" + + "golang.org/x/crypto/nacl/secretbox" +) + +func Example() { + // Load your secret key from a safe place and reuse it across multiple + // Seal calls. (Obviously don't use this example key for anything + // real.) If you want to convert a passphrase to a key, use a suitable + // package like bcrypt or scrypt. + secretKeyBytes, err := hex.DecodeString("6368616e676520746869732070617373776f726420746f206120736563726574") + if err != nil { + panic(err) + } + + var secretKey [32]byte + copy(secretKey[:], secretKeyBytes) + + // You must use a different nonce for each message you encrypt with the + // same key. Since the nonce here is 192 bits long, a random value + // provides a sufficiently small probability of repeats. + var nonce [24]byte + if _, err := io.ReadFull(rand.Reader, nonce[:]); err != nil { + panic(err) + } + + // This encrypts "hello world" and appends the result to the nonce. + encrypted := secretbox.Seal(nonce[:], []byte("hello world"), &nonce, &secretKey) + + // When you decrypt, you must use the same nonce and key you used to + // encrypt the message. One way to achieve this is to store the nonce + // alongside the encrypted message. Above, we stored the nonce in the first + // 24 bytes of the encrypted text. + var decryptNonce [24]byte + copy(decryptNonce[:], encrypted[:24]) + decrypted, ok := secretbox.Open(nil, encrypted[24:], &decryptNonce, &secretKey) + if !ok { + panic("decryption error") + } + + fmt.Println(string(decrypted)) + // Output: hello world +} diff --git a/vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go b/vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go new file mode 100644 index 0000000000000000000000000000000000000000..53ee83cfb7d22b96dbcb484c144e66853873bcdc --- /dev/null +++ b/vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go @@ -0,0 +1,166 @@ +// 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 secretbox encrypts and authenticates small messages. + +Secretbox uses XSalsa20 and Poly1305 to encrypt and authenticate messages with +secret-key cryptography. The length of messages is not hidden. + +It is the caller's responsibility to ensure the uniqueness of nonces—for +example, by using nonce 1 for the first message, nonce 2 for the second +message, etc. Nonces are long enough that randomly generated nonces have +negligible risk of collision. + +Messages should be small because: + +1. The whole message needs to be held in memory to be processed. + +2. Using large messages pressures implementations on small machines to decrypt +and process plaintext before authenticating it. This is very dangerous, and +this API does not allow it, but a protocol that uses excessive message sizes +might present some implementations with no other choice. + +3. Fixed overheads will be sufficiently amortised by messages as small as 8KB. + +4. Performance may be improved by working with messages that fit into data caches. + +Thus large amounts of data should be chunked so that each message is small. +(Each message still needs a unique nonce.) If in doubt, 16KB is a reasonable +chunk size. + +This package is interoperable with NaCl: https://nacl.cr.yp.to/secretbox.html. +*/ +package secretbox // import "golang.org/x/crypto/nacl/secretbox" + +import ( + "golang.org/x/crypto/poly1305" + "golang.org/x/crypto/salsa20/salsa" +) + +// Overhead is the number of bytes of overhead when boxing a message. +const Overhead = poly1305.TagSize + +// setup produces a sub-key and Salsa20 counter given a nonce and key. +func setup(subKey *[32]byte, counter *[16]byte, nonce *[24]byte, key *[32]byte) { + // We use XSalsa20 for encryption so first we need to generate a + // key and nonce with HSalsa20. + var hNonce [16]byte + copy(hNonce[:], nonce[:]) + salsa.HSalsa20(subKey, &hNonce, key, &salsa.Sigma) + + // The final 8 bytes of the original nonce form the new nonce. + copy(counter[:], nonce[16:]) +} + +// sliceForAppend takes a slice and a requested number of bytes. It returns a +// slice with the contents of the given slice followed by that many bytes and a +// second slice that aliases into it and contains only the extra bytes. If the +// original slice has sufficient capacity then no allocation is performed. +func sliceForAppend(in []byte, n int) (head, tail []byte) { + if total := len(in) + n; cap(in) >= total { + head = in[:total] + } else { + head = make([]byte, total) + copy(head, in) + } + tail = head[len(in):] + return +} + +// Seal appends an encrypted and authenticated copy of message to out, which +// must not overlap message. The key and nonce pair must be unique for each +// distinct message and the output will be Overhead bytes longer than message. +func Seal(out, message []byte, nonce *[24]byte, key *[32]byte) []byte { + var subKey [32]byte + var counter [16]byte + setup(&subKey, &counter, nonce, key) + + // The Poly1305 key is generated by encrypting 32 bytes of zeros. Since + // Salsa20 works with 64-byte blocks, we also generate 32 bytes of + // keystream as a side effect. + var firstBlock [64]byte + salsa.XORKeyStream(firstBlock[:], firstBlock[:], &counter, &subKey) + + var poly1305Key [32]byte + copy(poly1305Key[:], firstBlock[:]) + + ret, out := sliceForAppend(out, len(message)+poly1305.TagSize) + + // We XOR up to 32 bytes of message with the keystream generated from + // the first block. + firstMessageBlock := message + if len(firstMessageBlock) > 32 { + firstMessageBlock = firstMessageBlock[:32] + } + + tagOut := out + out = out[poly1305.TagSize:] + for i, x := range firstMessageBlock { + out[i] = firstBlock[32+i] ^ x + } + message = message[len(firstMessageBlock):] + ciphertext := out + out = out[len(firstMessageBlock):] + + // Now encrypt the rest. + counter[8] = 1 + salsa.XORKeyStream(out, message, &counter, &subKey) + + var tag [poly1305.TagSize]byte + poly1305.Sum(&tag, ciphertext, &poly1305Key) + copy(tagOut, tag[:]) + + return ret +} + +// Open authenticates and decrypts a box produced by Seal and appends the +// message to out, which must not overlap box. The output will be Overhead +// bytes smaller than box. +func Open(out []byte, box []byte, nonce *[24]byte, key *[32]byte) ([]byte, bool) { + if len(box) < Overhead { + return nil, false + } + + var subKey [32]byte + var counter [16]byte + setup(&subKey, &counter, nonce, key) + + // The Poly1305 key is generated by encrypting 32 bytes of zeros. Since + // Salsa20 works with 64-byte blocks, we also generate 32 bytes of + // keystream as a side effect. + var firstBlock [64]byte + salsa.XORKeyStream(firstBlock[:], firstBlock[:], &counter, &subKey) + + var poly1305Key [32]byte + copy(poly1305Key[:], firstBlock[:]) + var tag [poly1305.TagSize]byte + copy(tag[:], box) + + if !poly1305.Verify(&tag, box[poly1305.TagSize:], &poly1305Key) { + return nil, false + } + + ret, out := sliceForAppend(out, len(box)-Overhead) + + // We XOR up to 32 bytes of box with the keystream generated from + // the first block. + box = box[Overhead:] + firstMessageBlock := box + if len(firstMessageBlock) > 32 { + firstMessageBlock = firstMessageBlock[:32] + } + for i, x := range firstMessageBlock { + out[i] = firstBlock[32+i] ^ x + } + + box = box[len(firstMessageBlock):] + out = out[len(firstMessageBlock):] + + // Now decrypt the rest. + counter[8] = 1 + salsa.XORKeyStream(out, box, &counter, &subKey) + + return ret, true +} diff --git a/vendor/golang.org/x/crypto/nacl/secretbox/secretbox_test.go b/vendor/golang.org/x/crypto/nacl/secretbox/secretbox_test.go new file mode 100644 index 0000000000000000000000000000000000000000..3c70b0f4b3d230118c5778cae349544e9ff0e334 --- /dev/null +++ b/vendor/golang.org/x/crypto/nacl/secretbox/secretbox_test.go @@ -0,0 +1,154 @@ +// 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 secretbox + +import ( + "bytes" + "crypto/rand" + "encoding/hex" + "testing" +) + +func TestSealOpen(t *testing.T) { + var key [32]byte + var nonce [24]byte + + rand.Reader.Read(key[:]) + rand.Reader.Read(nonce[:]) + + var box, opened []byte + + for msgLen := 0; msgLen < 128; msgLen += 17 { + message := make([]byte, msgLen) + rand.Reader.Read(message) + + box = Seal(box[:0], message, &nonce, &key) + var ok bool + opened, ok = Open(opened[:0], box, &nonce, &key) + if !ok { + t.Errorf("%d: failed to open box", msgLen) + continue + } + + if !bytes.Equal(opened, message) { + t.Errorf("%d: got %x, expected %x", msgLen, opened, message) + continue + } + } + + for i := range box { + box[i] ^= 0x20 + _, ok := Open(opened[:0], box, &nonce, &key) + if ok { + t.Errorf("box was opened after corrupting byte %d", i) + } + box[i] ^= 0x20 + } +} + +func TestSecretBox(t *testing.T) { + var key [32]byte + var nonce [24]byte + var message [64]byte + + for i := range key[:] { + key[i] = 1 + } + for i := range nonce[:] { + nonce[i] = 2 + } + for i := range message[:] { + message[i] = 3 + } + + box := Seal(nil, message[:], &nonce, &key) + // expected was generated using the C implementation of NaCl. + expected, _ := hex.DecodeString("8442bc313f4626f1359e3b50122b6ce6fe66ddfe7d39d14e637eb4fd5b45beadab55198df6ab5368439792a23c87db70acb6156dc5ef957ac04f6276cf6093b84be77ff0849cc33e34b7254d5a8f65ad") + + if !bytes.Equal(box, expected) { + t.Fatalf("box didn't match, got\n%x\n, expected\n%x", box, expected) + } +} + +func TestAppend(t *testing.T) { + var key [32]byte + var nonce [24]byte + var message [8]byte + + out := make([]byte, 4) + box := Seal(out, message[:], &nonce, &key) + if !bytes.Equal(box[:4], out[:4]) { + t.Fatalf("Seal didn't correctly append") + } + + out = make([]byte, 4, 100) + box = Seal(out, message[:], &nonce, &key) + if !bytes.Equal(box[:4], out[:4]) { + t.Fatalf("Seal didn't correctly append with sufficient capacity.") + } +} + +func benchmarkSealSize(b *testing.B, size int) { + message := make([]byte, size) + out := make([]byte, size+Overhead) + var nonce [24]byte + var key [32]byte + + b.SetBytes(int64(size)) + b.ResetTimer() + + for i := 0; i < b.N; i++ { + out = Seal(out[:0], message, &nonce, &key) + } +} + +func BenchmarkSeal8Bytes(b *testing.B) { + benchmarkSealSize(b, 8) +} + +func BenchmarkSeal100Bytes(b *testing.B) { + benchmarkSealSize(b, 100) +} + +func BenchmarkSeal1K(b *testing.B) { + benchmarkSealSize(b, 1024) +} + +func BenchmarkSeal8K(b *testing.B) { + benchmarkSealSize(b, 8192) +} + +func benchmarkOpenSize(b *testing.B, size int) { + msg := make([]byte, size) + result := make([]byte, size) + var nonce [24]byte + var key [32]byte + box := Seal(nil, msg, &nonce, &key) + + b.SetBytes(int64(size)) + b.ResetTimer() + + for i := 0; i < b.N; i++ { + if _, ok := Open(result[:0], box, &nonce, &key); !ok { + panic("Open failed") + } + } +} + +func BenchmarkOpen8Bytes(b *testing.B) { + benchmarkOpenSize(b, 8) +} + +func BenchmarkOpen100Bytes(b *testing.B) { + benchmarkOpenSize(b, 100) +} + +func BenchmarkOpen1K(b *testing.B) { + benchmarkOpenSize(b, 1024) +} + +func BenchmarkOpen8K(b *testing.B) { + benchmarkOpenSize(b, 8192) +} diff --git a/vendor/golang.org/x/crypto/ocsp/ocsp.go b/vendor/golang.org/x/crypto/ocsp/ocsp.go new file mode 100644 index 0000000000000000000000000000000000000000..589dfd35f11264228071a71bd591f8d7ca467055 --- /dev/null +++ b/vendor/golang.org/x/crypto/ocsp/ocsp.go @@ -0,0 +1,778 @@ +// 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. + +// Package ocsp parses OCSP responses as specified in RFC 2560. OCSP responses +// are signed messages attesting to the validity of a certificate for a small +// period of time. This is used to manage revocation for X.509 certificates. +package ocsp // import "golang.org/x/crypto/ocsp" + +import ( + "crypto" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/rsa" + _ "crypto/sha1" + _ "crypto/sha256" + _ "crypto/sha512" + "crypto/x509" + "crypto/x509/pkix" + "encoding/asn1" + "errors" + "fmt" + "math/big" + "strconv" + "time" +) + +var idPKIXOCSPBasic = asn1.ObjectIdentifier([]int{1, 3, 6, 1, 5, 5, 7, 48, 1, 1}) + +// ResponseStatus contains the result of an OCSP request. See +// https://tools.ietf.org/html/rfc6960#section-2.3 +type ResponseStatus int + +const ( + Success ResponseStatus = 0 + Malformed ResponseStatus = 1 + InternalError ResponseStatus = 2 + TryLater ResponseStatus = 3 + // Status code four is unused in OCSP. See + // https://tools.ietf.org/html/rfc6960#section-4.2.1 + SignatureRequired ResponseStatus = 5 + Unauthorized ResponseStatus = 6 +) + +func (r ResponseStatus) String() string { + switch r { + case Success: + return "success" + case Malformed: + return "malformed" + case InternalError: + return "internal error" + case TryLater: + return "try later" + case SignatureRequired: + return "signature required" + case Unauthorized: + return "unauthorized" + default: + return "unknown OCSP status: " + strconv.Itoa(int(r)) + } +} + +// ResponseError is an error that may be returned by ParseResponse to indicate +// that the response itself is an error, not just that its indicating that a +// certificate is revoked, unknown, etc. +type ResponseError struct { + Status ResponseStatus +} + +func (r ResponseError) Error() string { + return "ocsp: error from server: " + r.Status.String() +} + +// These are internal structures that reflect the ASN.1 structure of an OCSP +// response. See RFC 2560, section 4.2. + +type certID struct { + HashAlgorithm pkix.AlgorithmIdentifier + NameHash []byte + IssuerKeyHash []byte + SerialNumber *big.Int +} + +// https://tools.ietf.org/html/rfc2560#section-4.1.1 +type ocspRequest struct { + TBSRequest tbsRequest +} + +type tbsRequest struct { + Version int `asn1:"explicit,tag:0,default:0,optional"` + RequestorName pkix.RDNSequence `asn1:"explicit,tag:1,optional"` + RequestList []request +} + +type request struct { + Cert certID +} + +type responseASN1 struct { + Status asn1.Enumerated + Response responseBytes `asn1:"explicit,tag:0,optional"` +} + +type responseBytes struct { + ResponseType asn1.ObjectIdentifier + Response []byte +} + +type basicResponse struct { + TBSResponseData responseData + SignatureAlgorithm pkix.AlgorithmIdentifier + Signature asn1.BitString + Certificates []asn1.RawValue `asn1:"explicit,tag:0,optional"` +} + +type responseData struct { + Raw asn1.RawContent + Version int `asn1:"optional,default:0,explicit,tag:0"` + RawResponderID asn1.RawValue + ProducedAt time.Time `asn1:"generalized"` + Responses []singleResponse +} + +type singleResponse struct { + CertID certID + Good asn1.Flag `asn1:"tag:0,optional"` + Revoked revokedInfo `asn1:"tag:1,optional"` + Unknown asn1.Flag `asn1:"tag:2,optional"` + ThisUpdate time.Time `asn1:"generalized"` + NextUpdate time.Time `asn1:"generalized,explicit,tag:0,optional"` + SingleExtensions []pkix.Extension `asn1:"explicit,tag:1,optional"` +} + +type revokedInfo struct { + RevocationTime time.Time `asn1:"generalized"` + Reason asn1.Enumerated `asn1:"explicit,tag:0,optional"` +} + +var ( + oidSignatureMD2WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 2} + oidSignatureMD5WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 4} + oidSignatureSHA1WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5} + oidSignatureSHA256WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11} + oidSignatureSHA384WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12} + oidSignatureSHA512WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13} + oidSignatureDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 3} + oidSignatureDSAWithSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 3, 2} + oidSignatureECDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 1} + oidSignatureECDSAWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2} + oidSignatureECDSAWithSHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3} + oidSignatureECDSAWithSHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4} +) + +var hashOIDs = map[crypto.Hash]asn1.ObjectIdentifier{ + crypto.SHA1: asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26}), + crypto.SHA256: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 1}), + crypto.SHA384: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 2}), + crypto.SHA512: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 3}), +} + +// TODO(rlb): This is also from crypto/x509, so same comment as AGL's below +var signatureAlgorithmDetails = []struct { + algo x509.SignatureAlgorithm + oid asn1.ObjectIdentifier + pubKeyAlgo x509.PublicKeyAlgorithm + hash crypto.Hash +}{ + {x509.MD2WithRSA, oidSignatureMD2WithRSA, x509.RSA, crypto.Hash(0) /* no value for MD2 */}, + {x509.MD5WithRSA, oidSignatureMD5WithRSA, x509.RSA, crypto.MD5}, + {x509.SHA1WithRSA, oidSignatureSHA1WithRSA, x509.RSA, crypto.SHA1}, + {x509.SHA256WithRSA, oidSignatureSHA256WithRSA, x509.RSA, crypto.SHA256}, + {x509.SHA384WithRSA, oidSignatureSHA384WithRSA, x509.RSA, crypto.SHA384}, + {x509.SHA512WithRSA, oidSignatureSHA512WithRSA, x509.RSA, crypto.SHA512}, + {x509.DSAWithSHA1, oidSignatureDSAWithSHA1, x509.DSA, crypto.SHA1}, + {x509.DSAWithSHA256, oidSignatureDSAWithSHA256, x509.DSA, crypto.SHA256}, + {x509.ECDSAWithSHA1, oidSignatureECDSAWithSHA1, x509.ECDSA, crypto.SHA1}, + {x509.ECDSAWithSHA256, oidSignatureECDSAWithSHA256, x509.ECDSA, crypto.SHA256}, + {x509.ECDSAWithSHA384, oidSignatureECDSAWithSHA384, x509.ECDSA, crypto.SHA384}, + {x509.ECDSAWithSHA512, oidSignatureECDSAWithSHA512, x509.ECDSA, crypto.SHA512}, +} + +// TODO(rlb): This is also from crypto/x509, so same comment as AGL's below +func signingParamsForPublicKey(pub interface{}, requestedSigAlgo x509.SignatureAlgorithm) (hashFunc crypto.Hash, sigAlgo pkix.AlgorithmIdentifier, err error) { + var pubType x509.PublicKeyAlgorithm + + switch pub := pub.(type) { + case *rsa.PublicKey: + pubType = x509.RSA + hashFunc = crypto.SHA256 + sigAlgo.Algorithm = oidSignatureSHA256WithRSA + sigAlgo.Parameters = asn1.RawValue{ + Tag: 5, + } + + case *ecdsa.PublicKey: + pubType = x509.ECDSA + + switch pub.Curve { + case elliptic.P224(), elliptic.P256(): + hashFunc = crypto.SHA256 + sigAlgo.Algorithm = oidSignatureECDSAWithSHA256 + case elliptic.P384(): + hashFunc = crypto.SHA384 + sigAlgo.Algorithm = oidSignatureECDSAWithSHA384 + case elliptic.P521(): + hashFunc = crypto.SHA512 + sigAlgo.Algorithm = oidSignatureECDSAWithSHA512 + default: + err = errors.New("x509: unknown elliptic curve") + } + + default: + err = errors.New("x509: only RSA and ECDSA keys supported") + } + + if err != nil { + return + } + + if requestedSigAlgo == 0 { + return + } + + found := false + for _, details := range signatureAlgorithmDetails { + if details.algo == requestedSigAlgo { + if details.pubKeyAlgo != pubType { + err = errors.New("x509: requested SignatureAlgorithm does not match private key type") + return + } + sigAlgo.Algorithm, hashFunc = details.oid, details.hash + if hashFunc == 0 { + err = errors.New("x509: cannot sign with hash function requested") + return + } + found = true + break + } + } + + if !found { + err = errors.New("x509: unknown SignatureAlgorithm") + } + + return +} + +// TODO(agl): this is taken from crypto/x509 and so should probably be exported +// from crypto/x509 or crypto/x509/pkix. +func getSignatureAlgorithmFromOID(oid asn1.ObjectIdentifier) x509.SignatureAlgorithm { + for _, details := range signatureAlgorithmDetails { + if oid.Equal(details.oid) { + return details.algo + } + } + return x509.UnknownSignatureAlgorithm +} + +// TODO(rlb): This is not taken from crypto/x509, but it's of the same general form. +func getHashAlgorithmFromOID(target asn1.ObjectIdentifier) crypto.Hash { + for hash, oid := range hashOIDs { + if oid.Equal(target) { + return hash + } + } + return crypto.Hash(0) +} + +func getOIDFromHashAlgorithm(target crypto.Hash) asn1.ObjectIdentifier { + for hash, oid := range hashOIDs { + if hash == target { + return oid + } + } + return nil +} + +// This is the exposed reflection of the internal OCSP structures. + +// The status values that can be expressed in OCSP. See RFC 6960. +const ( + // Good means that the certificate is valid. + Good = iota + // Revoked means that the certificate has been deliberately revoked. + Revoked + // Unknown means that the OCSP responder doesn't know about the certificate. + Unknown + // ServerFailed is unused and was never used (see + // https://go-review.googlesource.com/#/c/18944). ParseResponse will + // return a ResponseError when an error response is parsed. + ServerFailed +) + +// The enumerated reasons for revoking a certificate. See RFC 5280. +const ( + Unspecified = 0 + KeyCompromise = 1 + CACompromise = 2 + AffiliationChanged = 3 + Superseded = 4 + CessationOfOperation = 5 + CertificateHold = 6 + + RemoveFromCRL = 8 + PrivilegeWithdrawn = 9 + AACompromise = 10 +) + +// Request represents an OCSP request. See RFC 6960. +type Request struct { + HashAlgorithm crypto.Hash + IssuerNameHash []byte + IssuerKeyHash []byte + SerialNumber *big.Int +} + +// Marshal marshals the OCSP request to ASN.1 DER encoded form. +func (req *Request) Marshal() ([]byte, error) { + hashAlg := getOIDFromHashAlgorithm(req.HashAlgorithm) + if hashAlg == nil { + return nil, errors.New("Unknown hash algorithm") + } + return asn1.Marshal(ocspRequest{ + tbsRequest{ + Version: 0, + RequestList: []request{ + { + Cert: certID{ + pkix.AlgorithmIdentifier{ + Algorithm: hashAlg, + Parameters: asn1.RawValue{Tag: 5 /* ASN.1 NULL */}, + }, + req.IssuerNameHash, + req.IssuerKeyHash, + req.SerialNumber, + }, + }, + }, + }, + }) +} + +// Response represents an OCSP response containing a single SingleResponse. See +// RFC 6960. +type Response struct { + // Status is one of {Good, Revoked, Unknown} + Status int + SerialNumber *big.Int + ProducedAt, ThisUpdate, NextUpdate, RevokedAt time.Time + RevocationReason int + Certificate *x509.Certificate + // TBSResponseData contains the raw bytes of the signed response. If + // Certificate is nil then this can be used to verify Signature. + TBSResponseData []byte + Signature []byte + SignatureAlgorithm x509.SignatureAlgorithm + + // IssuerHash is the hash used to compute the IssuerNameHash and IssuerKeyHash. + // Valid values are crypto.SHA1, crypto.SHA256, crypto.SHA384, and crypto.SHA512. + // If zero, the default is crypto.SHA1. + IssuerHash crypto.Hash + + // RawResponderName optionally contains the DER-encoded subject of the + // responder certificate. Exactly one of RawResponderName and + // ResponderKeyHash is set. + RawResponderName []byte + // ResponderKeyHash optionally contains the SHA-1 hash of the + // responder's public key. Exactly one of RawResponderName and + // ResponderKeyHash is set. + ResponderKeyHash []byte + + // Extensions contains raw X.509 extensions from the singleExtensions field + // of the OCSP response. When parsing certificates, this can be used to + // extract non-critical extensions that are not parsed by this package. When + // marshaling OCSP responses, the Extensions field is ignored, see + // ExtraExtensions. + Extensions []pkix.Extension + + // ExtraExtensions contains extensions to be copied, raw, into any marshaled + // OCSP response (in the singleExtensions field). Values override any + // extensions that would otherwise be produced based on the other fields. The + // ExtraExtensions field is not populated when parsing certificates, see + // Extensions. + ExtraExtensions []pkix.Extension +} + +// These are pre-serialized error responses for the various non-success codes +// defined by OCSP. The Unauthorized code in particular can be used by an OCSP +// responder that supports only pre-signed responses as a response to requests +// for certificates with unknown status. See RFC 5019. +var ( + MalformedRequestErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x01} + InternalErrorErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x02} + TryLaterErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x03} + SigRequredErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x05} + UnauthorizedErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x06} +) + +// CheckSignatureFrom checks that the signature in resp is a valid signature +// from issuer. This should only be used if resp.Certificate is nil. Otherwise, +// the OCSP response contained an intermediate certificate that created the +// signature. That signature is checked by ParseResponse and only +// resp.Certificate remains to be validated. +func (resp *Response) CheckSignatureFrom(issuer *x509.Certificate) error { + return issuer.CheckSignature(resp.SignatureAlgorithm, resp.TBSResponseData, resp.Signature) +} + +// ParseError results from an invalid OCSP response. +type ParseError string + +func (p ParseError) Error() string { + return string(p) +} + +// ParseRequest parses an OCSP request in DER form. It only supports +// requests for a single certificate. Signed requests are not supported. +// If a request includes a signature, it will result in a ParseError. +func ParseRequest(bytes []byte) (*Request, error) { + var req ocspRequest + rest, err := asn1.Unmarshal(bytes, &req) + if err != nil { + return nil, err + } + if len(rest) > 0 { + return nil, ParseError("trailing data in OCSP request") + } + + if len(req.TBSRequest.RequestList) == 0 { + return nil, ParseError("OCSP request contains no request body") + } + innerRequest := req.TBSRequest.RequestList[0] + + hashFunc := getHashAlgorithmFromOID(innerRequest.Cert.HashAlgorithm.Algorithm) + if hashFunc == crypto.Hash(0) { + return nil, ParseError("OCSP request uses unknown hash function") + } + + return &Request{ + HashAlgorithm: hashFunc, + IssuerNameHash: innerRequest.Cert.NameHash, + IssuerKeyHash: innerRequest.Cert.IssuerKeyHash, + SerialNumber: innerRequest.Cert.SerialNumber, + }, nil +} + +// ParseResponse parses an OCSP response in DER form. It only supports +// responses for a single certificate. If the response contains a certificate +// then the signature over the response is checked. If issuer is not nil then +// it will be used to validate the signature or embedded certificate. +// +// Invalid responses and parse failures will result in a ParseError. +// Error responses will result in a ResponseError. +func ParseResponse(bytes []byte, issuer *x509.Certificate) (*Response, error) { + return ParseResponseForCert(bytes, nil, issuer) +} + +// ParseResponseForCert parses an OCSP response in DER form and searches for a +// Response relating to cert. If such a Response is found and the OCSP response +// contains a certificate then the signature over the response is checked. If +// issuer is not nil then it will be used to validate the signature or embedded +// certificate. +// +// Invalid responses and parse failures will result in a ParseError. +// Error responses will result in a ResponseError. +func ParseResponseForCert(bytes []byte, cert, issuer *x509.Certificate) (*Response, error) { + var resp responseASN1 + rest, err := asn1.Unmarshal(bytes, &resp) + if err != nil { + return nil, err + } + if len(rest) > 0 { + return nil, ParseError("trailing data in OCSP response") + } + + if status := ResponseStatus(resp.Status); status != Success { + return nil, ResponseError{status} + } + + if !resp.Response.ResponseType.Equal(idPKIXOCSPBasic) { + return nil, ParseError("bad OCSP response type") + } + + var basicResp basicResponse + rest, err = asn1.Unmarshal(resp.Response.Response, &basicResp) + if err != nil { + return nil, err + } + + if len(basicResp.Certificates) > 1 { + return nil, ParseError("OCSP response contains bad number of certificates") + } + + if n := len(basicResp.TBSResponseData.Responses); n == 0 || cert == nil && n > 1 { + return nil, ParseError("OCSP response contains bad number of responses") + } + + var singleResp singleResponse + if cert == nil { + singleResp = basicResp.TBSResponseData.Responses[0] + } else { + match := false + for _, resp := range basicResp.TBSResponseData.Responses { + if cert.SerialNumber.Cmp(resp.CertID.SerialNumber) == 0 { + singleResp = resp + match = true + break + } + } + if !match { + return nil, ParseError("no response matching the supplied certificate") + } + } + + ret := &Response{ + TBSResponseData: basicResp.TBSResponseData.Raw, + Signature: basicResp.Signature.RightAlign(), + SignatureAlgorithm: getSignatureAlgorithmFromOID(basicResp.SignatureAlgorithm.Algorithm), + Extensions: singleResp.SingleExtensions, + SerialNumber: singleResp.CertID.SerialNumber, + ProducedAt: basicResp.TBSResponseData.ProducedAt, + ThisUpdate: singleResp.ThisUpdate, + NextUpdate: singleResp.NextUpdate, + } + + // Handle the ResponderID CHOICE tag. ResponderID can be flattened into + // TBSResponseData once https://go-review.googlesource.com/34503 has been + // released. + rawResponderID := basicResp.TBSResponseData.RawResponderID + switch rawResponderID.Tag { + case 1: // Name + var rdn pkix.RDNSequence + if rest, err := asn1.Unmarshal(rawResponderID.Bytes, &rdn); err != nil || len(rest) != 0 { + return nil, ParseError("invalid responder name") + } + ret.RawResponderName = rawResponderID.Bytes + case 2: // KeyHash + if rest, err := asn1.Unmarshal(rawResponderID.Bytes, &ret.ResponderKeyHash); err != nil || len(rest) != 0 { + return nil, ParseError("invalid responder key hash") + } + default: + return nil, ParseError("invalid responder id tag") + } + + if len(basicResp.Certificates) > 0 { + ret.Certificate, err = x509.ParseCertificate(basicResp.Certificates[0].FullBytes) + if err != nil { + return nil, err + } + + if err := ret.CheckSignatureFrom(ret.Certificate); err != nil { + return nil, ParseError("bad signature on embedded certificate: " + err.Error()) + } + + if issuer != nil { + if err := issuer.CheckSignature(ret.Certificate.SignatureAlgorithm, ret.Certificate.RawTBSCertificate, ret.Certificate.Signature); err != nil { + return nil, ParseError("bad OCSP signature: " + err.Error()) + } + } + } else if issuer != nil { + if err := ret.CheckSignatureFrom(issuer); err != nil { + return nil, ParseError("bad OCSP signature: " + err.Error()) + } + } + + for _, ext := range singleResp.SingleExtensions { + if ext.Critical { + return nil, ParseError("unsupported critical extension") + } + } + + for h, oid := range hashOIDs { + if singleResp.CertID.HashAlgorithm.Algorithm.Equal(oid) { + ret.IssuerHash = h + break + } + } + if ret.IssuerHash == 0 { + return nil, ParseError("unsupported issuer hash algorithm") + } + + switch { + case bool(singleResp.Good): + ret.Status = Good + case bool(singleResp.Unknown): + ret.Status = Unknown + default: + ret.Status = Revoked + ret.RevokedAt = singleResp.Revoked.RevocationTime + ret.RevocationReason = int(singleResp.Revoked.Reason) + } + + return ret, nil +} + +// RequestOptions contains options for constructing OCSP requests. +type RequestOptions struct { + // Hash contains the hash function that should be used when + // constructing the OCSP request. If zero, SHA-1 will be used. + Hash crypto.Hash +} + +func (opts *RequestOptions) hash() crypto.Hash { + if opts == nil || opts.Hash == 0 { + // SHA-1 is nearly universally used in OCSP. + return crypto.SHA1 + } + return opts.Hash +} + +// CreateRequest returns a DER-encoded, OCSP request for the status of cert. If +// opts is nil then sensible defaults are used. +func CreateRequest(cert, issuer *x509.Certificate, opts *RequestOptions) ([]byte, error) { + hashFunc := opts.hash() + + // OCSP seems to be the only place where these raw hash identifiers are + // used. I took the following from + // http://msdn.microsoft.com/en-us/library/ff635603.aspx + _, ok := hashOIDs[hashFunc] + if !ok { + return nil, x509.ErrUnsupportedAlgorithm + } + + if !hashFunc.Available() { + return nil, x509.ErrUnsupportedAlgorithm + } + h := opts.hash().New() + + var publicKeyInfo struct { + Algorithm pkix.AlgorithmIdentifier + PublicKey asn1.BitString + } + if _, err := asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &publicKeyInfo); err != nil { + return nil, err + } + + h.Write(publicKeyInfo.PublicKey.RightAlign()) + issuerKeyHash := h.Sum(nil) + + h.Reset() + h.Write(issuer.RawSubject) + issuerNameHash := h.Sum(nil) + + req := &Request{ + HashAlgorithm: hashFunc, + IssuerNameHash: issuerNameHash, + IssuerKeyHash: issuerKeyHash, + SerialNumber: cert.SerialNumber, + } + return req.Marshal() +} + +// CreateResponse returns a DER-encoded OCSP response with the specified contents. +// The fields in the response are populated as follows: +// +// The responder cert is used to populate the responder's name field, and the +// certificate itself is provided alongside the OCSP response signature. +// +// The issuer cert is used to puplate the IssuerNameHash and IssuerKeyHash fields. +// +// The template is used to populate the SerialNumber, Status, RevokedAt, +// RevocationReason, ThisUpdate, and NextUpdate fields. +// +// If template.IssuerHash is not set, SHA1 will be used. +// +// The ProducedAt date is automatically set to the current date, to the nearest minute. +func CreateResponse(issuer, responderCert *x509.Certificate, template Response, priv crypto.Signer) ([]byte, error) { + var publicKeyInfo struct { + Algorithm pkix.AlgorithmIdentifier + PublicKey asn1.BitString + } + if _, err := asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &publicKeyInfo); err != nil { + return nil, err + } + + if template.IssuerHash == 0 { + template.IssuerHash = crypto.SHA1 + } + hashOID := getOIDFromHashAlgorithm(template.IssuerHash) + if hashOID == nil { + return nil, errors.New("unsupported issuer hash algorithm") + } + + if !template.IssuerHash.Available() { + return nil, fmt.Errorf("issuer hash algorithm %v not linked into binary", template.IssuerHash) + } + h := template.IssuerHash.New() + h.Write(publicKeyInfo.PublicKey.RightAlign()) + issuerKeyHash := h.Sum(nil) + + h.Reset() + h.Write(issuer.RawSubject) + issuerNameHash := h.Sum(nil) + + innerResponse := singleResponse{ + CertID: certID{ + HashAlgorithm: pkix.AlgorithmIdentifier{ + Algorithm: hashOID, + Parameters: asn1.RawValue{Tag: 5 /* ASN.1 NULL */}, + }, + NameHash: issuerNameHash, + IssuerKeyHash: issuerKeyHash, + SerialNumber: template.SerialNumber, + }, + ThisUpdate: template.ThisUpdate.UTC(), + NextUpdate: template.NextUpdate.UTC(), + SingleExtensions: template.ExtraExtensions, + } + + switch template.Status { + case Good: + innerResponse.Good = true + case Unknown: + innerResponse.Unknown = true + case Revoked: + innerResponse.Revoked = revokedInfo{ + RevocationTime: template.RevokedAt.UTC(), + Reason: asn1.Enumerated(template.RevocationReason), + } + } + + rawResponderID := asn1.RawValue{ + Class: 2, // context-specific + Tag: 1, // Name (explicit tag) + IsCompound: true, + Bytes: responderCert.RawSubject, + } + tbsResponseData := responseData{ + Version: 0, + RawResponderID: rawResponderID, + ProducedAt: time.Now().Truncate(time.Minute).UTC(), + Responses: []singleResponse{innerResponse}, + } + + tbsResponseDataDER, err := asn1.Marshal(tbsResponseData) + if err != nil { + return nil, err + } + + hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(priv.Public(), template.SignatureAlgorithm) + if err != nil { + return nil, err + } + + responseHash := hashFunc.New() + responseHash.Write(tbsResponseDataDER) + signature, err := priv.Sign(rand.Reader, responseHash.Sum(nil), hashFunc) + if err != nil { + return nil, err + } + + response := basicResponse{ + TBSResponseData: tbsResponseData, + SignatureAlgorithm: signatureAlgorithm, + Signature: asn1.BitString{ + Bytes: signature, + BitLength: 8 * len(signature), + }, + } + if template.Certificate != nil { + response.Certificates = []asn1.RawValue{ + {FullBytes: template.Certificate.Raw}, + } + } + responseDER, err := asn1.Marshal(response) + if err != nil { + return nil, err + } + + return asn1.Marshal(responseASN1{ + Status: asn1.Enumerated(Success), + Response: responseBytes{ + ResponseType: idPKIXOCSPBasic, + Response: responseDER, + }, + }) +} diff --git a/vendor/golang.org/x/crypto/ocsp/ocsp_test.go b/vendor/golang.org/x/crypto/ocsp/ocsp_test.go new file mode 100644 index 0000000000000000000000000000000000000000..70b19764f58e7de96928962a70067c53c9742a41 --- /dev/null +++ b/vendor/golang.org/x/crypto/ocsp/ocsp_test.go @@ -0,0 +1,875 @@ +// 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 go1.7 + +package ocsp + +import ( + "bytes" + "crypto" + "crypto/sha1" + "crypto/x509" + "crypto/x509/pkix" + "encoding/asn1" + "encoding/hex" + "math/big" + "reflect" + "testing" + "time" +) + +func TestOCSPDecode(t *testing.T) { + responseBytes, _ := hex.DecodeString(ocspResponseHex) + resp, err := ParseResponse(responseBytes, nil) + if err != nil { + t.Fatal(err) + } + + responderCert, _ := hex.DecodeString(startComResponderCertHex) + responder, err := x509.ParseCertificate(responderCert) + if err != nil { + t.Fatal(err) + } + + expected := Response{ + Status: Good, + SerialNumber: big.NewInt(0x1d0fa), + RevocationReason: Unspecified, + ThisUpdate: time.Date(2010, 7, 7, 15, 1, 5, 0, time.UTC), + NextUpdate: time.Date(2010, 7, 7, 18, 35, 17, 0, time.UTC), + RawResponderName: responder.RawSubject, + } + + if !reflect.DeepEqual(resp.ThisUpdate, expected.ThisUpdate) { + t.Errorf("resp.ThisUpdate: got %v, want %v", resp.ThisUpdate, expected.ThisUpdate) + } + + if !reflect.DeepEqual(resp.NextUpdate, expected.NextUpdate) { + t.Errorf("resp.NextUpdate: got %v, want %v", resp.NextUpdate, expected.NextUpdate) + } + + if resp.Status != expected.Status { + t.Errorf("resp.Status: got %d, want %d", resp.Status, expected.Status) + } + + if resp.SerialNumber.Cmp(expected.SerialNumber) != 0 { + t.Errorf("resp.SerialNumber: got %x, want %x", resp.SerialNumber, expected.SerialNumber) + } + + if resp.RevocationReason != expected.RevocationReason { + t.Errorf("resp.RevocationReason: got %d, want %d", resp.RevocationReason, expected.RevocationReason) + } + + if !bytes.Equal(resp.RawResponderName, expected.RawResponderName) { + t.Errorf("resp.RawResponderName: got %x, want %x", resp.RawResponderName, expected.RawResponderName) + } + + if !bytes.Equal(resp.ResponderKeyHash, expected.ResponderKeyHash) { + t.Errorf("resp.ResponderKeyHash: got %x, want %x", resp.ResponderKeyHash, expected.ResponderKeyHash) + } +} + +func TestOCSPDecodeWithoutCert(t *testing.T) { + responseBytes, _ := hex.DecodeString(ocspResponseWithoutCertHex) + _, err := ParseResponse(responseBytes, nil) + if err != nil { + t.Error(err) + } +} + +func TestOCSPDecodeWithExtensions(t *testing.T) { + responseBytes, _ := hex.DecodeString(ocspResponseWithCriticalExtensionHex) + _, err := ParseResponse(responseBytes, nil) + if err == nil { + t.Error(err) + } + + responseBytes, _ = hex.DecodeString(ocspResponseWithExtensionHex) + response, err := ParseResponse(responseBytes, nil) + if err != nil { + t.Fatal(err) + } + + if len(response.Extensions) != 1 { + t.Errorf("len(response.Extensions): got %v, want %v", len(response.Extensions), 1) + } + + extensionBytes := response.Extensions[0].Value + expectedBytes, _ := hex.DecodeString(ocspExtensionValueHex) + if !bytes.Equal(extensionBytes, expectedBytes) { + t.Errorf("response.Extensions[0]: got %x, want %x", extensionBytes, expectedBytes) + } +} + +func TestOCSPSignature(t *testing.T) { + issuerCert, _ := hex.DecodeString(startComHex) + issuer, err := x509.ParseCertificate(issuerCert) + if err != nil { + t.Fatal(err) + } + + response, _ := hex.DecodeString(ocspResponseHex) + if _, err := ParseResponse(response, issuer); err != nil { + t.Error(err) + } +} + +func TestOCSPRequest(t *testing.T) { + leafCert, _ := hex.DecodeString(leafCertHex) + cert, err := x509.ParseCertificate(leafCert) + if err != nil { + t.Fatal(err) + } + + issuerCert, _ := hex.DecodeString(issuerCertHex) + issuer, err := x509.ParseCertificate(issuerCert) + if err != nil { + t.Fatal(err) + } + + request, err := CreateRequest(cert, issuer, nil) + if err != nil { + t.Fatal(err) + } + + expectedBytes, _ := hex.DecodeString(ocspRequestHex) + if !bytes.Equal(request, expectedBytes) { + t.Errorf("request: got %x, wanted %x", request, expectedBytes) + } + + decodedRequest, err := ParseRequest(expectedBytes) + if err != nil { + t.Fatal(err) + } + + if decodedRequest.HashAlgorithm != crypto.SHA1 { + t.Errorf("request.HashAlgorithm: got %v, want %v", decodedRequest.HashAlgorithm, crypto.SHA1) + } + + var publicKeyInfo struct { + Algorithm pkix.AlgorithmIdentifier + PublicKey asn1.BitString + } + _, err = asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &publicKeyInfo) + if err != nil { + t.Fatal(err) + } + + h := sha1.New() + h.Write(publicKeyInfo.PublicKey.RightAlign()) + issuerKeyHash := h.Sum(nil) + + h.Reset() + h.Write(issuer.RawSubject) + issuerNameHash := h.Sum(nil) + + if got := decodedRequest.IssuerKeyHash; !bytes.Equal(got, issuerKeyHash) { + t.Errorf("request.IssuerKeyHash: got %x, want %x", got, issuerKeyHash) + } + + if got := decodedRequest.IssuerNameHash; !bytes.Equal(got, issuerNameHash) { + t.Errorf("request.IssuerKeyHash: got %x, want %x", got, issuerNameHash) + } + + if got := decodedRequest.SerialNumber; got.Cmp(cert.SerialNumber) != 0 { + t.Errorf("request.SerialNumber: got %x, want %x", got, cert.SerialNumber) + } + + marshaledRequest, err := decodedRequest.Marshal() + if err != nil { + t.Fatal(err) + } + + if bytes.Compare(expectedBytes, marshaledRequest) != 0 { + t.Errorf( + "Marshaled request doesn't match expected: wanted %x, got %x", + expectedBytes, + marshaledRequest, + ) + } +} + +func TestOCSPResponse(t *testing.T) { + leafCert, _ := hex.DecodeString(leafCertHex) + leaf, err := x509.ParseCertificate(leafCert) + if err != nil { + t.Fatal(err) + } + + issuerCert, _ := hex.DecodeString(issuerCertHex) + issuer, err := x509.ParseCertificate(issuerCert) + if err != nil { + t.Fatal(err) + } + + responderCert, _ := hex.DecodeString(responderCertHex) + responder, err := x509.ParseCertificate(responderCert) + if err != nil { + t.Fatal(err) + } + + responderPrivateKeyDER, _ := hex.DecodeString(responderPrivateKeyHex) + responderPrivateKey, err := x509.ParsePKCS1PrivateKey(responderPrivateKeyDER) + if err != nil { + t.Fatal(err) + } + + extensionBytes, _ := hex.DecodeString(ocspExtensionValueHex) + extensions := []pkix.Extension{ + { + Id: ocspExtensionOID, + Critical: false, + Value: extensionBytes, + }, + } + + thisUpdate := time.Date(2010, 7, 7, 15, 1, 5, 0, time.UTC) + nextUpdate := time.Date(2010, 7, 7, 18, 35, 17, 0, time.UTC) + template := Response{ + Status: Revoked, + SerialNumber: leaf.SerialNumber, + ThisUpdate: thisUpdate, + NextUpdate: nextUpdate, + RevokedAt: thisUpdate, + RevocationReason: KeyCompromise, + Certificate: responder, + ExtraExtensions: extensions, + } + + template.IssuerHash = crypto.MD5 + _, err = CreateResponse(issuer, responder, template, responderPrivateKey) + if err == nil { + t.Fatal("CreateResponse didn't fail with non-valid template.IssuerHash value crypto.MD5") + } + + testCases := []struct { + name string + issuerHash crypto.Hash + }{ + {"Zero value", 0}, + {"crypto.SHA1", crypto.SHA1}, + {"crypto.SHA256", crypto.SHA256}, + {"crypto.SHA384", crypto.SHA384}, + {"crypto.SHA512", crypto.SHA512}, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + template.IssuerHash = tc.issuerHash + responseBytes, err := CreateResponse(issuer, responder, template, responderPrivateKey) + if err != nil { + t.Fatalf("CreateResponse failed: %s", err) + } + + resp, err := ParseResponse(responseBytes, nil) + if err != nil { + t.Fatalf("ParseResponse failed: %s", err) + } + + if !reflect.DeepEqual(resp.ThisUpdate, template.ThisUpdate) { + t.Errorf("resp.ThisUpdate: got %v, want %v", resp.ThisUpdate, template.ThisUpdate) + } + + if !reflect.DeepEqual(resp.NextUpdate, template.NextUpdate) { + t.Errorf("resp.NextUpdate: got %v, want %v", resp.NextUpdate, template.NextUpdate) + } + + if !reflect.DeepEqual(resp.RevokedAt, template.RevokedAt) { + t.Errorf("resp.RevokedAt: got %v, want %v", resp.RevokedAt, template.RevokedAt) + } + + if !reflect.DeepEqual(resp.Extensions, template.ExtraExtensions) { + t.Errorf("resp.Extensions: got %v, want %v", resp.Extensions, template.ExtraExtensions) + } + + delay := time.Since(resp.ProducedAt) + if delay < -time.Hour || delay > time.Hour { + t.Errorf("resp.ProducedAt: got %s, want close to current time (%s)", resp.ProducedAt, time.Now()) + } + + if resp.Status != template.Status { + t.Errorf("resp.Status: got %d, want %d", resp.Status, template.Status) + } + + if resp.SerialNumber.Cmp(template.SerialNumber) != 0 { + t.Errorf("resp.SerialNumber: got %x, want %x", resp.SerialNumber, template.SerialNumber) + } + + if resp.RevocationReason != template.RevocationReason { + t.Errorf("resp.RevocationReason: got %d, want %d", resp.RevocationReason, template.RevocationReason) + } + + expectedHash := tc.issuerHash + if tc.issuerHash == 0 { + expectedHash = crypto.SHA1 + } + + if resp.IssuerHash != expectedHash { + t.Errorf("resp.IssuerHash: got %d, want %d", resp.IssuerHash, expectedHash) + } + }) + } +} + +func TestErrorResponse(t *testing.T) { + responseBytes, _ := hex.DecodeString(errorResponseHex) + _, err := ParseResponse(responseBytes, nil) + + respErr, ok := err.(ResponseError) + if !ok { + t.Fatalf("expected ResponseError from ParseResponse but got %#v", err) + } + if respErr.Status != Malformed { + t.Fatalf("expected Malformed status from ParseResponse but got %d", respErr.Status) + } +} + +func TestOCSPDecodeMultiResponse(t *testing.T) { + inclCert, _ := hex.DecodeString(ocspMultiResponseCertHex) + cert, err := x509.ParseCertificate(inclCert) + if err != nil { + t.Fatal(err) + } + + responseBytes, _ := hex.DecodeString(ocspMultiResponseHex) + resp, err := ParseResponseForCert(responseBytes, cert, nil) + if err != nil { + t.Fatal(err) + } + + if resp.SerialNumber.Cmp(cert.SerialNumber) != 0 { + t.Errorf("resp.SerialNumber: got %x, want %x", resp.SerialNumber, cert.SerialNumber) + } +} + +func TestOCSPDecodeMultiResponseWithoutMatchingCert(t *testing.T) { + wrongCert, _ := hex.DecodeString(startComHex) + cert, err := x509.ParseCertificate(wrongCert) + if err != nil { + t.Fatal(err) + } + + responseBytes, _ := hex.DecodeString(ocspMultiResponseHex) + _, err = ParseResponseForCert(responseBytes, cert, nil) + want := ParseError("no response matching the supplied certificate") + if err != want { + t.Errorf("err: got %q, want %q", err, want) + } +} + +// This OCSP response was taken from Thawte's public OCSP responder. +// To recreate: +// $ openssl s_client -tls1 -showcerts -servername www.google.com -connect www.google.com:443 +// Copy and paste the first certificate into /tmp/cert.crt and the second into +// /tmp/intermediate.crt +// $ openssl ocsp -issuer /tmp/intermediate.crt -cert /tmp/cert.crt -url http://ocsp.thawte.com -resp_text -respout /tmp/ocsp.der +// Then hex encode the result: +// $ python -c 'print file("/tmp/ocsp.der", "r").read().encode("hex")' + +const ocspResponseHex = "308206bc0a0100a08206b5308206b106092b0601050507300101048206a23082069e3081" + + "c9a14e304c310b300906035504061302494c31163014060355040a130d5374617274436f" + + "6d204c74642e312530230603550403131c5374617274436f6d20436c6173732031204f43" + + "5350205369676e6572180f32303130303730373137333531375a30663064303c30090605" + + "2b0e03021a050004146568874f40750f016a3475625e1f5c93e5a26d580414eb4234d098" + + "b0ab9ff41b6b08f7cc642eef0e2c45020301d0fa8000180f323031303037303731353031" + + "30355aa011180f32303130303730373138333531375a300d06092a864886f70d01010505" + + "000382010100ab557ff070d1d7cebbb5f0ec91a15c3fed22eb2e1b8244f1b84545f013a4" + + "fb46214c5e3fbfbebb8a56acc2b9db19f68fd3c3201046b3824d5ba689f99864328710cb" + + "467195eb37d84f539e49f859316b32964dc3e47e36814ce94d6c56dd02733b1d0802f7ff" + + "4eebdbbd2927dcf580f16cbc290f91e81b53cb365e7223f1d6e20a88ea064104875e0145" + + "672b20fc14829d51ca122f5f5d77d3ad6c83889c55c7dc43680ba2fe3cef8b05dbcabdc0" + + "d3e09aaf9725597f8c858c2fa38c0d6aed2e6318194420dd1a1137445d13e1c97ab47896" + + "17a4e08925f46f867b72e3a4dc1f08cb870b2b0717f7207faa0ac512e628a029aba7457a" + + "e63dcf3281e2162d9349a08204ba308204b6308204b23082039aa003020102020101300d" + + "06092a864886f70d010105050030818c310b300906035504061302494c31163014060355" + + "040a130d5374617274436f6d204c74642e312b3029060355040b13225365637572652044" + + "69676974616c204365727469666963617465205369676e696e6731383036060355040313" + + "2f5374617274436f6d20436c6173732031205072696d61727920496e7465726d65646961" + + "746520536572766572204341301e170d3037313032353030323330365a170d3132313032" + + "333030323330365a304c310b300906035504061302494c31163014060355040a130d5374" + + "617274436f6d204c74642e312530230603550403131c5374617274436f6d20436c617373" + + "2031204f435350205369676e657230820122300d06092a864886f70d0101010500038201" + + "0f003082010a0282010100b9561b4c45318717178084e96e178df2255e18ed8d8ecc7c2b" + + "7b51a6c1c2e6bf0aa3603066f132fe10ae97b50e99fa24b83fc53dd2777496387d14e1c3" + + "a9b6a4933e2ac12413d085570a95b8147414a0bc007c7bcf222446ef7f1a156d7ea1c577" + + "fc5f0facdfd42eb0f5974990cb2f5cefebceef4d1bdc7ae5c1075c5a99a93171f2b0845b" + + "4ff0864e973fcfe32f9d7511ff87a3e943410c90a4493a306b6944359340a9ca96f02b66" + + "ce67f028df2980a6aaee8d5d5d452b8b0eb93f923cc1e23fcccbdbe7ffcb114d08fa7a6a" + + "3c404f825d1a0e715935cf623a8c7b59670014ed0622f6089a9447a7a19010f7fe58f841" + + "29a2765ea367824d1c3bb2fda308530203010001a382015c30820158300c0603551d1301" + + "01ff04023000300b0603551d0f0404030203a8301e0603551d250417301506082b060105" + + "0507030906092b0601050507300105301d0603551d0e0416041445e0a36695414c5dd449" + + "bc00e33cdcdbd2343e173081a80603551d230481a030819d8014eb4234d098b0ab9ff41b" + + "6b08f7cc642eef0e2c45a18181a47f307d310b300906035504061302494c311630140603" + + "55040a130d5374617274436f6d204c74642e312b3029060355040b132253656375726520" + + "4469676974616c204365727469666963617465205369676e696e67312930270603550403" + + "13205374617274436f6d2043657274696669636174696f6e20417574686f726974798201" + + "0a30230603551d12041c301a8618687474703a2f2f7777772e737461727473736c2e636f" + + "6d2f302c06096086480186f842010d041f161d5374617274436f6d205265766f63617469" + + "6f6e20417574686f72697479300d06092a864886f70d01010505000382010100182d2215" + + "8f0fc0291324fa8574c49bb8ff2835085adcbf7b7fc4191c397ab6951328253fffe1e5ec" + + "2a7da0d50fca1a404e6968481366939e666c0a6209073eca57973e2fefa9ed1718e8176f" + + "1d85527ff522c08db702e3b2b180f1cbff05d98128252cf0f450f7dd2772f4188047f19d" + + "c85317366f94bc52d60f453a550af58e308aaab00ced33040b62bf37f5b1ab2a4f7f0f80" + + "f763bf4d707bc8841d7ad9385ee2a4244469260b6f2bf085977af9074796048ecc2f9d48" + + "a1d24ce16e41a9941568fec5b42771e118f16c106a54ccc339a4b02166445a167902e75e" + + "6d8620b0825dcd18a069b90fd851d10fa8effd409deec02860d26d8d833f304b10669b42" + +const startComResponderCertHex = "308204b23082039aa003020102020101300d06092a864886f70d010105050030818c310b" + + "300906035504061302494c31163014060355040a130d5374617274436f6d204c74642e31" + + "2b3029060355040b1322536563757265204469676974616c204365727469666963617465" + + "205369676e696e67313830360603550403132f5374617274436f6d20436c617373203120" + + "5072696d61727920496e7465726d65646961746520536572766572204341301e170d3037" + + "313032353030323330365a170d3132313032333030323330365a304c310b300906035504" + + "061302494c31163014060355040a130d5374617274436f6d204c74642e31253023060355" + + "0403131c5374617274436f6d20436c6173732031204f435350205369676e657230820122" + + "300d06092a864886f70d01010105000382010f003082010a0282010100b9561b4c453187" + + "17178084e96e178df2255e18ed8d8ecc7c2b7b51a6c1c2e6bf0aa3603066f132fe10ae97" + + "b50e99fa24b83fc53dd2777496387d14e1c3a9b6a4933e2ac12413d085570a95b8147414" + + "a0bc007c7bcf222446ef7f1a156d7ea1c577fc5f0facdfd42eb0f5974990cb2f5cefebce" + + "ef4d1bdc7ae5c1075c5a99a93171f2b0845b4ff0864e973fcfe32f9d7511ff87a3e94341" + + "0c90a4493a306b6944359340a9ca96f02b66ce67f028df2980a6aaee8d5d5d452b8b0eb9" + + "3f923cc1e23fcccbdbe7ffcb114d08fa7a6a3c404f825d1a0e715935cf623a8c7b596700" + + "14ed0622f6089a9447a7a19010f7fe58f84129a2765ea367824d1c3bb2fda30853020301" + + "0001a382015c30820158300c0603551d130101ff04023000300b0603551d0f0404030203" + + "a8301e0603551d250417301506082b0601050507030906092b0601050507300105301d06" + + "03551d0e0416041445e0a36695414c5dd449bc00e33cdcdbd2343e173081a80603551d23" + + "0481a030819d8014eb4234d098b0ab9ff41b6b08f7cc642eef0e2c45a18181a47f307d31" + + "0b300906035504061302494c31163014060355040a130d5374617274436f6d204c74642e" + + "312b3029060355040b1322536563757265204469676974616c2043657274696669636174" + + "65205369676e696e6731293027060355040313205374617274436f6d2043657274696669" + + "636174696f6e20417574686f7269747982010a30230603551d12041c301a861868747470" + + "3a2f2f7777772e737461727473736c2e636f6d2f302c06096086480186f842010d041f16" + + "1d5374617274436f6d205265766f636174696f6e20417574686f72697479300d06092a86" + + "4886f70d01010505000382010100182d22158f0fc0291324fa8574c49bb8ff2835085adc" + + "bf7b7fc4191c397ab6951328253fffe1e5ec2a7da0d50fca1a404e6968481366939e666c" + + "0a6209073eca57973e2fefa9ed1718e8176f1d85527ff522c08db702e3b2b180f1cbff05" + + "d98128252cf0f450f7dd2772f4188047f19dc85317366f94bc52d60f453a550af58e308a" + + "aab00ced33040b62bf37f5b1ab2a4f7f0f80f763bf4d707bc8841d7ad9385ee2a4244469" + + "260b6f2bf085977af9074796048ecc2f9d48a1d24ce16e41a9941568fec5b42771e118f1" + + "6c106a54ccc339a4b02166445a167902e75e6d8620b0825dcd18a069b90fd851d10fa8ef" + + "fd409deec02860d26d8d833f304b10669b42" + +const startComHex = "308206343082041ca003020102020118300d06092a864886f70d0101050500307d310b30" + + "0906035504061302494c31163014060355040a130d5374617274436f6d204c74642e312b" + + "3029060355040b1322536563757265204469676974616c20436572746966696361746520" + + "5369676e696e6731293027060355040313205374617274436f6d20436572746966696361" + + "74696f6e20417574686f72697479301e170d3037313032343230353431375a170d313731" + + "3032343230353431375a30818c310b300906035504061302494c31163014060355040a13" + + "0d5374617274436f6d204c74642e312b3029060355040b13225365637572652044696769" + + "74616c204365727469666963617465205369676e696e67313830360603550403132f5374" + + "617274436f6d20436c6173732031205072696d61727920496e7465726d65646961746520" + + "53657276657220434130820122300d06092a864886f70d01010105000382010f00308201" + + "0a0282010100b689c6acef09527807ac9263d0f44418188480561f91aee187fa3250b4d3" + + "4706f0e6075f700e10f71dc0ce103634855a0f92ac83c6ac58523fba38e8fce7a724e240" + + "a60876c0926e9e2a6d4d3f6e61200adb59ded27d63b33e46fefa215118d7cd30a6ed076e" + + "3b7087b4f9faebee823c056f92f7a4dc0a301e9373fe07cad75f809d225852ae06da8b87" + + "2369b0e42ad8ea83d2bdf371db705a280faf5a387045123f304dcd3baf17e50fcba0a95d" + + "48aab16150cb34cd3c5cc30be810c08c9bf0030362feb26c3e720eee1c432ac9480e5739" + + "c43121c810c12c87fe5495521f523c31129b7fe7c0a0a559d5e28f3ef0d5a8e1d77031a9" + + "c4b3cfaf6d532f06f4a70203010001a38201ad308201a9300f0603551d130101ff040530" + + "030101ff300e0603551d0f0101ff040403020106301d0603551d0e04160414eb4234d098" + + "b0ab9ff41b6b08f7cc642eef0e2c45301f0603551d230418301680144e0bef1aa4405ba5" + + "17698730ca346843d041aef2306606082b06010505070101045a3058302706082b060105" + + "05073001861b687474703a2f2f6f6373702e737461727473736c2e636f6d2f6361302d06" + + "082b060105050730028621687474703a2f2f7777772e737461727473736c2e636f6d2f73" + + "667363612e637274305b0603551d1f045430523027a025a0238621687474703a2f2f7777" + + "772e737461727473736c2e636f6d2f73667363612e63726c3027a025a023862168747470" + + "3a2f2f63726c2e737461727473736c2e636f6d2f73667363612e63726c3081800603551d" + + "20047930773075060b2b0601040181b5370102013066302e06082b060105050702011622" + + "687474703a2f2f7777772e737461727473736c2e636f6d2f706f6c6963792e7064663034" + + "06082b060105050702011628687474703a2f2f7777772e737461727473736c2e636f6d2f" + + "696e7465726d6564696174652e706466300d06092a864886f70d01010505000382020100" + + "2109493ea5886ee00b8b48da314d8ff75657a2e1d36257e9b556f38545753be5501f048b" + + "e6a05a3ee700ae85d0fbff200364cbad02e1c69172f8a34dd6dee8cc3fa18aa2e37c37a7" + + "c64f8f35d6f4d66e067bdd21d9cf56ffcb302249fe8904f385e5aaf1e71fe875904dddf9" + + "46f74234f745580c110d84b0c6da5d3ef9019ee7e1da5595be741c7bfc4d144fac7e5547" + + "7d7bf4a50d491e95e8f712c1ccff76a62547d0f37535be97b75816ebaa5c786fec5330af" + + "ea044dcca902e3f0b60412f630b1113d904e5664d7dc3c435f7339ef4baf87ebf6fe6888" + + "4472ead207c669b0c1a18bef1749d761b145485f3b2021e95bb2ccf4d7e931f50b15613b" + + "7a94e3ebd9bc7f94ae6ae3626296a8647cb887f399327e92a252bebbf865cfc9f230fc8b" + + "c1c2a696d75f89e15c3480f58f47072fb491bfb1a27e5f4b5ad05b9f248605515a690365" + + "434971c5e06f94346bf61bd8a9b04c7e53eb8f48dfca33b548fa364a1a53a6330cd089cd" + + "4915cd89313c90c072d7654b52358a461144b93d8e2865a63e799e5c084429adb035112e" + + "214eb8d2e7103e5d8483b3c3c2e4d2c6fd094b7409ddf1b3d3193e800da20b19f038e7c5" + + "c2afe223db61e29d5c6e2089492e236ab262c145b49faf8ba7f1223bf87de290d07a19fb" + + "4a4ce3d27d5f4a8303ed27d6239e6b8db459a2d9ef6c8229dd75193c3f4c108defbb7527" + + "d2ae83a7a8ce5ba7" + +const ocspResponseWithoutCertHex = "308201d40a0100a08201cd308201c906092b0601050507300101048201ba3082" + + "01b630819fa2160414884451ff502a695e2d88f421bad90cf2cecbea7c180f3230313330" + + "3631383037323434335a30743072304a300906052b0e03021a0500041448b60d38238df8" + + "456e4ee5843ea394111802979f0414884451ff502a695e2d88f421bad90cf2cecbea7c02" + + "1100f78b13b946fc9635d8ab49de9d2148218000180f3230313330363138303732343433" + + "5aa011180f32303133303632323037323434335a300d06092a864886f70d010105050003" + + "82010100103e18b3d297a5e7a6c07a4fc52ac46a15c0eba96f3be17f0ffe84de5b8c8e05" + + "5a8f577586a849dc4abd6440eb6fedde4622451e2823c1cbf3558b4e8184959c9fe96eff" + + "8bc5f95866c58c6d087519faabfdae37e11d9874f1bc0db292208f645dd848185e4dd38b" + + "6a8547dfa7b74d514a8470015719064d35476b95bebb03d4d2845c5ca15202d2784878f2" + + "0f904c24f09736f044609e9c271381713400e563023d212db422236440c6f377bbf24b2b" + + "9e7dec8698e36a8df68b7592ad3489fb2937afb90eb85d2aa96b81c94c25057dbd4759d9" + + "20a1a65c7f0b6427a224b3c98edd96b9b61f706099951188b0289555ad30a216fb774651" + + "5a35fca2e054dfa8" + +// PKIX nonce extension +var ocspExtensionOID = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 48, 1, 2} +var ocspExtensionValueHex = "0403000000" + +const ocspResponseWithCriticalExtensionHex = "308204fe0a0100a08204f7308204f306092b0601050507300101048204e4308204e03081" + + "dba003020100a11b3019311730150603550403130e4f43535020526573706f6e64657218" + + "0f32303136303130343137303130305a3081a53081a23049300906052b0e03021a050004" + + "14c0fe0278fc99188891b3f212e9c7e1b21ab7bfc004140dfc1df0a9e0f01ce7f2b21317" + + "7e6f8d157cd4f60210017f77deb3bcbb235d44ccc7dba62e72a116180f32303130303730" + + "373135303130355aa0030a0101180f32303130303730373135303130355aa011180f3230" + + "3130303730373138333531375aa1193017301506092b06010505073001020101ff040504" + + "03000000300d06092a864886f70d01010b0500038201010031c730ca60a7a0d92d8e4010" + + "911b469de95b4d27e89de6537552436237967694f76f701cf6b45c932bd308bca4a8d092" + + "5c604ba94796903091d9e6c000178e72c1f0a24a277dd262835af5d17d3f9d7869606c9f" + + "e7c8e708a41645699895beee38bfa63bb46296683761c5d1d65439b8ab868dc3017c9eeb" + + "b70b82dbf3a31c55b457d48bb9e82b335ed49f445042eaf606b06a3e0639824924c89c63" + + "eccddfe85e6694314138b2536f5e15e07085d0f6e26d4b2f8244bab0d70de07283ac6384" + + "a0501fc3dea7cf0adfd4c7f34871080900e252ddc403e3f0265f2a704af905d3727504ed" + + "28f3214a219d898a022463c78439799ca81c8cbafdbcec34ea937cd6a08202ea308202e6" + + "308202e2308201caa003020102020101300d06092a864886f70d01010b05003019311730" + + "150603550403130e4f43535020526573706f6e646572301e170d31353031333031353530" + + "33335a170d3136303133303135353033335a3019311730150603550403130e4f43535020" + + "526573706f6e64657230820122300d06092a864886f70d01010105000382010f00308201" + + "0a0282010100e8155f2d3e6f2e8d14c62a788bd462f9f844e7a6977c83ef1099f0f6616e" + + "c5265b56f356e62c5400f0b06a2e7945a82752c636df32a895152d6074df1701dc6ccfbc" + + "bec75a70bd2b55ae2be7e6cad3b5fd4cd5b7790ab401a436d3f5f346074ffde8a99d5b72" + + "3350f0a112076614b12ef79c78991b119453445acf2416ab0046b540db14c9fc0f27b898" + + "9ad0f63aa4b8aefc91aa8a72160c36307c60fec78a93d3fddf4259902aa77e7332971c7d" + + "285b6a04f648993c6922a3e9da9adf5f81508c3228791843e5d49f24db2f1290bafd97e6" + + "55b1049a199f652cd603c4fafa330c390b0da78fbbc67e8fa021cbd74eb96222b12ace31" + + "a77dcf920334dc94581b0203010001a3353033300e0603551d0f0101ff04040302078030" + + "130603551d25040c300a06082b06010505070309300c0603551d130101ff04023000300d" + + "06092a864886f70d01010b05000382010100718012761b5063e18f0dc44644d8e6ab8612" + + "31c15fd5357805425d82aec1de85bf6d3e30fce205e3e3b8b795bbe52e40a439286d2288" + + "9064f4aeeb150359b9425f1da51b3a5c939018555d13ac42c565a0603786a919328f3267" + + "09dce52c22ad958ecb7873b9771d1148b1c4be2efe80ba868919fc9f68b6090c2f33c156" + + "d67156e42766a50b5d51e79637b7e58af74c2a951b1e642fa7741fec982cc937de37eff5" + + "9e2005d5939bfc031589ca143e6e8ab83f40ee08cc20a6b4a95a318352c28d18528dcaf9" + + "66705de17afa19d6e8ae91ddf33179d16ebb6ac2c69cae8373d408ebf8c55308be6c04d9" + + "3a25439a94299a65a709756c7a3e568be049d5c38839" + +const ocspResponseWithExtensionHex = "308204fb0a0100a08204f4308204f006092b0601050507300101048204e1308204dd3081" + + "d8a003020100a11b3019311730150603550403130e4f43535020526573706f6e64657218" + + "0f32303136303130343136353930305a3081a230819f3049300906052b0e03021a050004" + + "14c0fe0278fc99188891b3f212e9c7e1b21ab7bfc004140dfc1df0a9e0f01ce7f2b21317" + + "7e6f8d157cd4f60210017f77deb3bcbb235d44ccc7dba62e72a116180f32303130303730" + + "373135303130355aa0030a0101180f32303130303730373135303130355aa011180f3230" + + "3130303730373138333531375aa1163014301206092b0601050507300102040504030000" + + "00300d06092a864886f70d01010b05000382010100c09a33e0b2324c852421bb83f85ac9" + + "9113f5426012bd2d2279a8166e9241d18a33c870894250622ffc7ed0c4601b16d624f90b" + + "779265442cdb6868cf40ab304ab4b66e7315ed02cf663b1601d1d4751772b31bc299db23" + + "9aebac78ed6797c06ed815a7a8d18d63cfbb609cafb47ec2e89e37db255216eb09307848" + + "d01be0a3e943653c78212b96ff524b74c9ec456b17cdfb950cc97645c577b2e09ff41dde" + + "b03afb3adaa381cc0f7c1d95663ef22a0f72f2c45613ae8e2b2d1efc96e8463c7d1d8a1d" + + "7e3b35df8fe73a301fc3f804b942b2b3afa337ff105fc1462b7b1c1d75eb4566c8665e59" + + "f80393b0adbf8004ff6c3327ed34f007cb4a3348a7d55e06e3a08202ea308202e6308202" + + "e2308201caa003020102020101300d06092a864886f70d01010b05003019311730150603" + + "550403130e4f43535020526573706f6e646572301e170d3135303133303135353033335a" + + "170d3136303133303135353033335a3019311730150603550403130e4f43535020526573" + + "706f6e64657230820122300d06092a864886f70d01010105000382010f003082010a0282" + + "010100e8155f2d3e6f2e8d14c62a788bd462f9f844e7a6977c83ef1099f0f6616ec5265b" + + "56f356e62c5400f0b06a2e7945a82752c636df32a895152d6074df1701dc6ccfbcbec75a" + + "70bd2b55ae2be7e6cad3b5fd4cd5b7790ab401a436d3f5f346074ffde8a99d5b723350f0" + + "a112076614b12ef79c78991b119453445acf2416ab0046b540db14c9fc0f27b8989ad0f6" + + "3aa4b8aefc91aa8a72160c36307c60fec78a93d3fddf4259902aa77e7332971c7d285b6a" + + "04f648993c6922a3e9da9adf5f81508c3228791843e5d49f24db2f1290bafd97e655b104" + + "9a199f652cd603c4fafa330c390b0da78fbbc67e8fa021cbd74eb96222b12ace31a77dcf" + + "920334dc94581b0203010001a3353033300e0603551d0f0101ff04040302078030130603" + + "551d25040c300a06082b06010505070309300c0603551d130101ff04023000300d06092a" + + "864886f70d01010b05000382010100718012761b5063e18f0dc44644d8e6ab861231c15f" + + "d5357805425d82aec1de85bf6d3e30fce205e3e3b8b795bbe52e40a439286d22889064f4" + + "aeeb150359b9425f1da51b3a5c939018555d13ac42c565a0603786a919328f326709dce5" + + "2c22ad958ecb7873b9771d1148b1c4be2efe80ba868919fc9f68b6090c2f33c156d67156" + + "e42766a50b5d51e79637b7e58af74c2a951b1e642fa7741fec982cc937de37eff59e2005" + + "d5939bfc031589ca143e6e8ab83f40ee08cc20a6b4a95a318352c28d18528dcaf966705d" + + "e17afa19d6e8ae91ddf33179d16ebb6ac2c69cae8373d408ebf8c55308be6c04d93a2543" + + "9a94299a65a709756c7a3e568be049d5c38839" + +const ocspMultiResponseHex = "30820ee60a0100a0820edf30820edb06092b060105050730010104820ecc30820ec83082" + + "0839a216041445ac2ecd75f53f1cf6e4c51d3de0047ad0aa7465180f3230313530363032" + + "3130303033305a3082080c3065303d300906052b0e03021a05000414f7452a0080601527" + + "72e4a135e76e9e52fde0f1580414edd8f2ee977252853a330b297a18f5c993853b3f0204" + + "5456656a8000180f32303135303630323039303230375aa011180f323031353036303331" + + "30303033305a3065303d300906052b0e03021a05000414f7452a008060152772e4a135e7" + + "6e9e52fde0f1580414edd8f2ee977252853a330b297a18f5c993853b3f02045456656b80" + + "00180f32303135303630323039303230375aa011180f3230313530363033313030303330" + + "5a3065303d300906052b0e03021a05000414f7452a008060152772e4a135e76e9e52fde0" + + "f1580414edd8f2ee977252853a330b297a18f5c993853b3f02045456656c8000180f3230" + + "3135303630323039303230375aa011180f32303135303630333130303033305a3065303d" + + "300906052b0e03021a05000414f7452a008060152772e4a135e76e9e52fde0f1580414ed" + + "d8f2ee977252853a330b297a18f5c993853b3f02045456656d8000180f32303135303630" + + "323039303230375aa011180f32303135303630333130303033305a3065303d300906052b" + + "0e03021a05000414f7452a008060152772e4a135e76e9e52fde0f1580414edd8f2ee9772" + + "52853a330b297a18f5c993853b3f02045456656e8000180f323031353036303230393032" + + "30375aa011180f32303135303630333130303033305a3065303d300906052b0e03021a05" + + "000414f7452a008060152772e4a135e76e9e52fde0f1580414edd8f2ee977252853a330b" + + "297a18f5c993853b3f02045456656f8000180f32303135303630323039303230375aa011" + + "180f32303135303630333130303033305a3065303d300906052b0e03021a05000414f745" + + "2a008060152772e4a135e76e9e52fde0f1580414edd8f2ee977252853a330b297a18f5c9" + + "93853b3f0204545665708000180f32303135303630323039303230375aa011180f323031" + + "35303630333130303033305a3065303d300906052b0e03021a05000414f7452a00806015" + + "2772e4a135e76e9e52fde0f1580414edd8f2ee977252853a330b297a18f5c993853b3f02" + + "04545665718000180f32303135303630323039303230375aa011180f3230313530363033" + + "3130303033305a3065303d300906052b0e03021a05000414f7452a008060152772e4a135" + + "e76e9e52fde0f1580414edd8f2ee977252853a330b297a18f5c993853b3f020454566572" + + "8000180f32303135303630323039303230375aa011180f32303135303630333130303033" + + "305a3065303d300906052b0e03021a05000414f7452a008060152772e4a135e76e9e52fd" + + "e0f1580414edd8f2ee977252853a330b297a18f5c993853b3f0204545665738000180f32" + + "303135303630323039303230375aa011180f32303135303630333130303033305a306530" + + "3d300906052b0e03021a05000414f7452a008060152772e4a135e76e9e52fde0f1580414" + + "edd8f2ee977252853a330b297a18f5c993853b3f0204545665748000180f323031353036" + + "30323039303230375aa011180f32303135303630333130303033305a3065303d30090605" + + "2b0e03021a05000414f7452a008060152772e4a135e76e9e52fde0f1580414edd8f2ee97" + + "7252853a330b297a18f5c993853b3f0204545665758000180f3230313530363032303930" + + "3230375aa011180f32303135303630333130303033305a3065303d300906052b0e03021a" + + "05000414f7452a008060152772e4a135e76e9e52fde0f1580414edd8f2ee977252853a33" + + "0b297a18f5c993853b3f0204545665768000180f32303135303630323039303230375aa0" + + "11180f32303135303630333130303033305a3065303d300906052b0e03021a05000414f7" + + "452a008060152772e4a135e76e9e52fde0f1580414edd8f2ee977252853a330b297a18f5" + + "c993853b3f0204545665778000180f32303135303630323039303230375aa011180f3230" + + "3135303630333130303033305a3065303d300906052b0e03021a05000414f7452a008060" + + "152772e4a135e76e9e52fde0f1580414edd8f2ee977252853a330b297a18f5c993853b3f" + + "0204545665788000180f32303135303630323039303230375aa011180f32303135303630" + + "333130303033305a3065303d300906052b0e03021a05000414f7452a008060152772e4a1" + + "35e76e9e52fde0f1580414edd8f2ee977252853a330b297a18f5c993853b3f0204545665" + + "798000180f32303135303630323039303230375aa011180f323031353036303331303030" + + "33305a3065303d300906052b0e03021a05000414f7452a008060152772e4a135e76e9e52" + + "fde0f1580414edd8f2ee977252853a330b297a18f5c993853b3f02045456657a8000180f" + + "32303135303630323039303230375aa011180f32303135303630333130303033305a3065" + + "303d300906052b0e03021a05000414f7452a008060152772e4a135e76e9e52fde0f15804" + + "14edd8f2ee977252853a330b297a18f5c993853b3f02045456657b8000180f3230313530" + + "3630323039303230375aa011180f32303135303630333130303033305a3065303d300906" + + "052b0e03021a05000414f7452a008060152772e4a135e76e9e52fde0f1580414edd8f2ee" + + "977252853a330b297a18f5c993853b3f02045456657c8000180f32303135303630323039" + + "303230375aa011180f32303135303630333130303033305a3065303d300906052b0e0302" + + "1a05000414f7452a008060152772e4a135e76e9e52fde0f1580414edd8f2ee977252853a" + + "330b297a18f5c993853b3f02045456657d8000180f32303135303630323039303230375a" + + "a011180f32303135303630333130303033305a300d06092a864886f70d01010505000382" + + "01010016b73b92859979f27d15eb018cf069eed39c3d280213565f3026de11ba15bdb94d" + + "764cf2d0fdd204ef926c588d7b183483c8a2b1995079c7ed04dcefcc650c1965be4b6832" + + "a8839e832f7f60f638425eccdf9bc3a81fbe700fda426ddf4f06c29bee431bbbe81effda" + + "a60b7da5b378f199af2f3c8380be7ba6c21c8e27124f8a4d8989926aea19055700848d33" + + "799e833512945fd75364edbd2dd18b783c1e96e332266b17979a0b88c35b43f47c87c493" + + "19155056ad8dbbae5ff2afad3c0e1c69ed111206ffda49875e8e4efc0926264823bc4423" + + "c8a002f34288c4bc22516f98f54fc609943721f590ddd8d24f989457526b599b0eb75cb5" + + "a80da1ad93a621a08205733082056f3082056b30820453a0030201020204545638c4300d" + + "06092a864886f70d01010b0500308182310b300906035504061302555331183016060355" + + "040a130f552e532e20476f7665726e6d656e7431233021060355040b131a446570617274" + + "6d656e74206f662074686520547265617375727931223020060355040b13194365727469" + + "6669636174696f6e20417574686f7269746965733110300e060355040b13074f43494f20" + + "4341301e170d3135303332303131353531335a170d3135303633303034303030305a3081" + + "98310b300906035504061302555331183016060355040a130f552e532e20476f7665726e" + + "6d656e7431233021060355040b131a4465706172746d656e74206f662074686520547265" + + "617375727931223020060355040b131943657274696669636174696f6e20417574686f72" + + "69746965733110300e060355040b13074f43494f204341311430120603550403130b4f43" + + "5350205369676e657230820122300d06092a864886f70d01010105000382010f00308201" + + "0a0282010100c1b6fe1ba1ad50bb98c855811acbd67fe68057f48b8e08d3800e7f2c51b7" + + "9e20551934971fd92b9c9e6c49453097927cba83a94c0b2fea7124ba5ac442b38e37dba6" + + "7303d4962dd7d92b22a04b0e0e182e9ea67620b1c6ce09ee607c19e0e6e3adae81151db1" + + "2bb7f706149349a292e21c1eb28565b6839df055e1a838a772ff34b5a1452618e2c26042" + + "705d53f0af4b57aae6163f58216af12f3887813fe44b0321827b3a0c52b0e47d0aab94a2" + + "f768ab0ba3901d22f8bb263823090b0e37a7f8856db4b0d165c42f3aa7e94f5f6ce1855e" + + "98dc57adea0ae98ad39f67ecdec00b88685566e9e8d69f6cefb6ddced53015d0d3b862bc" + + "be21f3d72251eefcec730203010001a38201cf308201cb300e0603551d0f0101ff040403" + + "020780306b0603551d2004643062300c060a60864801650302010502300c060a60864801" + + "650302010503300c060a60864801650302010504300c060a60864801650302010507300c" + + "060a60864801650302010508300c060a6086480165030201030d300c060a608648016503" + + "020103113081e506082b060105050701010481d83081d5303006082b0601050507300286" + + "24687474703a2f2f706b692e74726561732e676f762f746f63615f65655f6169612e7037" + + "633081a006082b060105050730028681936c6461703a2f2f6c6461702e74726561732e67" + + "6f762f6f753d4f43494f25323043412c6f753d43657274696669636174696f6e25323041" + + "7574686f7269746965732c6f753d4465706172746d656e742532306f6625323074686525" + + "323054726561737572792c6f3d552e532e253230476f7665726e6d656e742c633d55533f" + + "634143657274696669636174653b62696e61727930130603551d25040c300a06082b0601" + + "0505070309300f06092b060105050730010504020500301f0603551d23041830168014a2" + + "13a8e5c607546c243d4eb72b27a2a7711ab5af301d0603551d0e0416041451f98046818a" + + "e46d953ac90c210ccfaa1a06980c300d06092a864886f70d01010b050003820101003a37" + + "0b301d14ffdeb370883639bec5ae6f572dcbddadd672af16ee2a8303316b14e1fbdca8c2" + + "8f4bad9c7b1410250e149c14e9830ca6f17370a8d13151205d956e28c141cc0500379596" + + "c5b9239fcfa3d2de8f1d4f1a2b1bf2d1851bed1c86012ee8135bdc395cd4496ce69fadd0" + + "3b682b90350ca7b4f458190b7a0ab5c33a04cf1347a77d541877a380a4c94988c5658908" + + "44fdc22637a72b9fa410333e2caf969477f9fe07f50e3681c204fb3bf073b9da01cd8d91" + + "8044c40b1159955af12a3263ab1d34119d7f59bfa6cae88ed058addc4e08250263f8f836" + + "2f5bdffd45636fea7474c60a55c535954477b2f286e1b2535f0dd12c162f1b353c370e08" + + "be67" + +const ocspMultiResponseCertHex = "308207943082067ca003020102020454566573300d06092a864886f70d01010b05003081" + + "82310b300906035504061302555331183016060355040a130f552e532e20476f7665726e" + + "6d656e7431233021060355040b131a4465706172746d656e74206f662074686520547265" + + "617375727931223020060355040b131943657274696669636174696f6e20417574686f72" + + "69746965733110300e060355040b13074f43494f204341301e170d313530343130313535" + + "3733385a170d3138303431303136323733385a30819d310b300906035504061302555331" + + "183016060355040a130f552e532e20476f7665726e6d656e7431233021060355040b131a" + + "4465706172746d656e74206f662074686520547265617375727931253023060355040b13" + + "1c427572656175206f66207468652046697363616c20536572766963653110300e060355" + + "040b130744657669636573311630140603550403130d706b692e74726561732e676f7630" + + "820122300d06092a864886f70d01010105000382010f003082010a0282010100c7273623" + + "8c49c48bf501515a2490ef6e5ae0c06e0ad2aa9a6bb77f3d0370d846b2571581ebf38fd3" + + "1948daad3dec7a4da095f1dcbe9654e65bcf7acdfd4ee802421dad9b90536c721d2bca58" + + "8413e6bfd739a72470560bb7d64f9a09284f90ff8af1d5a3c5c84d0f95a00f9c6d988dd0" + + "d87f1d0d3344580901c955139f54d09de0acdbd3322b758cb0c58881bf04913243401f44" + + "013fd9f6d8348044cc8bb0a71978ad93366b2a4687a5274b2ee07d0fb40225453eb244ed" + + "b20152251ac77c59455260ff07eeceb3cb3c60fb8121cf92afd3daa2a4650e1942ccb555" + + "de10b3d481feb299838ef05d0fd1810b146753472ae80da65dd34da25ca1f89971f10039" + + "0203010001a38203f3308203ef300e0603551d0f0101ff0404030205a030170603551d20" + + "0410300e300c060a60864801650302010503301106096086480186f84201010404030206" + + "4030130603551d25040c300a06082b060105050703013082010806082b06010505070101" + + "0481fb3081f8303006082b060105050730028624687474703a2f2f706b692e7472656173" + + "2e676f762f746f63615f65655f6169612e7037633081a006082b06010505073002868193" + + "6c6461703a2f2f6c6461702e74726561732e676f762f6f753d4f43494f25323043412c6f" + + "753d43657274696669636174696f6e253230417574686f7269746965732c6f753d446570" + + "6172746d656e742532306f6625323074686525323054726561737572792c6f3d552e532e" + + "253230476f7665726e6d656e742c633d55533f634143657274696669636174653b62696e" + + "617279302106082b060105050730018615687474703a2f2f6f6373702e74726561732e67" + + "6f76307b0603551d1104743072811c6373612d7465616d4066697363616c2e7472656173" + + "7572792e676f768210706b692e74726561737572792e676f768210706b692e64696d632e" + + "6468732e676f76820d706b692e74726561732e676f76811f6563622d686f7374696e6740" + + "66697363616c2e74726561737572792e676f76308201890603551d1f048201803082017c" + + "3027a025a0238621687474703a2f2f706b692e74726561732e676f762f4f43494f5f4341" + + "332e63726c3082014fa082014ba0820147a48197308194310b3009060355040613025553" + + "31183016060355040a130f552e532e20476f7665726e6d656e7431233021060355040b13" + + "1a4465706172746d656e74206f662074686520547265617375727931223020060355040b" + + "131943657274696669636174696f6e20417574686f7269746965733110300e060355040b" + + "13074f43494f2043413110300e0603550403130743524c313430398681aa6c6461703a2f" + + "2f6c6461702e74726561732e676f762f636e3d43524c313430392c6f753d4f43494f2532" + + "3043412c6f753d43657274696669636174696f6e253230417574686f7269746965732c6f" + + "753d4465706172746d656e742532306f6625323074686525323054726561737572792c6f" + + "3d552e532e253230476f7665726e6d656e742c633d55533f636572746966696361746552" + + "65766f636174696f6e4c6973743b62696e617279302b0603551d1004243022800f323031" + + "35303431303135353733385a810f32303138303431303136323733385a301f0603551d23" + + "041830168014a213a8e5c607546c243d4eb72b27a2a7711ab5af301d0603551d0e041604" + + "14b0869c12c293914cd460e33ed43e6c5a26e0d68f301906092a864886f67d074100040c" + + "300a1b0456382e31030203a8300d06092a864886f70d01010b050003820101004968d182" + + "8f9efdc147e747bb5dda15536a42a079b32d3d7f87e619b483aeee70b7e26bda393c6028" + + "7c733ecb468fe8b8b11bf809ff76add6b90eb25ad8d3a1052e43ee281e48a3a1ebe7efb5" + + "9e2c4a48765dedeb23f5346242145786cc988c762d230d28dd33bf4c2405d80cbb2cb1d6" + + "4c8f10ba130d50cb174f6ffb9cfc12808297a2cefba385f4fad170f39b51ebd87c12abf9" + + "3c51fc000af90d8aaba78f48923908804a5eb35f617ccf71d201e3708a559e6d16f9f13e" + + "074361eb9007e28d86bb4e0bfa13aad0e9ddd9124e84519de60e2fc6040b18d9fd602b02" + + "684b4c071c3019fc842197d00c120c41654bcbfbc4a096a1c637b79112b81ce1fa3899f9" + +const ocspRequestHex = "3051304f304d304b3049300906052b0e03021a05000414c0fe0278fc99188891b3f212e9" + + "c7e1b21ab7bfc004140dfc1df0a9e0f01ce7f2b213177e6f8d157cd4f60210017f77deb3" + + "bcbb235d44ccc7dba62e72" + +const leafCertHex = "308203c830820331a0030201020210017f77deb3bcbb235d44ccc7dba62e72300d06092a" + + "864886f70d01010505003081ba311f301d060355040a1316566572695369676e20547275" + + "7374204e6574776f726b31173015060355040b130e566572695369676e2c20496e632e31" + + "333031060355040b132a566572695369676e20496e7465726e6174696f6e616c20536572" + + "766572204341202d20436c617373203331493047060355040b13407777772e7665726973" + + "69676e2e636f6d2f43505320496e636f72702e6279205265662e204c494142494c495459" + + "204c54442e286329393720566572695369676e301e170d3132303632313030303030305a" + + "170d3133313233313233353935395a3068310b3009060355040613025553311330110603" + + "550408130a43616c69666f726e6961311230100603550407130950616c6f20416c746f31" + + "173015060355040a130e46616365626f6f6b2c20496e632e311730150603550403140e2a" + + "2e66616365626f6f6b2e636f6d30819f300d06092a864886f70d010101050003818d0030" + + "818902818100ae94b171e2deccc1693e051063240102e0689ae83c39b6b3e74b97d48d7b" + + "23689100b0b496ee62f0e6d356bcf4aa0f50643402f5d1766aa972835a7564723f39bbef" + + "5290ded9bcdbf9d3d55dfad23aa03dc604c54d29cf1d4b3bdbd1a809cfae47b44c7eae17" + + "c5109bee24a9cf4a8d911bb0fd0415ae4c3f430aa12a557e2ae10203010001a382011e30" + + "82011a30090603551d130402300030440603551d20043d303b3039060b6086480186f845" + + "01071703302a302806082b06010505070201161c68747470733a2f2f7777772e76657269" + + "7369676e2e636f6d2f727061303c0603551d1f043530333031a02fa02d862b687474703a" + + "2f2f535652496e746c2d63726c2e766572697369676e2e636f6d2f535652496e746c2e63" + + "726c301d0603551d250416301406082b0601050507030106082b06010505070302300b06" + + "03551d0f0404030205a0303406082b0601050507010104283026302406082b0601050507" + + "30018618687474703a2f2f6f6373702e766572697369676e2e636f6d30270603551d1104" + + "20301e820e2a2e66616365626f6f6b2e636f6d820c66616365626f6f6b2e636f6d300d06" + + "092a864886f70d0101050500038181005b6c2b75f8ed30aa51aad36aba595e555141951f" + + "81a53b447910ac1f76ff78fc2781616b58f3122afc1c87010425e9ed43df1a7ba6498060" + + "67e2688af03db58c7df4ee03309a6afc247ccb134dc33e54c6bc1d5133a532a73273b1d7" + + "9cadc08e7e1a83116d34523340b0305427a21742827c98916698ee7eaf8c3bdd71700817" + +const issuerCertHex = "30820383308202eca003020102021046fcebbab4d02f0f926098233f93078f300d06092a" + + "864886f70d0101050500305f310b300906035504061302555331173015060355040a130e" + + "566572695369676e2c20496e632e31373035060355040b132e436c617373203320507562" + + "6c6963205072696d6172792043657274696669636174696f6e20417574686f7269747930" + + "1e170d3937303431373030303030305a170d3136313032343233353935395a3081ba311f" + + "301d060355040a1316566572695369676e205472757374204e6574776f726b3117301506" + + "0355040b130e566572695369676e2c20496e632e31333031060355040b132a5665726953" + + "69676e20496e7465726e6174696f6e616c20536572766572204341202d20436c61737320" + + "3331493047060355040b13407777772e766572697369676e2e636f6d2f43505320496e63" + + "6f72702e6279205265662e204c494142494c495459204c54442e28632939372056657269" + + "5369676e30819f300d06092a864886f70d010101050003818d0030818902818100d88280" + + "e8d619027d1f85183925a2652be1bfd405d3bce6363baaf04c6c5bb6e7aa3c734555b2f1" + + "bdea9742ed9a340a15d4a95cf54025ddd907c132b2756cc4cabba3fe56277143aa63f530" + + "3e9328e5faf1093bf3b74d4e39f75c495ab8c11dd3b28afe70309542cbfe2b518b5a3c3a" + + "f9224f90b202a7539c4f34e7ab04b27b6f0203010001a381e33081e0300f0603551d1304" + + "0830060101ff02010030440603551d20043d303b3039060b6086480186f8450107010130" + + "2a302806082b06010505070201161c68747470733a2f2f7777772e766572697369676e2e" + + "636f6d2f43505330340603551d25042d302b06082b0601050507030106082b0601050507" + + "030206096086480186f8420401060a6086480186f845010801300b0603551d0f04040302" + + "0106301106096086480186f842010104040302010630310603551d1f042a30283026a024" + + "a0228620687474703a2f2f63726c2e766572697369676e2e636f6d2f706361332e63726c" + + "300d06092a864886f70d010105050003818100408e4997968a73dd8e4def3e61b7caa062" + + "adf40e0abb753de26ed82cc7bff4b98c369bcaa2d09c724639f6a682036511c4bcbf2da6" + + "f5d93b0ab598fab378b91ef22b4c62d5fdb27a1ddf33fd73f9a5d82d8c2aead1fcb028b6" + + "e94948134b838a1b487b24f738de6f4154b8ab576b06dfc7a2d4a9f6f136628088f28b75" + + "d68071" + +// Key and certificate for the OCSP responder were not taken from the Thawte +// responder, since CreateResponse requires that we have the private key. +// Instead, they were generated randomly. +const responderPrivateKeyHex = "308204a40201000282010100e8155f2d3e6f2e8d14c62a788bd462f9f844e7a6977c83ef" + + "1099f0f6616ec5265b56f356e62c5400f0b06a2e7945a82752c636df32a895152d6074df" + + "1701dc6ccfbcbec75a70bd2b55ae2be7e6cad3b5fd4cd5b7790ab401a436d3f5f346074f" + + "fde8a99d5b723350f0a112076614b12ef79c78991b119453445acf2416ab0046b540db14" + + "c9fc0f27b8989ad0f63aa4b8aefc91aa8a72160c36307c60fec78a93d3fddf4259902aa7" + + "7e7332971c7d285b6a04f648993c6922a3e9da9adf5f81508c3228791843e5d49f24db2f" + + "1290bafd97e655b1049a199f652cd603c4fafa330c390b0da78fbbc67e8fa021cbd74eb9" + + "6222b12ace31a77dcf920334dc94581b02030100010282010100bcf0b93d7238bda329a8" + + "72e7149f61bcb37c154330ccb3f42a85c9002c2e2bdea039d77d8581cd19bed94078794e" + + "56293d601547fc4bf6a2f9002fe5772b92b21b254403b403585e3130cc99ccf08f0ef81a" + + "575b38f597ba4660448b54f44bfbb97072b5a2bf043bfeca828cf7741d13698e3f38162b" + + "679faa646b82abd9a72c5c7d722c5fc577a76d2c2daac588accad18516d1bbad10b0dfa2" + + "05cfe246b59e28608a43942e1b71b0c80498075121de5b900d727c31c42c78cf1db5c0aa" + + "5b491e10ea4ed5c0962aaf2ae025dd81fa4ce490d9d6b4a4465411d8e542fc88617e5695" + + "1aa4fc8ea166f2b4d0eb89ef17f2b206bd5f1014bf8fe0e71fe62f2cccf102818100f2dc" + + "ddf878d553286daad68bac4070a82ffec3dc4666a2750f47879eec913f91836f1d976b60" + + "daf9356e078446dafab5bd2e489e5d64f8572ba24a4ba4f3729b5e106c4dd831cc2497a7" + + "e6c7507df05cb64aeb1bbc81c1e340d58b5964cf39cff84ea30c29ec5d3f005ee1362698" + + "07395037955955655292c3e85f6187fa1f9502818100f4a33c102630840705f8c778a47b" + + "87e8da31e68809af981ac5e5999cf1551685d761cdf0d6520361b99aebd5777a940fa64d" + + "327c09fa63746fbb3247ec73a86edf115f1fe5c83598db803881ade71c33c6e956118345" + + "497b98b5e07bb5be75971465ec78f2f9467e1b74956ca9d4c7c3e314e742a72d8b33889c" + + "6c093a466cef0281801d3df0d02124766dd0be98349b19eb36a508c4e679e793ba0a8bef" + + "4d786888c1e9947078b1ea28938716677b4ad8c5052af12eb73ac194915264a913709a0b" + + "7b9f98d4a18edd781a13d49899f91c20dbd8eb2e61d991ba19b5cdc08893f5cb9d39e5a6" + + "0629ea16d426244673b1b3ee72bd30e41fac8395acac40077403de5efd028180050731dd" + + "d71b1a2b96c8d538ba90bb6b62c8b1c74c03aae9a9f59d21a7a82b0d572ef06fa9c807bf" + + "c373d6b30d809c7871df96510c577421d9860c7383fda0919ece19996b3ca13562159193" + + "c0c246471e287f975e8e57034e5136aaf44254e2650def3d51292474c515b1588969112e" + + "0a85cc77073e9d64d2c2fc497844284b02818100d71d63eabf416cf677401ebf965f8314" + + "120b568a57dd3bd9116c629c40dc0c6948bab3a13cc544c31c7da40e76132ef5dd3f7534" + + "45a635930c74326ae3df0edd1bfb1523e3aa259873ac7cf1ac31151ec8f37b528c275622" + + "48f99b8bed59fd4da2576aa6ee20d93a684900bf907e80c66d6e2261ae15e55284b4ed9d" + + "6bdaa059" + +const responderCertHex = "308202e2308201caa003020102020101300d06092a864886f70d01010b05003019311730" + + "150603550403130e4f43535020526573706f6e646572301e170d31353031333031353530" + + "33335a170d3136303133303135353033335a3019311730150603550403130e4f43535020" + + "526573706f6e64657230820122300d06092a864886f70d01010105000382010f00308201" + + "0a0282010100e8155f2d3e6f2e8d14c62a788bd462f9f844e7a6977c83ef1099f0f6616e" + + "c5265b56f356e62c5400f0b06a2e7945a82752c636df32a895152d6074df1701dc6ccfbc" + + "bec75a70bd2b55ae2be7e6cad3b5fd4cd5b7790ab401a436d3f5f346074ffde8a99d5b72" + + "3350f0a112076614b12ef79c78991b119453445acf2416ab0046b540db14c9fc0f27b898" + + "9ad0f63aa4b8aefc91aa8a72160c36307c60fec78a93d3fddf4259902aa77e7332971c7d" + + "285b6a04f648993c6922a3e9da9adf5f81508c3228791843e5d49f24db2f1290bafd97e6" + + "55b1049a199f652cd603c4fafa330c390b0da78fbbc67e8fa021cbd74eb96222b12ace31" + + "a77dcf920334dc94581b0203010001a3353033300e0603551d0f0101ff04040302078030" + + "130603551d25040c300a06082b06010505070309300c0603551d130101ff04023000300d" + + "06092a864886f70d01010b05000382010100718012761b5063e18f0dc44644d8e6ab8612" + + "31c15fd5357805425d82aec1de85bf6d3e30fce205e3e3b8b795bbe52e40a439286d2288" + + "9064f4aeeb150359b9425f1da51b3a5c939018555d13ac42c565a0603786a919328f3267" + + "09dce52c22ad958ecb7873b9771d1148b1c4be2efe80ba868919fc9f68b6090c2f33c156" + + "d67156e42766a50b5d51e79637b7e58af74c2a951b1e642fa7741fec982cc937de37eff5" + + "9e2005d5939bfc031589ca143e6e8ab83f40ee08cc20a6b4a95a318352c28d18528dcaf9" + + "66705de17afa19d6e8ae91ddf33179d16ebb6ac2c69cae8373d408ebf8c55308be6c04d9" + + "3a25439a94299a65a709756c7a3e568be049d5c38839" + +const errorResponseHex = "30030a0101" diff --git a/vendor/golang.org/x/crypto/openpgp/armor/armor.go b/vendor/golang.org/x/crypto/openpgp/armor/armor.go new file mode 100644 index 0000000000000000000000000000000000000000..592d18643617b28b90d0ab93bbaf6c2e09e722dc --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/armor/armor.go @@ -0,0 +1,219 @@ +// 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 armor implements OpenPGP ASCII Armor, see RFC 4880. OpenPGP Armor is +// very similar to PEM except that it has an additional CRC checksum. +package armor // import "golang.org/x/crypto/openpgp/armor" + +import ( + "bufio" + "bytes" + "encoding/base64" + "golang.org/x/crypto/openpgp/errors" + "io" +) + +// A Block represents an OpenPGP armored structure. +// +// The encoded form is: +// -----BEGIN Type----- +// Headers +// +// base64-encoded Bytes +// '=' base64 encoded checksum +// -----END Type----- +// where Headers is a possibly empty sequence of Key: Value lines. +// +// Since the armored data can be very large, this package presents a streaming +// interface. +type Block struct { + Type string // The type, taken from the preamble (i.e. "PGP SIGNATURE"). + Header map[string]string // Optional headers. + Body io.Reader // A Reader from which the contents can be read + lReader lineReader + oReader openpgpReader +} + +var ArmorCorrupt error = errors.StructuralError("armor invalid") + +const crc24Init = 0xb704ce +const crc24Poly = 0x1864cfb +const crc24Mask = 0xffffff + +// crc24 calculates the OpenPGP checksum as specified in RFC 4880, section 6.1 +func crc24(crc uint32, d []byte) uint32 { + for _, b := range d { + crc ^= uint32(b) << 16 + for i := 0; i < 8; i++ { + crc <<= 1 + if crc&0x1000000 != 0 { + crc ^= crc24Poly + } + } + } + return crc +} + +var armorStart = []byte("-----BEGIN ") +var armorEnd = []byte("-----END ") +var armorEndOfLine = []byte("-----") + +// lineReader wraps a line based reader. It watches for the end of an armor +// block and records the expected CRC value. +type lineReader struct { + in *bufio.Reader + buf []byte + eof bool + crc uint32 +} + +func (l *lineReader) Read(p []byte) (n int, err error) { + if l.eof { + return 0, io.EOF + } + + if len(l.buf) > 0 { + n = copy(p, l.buf) + l.buf = l.buf[n:] + return + } + + line, isPrefix, err := l.in.ReadLine() + if err != nil { + return + } + if isPrefix { + return 0, ArmorCorrupt + } + + if len(line) == 5 && line[0] == '=' { + // This is the checksum line + var expectedBytes [3]byte + var m int + m, err = base64.StdEncoding.Decode(expectedBytes[0:], line[1:]) + if m != 3 || err != nil { + return + } + l.crc = uint32(expectedBytes[0])<<16 | + uint32(expectedBytes[1])<<8 | + uint32(expectedBytes[2]) + + line, _, err = l.in.ReadLine() + if err != nil && err != io.EOF { + return + } + if !bytes.HasPrefix(line, armorEnd) { + return 0, ArmorCorrupt + } + + l.eof = true + return 0, io.EOF + } + + if len(line) > 96 { + return 0, ArmorCorrupt + } + + n = copy(p, line) + bytesToSave := len(line) - n + if bytesToSave > 0 { + if cap(l.buf) < bytesToSave { + l.buf = make([]byte, 0, bytesToSave) + } + l.buf = l.buf[0:bytesToSave] + copy(l.buf, line[n:]) + } + + return +} + +// openpgpReader passes Read calls to the underlying base64 decoder, but keeps +// a running CRC of the resulting data and checks the CRC against the value +// found by the lineReader at EOF. +type openpgpReader struct { + lReader *lineReader + b64Reader io.Reader + currentCRC uint32 +} + +func (r *openpgpReader) Read(p []byte) (n int, err error) { + n, err = r.b64Reader.Read(p) + r.currentCRC = crc24(r.currentCRC, p[:n]) + + if err == io.EOF { + if r.lReader.crc != uint32(r.currentCRC&crc24Mask) { + return 0, ArmorCorrupt + } + } + + return +} + +// Decode reads a PGP armored block from the given Reader. It will ignore +// leading garbage. If it doesn't find a block, it will return nil, io.EOF. The +// given Reader is not usable after calling this function: an arbitrary amount +// of data may have been read past the end of the block. +func Decode(in io.Reader) (p *Block, err error) { + r := bufio.NewReaderSize(in, 100) + var line []byte + ignoreNext := false + +TryNextBlock: + p = nil + + // Skip leading garbage + for { + ignoreThis := ignoreNext + line, ignoreNext, err = r.ReadLine() + if err != nil { + return + } + if ignoreNext || ignoreThis { + continue + } + line = bytes.TrimSpace(line) + if len(line) > len(armorStart)+len(armorEndOfLine) && bytes.HasPrefix(line, armorStart) { + break + } + } + + p = new(Block) + p.Type = string(line[len(armorStart) : len(line)-len(armorEndOfLine)]) + p.Header = make(map[string]string) + nextIsContinuation := false + var lastKey string + + // Read headers + for { + isContinuation := nextIsContinuation + line, nextIsContinuation, err = r.ReadLine() + if err != nil { + p = nil + return + } + if isContinuation { + p.Header[lastKey] += string(line) + continue + } + line = bytes.TrimSpace(line) + if len(line) == 0 { + break + } + + i := bytes.Index(line, []byte(": ")) + if i == -1 { + goto TryNextBlock + } + lastKey = string(line[:i]) + p.Header[lastKey] = string(line[i+2:]) + } + + p.lReader.in = r + p.oReader.currentCRC = crc24Init + p.oReader.lReader = &p.lReader + p.oReader.b64Reader = base64.NewDecoder(base64.StdEncoding, &p.lReader) + p.Body = &p.oReader + + return +} diff --git a/vendor/golang.org/x/crypto/openpgp/armor/armor_test.go b/vendor/golang.org/x/crypto/openpgp/armor/armor_test.go new file mode 100644 index 0000000000000000000000000000000000000000..9334e94e96cdd01c35180f88b2d81a667bb35ab5 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/armor/armor_test.go @@ -0,0 +1,95 @@ +// 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 armor + +import ( + "bytes" + "hash/adler32" + "io/ioutil" + "testing" +) + +func TestDecodeEncode(t *testing.T) { + buf := bytes.NewBuffer([]byte(armorExample1)) + result, err := Decode(buf) + if err != nil { + t.Error(err) + } + expectedType := "PGP SIGNATURE" + if result.Type != expectedType { + t.Errorf("result.Type: got:%s want:%s", result.Type, expectedType) + } + if len(result.Header) != 1 { + t.Errorf("len(result.Header): got:%d want:1", len(result.Header)) + } + v, ok := result.Header["Version"] + if !ok || v != "GnuPG v1.4.10 (GNU/Linux)" { + t.Errorf("result.Header: got:%#v", result.Header) + } + + contents, err := ioutil.ReadAll(result.Body) + if err != nil { + t.Error(err) + } + + if adler32.Checksum(contents) != 0x27b144be { + t.Errorf("contents: got: %x", contents) + } + + buf = bytes.NewBuffer(nil) + w, err := Encode(buf, result.Type, result.Header) + if err != nil { + t.Error(err) + } + _, err = w.Write(contents) + if err != nil { + t.Error(err) + } + w.Close() + + if !bytes.Equal(buf.Bytes(), []byte(armorExample1)) { + t.Errorf("got: %s\nwant: %s", string(buf.Bytes()), armorExample1) + } +} + +func TestLongHeader(t *testing.T) { + buf := bytes.NewBuffer([]byte(armorLongLine)) + result, err := Decode(buf) + if err != nil { + t.Error(err) + return + } + value, ok := result.Header["Version"] + if !ok { + t.Errorf("missing Version header") + } + if value != longValueExpected { + t.Errorf("got: %s want: %s", value, longValueExpected) + } +} + +const armorExample1 = `-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.4.10 (GNU/Linux) + +iJwEAAECAAYFAk1Fv/0ACgkQo01+GMIMMbsYTwQAiAw+QAaNfY6WBdplZ/uMAccm +4g+81QPmTSGHnetSb6WBiY13kVzK4HQiZH8JSkmmroMLuGeJwsRTEL4wbjRyUKEt +p1xwUZDECs234F1xiG5enc5SGlRtP7foLBz9lOsjx+LEcA4sTl5/2eZR9zyFZqWW +TxRjs+fJCIFuo71xb1g= +=/teI +-----END PGP SIGNATURE-----` + +const armorLongLine = `-----BEGIN PGP SIGNATURE----- +Version: 0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz + +iQEcBAABAgAGBQJMtFESAAoJEKsQXJGvOPsVj40H/1WW6jaMXv4BW+1ueDSMDwM8 +kx1fLOXbVM5/Kn5LStZNt1jWWnpxdz7eq3uiqeCQjmqUoRde3YbB2EMnnwRbAhpp +cacnAvy9ZQ78OTxUdNW1mhX5bS6q1MTEJnl+DcyigD70HG/yNNQD7sOPMdYQw0TA +byQBwmLwmTsuZsrYqB68QyLHI+DUugn+kX6Hd2WDB62DKa2suoIUIHQQCd/ofwB3 +WfCYInXQKKOSxu2YOg2Eb4kLNhSMc1i9uKUWAH+sdgJh7NBgdoE4MaNtBFkHXRvv +okWuf3+xA9ksp1npSY/mDvgHijmjvtpRDe6iUeqfCn8N9u9CBg8geANgaG8+QA4= +=wfQG +-----END PGP SIGNATURE-----` + +const longValueExpected = "0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz" diff --git a/vendor/golang.org/x/crypto/openpgp/armor/encode.go b/vendor/golang.org/x/crypto/openpgp/armor/encode.go new file mode 100644 index 0000000000000000000000000000000000000000..6f07582c37cea69c0f972ccd1f3d53f9a5fe1d02 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/armor/encode.go @@ -0,0 +1,160 @@ +// 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 armor + +import ( + "encoding/base64" + "io" +) + +var armorHeaderSep = []byte(": ") +var blockEnd = []byte("\n=") +var newline = []byte("\n") +var armorEndOfLineOut = []byte("-----\n") + +// writeSlices writes its arguments to the given Writer. +func writeSlices(out io.Writer, slices ...[]byte) (err error) { + for _, s := range slices { + _, err = out.Write(s) + if err != nil { + return err + } + } + return +} + +// lineBreaker breaks data across several lines, all of the same byte length +// (except possibly the last). Lines are broken with a single '\n'. +type lineBreaker struct { + lineLength int + line []byte + used int + out io.Writer + haveWritten bool +} + +func newLineBreaker(out io.Writer, lineLength int) *lineBreaker { + return &lineBreaker{ + lineLength: lineLength, + line: make([]byte, lineLength), + used: 0, + out: out, + } +} + +func (l *lineBreaker) Write(b []byte) (n int, err error) { + n = len(b) + + if n == 0 { + return + } + + if l.used == 0 && l.haveWritten { + _, err = l.out.Write([]byte{'\n'}) + if err != nil { + return + } + } + + if l.used+len(b) < l.lineLength { + l.used += copy(l.line[l.used:], b) + return + } + + l.haveWritten = true + _, err = l.out.Write(l.line[0:l.used]) + if err != nil { + return + } + excess := l.lineLength - l.used + l.used = 0 + + _, err = l.out.Write(b[0:excess]) + if err != nil { + return + } + + _, err = l.Write(b[excess:]) + return +} + +func (l *lineBreaker) Close() (err error) { + if l.used > 0 { + _, err = l.out.Write(l.line[0:l.used]) + if err != nil { + return + } + } + + return +} + +// encoding keeps track of a running CRC24 over the data which has been written +// to it and outputs a OpenPGP checksum when closed, followed by an armor +// trailer. +// +// It's built into a stack of io.Writers: +// encoding -> base64 encoder -> lineBreaker -> out +type encoding struct { + out io.Writer + breaker *lineBreaker + b64 io.WriteCloser + crc uint32 + blockType []byte +} + +func (e *encoding) Write(data []byte) (n int, err error) { + e.crc = crc24(e.crc, data) + return e.b64.Write(data) +} + +func (e *encoding) Close() (err error) { + err = e.b64.Close() + if err != nil { + return + } + e.breaker.Close() + + var checksumBytes [3]byte + checksumBytes[0] = byte(e.crc >> 16) + checksumBytes[1] = byte(e.crc >> 8) + checksumBytes[2] = byte(e.crc) + + var b64ChecksumBytes [4]byte + base64.StdEncoding.Encode(b64ChecksumBytes[:], checksumBytes[:]) + + return writeSlices(e.out, blockEnd, b64ChecksumBytes[:], newline, armorEnd, e.blockType, armorEndOfLine) +} + +// Encode returns a WriteCloser which will encode the data written to it in +// OpenPGP armor. +func Encode(out io.Writer, blockType string, headers map[string]string) (w io.WriteCloser, err error) { + bType := []byte(blockType) + err = writeSlices(out, armorStart, bType, armorEndOfLineOut) + if err != nil { + return + } + + for k, v := range headers { + err = writeSlices(out, []byte(k), armorHeaderSep, []byte(v), newline) + if err != nil { + return + } + } + + _, err = out.Write(newline) + if err != nil { + return + } + + e := &encoding{ + out: out, + breaker: newLineBreaker(out, 64), + crc: crc24Init, + blockType: bType, + } + e.b64 = base64.NewEncoder(base64.StdEncoding, e.breaker) + return e, nil +} diff --git a/vendor/golang.org/x/crypto/openpgp/canonical_text.go b/vendor/golang.org/x/crypto/openpgp/canonical_text.go new file mode 100644 index 0000000000000000000000000000000000000000..e601e389f1299cd0f02e3a11f0f5e42ca8bb6e22 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/canonical_text.go @@ -0,0 +1,59 @@ +// 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 openpgp + +import "hash" + +// NewCanonicalTextHash reformats text written to it into the canonical +// form and then applies the hash h. See RFC 4880, section 5.2.1. +func NewCanonicalTextHash(h hash.Hash) hash.Hash { + return &canonicalTextHash{h, 0} +} + +type canonicalTextHash struct { + h hash.Hash + s int +} + +var newline = []byte{'\r', '\n'} + +func (cth *canonicalTextHash) Write(buf []byte) (int, error) { + start := 0 + + for i, c := range buf { + switch cth.s { + case 0: + if c == '\r' { + cth.s = 1 + } else if c == '\n' { + cth.h.Write(buf[start:i]) + cth.h.Write(newline) + start = i + 1 + } + case 1: + cth.s = 0 + } + } + + cth.h.Write(buf[start:]) + return len(buf), nil +} + +func (cth *canonicalTextHash) Sum(in []byte) []byte { + return cth.h.Sum(in) +} + +func (cth *canonicalTextHash) Reset() { + cth.h.Reset() + cth.s = 0 +} + +func (cth *canonicalTextHash) Size() int { + return cth.h.Size() +} + +func (cth *canonicalTextHash) BlockSize() int { + return cth.h.BlockSize() +} diff --git a/vendor/golang.org/x/crypto/openpgp/canonical_text_test.go b/vendor/golang.org/x/crypto/openpgp/canonical_text_test.go new file mode 100644 index 0000000000000000000000000000000000000000..8f3ba2a8814ea9c48b0d34fa6018c5aa5468d283 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/canonical_text_test.go @@ -0,0 +1,52 @@ +// 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 openpgp + +import ( + "bytes" + "testing" +) + +type recordingHash struct { + buf *bytes.Buffer +} + +func (r recordingHash) Write(b []byte) (n int, err error) { + return r.buf.Write(b) +} + +func (r recordingHash) Sum(in []byte) []byte { + return append(in, r.buf.Bytes()...) +} + +func (r recordingHash) Reset() { + panic("shouldn't be called") +} + +func (r recordingHash) Size() int { + panic("shouldn't be called") +} + +func (r recordingHash) BlockSize() int { + panic("shouldn't be called") +} + +func testCanonicalText(t *testing.T, input, expected string) { + r := recordingHash{bytes.NewBuffer(nil)} + c := NewCanonicalTextHash(r) + c.Write([]byte(input)) + result := c.Sum(nil) + if expected != string(result) { + t.Errorf("input: %x got: %x want: %x", input, result, expected) + } +} + +func TestCanonicalText(t *testing.T) { + testCanonicalText(t, "foo\n", "foo\r\n") + testCanonicalText(t, "foo", "foo") + testCanonicalText(t, "foo\r\n", "foo\r\n") + testCanonicalText(t, "foo\r\nbar", "foo\r\nbar") + testCanonicalText(t, "foo\r\nbar\n\n", "foo\r\nbar\r\n\r\n") +} diff --git a/vendor/golang.org/x/crypto/openpgp/clearsign/clearsign.go b/vendor/golang.org/x/crypto/openpgp/clearsign/clearsign.go new file mode 100644 index 0000000000000000000000000000000000000000..def4cabaff2f3730a50f2741091651b4f6d52376 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/clearsign/clearsign.go @@ -0,0 +1,376 @@ +// 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 clearsign generates and processes OpenPGP, clear-signed data. See +// RFC 4880, section 7. +// +// Clearsigned messages are cryptographically signed, but the contents of the +// message are kept in plaintext so that it can be read without special tools. +package clearsign // import "golang.org/x/crypto/openpgp/clearsign" + +import ( + "bufio" + "bytes" + "crypto" + "hash" + "io" + "net/textproto" + "strconv" + + "golang.org/x/crypto/openpgp/armor" + "golang.org/x/crypto/openpgp/errors" + "golang.org/x/crypto/openpgp/packet" +) + +// A Block represents a clearsigned message. A signature on a Block can +// be checked by passing Bytes into openpgp.CheckDetachedSignature. +type Block struct { + Headers textproto.MIMEHeader // Optional message headers + Plaintext []byte // The original message text + Bytes []byte // The signed message + ArmoredSignature *armor.Block // The signature block +} + +// start is the marker which denotes the beginning of a clearsigned message. +var start = []byte("\n-----BEGIN PGP SIGNED MESSAGE-----") + +// dashEscape is prefixed to any lines that begin with a hyphen so that they +// can't be confused with endText. +var dashEscape = []byte("- ") + +// endText is a marker which denotes the end of the message and the start of +// an armored signature. +var endText = []byte("-----BEGIN PGP SIGNATURE-----") + +// end is a marker which denotes the end of the armored signature. +var end = []byte("\n-----END PGP SIGNATURE-----") + +var crlf = []byte("\r\n") +var lf = byte('\n') + +// getLine returns the first \r\n or \n delineated line from the given byte +// array. The line does not include the \r\n or \n. The remainder of the byte +// array (also not including the new line bytes) is also returned and this will +// always be smaller than the original argument. +func getLine(data []byte) (line, rest []byte) { + i := bytes.Index(data, []byte{'\n'}) + var j int + if i < 0 { + i = len(data) + j = i + } else { + j = i + 1 + if i > 0 && data[i-1] == '\r' { + i-- + } + } + return data[0:i], data[j:] +} + +// Decode finds the first clearsigned message in data and returns it, as well +// as the suffix of data which remains after the message. +func Decode(data []byte) (b *Block, rest []byte) { + // start begins with a newline. However, at the very beginning of + // the byte array, we'll accept the start string without it. + rest = data + if bytes.HasPrefix(data, start[1:]) { + rest = rest[len(start)-1:] + } else if i := bytes.Index(data, start); i >= 0 { + rest = rest[i+len(start):] + } else { + return nil, data + } + + // Consume the start line. + _, rest = getLine(rest) + + var line []byte + b = &Block{ + Headers: make(textproto.MIMEHeader), + } + + // Next come a series of header lines. + for { + // This loop terminates because getLine's second result is + // always smaller than its argument. + if len(rest) == 0 { + return nil, data + } + // An empty line marks the end of the headers. + if line, rest = getLine(rest); len(line) == 0 { + break + } + + i := bytes.Index(line, []byte{':'}) + if i == -1 { + return nil, data + } + + key, val := line[0:i], line[i+1:] + key = bytes.TrimSpace(key) + val = bytes.TrimSpace(val) + b.Headers.Add(string(key), string(val)) + } + + firstLine := true + for { + start := rest + + line, rest = getLine(rest) + if len(line) == 0 && len(rest) == 0 { + // No armored data was found, so this isn't a complete message. + return nil, data + } + if bytes.Equal(line, endText) { + // Back up to the start of the line because armor expects to see the + // header line. + rest = start + break + } + + // The final CRLF isn't included in the hash so we don't write it until + // we've seen the next line. + if firstLine { + firstLine = false + } else { + b.Bytes = append(b.Bytes, crlf...) + } + + if bytes.HasPrefix(line, dashEscape) { + line = line[2:] + } + line = bytes.TrimRight(line, " \t") + b.Bytes = append(b.Bytes, line...) + + b.Plaintext = append(b.Plaintext, line...) + b.Plaintext = append(b.Plaintext, lf) + } + + // We want to find the extent of the armored data (including any newlines at + // the end). + i := bytes.Index(rest, end) + if i == -1 { + return nil, data + } + i += len(end) + for i < len(rest) && (rest[i] == '\r' || rest[i] == '\n') { + i++ + } + armored := rest[:i] + rest = rest[i:] + + var err error + b.ArmoredSignature, err = armor.Decode(bytes.NewBuffer(armored)) + if err != nil { + return nil, data + } + + return b, rest +} + +// A dashEscaper is an io.WriteCloser which processes the body of a clear-signed +// message. The clear-signed message is written to buffered and a hash, suitable +// for signing, is maintained in h. +// +// When closed, an armored signature is created and written to complete the +// message. +type dashEscaper struct { + buffered *bufio.Writer + h hash.Hash + hashType crypto.Hash + + atBeginningOfLine bool + isFirstLine bool + + whitespace []byte + byteBuf []byte // a one byte buffer to save allocations + + privateKey *packet.PrivateKey + config *packet.Config +} + +func (d *dashEscaper) Write(data []byte) (n int, err error) { + for _, b := range data { + d.byteBuf[0] = b + + if d.atBeginningOfLine { + // The final CRLF isn't included in the hash so we have to wait + // until this point (the start of the next line) before writing it. + if !d.isFirstLine { + d.h.Write(crlf) + } + d.isFirstLine = false + } + + // Any whitespace at the end of the line has to be removed so we + // buffer it until we find out whether there's more on this line. + if b == ' ' || b == '\t' || b == '\r' { + d.whitespace = append(d.whitespace, b) + d.atBeginningOfLine = false + continue + } + + if d.atBeginningOfLine { + // At the beginning of a line, hyphens have to be escaped. + if b == '-' { + // The signature isn't calculated over the dash-escaped text so + // the escape is only written to buffered. + if _, err = d.buffered.Write(dashEscape); err != nil { + return + } + d.h.Write(d.byteBuf) + d.atBeginningOfLine = false + } else if b == '\n' { + // Nothing to do because we delay writing CRLF to the hash. + } else { + d.h.Write(d.byteBuf) + d.atBeginningOfLine = false + } + if err = d.buffered.WriteByte(b); err != nil { + return + } + } else { + if b == '\n' { + // We got a raw \n. Drop any trailing whitespace and write a + // CRLF. + d.whitespace = d.whitespace[:0] + // We delay writing CRLF to the hash until the start of the + // next line. + if err = d.buffered.WriteByte(b); err != nil { + return + } + d.atBeginningOfLine = true + } else { + // Any buffered whitespace wasn't at the end of the line so + // we need to write it out. + if len(d.whitespace) > 0 { + d.h.Write(d.whitespace) + if _, err = d.buffered.Write(d.whitespace); err != nil { + return + } + d.whitespace = d.whitespace[:0] + } + d.h.Write(d.byteBuf) + if err = d.buffered.WriteByte(b); err != nil { + return + } + } + } + } + + n = len(data) + return +} + +func (d *dashEscaper) Close() (err error) { + if !d.atBeginningOfLine { + if err = d.buffered.WriteByte(lf); err != nil { + return + } + } + sig := new(packet.Signature) + sig.SigType = packet.SigTypeText + sig.PubKeyAlgo = d.privateKey.PubKeyAlgo + sig.Hash = d.hashType + sig.CreationTime = d.config.Now() + sig.IssuerKeyId = &d.privateKey.KeyId + + if err = sig.Sign(d.h, d.privateKey, d.config); err != nil { + return + } + + out, err := armor.Encode(d.buffered, "PGP SIGNATURE", nil) + if err != nil { + return + } + + if err = sig.Serialize(out); err != nil { + return + } + if err = out.Close(); err != nil { + return + } + if err = d.buffered.Flush(); err != nil { + return + } + return +} + +// Encode returns a WriteCloser which will clear-sign a message with privateKey +// and write it to w. If config is nil, sensible defaults are used. +func Encode(w io.Writer, privateKey *packet.PrivateKey, config *packet.Config) (plaintext io.WriteCloser, err error) { + if privateKey.Encrypted { + return nil, errors.InvalidArgumentError("signing key is encrypted") + } + + hashType := config.Hash() + name := nameOfHash(hashType) + if len(name) == 0 { + return nil, errors.UnsupportedError("unknown hash type: " + strconv.Itoa(int(hashType))) + } + + if !hashType.Available() { + return nil, errors.UnsupportedError("unsupported hash type: " + strconv.Itoa(int(hashType))) + } + h := hashType.New() + + buffered := bufio.NewWriter(w) + // start has a \n at the beginning that we don't want here. + if _, err = buffered.Write(start[1:]); err != nil { + return + } + if err = buffered.WriteByte(lf); err != nil { + return + } + if _, err = buffered.WriteString("Hash: "); err != nil { + return + } + if _, err = buffered.WriteString(name); err != nil { + return + } + if err = buffered.WriteByte(lf); err != nil { + return + } + if err = buffered.WriteByte(lf); err != nil { + return + } + + plaintext = &dashEscaper{ + buffered: buffered, + h: h, + hashType: hashType, + + atBeginningOfLine: true, + isFirstLine: true, + + byteBuf: make([]byte, 1), + + privateKey: privateKey, + config: config, + } + + return +} + +// nameOfHash returns the OpenPGP name for the given hash, or the empty string +// if the name isn't known. See RFC 4880, section 9.4. +func nameOfHash(h crypto.Hash) string { + switch h { + case crypto.MD5: + return "MD5" + case crypto.SHA1: + return "SHA1" + case crypto.RIPEMD160: + return "RIPEMD160" + case crypto.SHA224: + return "SHA224" + case crypto.SHA256: + return "SHA256" + case crypto.SHA384: + return "SHA384" + case crypto.SHA512: + return "SHA512" + } + return "" +} diff --git a/vendor/golang.org/x/crypto/openpgp/clearsign/clearsign_test.go b/vendor/golang.org/x/crypto/openpgp/clearsign/clearsign_test.go new file mode 100644 index 0000000000000000000000000000000000000000..2c09480789a75ec46998f0e3e31ca40711f13a86 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/clearsign/clearsign_test.go @@ -0,0 +1,210 @@ +// 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 clearsign + +import ( + "bytes" + "golang.org/x/crypto/openpgp" + "testing" +) + +func testParse(t *testing.T, input []byte, expected, expectedPlaintext string) { + b, rest := Decode(input) + if b == nil { + t.Fatal("failed to decode clearsign message") + } + if !bytes.Equal(rest, []byte("trailing")) { + t.Errorf("unexpected remaining bytes returned: %s", string(rest)) + } + if b.ArmoredSignature.Type != "PGP SIGNATURE" { + t.Errorf("bad armor type, got:%s, want:PGP SIGNATURE", b.ArmoredSignature.Type) + } + if !bytes.Equal(b.Bytes, []byte(expected)) { + t.Errorf("bad body, got:%x want:%x", b.Bytes, expected) + } + + if !bytes.Equal(b.Plaintext, []byte(expectedPlaintext)) { + t.Errorf("bad plaintext, got:%x want:%x", b.Plaintext, expectedPlaintext) + } + + keyring, err := openpgp.ReadArmoredKeyRing(bytes.NewBufferString(signingKey)) + if err != nil { + t.Errorf("failed to parse public key: %s", err) + } + + if _, err := openpgp.CheckDetachedSignature(keyring, bytes.NewBuffer(b.Bytes), b.ArmoredSignature.Body); err != nil { + t.Errorf("failed to check signature: %s", err) + } +} + +func TestParse(t *testing.T) { + testParse(t, clearsignInput, "Hello world\r\nline 2", "Hello world\nline 2\n") + testParse(t, clearsignInput2, "\r\n\r\n(This message has a couple of blank lines at the start and end.)\r\n\r\n", "\n\n(This message has a couple of blank lines at the start and end.)\n\n\n") +} + +func TestParseInvalid(t *testing.T) { + if b, _ := Decode(clearsignInput3); b != nil { + t.Fatal("decoded a bad clearsigned message without any error") + } +} + +func TestParseWithNoNewlineAtEnd(t *testing.T) { + input := clearsignInput + input = input[:len(input)-len("trailing")-1] + b, rest := Decode(input) + if b == nil { + t.Fatal("failed to decode clearsign message") + } + if len(rest) > 0 { + t.Errorf("unexpected remaining bytes returned: %s", string(rest)) + } +} + +var signingTests = []struct { + in, signed, plaintext string +}{ + {"", "", ""}, + {"a", "a", "a\n"}, + {"a\n", "a", "a\n"}, + {"-a\n", "-a", "-a\n"}, + {"--a\nb", "--a\r\nb", "--a\nb\n"}, + // leading whitespace + {" a\n", " a", " a\n"}, + {" a\n", " a", " a\n"}, + // trailing whitespace (should be stripped) + {"a \n", "a", "a\n"}, + {"a ", "a", "a\n"}, + // whitespace-only lines (should be stripped) + {" \n", "", "\n"}, + {" ", "", "\n"}, + {"a\n \n \nb\n", "a\r\n\r\n\r\nb", "a\n\n\nb\n"}, +} + +func TestSigning(t *testing.T) { + keyring, err := openpgp.ReadArmoredKeyRing(bytes.NewBufferString(signingKey)) + if err != nil { + t.Errorf("failed to parse public key: %s", err) + } + + for i, test := range signingTests { + var buf bytes.Buffer + + plaintext, err := Encode(&buf, keyring[0].PrivateKey, nil) + if err != nil { + t.Errorf("#%d: error from Encode: %s", i, err) + continue + } + if _, err := plaintext.Write([]byte(test.in)); err != nil { + t.Errorf("#%d: error from Write: %s", i, err) + continue + } + if err := plaintext.Close(); err != nil { + t.Fatalf("#%d: error from Close: %s", i, err) + continue + } + + b, _ := Decode(buf.Bytes()) + if b == nil { + t.Errorf("#%d: failed to decode clearsign message", i) + continue + } + if !bytes.Equal(b.Bytes, []byte(test.signed)) { + t.Errorf("#%d: bad result, got:%x, want:%x", i, b.Bytes, test.signed) + continue + } + if !bytes.Equal(b.Plaintext, []byte(test.plaintext)) { + t.Errorf("#%d: bad result, got:%x, want:%x", i, b.Plaintext, test.plaintext) + continue + } + + if _, err := openpgp.CheckDetachedSignature(keyring, bytes.NewBuffer(b.Bytes), b.ArmoredSignature.Body); err != nil { + t.Errorf("#%d: failed to check signature: %s", i, err) + } + } +} + +var clearsignInput = []byte(` +;lasjlkfdsa + +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA1 + +Hello world +line 2 +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.4.10 (GNU/Linux) + +iJwEAQECAAYFAk8kMuEACgkQO9o98PRieSpMsAQAhmY/vwmNpflrPgmfWsYhk5O8 +pjnBUzZwqTDoDeINjZEoPDSpQAHGhjFjgaDx/Gj4fAl0dM4D0wuUEBb6QOrwflog +2A2k9kfSOMOtk0IH/H5VuFN1Mie9L/erYXjTQIptv9t9J7NoRBMU0QOOaFU0JaO9 +MyTpno24AjIAGb+mH1U= +=hIJ6 +-----END PGP SIGNATURE----- +trailing`) + +var clearsignInput2 = []byte(` +asdlfkjasdlkfjsadf + +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA256 + + + +(This message has a couple of blank lines at the start and end.) + + +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.4.11 (GNU/Linux) + +iJwEAQEIAAYFAlPpSREACgkQO9o98PRieSpZTAP+M8QUoCt/7Rf3YbXPcdzIL32v +pt1I+cMNeopzfLy0u4ioEFi8s5VkwpL1AFmirvgViCwlf82inoRxzZRiW05JQ5LI +ESEzeCoy2LIdRCQ2hcrG8pIUPzUO4TqO5D/dMbdHwNH4h5nNmGJUAEG6FpURlPm+ +qZg6BaTvOxepqOxnhVU= +=e+C6 +-----END PGP SIGNATURE----- + +trailing`) + +var clearsignInput3 = []byte(` +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA256 + +(This message was truncated.) +`) + +var signingKey = `-----BEGIN PGP PRIVATE KEY BLOCK----- +Version: GnuPG v1.4.10 (GNU/Linux) + +lQHYBE2rFNoBBADFwqWQIW/DSqcB4yCQqnAFTJ27qS5AnB46ccAdw3u4Greeu3Bp +idpoHdjULy7zSKlwR1EA873dO/k/e11Ml3dlAFUinWeejWaK2ugFP6JjiieSsrKn +vWNicdCS4HTWn0X4sjl0ZiAygw6GNhqEQ3cpLeL0g8E9hnYzJKQ0LWJa0QARAQAB +AAP/TB81EIo2VYNmTq0pK1ZXwUpxCrvAAIG3hwKjEzHcbQznsjNvPUihZ+NZQ6+X +0HCfPAdPkGDCLCb6NavcSW+iNnLTrdDnSI6+3BbIONqWWdRDYJhqZCkqmG6zqSfL +IdkJgCw94taUg5BWP/AAeQrhzjChvpMQTVKQL5mnuZbUCeMCAN5qrYMP2S9iKdnk +VANIFj7656ARKt/nf4CBzxcpHTyB8+d2CtPDKCmlJP6vL8t58Jmih+kHJMvC0dzn +gr5f5+sCAOOe5gt9e0am7AvQWhdbHVfJU0TQJx+m2OiCJAqGTB1nvtBLHdJnfdC9 +TnXXQ6ZXibqLyBies/xeY2sCKL5qtTMCAKnX9+9d/5yQxRyrQUHt1NYhaXZnJbHx +q4ytu0eWz+5i68IYUSK69jJ1NWPM0T6SkqpB3KCAIv68VFm9PxqG1KmhSrQIVGVz +dCBLZXmIuAQTAQIAIgUCTasU2gIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AA +CgkQO9o98PRieSoLhgQAkLEZex02Qt7vGhZzMwuN0R22w3VwyYyjBx+fM3JFETy1 +ut4xcLJoJfIaF5ZS38UplgakHG0FQ+b49i8dMij0aZmDqGxrew1m4kBfjXw9B/v+ +eIqpODryb6cOSwyQFH0lQkXC040pjq9YqDsO5w0WYNXYKDnzRV0p4H1pweo2VDid +AdgETasU2gEEAN46UPeWRqKHvA99arOxee38fBt2CI08iiWyI8T3J6ivtFGixSqV +bRcPxYO/qLpVe5l84Nb3X71GfVXlc9hyv7CD6tcowL59hg1E/DC5ydI8K8iEpUmK +/UnHdIY5h8/kqgGxkY/T/hgp5fRQgW1ZoZxLajVlMRZ8W4tFtT0DeA+JABEBAAEA +A/0bE1jaaZKj6ndqcw86jd+QtD1SF+Cf21CWRNeLKnUds4FRRvclzTyUMuWPkUeX +TaNNsUOFqBsf6QQ2oHUBBK4VCHffHCW4ZEX2cd6umz7mpHW6XzN4DECEzOVksXtc +lUC1j4UB91DC/RNQqwX1IV2QLSwssVotPMPqhOi0ZLNY7wIA3n7DWKInxYZZ4K+6 +rQ+POsz6brEoRHwr8x6XlHenq1Oki855pSa1yXIARoTrSJkBtn5oI+f8AzrnN0BN +oyeQAwIA/7E++3HDi5aweWrViiul9cd3rcsS0dEnksPhvS0ozCJiHsq/6GFmy7J8 +QSHZPteedBnZyNp5jR+H7cIfVN3KgwH/Skq4PsuPhDq5TKK6i8Pc1WW8MA6DXTdU +nLkX7RGmMwjC0DBf7KWAlPjFaONAX3a8ndnz//fy1q7u2l9AZwrj1qa1iJ8EGAEC +AAkFAk2rFNoCGwwACgkQO9o98PRieSo2/QP/WTzr4ioINVsvN1akKuekmEMI3LAp +BfHwatufxxP1U+3Si/6YIk7kuPB9Hs+pRqCXzbvPRrI8NHZBmc8qIGthishdCYad +AHcVnXjtxrULkQFGbGvhKURLvS9WnzD/m1K2zzwxzkPTzT9/Yf06O6Mal5AdugPL +VrM0m72/jnpKo04= +=zNCn +-----END PGP PRIVATE KEY BLOCK----- +` diff --git a/vendor/golang.org/x/crypto/openpgp/elgamal/elgamal.go b/vendor/golang.org/x/crypto/openpgp/elgamal/elgamal.go new file mode 100644 index 0000000000000000000000000000000000000000..73f4fe3785914493b0b3fd214e40fac892ce2b1b --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/elgamal/elgamal.go @@ -0,0 +1,122 @@ +// 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 elgamal implements ElGamal encryption, suitable for OpenPGP, +// as specified in "A Public-Key Cryptosystem and a Signature Scheme Based on +// Discrete Logarithms," IEEE Transactions on Information Theory, v. IT-31, +// n. 4, 1985, pp. 469-472. +// +// This form of ElGamal embeds PKCS#1 v1.5 padding, which may make it +// unsuitable for other protocols. RSA should be used in preference in any +// case. +package elgamal // import "golang.org/x/crypto/openpgp/elgamal" + +import ( + "crypto/rand" + "crypto/subtle" + "errors" + "io" + "math/big" +) + +// PublicKey represents an ElGamal public key. +type PublicKey struct { + G, P, Y *big.Int +} + +// PrivateKey represents an ElGamal private key. +type PrivateKey struct { + PublicKey + X *big.Int +} + +// Encrypt encrypts the given message to the given public key. The result is a +// pair of integers. Errors can result from reading random, or because msg is +// too large to be encrypted to the public key. +func Encrypt(random io.Reader, pub *PublicKey, msg []byte) (c1, c2 *big.Int, err error) { + pLen := (pub.P.BitLen() + 7) / 8 + if len(msg) > pLen-11 { + err = errors.New("elgamal: message too long") + return + } + + // EM = 0x02 || PS || 0x00 || M + em := make([]byte, pLen-1) + em[0] = 2 + ps, mm := em[1:len(em)-len(msg)-1], em[len(em)-len(msg):] + err = nonZeroRandomBytes(ps, random) + if err != nil { + return + } + em[len(em)-len(msg)-1] = 0 + copy(mm, msg) + + m := new(big.Int).SetBytes(em) + + k, err := rand.Int(random, pub.P) + if err != nil { + return + } + + c1 = new(big.Int).Exp(pub.G, k, pub.P) + s := new(big.Int).Exp(pub.Y, k, pub.P) + c2 = s.Mul(s, m) + c2.Mod(c2, pub.P) + + return +} + +// Decrypt takes two integers, resulting from an ElGamal encryption, and +// returns the plaintext of the message. An error can result only if the +// ciphertext is invalid. Users should keep in mind that this is a padding +// oracle and thus, if exposed to an adaptive chosen ciphertext attack, can +// be used to break the cryptosystem. See ``Chosen Ciphertext Attacks +// Against Protocols Based on the RSA Encryption Standard PKCS #1'', Daniel +// Bleichenbacher, Advances in Cryptology (Crypto '98), +func Decrypt(priv *PrivateKey, c1, c2 *big.Int) (msg []byte, err error) { + s := new(big.Int).Exp(c1, priv.X, priv.P) + s.ModInverse(s, priv.P) + s.Mul(s, c2) + s.Mod(s, priv.P) + em := s.Bytes() + + firstByteIsTwo := subtle.ConstantTimeByteEq(em[0], 2) + + // The remainder of the plaintext must be a string of non-zero random + // octets, followed by a 0, followed by the message. + // lookingForIndex: 1 iff we are still looking for the zero. + // index: the offset of the first zero byte. + var lookingForIndex, index int + lookingForIndex = 1 + + for i := 1; i < len(em); i++ { + equals0 := subtle.ConstantTimeByteEq(em[i], 0) + index = subtle.ConstantTimeSelect(lookingForIndex&equals0, i, index) + lookingForIndex = subtle.ConstantTimeSelect(equals0, 0, lookingForIndex) + } + + if firstByteIsTwo != 1 || lookingForIndex != 0 || index < 9 { + return nil, errors.New("elgamal: decryption error") + } + return em[index+1:], nil +} + +// nonZeroRandomBytes fills the given slice with non-zero random octets. +func nonZeroRandomBytes(s []byte, rand io.Reader) (err error) { + _, err = io.ReadFull(rand, s) + if err != nil { + return + } + + for i := 0; i < len(s); i++ { + for s[i] == 0 { + _, err = io.ReadFull(rand, s[i:i+1]) + if err != nil { + return + } + } + } + + return +} diff --git a/vendor/golang.org/x/crypto/openpgp/elgamal/elgamal_test.go b/vendor/golang.org/x/crypto/openpgp/elgamal/elgamal_test.go new file mode 100644 index 0000000000000000000000000000000000000000..c4f99f5c48cd21ff31eb21353ffb76617aa5523b --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/elgamal/elgamal_test.go @@ -0,0 +1,49 @@ +// 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 elgamal + +import ( + "bytes" + "crypto/rand" + "math/big" + "testing" +) + +// This is the 1024-bit MODP group from RFC 5114, section 2.1: +const primeHex = "B10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C69A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C013ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD7098488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708DF1FB2BC2E4A4371" + +const generatorHex = "A4D1CBD5C3FD34126765A442EFB99905F8104DD258AC507FD6406CFF14266D31266FEA1E5C41564B777E690F5504F213160217B4B01B886A5E91547F9E2749F4D7FBD7D3B9A92EE1909D0D2263F80A76A6A24C087A091F531DBF0A0169B6A28AD662A4D18E73AFA32D779D5918D08BC8858F4DCEF97C2A24855E6EEB22B3B2E5" + +func fromHex(hex string) *big.Int { + n, ok := new(big.Int).SetString(hex, 16) + if !ok { + panic("failed to parse hex number") + } + return n +} + +func TestEncryptDecrypt(t *testing.T) { + priv := &PrivateKey{ + PublicKey: PublicKey{ + G: fromHex(generatorHex), + P: fromHex(primeHex), + }, + X: fromHex("42"), + } + priv.Y = new(big.Int).Exp(priv.G, priv.X, priv.P) + + message := []byte("hello world") + c1, c2, err := Encrypt(rand.Reader, &priv.PublicKey, message) + if err != nil { + t.Errorf("error encrypting: %s", err) + } + message2, err := Decrypt(priv, c1, c2) + if err != nil { + t.Errorf("error decrypting: %s", err) + } + if !bytes.Equal(message2, message) { + t.Errorf("decryption failed, got: %x, want: %x", message2, message) + } +} diff --git a/vendor/golang.org/x/crypto/openpgp/errors/errors.go b/vendor/golang.org/x/crypto/openpgp/errors/errors.go new file mode 100644 index 0000000000000000000000000000000000000000..eb0550b2d04f9301955003ababd52712fffaf086 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/errors/errors.go @@ -0,0 +1,72 @@ +// 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 errors contains common error types for the OpenPGP packages. +package errors // import "golang.org/x/crypto/openpgp/errors" + +import ( + "strconv" +) + +// A StructuralError is returned when OpenPGP data is found to be syntactically +// invalid. +type StructuralError string + +func (s StructuralError) Error() string { + return "openpgp: invalid data: " + string(s) +} + +// UnsupportedError indicates that, although the OpenPGP data is valid, it +// makes use of currently unimplemented features. +type UnsupportedError string + +func (s UnsupportedError) Error() string { + return "openpgp: unsupported feature: " + string(s) +} + +// InvalidArgumentError indicates that the caller is in error and passed an +// incorrect value. +type InvalidArgumentError string + +func (i InvalidArgumentError) Error() string { + return "openpgp: invalid argument: " + string(i) +} + +// SignatureError indicates that a syntactically valid signature failed to +// validate. +type SignatureError string + +func (b SignatureError) Error() string { + return "openpgp: invalid signature: " + string(b) +} + +type keyIncorrectError int + +func (ki keyIncorrectError) Error() string { + return "openpgp: incorrect key" +} + +var ErrKeyIncorrect error = keyIncorrectError(0) + +type unknownIssuerError int + +func (unknownIssuerError) Error() string { + return "openpgp: signature made by unknown entity" +} + +var ErrUnknownIssuer error = unknownIssuerError(0) + +type keyRevokedError int + +func (keyRevokedError) Error() string { + return "openpgp: signature made by revoked key" +} + +var ErrKeyRevoked error = keyRevokedError(0) + +type UnknownPacketTypeError uint8 + +func (upte UnknownPacketTypeError) Error() string { + return "openpgp: unknown packet type: " + strconv.Itoa(int(upte)) +} diff --git a/vendor/golang.org/x/crypto/openpgp/keys.go b/vendor/golang.org/x/crypto/openpgp/keys.go new file mode 100644 index 0000000000000000000000000000000000000000..744e293febe64c7b2ec3350e167a495ec8f40d1d --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/keys.go @@ -0,0 +1,636 @@ +// 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 openpgp + +import ( + "crypto/rsa" + "io" + "time" + + "golang.org/x/crypto/openpgp/armor" + "golang.org/x/crypto/openpgp/errors" + "golang.org/x/crypto/openpgp/packet" +) + +// PublicKeyType is the armor type for a PGP public key. +var PublicKeyType = "PGP PUBLIC KEY BLOCK" + +// PrivateKeyType is the armor type for a PGP private key. +var PrivateKeyType = "PGP PRIVATE KEY BLOCK" + +// An Entity represents the components of an OpenPGP key: a primary public key +// (which must be a signing key), one or more identities claimed by that key, +// and zero or more subkeys, which may be encryption keys. +type Entity struct { + PrimaryKey *packet.PublicKey + PrivateKey *packet.PrivateKey + Identities map[string]*Identity // indexed by Identity.Name + Revocations []*packet.Signature + Subkeys []Subkey +} + +// An Identity represents an identity claimed by an Entity and zero or more +// assertions by other entities about that claim. +type Identity struct { + Name string // by convention, has the form "Full Name (comment) " + UserId *packet.UserId + SelfSignature *packet.Signature + Signatures []*packet.Signature +} + +// A Subkey is an additional public key in an Entity. Subkeys can be used for +// encryption. +type Subkey struct { + PublicKey *packet.PublicKey + PrivateKey *packet.PrivateKey + Sig *packet.Signature +} + +// A Key identifies a specific public key in an Entity. This is either the +// Entity's primary key or a subkey. +type Key struct { + Entity *Entity + PublicKey *packet.PublicKey + PrivateKey *packet.PrivateKey + SelfSignature *packet.Signature +} + +// A KeyRing provides access to public and private keys. +type KeyRing interface { + // KeysById returns the set of keys that have the given key id. + KeysById(id uint64) []Key + // KeysByIdAndUsage returns the set of keys with the given id + // that also meet the key usage given by requiredUsage. + // The requiredUsage is expressed as the bitwise-OR of + // packet.KeyFlag* values. + KeysByIdUsage(id uint64, requiredUsage byte) []Key + // DecryptionKeys returns all private keys that are valid for + // decryption. + DecryptionKeys() []Key +} + +// primaryIdentity returns the Identity marked as primary or the first identity +// if none are so marked. +func (e *Entity) primaryIdentity() *Identity { + var firstIdentity *Identity + for _, ident := range e.Identities { + if firstIdentity == nil { + firstIdentity = ident + } + if ident.SelfSignature.IsPrimaryId != nil && *ident.SelfSignature.IsPrimaryId { + return ident + } + } + return firstIdentity +} + +// encryptionKey returns the best candidate Key for encrypting a message to the +// given Entity. +func (e *Entity) encryptionKey(now time.Time) (Key, bool) { + candidateSubkey := -1 + + // Iterate the keys to find the newest key + var maxTime time.Time + for i, subkey := range e.Subkeys { + if subkey.Sig.FlagsValid && + subkey.Sig.FlagEncryptCommunications && + subkey.PublicKey.PubKeyAlgo.CanEncrypt() && + !subkey.Sig.KeyExpired(now) && + (maxTime.IsZero() || subkey.Sig.CreationTime.After(maxTime)) { + candidateSubkey = i + maxTime = subkey.Sig.CreationTime + } + } + + if candidateSubkey != -1 { + subkey := e.Subkeys[candidateSubkey] + return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig}, true + } + + // If we don't have any candidate subkeys for encryption and + // the primary key doesn't have any usage metadata then we + // assume that the primary key is ok. Or, if the primary key is + // marked as ok to encrypt to, then we can obviously use it. + i := e.primaryIdentity() + if !i.SelfSignature.FlagsValid || i.SelfSignature.FlagEncryptCommunications && + e.PrimaryKey.PubKeyAlgo.CanEncrypt() && + !i.SelfSignature.KeyExpired(now) { + return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature}, true + } + + // This Entity appears to be signing only. + return Key{}, false +} + +// signingKey return the best candidate Key for signing a message with this +// Entity. +func (e *Entity) signingKey(now time.Time) (Key, bool) { + candidateSubkey := -1 + + for i, subkey := range e.Subkeys { + if subkey.Sig.FlagsValid && + subkey.Sig.FlagSign && + subkey.PublicKey.PubKeyAlgo.CanSign() && + !subkey.Sig.KeyExpired(now) { + candidateSubkey = i + break + } + } + + if candidateSubkey != -1 { + subkey := e.Subkeys[candidateSubkey] + return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig}, true + } + + // If we have no candidate subkey then we assume that it's ok to sign + // with the primary key. + i := e.primaryIdentity() + if !i.SelfSignature.FlagsValid || i.SelfSignature.FlagSign && + !i.SelfSignature.KeyExpired(now) { + return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature}, true + } + + return Key{}, false +} + +// An EntityList contains one or more Entities. +type EntityList []*Entity + +// KeysById returns the set of keys that have the given key id. +func (el EntityList) KeysById(id uint64) (keys []Key) { + for _, e := range el { + if e.PrimaryKey.KeyId == id { + var selfSig *packet.Signature + for _, ident := range e.Identities { + if selfSig == nil { + selfSig = ident.SelfSignature + } else if ident.SelfSignature.IsPrimaryId != nil && *ident.SelfSignature.IsPrimaryId { + selfSig = ident.SelfSignature + break + } + } + keys = append(keys, Key{e, e.PrimaryKey, e.PrivateKey, selfSig}) + } + + for _, subKey := range e.Subkeys { + if subKey.PublicKey.KeyId == id { + keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig}) + } + } + } + return +} + +// KeysByIdAndUsage returns the set of keys with the given id that also meet +// the key usage given by requiredUsage. The requiredUsage is expressed as +// the bitwise-OR of packet.KeyFlag* values. +func (el EntityList) KeysByIdUsage(id uint64, requiredUsage byte) (keys []Key) { + for _, key := range el.KeysById(id) { + if len(key.Entity.Revocations) > 0 { + continue + } + + if key.SelfSignature.RevocationReason != nil { + continue + } + + if key.SelfSignature.FlagsValid && requiredUsage != 0 { + var usage byte + if key.SelfSignature.FlagCertify { + usage |= packet.KeyFlagCertify + } + if key.SelfSignature.FlagSign { + usage |= packet.KeyFlagSign + } + if key.SelfSignature.FlagEncryptCommunications { + usage |= packet.KeyFlagEncryptCommunications + } + if key.SelfSignature.FlagEncryptStorage { + usage |= packet.KeyFlagEncryptStorage + } + if usage&requiredUsage != requiredUsage { + continue + } + } + + keys = append(keys, key) + } + return +} + +// DecryptionKeys returns all private keys that are valid for decryption. +func (el EntityList) DecryptionKeys() (keys []Key) { + for _, e := range el { + for _, subKey := range e.Subkeys { + if subKey.PrivateKey != nil && (!subKey.Sig.FlagsValid || subKey.Sig.FlagEncryptStorage || subKey.Sig.FlagEncryptCommunications) { + keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig}) + } + } + } + return +} + +// ReadArmoredKeyRing reads one or more public/private keys from an armor keyring file. +func ReadArmoredKeyRing(r io.Reader) (EntityList, error) { + block, err := armor.Decode(r) + if err == io.EOF { + return nil, errors.InvalidArgumentError("no armored data found") + } + if err != nil { + return nil, err + } + if block.Type != PublicKeyType && block.Type != PrivateKeyType { + return nil, errors.InvalidArgumentError("expected public or private key block, got: " + block.Type) + } + + return ReadKeyRing(block.Body) +} + +// ReadKeyRing reads one or more public/private keys. Unsupported keys are +// ignored as long as at least a single valid key is found. +func ReadKeyRing(r io.Reader) (el EntityList, err error) { + packets := packet.NewReader(r) + var lastUnsupportedError error + + for { + var e *Entity + e, err = ReadEntity(packets) + if err != nil { + // TODO: warn about skipped unsupported/unreadable keys + if _, ok := err.(errors.UnsupportedError); ok { + lastUnsupportedError = err + err = readToNextPublicKey(packets) + } else if _, ok := err.(errors.StructuralError); ok { + // Skip unreadable, badly-formatted keys + lastUnsupportedError = err + err = readToNextPublicKey(packets) + } + if err == io.EOF { + err = nil + break + } + if err != nil { + el = nil + break + } + } else { + el = append(el, e) + } + } + + if len(el) == 0 && err == nil { + err = lastUnsupportedError + } + return +} + +// readToNextPublicKey reads packets until the start of the entity and leaves +// the first packet of the new entity in the Reader. +func readToNextPublicKey(packets *packet.Reader) (err error) { + var p packet.Packet + for { + p, err = packets.Next() + if err == io.EOF { + return + } else if err != nil { + if _, ok := err.(errors.UnsupportedError); ok { + err = nil + continue + } + return + } + + if pk, ok := p.(*packet.PublicKey); ok && !pk.IsSubkey { + packets.Unread(p) + return + } + } +} + +// ReadEntity reads an entity (public key, identities, subkeys etc) from the +// given Reader. +func ReadEntity(packets *packet.Reader) (*Entity, error) { + e := new(Entity) + e.Identities = make(map[string]*Identity) + + p, err := packets.Next() + if err != nil { + return nil, err + } + + var ok bool + if e.PrimaryKey, ok = p.(*packet.PublicKey); !ok { + if e.PrivateKey, ok = p.(*packet.PrivateKey); !ok { + packets.Unread(p) + return nil, errors.StructuralError("first packet was not a public/private key") + } + e.PrimaryKey = &e.PrivateKey.PublicKey + } + + if !e.PrimaryKey.PubKeyAlgo.CanSign() { + return nil, errors.StructuralError("primary key cannot be used for signatures") + } + + var current *Identity + var revocations []*packet.Signature +EachPacket: + for { + p, err := packets.Next() + if err == io.EOF { + break + } else if err != nil { + return nil, err + } + + switch pkt := p.(type) { + case *packet.UserId: + current = new(Identity) + current.Name = pkt.Id + current.UserId = pkt + e.Identities[pkt.Id] = current + + for { + p, err = packets.Next() + if err == io.EOF { + return nil, io.ErrUnexpectedEOF + } else if err != nil { + return nil, err + } + + sig, ok := p.(*packet.Signature) + if !ok { + return nil, errors.StructuralError("user ID packet not followed by self-signature") + } + + if (sig.SigType == packet.SigTypePositiveCert || sig.SigType == packet.SigTypeGenericCert) && sig.IssuerKeyId != nil && *sig.IssuerKeyId == e.PrimaryKey.KeyId { + if err = e.PrimaryKey.VerifyUserIdSignature(pkt.Id, e.PrimaryKey, sig); err != nil { + return nil, errors.StructuralError("user ID self-signature invalid: " + err.Error()) + } + current.SelfSignature = sig + break + } + current.Signatures = append(current.Signatures, sig) + } + case *packet.Signature: + if pkt.SigType == packet.SigTypeKeyRevocation { + revocations = append(revocations, pkt) + } else if pkt.SigType == packet.SigTypeDirectSignature { + // TODO: RFC4880 5.2.1 permits signatures + // directly on keys (eg. to bind additional + // revocation keys). + } else if current == nil { + return nil, errors.StructuralError("signature packet found before user id packet") + } else { + current.Signatures = append(current.Signatures, pkt) + } + case *packet.PrivateKey: + if pkt.IsSubkey == false { + packets.Unread(p) + break EachPacket + } + err = addSubkey(e, packets, &pkt.PublicKey, pkt) + if err != nil { + return nil, err + } + case *packet.PublicKey: + if pkt.IsSubkey == false { + packets.Unread(p) + break EachPacket + } + err = addSubkey(e, packets, pkt, nil) + if err != nil { + return nil, err + } + default: + // we ignore unknown packets + } + } + + if len(e.Identities) == 0 { + return nil, errors.StructuralError("entity without any identities") + } + + for _, revocation := range revocations { + err = e.PrimaryKey.VerifyRevocationSignature(revocation) + if err == nil { + e.Revocations = append(e.Revocations, revocation) + } else { + // TODO: RFC 4880 5.2.3.15 defines revocation keys. + return nil, errors.StructuralError("revocation signature signed by alternate key") + } + } + + return e, nil +} + +func addSubkey(e *Entity, packets *packet.Reader, pub *packet.PublicKey, priv *packet.PrivateKey) error { + var subKey Subkey + subKey.PublicKey = pub + subKey.PrivateKey = priv + p, err := packets.Next() + if err == io.EOF { + return io.ErrUnexpectedEOF + } + if err != nil { + return errors.StructuralError("subkey signature invalid: " + err.Error()) + } + var ok bool + subKey.Sig, ok = p.(*packet.Signature) + if !ok { + return errors.StructuralError("subkey packet not followed by signature") + } + if subKey.Sig.SigType != packet.SigTypeSubkeyBinding && subKey.Sig.SigType != packet.SigTypeSubkeyRevocation { + return errors.StructuralError("subkey signature with wrong type") + } + err = e.PrimaryKey.VerifyKeySignature(subKey.PublicKey, subKey.Sig) + if err != nil { + return errors.StructuralError("subkey signature invalid: " + err.Error()) + } + e.Subkeys = append(e.Subkeys, subKey) + return nil +} + +const defaultRSAKeyBits = 2048 + +// NewEntity returns an Entity that contains a fresh RSA/RSA keypair with a +// single identity composed of the given full name, comment and email, any of +// which may be empty but must not contain any of "()<>\x00". +// If config is nil, sensible defaults will be used. +func NewEntity(name, comment, email string, config *packet.Config) (*Entity, error) { + currentTime := config.Now() + + bits := defaultRSAKeyBits + if config != nil && config.RSABits != 0 { + bits = config.RSABits + } + + uid := packet.NewUserId(name, comment, email) + if uid == nil { + return nil, errors.InvalidArgumentError("user id field contained invalid characters") + } + signingPriv, err := rsa.GenerateKey(config.Random(), bits) + if err != nil { + return nil, err + } + encryptingPriv, err := rsa.GenerateKey(config.Random(), bits) + if err != nil { + return nil, err + } + + e := &Entity{ + PrimaryKey: packet.NewRSAPublicKey(currentTime, &signingPriv.PublicKey), + PrivateKey: packet.NewRSAPrivateKey(currentTime, signingPriv), + Identities: make(map[string]*Identity), + } + isPrimaryId := true + e.Identities[uid.Id] = &Identity{ + Name: uid.Name, + UserId: uid, + SelfSignature: &packet.Signature{ + CreationTime: currentTime, + SigType: packet.SigTypePositiveCert, + PubKeyAlgo: packet.PubKeyAlgoRSA, + Hash: config.Hash(), + IsPrimaryId: &isPrimaryId, + FlagsValid: true, + FlagSign: true, + FlagCertify: true, + IssuerKeyId: &e.PrimaryKey.KeyId, + }, + } + + // If the user passes in a DefaultHash via packet.Config, + // set the PreferredHash for the SelfSignature. + if config != nil && config.DefaultHash != 0 { + e.Identities[uid.Id].SelfSignature.PreferredHash = []uint8{hashToHashId(config.DefaultHash)} + } + + e.Subkeys = make([]Subkey, 1) + e.Subkeys[0] = Subkey{ + PublicKey: packet.NewRSAPublicKey(currentTime, &encryptingPriv.PublicKey), + PrivateKey: packet.NewRSAPrivateKey(currentTime, encryptingPriv), + Sig: &packet.Signature{ + CreationTime: currentTime, + SigType: packet.SigTypeSubkeyBinding, + PubKeyAlgo: packet.PubKeyAlgoRSA, + Hash: config.Hash(), + FlagsValid: true, + FlagEncryptStorage: true, + FlagEncryptCommunications: true, + IssuerKeyId: &e.PrimaryKey.KeyId, + }, + } + e.Subkeys[0].PublicKey.IsSubkey = true + e.Subkeys[0].PrivateKey.IsSubkey = true + + return e, nil +} + +// SerializePrivate serializes an Entity, including private key material, to +// the given Writer. For now, it must only be used on an Entity returned from +// NewEntity. +// If config is nil, sensible defaults will be used. +func (e *Entity) SerializePrivate(w io.Writer, config *packet.Config) (err error) { + err = e.PrivateKey.Serialize(w) + if err != nil { + return + } + for _, ident := range e.Identities { + err = ident.UserId.Serialize(w) + if err != nil { + return + } + err = ident.SelfSignature.SignUserId(ident.UserId.Id, e.PrimaryKey, e.PrivateKey, config) + if err != nil { + return + } + err = ident.SelfSignature.Serialize(w) + if err != nil { + return + } + } + for _, subkey := range e.Subkeys { + err = subkey.PrivateKey.Serialize(w) + if err != nil { + return + } + err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config) + if err != nil { + return + } + err = subkey.Sig.Serialize(w) + if err != nil { + return + } + } + return nil +} + +// Serialize writes the public part of the given Entity to w. (No private +// key material will be output). +func (e *Entity) Serialize(w io.Writer) error { + err := e.PrimaryKey.Serialize(w) + if err != nil { + return err + } + for _, ident := range e.Identities { + err = ident.UserId.Serialize(w) + if err != nil { + return err + } + err = ident.SelfSignature.Serialize(w) + if err != nil { + return err + } + for _, sig := range ident.Signatures { + err = sig.Serialize(w) + if err != nil { + return err + } + } + } + for _, subkey := range e.Subkeys { + err = subkey.PublicKey.Serialize(w) + if err != nil { + return err + } + err = subkey.Sig.Serialize(w) + if err != nil { + return err + } + } + return nil +} + +// SignIdentity adds a signature to e, from signer, attesting that identity is +// associated with e. The provided identity must already be an element of +// e.Identities and the private key of signer must have been decrypted if +// necessary. +// If config is nil, sensible defaults will be used. +func (e *Entity) SignIdentity(identity string, signer *Entity, config *packet.Config) error { + if signer.PrivateKey == nil { + return errors.InvalidArgumentError("signing Entity must have a private key") + } + if signer.PrivateKey.Encrypted { + return errors.InvalidArgumentError("signing Entity's private key must be decrypted") + } + ident, ok := e.Identities[identity] + if !ok { + return errors.InvalidArgumentError("given identity string not found in Entity") + } + + sig := &packet.Signature{ + SigType: packet.SigTypeGenericCert, + PubKeyAlgo: signer.PrivateKey.PubKeyAlgo, + Hash: config.Hash(), + CreationTime: config.Now(), + IssuerKeyId: &signer.PrivateKey.KeyId, + } + if err := sig.SignUserId(identity, e.PrimaryKey, signer.PrivateKey, config); err != nil { + return err + } + ident.Signatures = append(ident.Signatures, sig) + return nil +} diff --git a/vendor/golang.org/x/crypto/openpgp/keys_test.go b/vendor/golang.org/x/crypto/openpgp/keys_test.go new file mode 100644 index 0000000000000000000000000000000000000000..76ba13ed115cd81ad86ef37811ee7195b79a0f5d --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/keys_test.go @@ -0,0 +1,419 @@ +package openpgp + +import ( + "bytes" + "crypto" + "strings" + "testing" + "time" + + "golang.org/x/crypto/openpgp/errors" + "golang.org/x/crypto/openpgp/packet" +) + +func TestKeyExpiry(t *testing.T) { + kring, err := ReadKeyRing(readerFromHex(expiringKeyHex)) + if err != nil { + t.Fatal(err) + } + entity := kring[0] + + const timeFormat = "2006-01-02" + time1, _ := time.Parse(timeFormat, "2013-07-01") + + // The expiringKeyHex key is structured as: + // + // pub 1024R/5E237D8C created: 2013-07-01 expires: 2013-07-31 usage: SC + // sub 1024R/1ABB25A0 created: 2013-07-01 23:11:07 +0200 CEST expires: 2013-07-08 usage: E + // sub 1024R/96A672F5 created: 2013-07-01 23:11:23 +0200 CEST expires: 2013-07-31 usage: E + // + // So this should select the newest, non-expired encryption key. + key, _ := entity.encryptionKey(time1) + if id := key.PublicKey.KeyIdShortString(); id != "96A672F5" { + t.Errorf("Expected key 1ABB25A0 at time %s, but got key %s", time1.Format(timeFormat), id) + } + + // Once the first encryption subkey has expired, the second should be + // selected. + time2, _ := time.Parse(timeFormat, "2013-07-09") + key, _ = entity.encryptionKey(time2) + if id := key.PublicKey.KeyIdShortString(); id != "96A672F5" { + t.Errorf("Expected key 96A672F5 at time %s, but got key %s", time2.Format(timeFormat), id) + } + + // Once all the keys have expired, nothing should be returned. + time3, _ := time.Parse(timeFormat, "2013-08-01") + if key, ok := entity.encryptionKey(time3); ok { + t.Errorf("Expected no key at time %s, but got key %s", time3.Format(timeFormat), key.PublicKey.KeyIdShortString()) + } +} + +func TestMissingCrossSignature(t *testing.T) { + // This public key has a signing subkey, but the subkey does not + // contain a cross-signature. + keys, err := ReadArmoredKeyRing(bytes.NewBufferString(missingCrossSignatureKey)) + if len(keys) != 0 { + t.Errorf("Accepted key with missing cross signature") + } + if err == nil { + t.Fatal("Failed to detect error in keyring with missing cross signature") + } + structural, ok := err.(errors.StructuralError) + if !ok { + t.Fatalf("Unexpected class of error: %T. Wanted StructuralError", err) + } + const expectedMsg = "signing subkey is missing cross-signature" + if !strings.Contains(string(structural), expectedMsg) { + t.Fatalf("Unexpected error: %q. Expected it to contain %q", err, expectedMsg) + } +} + +func TestInvalidCrossSignature(t *testing.T) { + // This public key has a signing subkey, and the subkey has an + // embedded cross-signature. However, the cross-signature does + // not correctly validate over the primary and subkey. + keys, err := ReadArmoredKeyRing(bytes.NewBufferString(invalidCrossSignatureKey)) + if len(keys) != 0 { + t.Errorf("Accepted key with invalid cross signature") + } + if err == nil { + t.Fatal("Failed to detect error in keyring with an invalid cross signature") + } + structural, ok := err.(errors.StructuralError) + if !ok { + t.Fatalf("Unexpected class of error: %T. Wanted StructuralError", err) + } + const expectedMsg = "subkey signature invalid" + if !strings.Contains(string(structural), expectedMsg) { + t.Fatalf("Unexpected error: %q. Expected it to contain %q", err, expectedMsg) + } +} + +func TestGoodCrossSignature(t *testing.T) { + // This public key has a signing subkey, and the subkey has an + // embedded cross-signature which correctly validates over the + // primary and subkey. + keys, err := ReadArmoredKeyRing(bytes.NewBufferString(goodCrossSignatureKey)) + if err != nil { + t.Fatal(err) + } + if len(keys) != 1 { + t.Errorf("Failed to accept key with good cross signature, %d", len(keys)) + } + if len(keys[0].Subkeys) != 1 { + t.Errorf("Failed to accept good subkey, %d", len(keys[0].Subkeys)) + } +} + +// TestExternallyRevokableKey attempts to load and parse a key with a third party revocation permission. +func TestExternallyRevocableKey(t *testing.T) { + kring, err := ReadKeyRing(readerFromHex(subkeyUsageHex)) + if err != nil { + t.Fatal(err) + } + + // The 0xA42704B92866382A key can be revoked by 0xBE3893CB843D0FE70C + // according to this signature that appears within the key: + // :signature packet: algo 1, keyid A42704B92866382A + // version 4, created 1396409682, md5len 0, sigclass 0x1f + // digest algo 2, begin of digest a9 84 + // hashed subpkt 2 len 4 (sig created 2014-04-02) + // hashed subpkt 12 len 22 (revocation key: c=80 a=1 f=CE094AA433F7040BB2DDF0BE3893CB843D0FE70C) + // hashed subpkt 7 len 1 (not revocable) + // subpkt 16 len 8 (issuer key ID A42704B92866382A) + // data: [1024 bits] + + id := uint64(0xA42704B92866382A) + keys := kring.KeysById(id) + if len(keys) != 1 { + t.Errorf("Expected to find key id %X, but got %d matches", id, len(keys)) + } +} + +func TestKeyRevocation(t *testing.T) { + kring, err := ReadKeyRing(readerFromHex(revokedKeyHex)) + if err != nil { + t.Fatal(err) + } + + // revokedKeyHex contains these keys: + // pub 1024R/9A34F7C0 2014-03-25 [revoked: 2014-03-25] + // sub 1024R/1BA3CD60 2014-03-25 [revoked: 2014-03-25] + ids := []uint64{0xA401D9F09A34F7C0, 0x5CD3BE0A1BA3CD60} + + for _, id := range ids { + keys := kring.KeysById(id) + if len(keys) != 1 { + t.Errorf("Expected KeysById to find revoked key %X, but got %d matches", id, len(keys)) + } + keys = kring.KeysByIdUsage(id, 0) + if len(keys) != 0 { + t.Errorf("Expected KeysByIdUsage to filter out revoked key %X, but got %d matches", id, len(keys)) + } + } +} + +func TestSubkeyRevocation(t *testing.T) { + kring, err := ReadKeyRing(readerFromHex(revokedSubkeyHex)) + if err != nil { + t.Fatal(err) + } + + // revokedSubkeyHex contains these keys: + // pub 1024R/4EF7E4BECCDE97F0 2014-03-25 + // sub 1024R/D63636E2B96AE423 2014-03-25 + // sub 1024D/DBCE4EE19529437F 2014-03-25 + // sub 1024R/677815E371C2FD23 2014-03-25 [revoked: 2014-03-25] + validKeys := []uint64{0x4EF7E4BECCDE97F0, 0xD63636E2B96AE423, 0xDBCE4EE19529437F} + revokedKey := uint64(0x677815E371C2FD23) + + for _, id := range validKeys { + keys := kring.KeysById(id) + if len(keys) != 1 { + t.Errorf("Expected KeysById to find key %X, but got %d matches", id, len(keys)) + } + keys = kring.KeysByIdUsage(id, 0) + if len(keys) != 1 { + t.Errorf("Expected KeysByIdUsage to find key %X, but got %d matches", id, len(keys)) + } + } + + keys := kring.KeysById(revokedKey) + if len(keys) != 1 { + t.Errorf("Expected KeysById to find key %X, but got %d matches", revokedKey, len(keys)) + } + + keys = kring.KeysByIdUsage(revokedKey, 0) + if len(keys) != 0 { + t.Errorf("Expected KeysByIdUsage to filter out revoked key %X, but got %d matches", revokedKey, len(keys)) + } +} + +func TestKeyUsage(t *testing.T) { + kring, err := ReadKeyRing(readerFromHex(subkeyUsageHex)) + if err != nil { + t.Fatal(err) + } + + // subkeyUsageHex contains these keys: + // pub 1024R/2866382A created: 2014-04-01 expires: never usage: SC + // sub 1024R/936C9153 created: 2014-04-01 expires: never usage: E + // sub 1024R/64D5F5BB created: 2014-04-02 expires: never usage: E + // sub 1024D/BC0BA992 created: 2014-04-02 expires: never usage: S + certifiers := []uint64{0xA42704B92866382A} + signers := []uint64{0xA42704B92866382A, 0x42CE2C64BC0BA992} + encrypters := []uint64{0x09C0C7D9936C9153, 0xC104E98664D5F5BB} + + for _, id := range certifiers { + keys := kring.KeysByIdUsage(id, packet.KeyFlagCertify) + if len(keys) == 1 { + if keys[0].PublicKey.KeyId != id { + t.Errorf("Expected to find certifier key id %X, but got %X", id, keys[0].PublicKey.KeyId) + } + } else { + t.Errorf("Expected one match for certifier key id %X, but got %d matches", id, len(keys)) + } + } + + for _, id := range signers { + keys := kring.KeysByIdUsage(id, packet.KeyFlagSign) + if len(keys) == 1 { + if keys[0].PublicKey.KeyId != id { + t.Errorf("Expected to find signing key id %X, but got %X", id, keys[0].PublicKey.KeyId) + } + } else { + t.Errorf("Expected one match for signing key id %X, but got %d matches", id, len(keys)) + } + + // This keyring contains no encryption keys that are also good for signing. + keys = kring.KeysByIdUsage(id, packet.KeyFlagEncryptStorage|packet.KeyFlagEncryptCommunications) + if len(keys) != 0 { + t.Errorf("Unexpected match for encryption key id %X", id) + } + } + + for _, id := range encrypters { + keys := kring.KeysByIdUsage(id, packet.KeyFlagEncryptStorage|packet.KeyFlagEncryptCommunications) + if len(keys) == 1 { + if keys[0].PublicKey.KeyId != id { + t.Errorf("Expected to find encryption key id %X, but got %X", id, keys[0].PublicKey.KeyId) + } + } else { + t.Errorf("Expected one match for encryption key id %X, but got %d matches", id, len(keys)) + } + + // This keyring contains no encryption keys that are also good for signing. + keys = kring.KeysByIdUsage(id, packet.KeyFlagSign) + if len(keys) != 0 { + t.Errorf("Unexpected match for signing key id %X", id) + } + } +} + +func TestIdVerification(t *testing.T) { + kring, err := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex)) + if err != nil { + t.Fatal(err) + } + if err := kring[1].PrivateKey.Decrypt([]byte("passphrase")); err != nil { + t.Fatal(err) + } + + const identity = "Test Key 1 (RSA)" + if err := kring[0].SignIdentity(identity, kring[1], nil); err != nil { + t.Fatal(err) + } + + ident, ok := kring[0].Identities[identity] + if !ok { + t.Fatal("identity missing from key after signing") + } + + checked := false + for _, sig := range ident.Signatures { + if sig.IssuerKeyId == nil || *sig.IssuerKeyId != kring[1].PrimaryKey.KeyId { + continue + } + + if err := kring[1].PrimaryKey.VerifyUserIdSignature(identity, kring[0].PrimaryKey, sig); err != nil { + t.Fatalf("error verifying new identity signature: %s", err) + } + checked = true + break + } + + if !checked { + t.Fatal("didn't find identity signature in Entity") + } +} + +func TestNewEntityWithPreferredHash(t *testing.T) { + c := &packet.Config{ + DefaultHash: crypto.SHA256, + } + entity, err := NewEntity("Golang Gopher", "Test Key", "no-reply@golang.com", c) + if err != nil { + t.Fatal(err) + } + + for _, identity := range entity.Identities { + if len(identity.SelfSignature.PreferredHash) == 0 { + t.Fatal("didn't find a preferred hash in self signature") + } + ph := hashToHashId(c.DefaultHash) + if identity.SelfSignature.PreferredHash[0] != ph { + t.Fatalf("Expected preferred hash to be %d, got %d", ph, identity.SelfSignature.PreferredHash[0]) + } + } +} + +func TestNewEntityWithoutPreferredHash(t *testing.T) { + entity, err := NewEntity("Golang Gopher", "Test Key", "no-reply@golang.com", nil) + if err != nil { + t.Fatal(err) + } + + for _, identity := range entity.Identities { + if len(identity.SelfSignature.PreferredHash) != 0 { + t.Fatalf("Expected preferred hash to be empty but got length %d", len(identity.SelfSignature.PreferredHash)) + } + } +} + +const expiringKeyHex = "988d0451d1ec5d010400ba3385721f2dc3f4ab096b2ee867ab77213f0a27a8538441c35d2fa225b08798a1439a66a5150e6bdc3f40f5d28d588c712394c632b6299f77db8c0d48d37903fb72ebd794d61be6aa774688839e5fdecfe06b2684cc115d240c98c66cb1ef22ae84e3aa0c2b0c28665c1e7d4d044e7f270706193f5223c8d44e0d70b7b8da830011010001b40f4578706972792074657374206b657988be041301020028050251d1ec5d021b03050900278d00060b090807030206150802090a0b0416020301021e01021780000a091072589ad75e237d8c033503fd10506d72837834eb7f994117740723adc39227104b0d326a1161871c0b415d25b4aedef946ca77ea4c05af9c22b32cf98be86ab890111fced1ee3f75e87b7cc3c00dc63bbc85dfab91c0dc2ad9de2c4d13a34659333a85c6acc1a669c5e1d6cecb0cf1e56c10e72d855ae177ddc9e766f9b2dda57ccbb75f57156438bbdb4e42b88d0451d1ec5d0104009c64906559866c5cb61578f5846a94fcee142a489c9b41e67b12bb54cfe86eb9bc8566460f9a720cb00d6526fbccfd4f552071a8e3f7744b1882d01036d811ee5a3fb91a1c568055758f43ba5d2c6a9676b012f3a1a89e47bbf624f1ad571b208f3cc6224eb378f1645dd3d47584463f9eadeacfd1ce6f813064fbfdcc4b5a53001101000188a504180102000f021b0c050251d1f06b050900093e89000a091072589ad75e237d8c20e00400ab8310a41461425b37889c4da28129b5fae6084fafbc0a47dd1adc74a264c6e9c9cc125f40462ee1433072a58384daef88c961c390ed06426a81b464a53194c4e291ddd7e2e2ba3efced01537d713bd111f48437bde2363446200995e8e0d4e528dda377fd1e8f8ede9c8e2198b393bd86852ce7457a7e3daf74d510461a5b77b88d0451d1ece8010400b3a519f83ab0010307e83bca895170acce8964a044190a2b368892f7a244758d9fc193482648acb1fb9780d28cc22d171931f38bb40279389fc9bf2110876d4f3db4fcfb13f22f7083877fe56592b3b65251312c36f83ffcb6d313c6a17f197dd471f0712aad15a8537b435a92471ba2e5b0c72a6c72536c3b567c558d7b6051001101000188a504180102000f021b0c050251d1f07b050900279091000a091072589ad75e237d8ce69e03fe286026afacf7c97ee20673864d4459a2240b5655219950643c7dba0ac384b1d4359c67805b21d98211f7b09c2a0ccf6410c8c04d4ff4a51293725d8d6570d9d8bb0e10c07d22357caeb49626df99c180be02d77d1fe8ed25e7a54481237646083a9f89a11566cd20b9e995b1487c5f9e02aeb434f3a1897cd416dd0a87861838da3e9e" +const subkeyUsageHex = "988d04533a52bc010400d26af43085558f65b9e7dbc90cb9238015259aed5e954637adcfa2181548b2d0b60c65f1f42ec5081cbf1bc0a8aa4900acfb77070837c58f26012fbce297d70afe96e759ad63531f0037538e70dbf8e384569b9720d99d8eb39d8d0a2947233ed242436cb6ac7dfe74123354b3d0119b5c235d3dd9c9d6c004f8ffaf67ad8583001101000188b7041f010200210502533b8552170c8001ce094aa433f7040bb2ddf0be3893cb843d0fe70c020700000a0910a42704b92866382aa98404009d63d916a27543da4221c60087c33f1c44bec9998c5438018ed370cca4962876c748e94b73eb39c58eb698063f3fd6346d58dd2a11c0247934c4a9d71f24754f7468f96fb24c3e791dd2392b62f626148ad724189498cbf993db2df7c0cdc2d677c35da0f16cb16c9ce7c33b4de65a4a91b1d21a130ae9cc26067718910ef8e2b417556d627261203c756d627261407379642e65642e61753e88b80413010200220502533a52bc021b03060b090807030206150802090a0b0416020301021e01021780000a0910a42704b92866382a47840400c0c2bd04f5fca586de408b395b3c280a278259c93eaaa8b79a53b97003f8ed502a8a00446dd9947fb462677e4fcac0dac2f0701847d15130aadb6cd9e0705ea0cf5f92f129136c7be21a718d46c8e641eb7f044f2adae573e11ae423a0a9ca51324f03a8a2f34b91fa40c3cc764bee4dccadedb54c768ba0469b683ea53f1c29b88d04533a52bc01040099c92a5d6f8b744224da27bc2369127c35269b58bec179de6bbc038f749344222f85a31933224f26b70243c4e4b2d242f0c4777eaef7b5502f9dad6d8bf3aaeb471210674b74de2d7078af497d55f5cdad97c7bedfbc1b41e8065a97c9c3d344b21fc81d27723af8e374bc595da26ea242dccb6ae497be26eea57e563ed517e90011010001889f0418010200090502533a52bc021b0c000a0910a42704b92866382afa1403ff70284c2de8a043ff51d8d29772602fa98009b7861c540535f874f2c230af8caf5638151a636b21f8255003997ccd29747fdd06777bb24f9593bd7d98a3e887689bf902f999915fcc94625ae487e5d13e6616f89090ebc4fdc7eb5cad8943e4056995bb61c6af37f8043016876a958ec7ebf39c43d20d53b7f546cfa83e8d2604b88d04533b8283010400c0b529316dbdf58b4c54461e7e669dc11c09eb7f73819f178ccd4177b9182b91d138605fcf1e463262fabefa73f94a52b5e15d1904635541c7ea540f07050ce0fb51b73e6f88644cec86e91107c957a114f69554548a85295d2b70bd0b203992f76eb5d493d86d9eabcaa7ef3fc7db7e458438db3fcdb0ca1cc97c638439a9170011010001889f0418010200090502533b8283021b0c000a0910a42704b92866382adc6d0400cfff6258485a21675adb7a811c3e19ebca18851533f75a7ba317950b9997fda8d1a4c8c76505c08c04b6c2cc31dc704d33da36a21273f2b388a1a706f7c3378b66d887197a525936ed9a69acb57fe7f718133da85ec742001c5d1864e9c6c8ea1b94f1c3759cebfd93b18606066c063a63be86085b7e37bdbc65f9a915bf084bb901a204533b85cd110400aed3d2c52af2b38b5b67904b0ef73d6dd7aef86adb770e2b153cd22489654dcc91730892087bb9856ae2d9f7ed1eb48f214243fe86bfe87b349ebd7c30e630e49c07b21fdabf78b7a95c8b7f969e97e3d33f2e074c63552ba64a2ded7badc05ce0ea2be6d53485f6900c7860c7aa76560376ce963d7271b9b54638a4028b573f00a0d8854bfcdb04986141568046202192263b9b67350400aaa1049dbc7943141ef590a70dcb028d730371d92ea4863de715f7f0f16d168bd3dc266c2450457d46dcbbf0b071547e5fbee7700a820c3750b236335d8d5848adb3c0da010e998908dfd93d961480084f3aea20b247034f8988eccb5546efaa35a92d0451df3aaf1aee5aa36a4c4d462c760ecd9cebcabfbe1412b1f21450f203fd126687cd486496e971a87fd9e1a8a765fe654baa219a6871ab97768596ab05c26c1aeea8f1a2c72395a58dbc12ef9640d2b95784e974a4d2d5a9b17c25fedacfe551bda52602de8f6d2e48443f5dd1a2a2a8e6a5e70ecdb88cd6e766ad9745c7ee91d78cc55c3d06536b49c3fee6c3d0b6ff0fb2bf13a314f57c953b8f4d93bf88e70418010200090502533b85cd021b0200520910a42704b92866382a47200419110200060502533b85cd000a091042ce2c64bc0ba99214b2009e26b26852c8b13b10c35768e40e78fbbb48bd084100a0c79d9ea0844fa5853dd3c85ff3ecae6f2c9dd6c557aa04008bbbc964cd65b9b8299d4ebf31f41cc7264b8cf33a00e82c5af022331fac79efc9563a822497ba012953cefe2629f1242fcdcb911dbb2315985bab060bfd58261ace3c654bdbbe2e8ed27a46e836490145c86dc7bae15c011f7e1ffc33730109b9338cd9f483e7cef3d2f396aab5bd80efb6646d7e778270ee99d934d187dd98" +const revokedKeyHex = "988d045331ce82010400c4fdf7b40a5477f206e6ee278eaef888ca73bf9128a9eef9f2f1ddb8b7b71a4c07cfa241f028a04edb405e4d916c61d6beabc333813dc7b484d2b3c52ee233c6a79b1eea4e9cc51596ba9cd5ac5aeb9df62d86ea051055b79d03f8a4fa9f38386f5bd17529138f3325d46801514ea9047977e0829ed728e68636802796801be10011010001889f04200102000905025331d0e3021d03000a0910a401d9f09a34f7c042aa040086631196405b7e6af71026b88e98012eab44aa9849f6ef3fa930c7c9f23deaedba9db1538830f8652fb7648ec3fcade8dbcbf9eaf428e83c6cbcc272201bfe2fbb90d41963397a7c0637a1a9d9448ce695d9790db2dc95433ad7be19eb3de72dacf1d6db82c3644c13eae2a3d072b99bb341debba012c5ce4006a7d34a1f4b94b444526567205265766f6b657220283c52656727732022424d204261726973746122204b657920262530305c303e5c29203c72656740626d626172697374612e636f2e61753e88b704130102002205025331ce82021b03060b090807030206150802090a0b0416020301021e01021780000a0910a401d9f09a34f7c0019c03f75edfbeb6a73e7225ad3cc52724e2872e04260d7daf0d693c170d8c4b243b8767bc7785763533febc62ec2600c30603c433c095453ede59ff2fcabeb84ce32e0ed9d5cf15ffcbc816202b64370d4d77c1e9077d74e94a16fb4fa2e5bec23a56d7a73cf275f91691ae1801a976fcde09e981a2f6327ac27ea1fecf3185df0d56889c04100102000605025331cfb5000a0910fe9645554e8266b64b4303fc084075396674fb6f778d302ac07cef6bc0b5d07b66b2004c44aef711cbac79617ef06d836b4957522d8772dd94bf41a2f4ac8b1ee6d70c57503f837445a74765a076d07b829b8111fc2a918423ddb817ead7ca2a613ef0bfb9c6b3562aec6c3cf3c75ef3031d81d95f6563e4cdcc9960bcb386c5d757b104fcca5fe11fc709df884604101102000605025331cfe7000a09107b15a67f0b3ddc0317f6009e360beea58f29c1d963a22b962b80788c3fa6c84e009d148cfde6b351469b8eae91187eff07ad9d08fcaab88d045331ce820104009f25e20a42b904f3fa555530fe5c46737cf7bd076c35a2a0d22b11f7e0b61a69320b768f4a80fe13980ce380d1cfc4a0cd8fbe2d2e2ef85416668b77208baa65bf973fe8e500e78cc310d7c8705cdb34328bf80e24f0385fce5845c33bc7943cf6b11b02348a23da0bf6428e57c05135f2dc6bd7c1ce325d666d5a5fd2fd5e410011010001889f04180102000905025331ce82021b0c000a0910a401d9f09a34f7c0418003fe34feafcbeaef348a800a0d908a7a6809cc7304017d820f70f0474d5e23cb17e38b67dc6dca282c6ca00961f4ec9edf2738d0f087b1d81e4871ef08e1798010863afb4eac4c44a376cb343be929c5be66a78cfd4456ae9ec6a99d97f4e1c3ff3583351db2147a65c0acef5c003fb544ab3a2e2dc4d43646f58b811a6c3a369d1f" +const revokedSubkeyHex = "988d04533121f6010400aefc803a3e4bb1a61c86e8a86d2726c6a43e0079e9f2713f1fa017e9854c83877f4aced8e331d675c67ea83ddab80aacbfa0b9040bb12d96f5a3d6be09455e2a76546cbd21677537db941cab710216b6d24ec277ee0bd65b910f416737ed120f6b93a9d3b306245c8cfd8394606fdb462e5cf43c551438d2864506c63367fc890011010001b41d416c696365203c616c69636540626d626172697374612e636f2e61753e88bb041301020025021b03060b090807030206150802090a0b0416020301021e01021780050253312798021901000a09104ef7e4beccde97f015a803ff5448437780f63263b0df8442a995e7f76c221351a51edd06f2063d8166cf3157aada4923dfc44aa0f2a6a4da5cf83b7fe722ba8ab416c976e77c6b5682e7f1069026673bd0de56ba06fd5d7a9f177607f277d9b55ff940a638c3e68525c67517e2b3d976899b93ca267f705b3e5efad7d61220e96b618a4497eab8d04403d23f8846041011020006050253312910000a09107b15a67f0b3ddc03d96e009f50b6365d86c4be5d5e9d0ea42d5e56f5794c617700a0ab274e19c2827780016d23417ce89e0a2c0d987d889c04100102000605025331cf7a000a0910a401d9f09a34f7c0ee970400aca292f213041c9f3b3fc49148cbda9d84afee6183c8dd6c5ff2600b29482db5fecd4303797be1ee6d544a20a858080fec43412061c9a71fae4039fd58013b4ae341273e6c66ad4c7cdd9e68245bedb260562e7b166f2461a1032f2b38c0e0e5715fb3d1656979e052b55ca827a76f872b78a9fdae64bc298170bfcebedc1271b41a416c696365203c616c696365407379646973702e6f722e61753e88b804130102002205025331278b021b03060b090807030206150802090a0b0416020301021e01021780000a09104ef7e4beccde97f06a7003fa03c3af68d272ebc1fa08aa72a03b02189c26496a2833d90450801c4e42c5b5f51ad96ce2d2c9cef4b7c02a6a2fcf1412d6a2d486098eb762f5010a201819c17fd2888aec8eda20c65a3b75744de7ee5cc8ac7bfc470cbe3cb982720405a27a3c6a8c229cfe36905f881b02ed5680f6a8f05866efb9d6c5844897e631deb949ca8846041011020006050253312910000a09107b15a67f0b3ddc0347bc009f7fa35db59147469eb6f2c5aaf6428accb138b22800a0caa2f5f0874bacc5909c652a57a31beda65eddd5889c04100102000605025331cf7a000a0910a401d9f09a34f7c0316403ff46f2a5c101256627f16384d34a38fb47a6c88ba60506843e532d91614339fccae5f884a5741e7582ffaf292ba38ee10a270a05f139bde3814b6a077e8cd2db0f105ebea2a83af70d385f13b507fac2ad93ff79d84950328bb86f3074745a8b7f9b64990fb142e2a12976e27e8d09a28dc5621f957ac49091116da410ac3cbde1b88d04533121f6010400cbd785b56905e4192e2fb62a720727d43c4fa487821203cf72138b884b78b701093243e1d8c92a0248a6c0203a5a88693da34af357499abacaf4b3309c640797d03093870a323b4b6f37865f6eaa2838148a67df4735d43a90ca87942554cdf1c4a751b1e75f9fd4ce4e97e278d6c1c7ed59d33441df7d084f3f02beb68896c70011010001889f0418010200090502533121f6021b0c000a09104ef7e4beccde97f0b98b03fc0a5ccf6a372995835a2f5da33b282a7d612c0ab2a97f59cf9fff73e9110981aac2858c41399afa29624a7fd8a0add11654e3d882c0fd199e161bdad65e5e2548f7b68a437ea64293db1246e3011cbb94dc1bcdeaf0f2539bd88ff16d95547144d97cead6a8c5927660a91e6db0d16eb36b7b49a3525b54d1644e65599b032b7eb901a204533127a0110400bd3edaa09eff9809c4edc2c2a0ebe52e53c50a19c1e49ab78e6167bf61473bb08f2050d78a5cbbc6ed66aff7b42cd503f16b4a0b99fa1609681fca9b7ce2bbb1a5b3864d6cdda4d7ef7849d156d534dea30fb0efb9e4cf8959a2b2ce623905882d5430b995a15c3b9fe92906086788b891002924f94abe139b42cbbfaaabe42f00a0b65dc1a1ad27d798adbcb5b5ad02d2688c89477b03ff4eebb6f7b15a73b96a96bed201c0e5e4ea27e4c6e2dd1005b94d4b90137a5b1cf5e01c6226c070c4cc999938101578877ee76d296b9aab8246d57049caacf489e80a3f40589cade790a020b1ac146d6f7a6241184b8c7fcde680eae3188f5dcbe846d7f7bdad34f6fcfca08413e19c1d5df83fc7c7c627d493492e009c2f52a80400a2fe82de87136fd2e8845888c4431b032ba29d9a29a804277e31002a8201fb8591a3e55c7a0d0881496caf8b9fb07544a5a4879291d0dc026a0ea9e5bd88eb4aa4947bbd694b25012e208a250d65ddc6f1eea59d3aed3b4ec15fcab85e2afaa23a40ab1ef9ce3e11e1bc1c34a0e758e7aa64deb8739276df0af7d4121f834a9b88e70418010200090502533127a0021b02005209104ef7e4beccde97f047200419110200060502533127a0000a0910dbce4ee19529437fe045009c0b32f5ead48ee8a7e98fac0dea3d3e6c0e2c552500a0ad71fadc5007cfaf842d9b7db3335a8cdad15d3d1a6404009b08e2c68fe8f3b45c1bb72a4b3278cdf3012aa0f229883ad74aa1f6000bb90b18301b2f85372ca5d6b9bf478d235b733b1b197d19ccca48e9daf8e890cb64546b4ce1b178faccfff07003c172a2d4f5ebaba9f57153955f3f61a9b80a4f5cb959908f8b211b03b7026a8a82fc612bfedd3794969bcf458c4ce92be215a1176ab88d045331d144010400a5063000c5aaf34953c1aa3bfc95045b3aab9882b9a8027fecfe2142dc6b47ba8aca667399990244d513dd0504716908c17d92c65e74219e004f7b83fc125e575dd58efec3ab6dd22e3580106998523dea42ec75bf9aa111734c82df54630bebdff20fe981cfc36c76f865eb1c2fb62c9e85bc3a6e5015a361a2eb1c8431578d0011010001889f04280102000905025331d433021d03000a09104ef7e4beccde97f02e5503ff5e0630d1b65291f4882b6d40a29da4616bb5088717d469fbcc3648b8276de04a04988b1f1b9f3e18f52265c1f8b6c85861691c1a6b8a3a25a1809a0b32ad330aec5667cb4262f4450649184e8113849b05e5ad06a316ea80c001e8e71838190339a6e48bbde30647bcf245134b9a97fa875c1d83a9862cae87ffd7e2c4ce3a1b89013d04180102000905025331d144021b0200a809104ef7e4beccde97f09d2004190102000605025331d144000a0910677815e371c2fd23522203fe22ab62b8e7a151383cea3edd3a12995693911426f8ccf125e1f6426388c0010f88d9ca7da2224aee8d1c12135998640c5e1813d55a93df472faae75bef858457248db41b4505827590aeccf6f9eb646da7f980655dd3050c6897feddddaca90676dee856d66db8923477d251712bb9b3186b4d0114daf7d6b59272b53218dd1da94a03ff64006fcbe71211e5daecd9961fba66cdb6de3f914882c58ba5beddeba7dcb950c1156d7fba18c19ea880dccc800eae335deec34e3b84ac75ffa24864f782f87815cda1c0f634b3dd2fa67cea30811d21723d21d9551fa12ccbcfa62b6d3a15d01307b99925707992556d50065505b090aadb8579083a20fe65bd2a270da9b011" +const missingCrossSignatureKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- +Charset: UTF-8 + +mQENBFMYynYBCACVOZ3/e8Bm2b9KH9QyIlHGo/i1bnkpqsgXj8tpJ2MIUOnXMMAY +ztW7kKFLCmgVdLIC0vSoLA4yhaLcMojznh/2CcUglZeb6Ao8Gtelr//Rd5DRfPpG +zqcfUo+m+eO1co2Orabw0tZDfGpg5p3AYl0hmxhUyYSc/xUq93xL1UJzBFgYXY54 +QsM8dgeQgFseSk/YvdP5SMx1ev+eraUyiiUtWzWrWC1TdyRa5p4UZg6Rkoppf+WJ +QrW6BWrhAtqATHc8ozV7uJjeONjUEq24roRc/OFZdmQQGK6yrzKnnbA6MdHhqpdo +9kWDcXYb7pSE63Lc+OBa5X2GUVvXJLS/3nrtABEBAAG0F2ludmFsaWQtc2lnbmlu +Zy1zdWJrZXlziQEoBBMBAgASBQJTnKB5AhsBAgsHAhUIAh4BAAoJEO3UDQUIHpI/ +dN4H/idX4FQ1LIZCnpHS/oxoWQWfpRgdKAEM0qCqjMgiipJeEwSQbqjTCynuh5/R +JlODDz85ABR06aoF4l5ebGLQWFCYifPnJZ/Yf5OYcMGtb7dIbqxWVFL9iLMO/oDL +ioI3dotjPui5e+2hI9pVH1UHB/bZ/GvMGo6Zg0XxLPolKQODMVjpjLAQ0YJ3spew +RAmOGre6tIvbDsMBnm8qREt7a07cBJ6XK7xjxYaZHQBiHVxyEWDa6gyANONx8duW +/fhQ/zDTnyVM/ik6VO0Ty9BhPpcEYLFwh5c1ilFari1ta3e6qKo6ZGa9YMk/REhu +yBHd9nTkI+0CiQUmbckUiVjDKKe5AQ0EUxjKdgEIAJcXQeP+NmuciE99YcJoffxv +2gVLU4ZXBNHEaP0mgaJ1+tmMD089vUQAcyGRvw8jfsNsVZQIOAuRxY94aHQhIRHR +bUzBN28ofo/AJJtfx62C15xt6fDKRV6HXYqAiygrHIpEoRLyiN69iScUsjIJeyFL +C8wa72e8pSL6dkHoaV1N9ZH/xmrJ+k0vsgkQaAh9CzYufncDxcwkoP+aOlGtX1gP +WwWoIbz0JwLEMPHBWvDDXQcQPQTYQyj+LGC9U6f9VZHN25E94subM1MjuT9OhN9Y +MLfWaaIc5WyhLFyQKW2Upofn9wSFi8ubyBnv640Dfd0rVmaWv7LNTZpoZ/GbJAMA +EQEAAYkBHwQYAQIACQUCU5ygeQIbAgAKCRDt1A0FCB6SP0zCB/sEzaVR38vpx+OQ +MMynCBJrakiqDmUZv9xtplY7zsHSQjpd6xGflbU2n+iX99Q+nav0ETQZifNUEd4N +1ljDGQejcTyKD6Pkg6wBL3x9/RJye7Zszazm4+toJXZ8xJ3800+BtaPoI39akYJm ++ijzbskvN0v/j5GOFJwQO0pPRAFtdHqRs9Kf4YanxhedB4dIUblzlIJuKsxFit6N +lgGRblagG3Vv2eBszbxzPbJjHCgVLR3RmrVezKOsZjr/2i7X+xLWIR0uD3IN1qOW +CXQxLBizEEmSNVNxsp7KPGTLnqO3bPtqFirxS9PJLIMPTPLNBY7ZYuPNTMqVIUWF +4artDmrG +=7FfJ +-----END PGP PUBLIC KEY BLOCK-----` + +const invalidCrossSignatureKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQENBFMYynYBCACVOZ3/e8Bm2b9KH9QyIlHGo/i1bnkpqsgXj8tpJ2MIUOnXMMAY +ztW7kKFLCmgVdLIC0vSoLA4yhaLcMojznh/2CcUglZeb6Ao8Gtelr//Rd5DRfPpG +zqcfUo+m+eO1co2Orabw0tZDfGpg5p3AYl0hmxhUyYSc/xUq93xL1UJzBFgYXY54 +QsM8dgeQgFseSk/YvdP5SMx1ev+eraUyiiUtWzWrWC1TdyRa5p4UZg6Rkoppf+WJ +QrW6BWrhAtqATHc8ozV7uJjeONjUEq24roRc/OFZdmQQGK6yrzKnnbA6MdHhqpdo +9kWDcXYb7pSE63Lc+OBa5X2GUVvXJLS/3nrtABEBAAG0F2ludmFsaWQtc2lnbmlu +Zy1zdWJrZXlziQEoBBMBAgASBQJTnKB5AhsBAgsHAhUIAh4BAAoJEO3UDQUIHpI/ +dN4H/idX4FQ1LIZCnpHS/oxoWQWfpRgdKAEM0qCqjMgiipJeEwSQbqjTCynuh5/R +JlODDz85ABR06aoF4l5ebGLQWFCYifPnJZ/Yf5OYcMGtb7dIbqxWVFL9iLMO/oDL +ioI3dotjPui5e+2hI9pVH1UHB/bZ/GvMGo6Zg0XxLPolKQODMVjpjLAQ0YJ3spew +RAmOGre6tIvbDsMBnm8qREt7a07cBJ6XK7xjxYaZHQBiHVxyEWDa6gyANONx8duW +/fhQ/zDTnyVM/ik6VO0Ty9BhPpcEYLFwh5c1ilFari1ta3e6qKo6ZGa9YMk/REhu +yBHd9nTkI+0CiQUmbckUiVjDKKe5AQ0EUxjKdgEIAIINDqlj7X6jYKc6DjwrOkjQ +UIRWbQQar0LwmNilehmt70g5DCL1SYm9q4LcgJJ2Nhxj0/5qqsYib50OSWMcKeEe +iRXpXzv1ObpcQtI5ithp0gR53YPXBib80t3bUzomQ5UyZqAAHzMp3BKC54/vUrSK +FeRaxDzNLrCeyI00+LHNUtwghAqHvdNcsIf8VRumK8oTm3RmDh0TyjASWYbrt9c8 +R1Um3zuoACOVy+mEIgIzsfHq0u7dwYwJB5+KeM7ZLx+HGIYdUYzHuUE1sLwVoELh ++SHIGHI1HDicOjzqgajShuIjj5hZTyQySVprrsLKiXS6NEwHAP20+XjayJ/R3tEA +EQEAAYkCPgQYAQIBKAUCU5ygeQIbAsBdIAQZAQIABgUCU5ygeQAKCRCpVlnFZmhO +52RJB/9uD1MSa0wjY6tHOIgquZcP3bHBvHmrHNMw9HR2wRCMO91ZkhrpdS3ZHtgb +u3/55etj0FdvDo1tb8P8FGSVtO5Vcwf5APM8sbbqoi8L951Q3i7qt847lfhu6sMl +w0LWFvPTOLHrliZHItPRjOltS1WAWfr2jUYhsU9ytaDAJmvf9DujxEOsN5G1YJep +54JCKVCkM/y585Zcnn+yxk/XwqoNQ0/iJUT9qRrZWvoeasxhl1PQcwihCwss44A+ +YXaAt3hbk+6LEQuZoYS73yR3WHj+42tfm7YxRGeubXfgCEz/brETEWXMh4pe0vCL +bfWrmfSPq2rDegYcAybxRQz0lF8PAAoJEO3UDQUIHpI/exkH/0vQfdHA8g/N4T6E +i6b1CUVBAkvtdJpCATZjWPhXmShOw62gkDw306vHPilL4SCvEEi4KzG72zkp6VsB +DSRcpxCwT4mHue+duiy53/aRMtSJ+vDfiV1Vhq+3sWAck/yUtfDU9/u4eFaiNok1 +8/Gd7reyuZt5CiJnpdPpjCwelK21l2w7sHAnJF55ITXdOxI8oG3BRKufz0z5lyDY +s2tXYmhhQIggdgelN8LbcMhWs/PBbtUr6uZlNJG2lW1yscD4aI529VjwJlCeo745 +U7pO4eF05VViUJ2mmfoivL3tkhoTUWhx8xs8xCUcCg8DoEoSIhxtOmoTPR22Z9BL +6LCg2mg= +=Dhm4 +-----END PGP PUBLIC KEY BLOCK-----` + +const goodCrossSignatureKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1 + +mI0EVUqeVwEEAMufHRrMPWK3gyvi0O0tABCs/oON9zV9KDZlr1a1M91ShCSFwCPo +7r80PxdWVWcj0V5h50/CJYtpN3eE/mUIgW2z1uDYQF1OzrQ8ubrksfsJvpAhENom +lTQEppv9mV8qhcM278teb7TX0pgrUHLYF5CfPdp1L957JLLXoQR/lwLVABEBAAG0 +E2dvb2Qtc2lnbmluZy1zdWJrZXmIuAQTAQIAIgUCVUqeVwIbAwYLCQgHAwIGFQgC +CQoLBBYCAwECHgECF4AACgkQNRjL95IRWP69XQQAlH6+eyXJN4DZTLX78KGjHrsw +6FCvxxClEPtPUjcJy/1KCRQmtLAt9PbbA78dvgzjDeZMZqRAwdjyJhjyg/fkU2OH +7wq4ktjUu+dLcOBb+BFMEY+YjKZhf6EJuVfxoTVr5f82XNPbYHfTho9/OABKH6kv +X70PaKZhbwnwij8Nts65AaIEVUqftREEAJ3WxZfqAX0bTDbQPf2CMT2IVMGDfhK7 +GyubOZgDFFjwUJQvHNvsrbeGLZ0xOBumLINyPO1amIfTgJNm1iiWFWfmnHReGcDl +y5mpYG60Mb79Whdcer7CMm3AqYh/dW4g6IB02NwZMKoUHo3PXmFLxMKXnWyJ0clw +R0LI/Qn509yXAKDh1SO20rqrBM+EAP2c5bfI98kyNwQAi3buu94qo3RR1ZbvfxgW +CKXDVm6N99jdZGNK7FbRifXqzJJDLcXZKLnstnC4Sd3uyfyf1uFhmDLIQRryn5m+ +LBYHfDBPN3kdm7bsZDDq9GbTHiFZUfm/tChVKXWxkhpAmHhU/tH6GGzNSMXuIWSO +aOz3Rqq0ED4NXyNKjdF9MiwD/i83S0ZBc0LmJYt4Z10jtH2B6tYdqnAK29uQaadx +yZCX2scE09UIm32/w7pV77CKr1Cp/4OzAXS1tmFzQ+bX7DR+Gl8t4wxr57VeEMvl +BGw4Vjh3X8//m3xynxycQU18Q1zJ6PkiMyPw2owZ/nss3hpSRKFJsxMLhW3fKmKr +Ey2KiOcEGAECAAkFAlVKn7UCGwIAUgkQNRjL95IRWP5HIAQZEQIABgUCVUqftQAK +CRD98VjDN10SqkWrAKDTpEY8D8HC02E/KVC5YUI01B30wgCgurpILm20kXEDCeHp +C5pygfXw1DJrhAP+NyPJ4um/bU1I+rXaHHJYroYJs8YSweiNcwiHDQn0Engh/mVZ +SqLHvbKh2dL/RXymC3+rjPvQf5cup9bPxNMa6WagdYBNAfzWGtkVISeaQW+cTEp/ +MtgVijRGXR/lGLGETPg2X3Afwn9N9bLMBkBprKgbBqU7lpaoPupxT61bL70= +=vtbN +-----END PGP PUBLIC KEY BLOCK-----` diff --git a/vendor/golang.org/x/crypto/openpgp/packet/compressed.go b/vendor/golang.org/x/crypto/openpgp/packet/compressed.go new file mode 100644 index 0000000000000000000000000000000000000000..e8f0b5caa7dfed6e6f3b078722747d673253e1bc --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/compressed.go @@ -0,0 +1,123 @@ +// 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 packet + +import ( + "compress/bzip2" + "compress/flate" + "compress/zlib" + "golang.org/x/crypto/openpgp/errors" + "io" + "strconv" +) + +// Compressed represents a compressed OpenPGP packet. The decompressed contents +// will contain more OpenPGP packets. See RFC 4880, section 5.6. +type Compressed struct { + Body io.Reader +} + +const ( + NoCompression = flate.NoCompression + BestSpeed = flate.BestSpeed + BestCompression = flate.BestCompression + DefaultCompression = flate.DefaultCompression +) + +// CompressionConfig contains compressor configuration settings. +type CompressionConfig struct { + // Level is the compression level to use. It must be set to + // between -1 and 9, with -1 causing the compressor to use the + // default compression level, 0 causing the compressor to use + // no compression and 1 to 9 representing increasing (better, + // slower) compression levels. If Level is less than -1 or + // more then 9, a non-nil error will be returned during + // encryption. See the constants above for convenient common + // settings for Level. + Level int +} + +func (c *Compressed) parse(r io.Reader) error { + var buf [1]byte + _, err := readFull(r, buf[:]) + if err != nil { + return err + } + + switch buf[0] { + case 1: + c.Body = flate.NewReader(r) + case 2: + c.Body, err = zlib.NewReader(r) + case 3: + c.Body = bzip2.NewReader(r) + default: + err = errors.UnsupportedError("unknown compression algorithm: " + strconv.Itoa(int(buf[0]))) + } + + return err +} + +// compressedWriterCloser represents the serialized compression stream +// header and the compressor. Its Close() method ensures that both the +// compressor and serialized stream header are closed. Its Write() +// method writes to the compressor. +type compressedWriteCloser struct { + sh io.Closer // Stream Header + c io.WriteCloser // Compressor +} + +func (cwc compressedWriteCloser) Write(p []byte) (int, error) { + return cwc.c.Write(p) +} + +func (cwc compressedWriteCloser) Close() (err error) { + err = cwc.c.Close() + if err != nil { + return err + } + + return cwc.sh.Close() +} + +// SerializeCompressed serializes a compressed data packet to w and +// returns a WriteCloser to which the literal data packets themselves +// can be written and which MUST be closed on completion. If cc is +// nil, sensible defaults will be used to configure the compression +// algorithm. +func SerializeCompressed(w io.WriteCloser, algo CompressionAlgo, cc *CompressionConfig) (literaldata io.WriteCloser, err error) { + compressed, err := serializeStreamHeader(w, packetTypeCompressed) + if err != nil { + return + } + + _, err = compressed.Write([]byte{uint8(algo)}) + if err != nil { + return + } + + level := DefaultCompression + if cc != nil { + level = cc.Level + } + + var compressor io.WriteCloser + switch algo { + case CompressionZIP: + compressor, err = flate.NewWriter(compressed, level) + case CompressionZLIB: + compressor, err = zlib.NewWriterLevel(compressed, level) + default: + s := strconv.Itoa(int(algo)) + err = errors.UnsupportedError("Unsupported compression algorithm: " + s) + } + if err != nil { + return + } + + literaldata = compressedWriteCloser{compressed, compressor} + + return +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/compressed_test.go b/vendor/golang.org/x/crypto/openpgp/packet/compressed_test.go new file mode 100644 index 0000000000000000000000000000000000000000..cb2d70bd411a131bdae47e94aade6594d443b440 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/compressed_test.go @@ -0,0 +1,41 @@ +// 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 packet + +import ( + "bytes" + "encoding/hex" + "io" + "io/ioutil" + "testing" +) + +func TestCompressed(t *testing.T) { + packet, err := Read(readerFromHex(compressedHex)) + if err != nil { + t.Errorf("failed to read Compressed: %s", err) + return + } + + c, ok := packet.(*Compressed) + if !ok { + t.Error("didn't find Compressed packet") + return + } + + contents, err := ioutil.ReadAll(c.Body) + if err != nil && err != io.EOF { + t.Error(err) + return + } + + expected, _ := hex.DecodeString(compressedExpectedHex) + if !bytes.Equal(expected, contents) { + t.Errorf("got:%x want:%x", contents, expected) + } +} + +const compressedHex = "a3013b2d90c4e02b72e25f727e5e496a5e49b11e1700" +const compressedExpectedHex = "cb1062004d14c8fe636f6e74656e74732e0a" diff --git a/vendor/golang.org/x/crypto/openpgp/packet/config.go b/vendor/golang.org/x/crypto/openpgp/packet/config.go new file mode 100644 index 0000000000000000000000000000000000000000..c76eecc963acd2e901c99a2d9d5da390fc39c1fc --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/config.go @@ -0,0 +1,91 @@ +// 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 packet + +import ( + "crypto" + "crypto/rand" + "io" + "time" +) + +// Config collects a number of parameters along with sensible defaults. +// A nil *Config is valid and results in all default values. +type Config struct { + // Rand provides the source of entropy. + // If nil, the crypto/rand Reader is used. + Rand io.Reader + // DefaultHash is the default hash function to be used. + // If zero, SHA-256 is used. + DefaultHash crypto.Hash + // DefaultCipher is the cipher to be used. + // If zero, AES-128 is used. + DefaultCipher CipherFunction + // Time returns the current time as the number of seconds since the + // epoch. If Time is nil, time.Now is used. + Time func() time.Time + // DefaultCompressionAlgo is the compression algorithm to be + // applied to the plaintext before encryption. If zero, no + // compression is done. + DefaultCompressionAlgo CompressionAlgo + // CompressionConfig configures the compression settings. + CompressionConfig *CompressionConfig + // S2KCount is only used for symmetric encryption. It + // determines the strength of the passphrase stretching when + // the said passphrase is hashed to produce a key. S2KCount + // should be between 1024 and 65011712, inclusive. If Config + // is nil or S2KCount is 0, the value 65536 used. Not all + // values in the above range can be represented. S2KCount will + // be rounded up to the next representable value if it cannot + // be encoded exactly. When set, it is strongly encrouraged to + // use a value that is at least 65536. See RFC 4880 Section + // 3.7.1.3. + S2KCount int + // RSABits is the number of bits in new RSA keys made with NewEntity. + // If zero, then 2048 bit keys are created. + RSABits int +} + +func (c *Config) Random() io.Reader { + if c == nil || c.Rand == nil { + return rand.Reader + } + return c.Rand +} + +func (c *Config) Hash() crypto.Hash { + if c == nil || uint(c.DefaultHash) == 0 { + return crypto.SHA256 + } + return c.DefaultHash +} + +func (c *Config) Cipher() CipherFunction { + if c == nil || uint8(c.DefaultCipher) == 0 { + return CipherAES128 + } + return c.DefaultCipher +} + +func (c *Config) Now() time.Time { + if c == nil || c.Time == nil { + return time.Now() + } + return c.Time() +} + +func (c *Config) Compression() CompressionAlgo { + if c == nil { + return CompressionNone + } + return c.DefaultCompressionAlgo +} + +func (c *Config) PasswordHashIterations() int { + if c == nil || c.S2KCount == 0 { + return 0 + } + return c.S2KCount +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go b/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go new file mode 100644 index 0000000000000000000000000000000000000000..266840d05a360a0a8b6ef55e32bd7a2492139d5a --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go @@ -0,0 +1,199 @@ +// 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 packet + +import ( + "crypto/rsa" + "encoding/binary" + "io" + "math/big" + "strconv" + + "golang.org/x/crypto/openpgp/elgamal" + "golang.org/x/crypto/openpgp/errors" +) + +const encryptedKeyVersion = 3 + +// EncryptedKey represents a public-key encrypted session key. See RFC 4880, +// section 5.1. +type EncryptedKey struct { + KeyId uint64 + Algo PublicKeyAlgorithm + CipherFunc CipherFunction // only valid after a successful Decrypt + Key []byte // only valid after a successful Decrypt + + encryptedMPI1, encryptedMPI2 parsedMPI +} + +func (e *EncryptedKey) parse(r io.Reader) (err error) { + var buf [10]byte + _, err = readFull(r, buf[:]) + if err != nil { + return + } + if buf[0] != encryptedKeyVersion { + return errors.UnsupportedError("unknown EncryptedKey version " + strconv.Itoa(int(buf[0]))) + } + e.KeyId = binary.BigEndian.Uint64(buf[1:9]) + e.Algo = PublicKeyAlgorithm(buf[9]) + switch e.Algo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: + e.encryptedMPI1.bytes, e.encryptedMPI1.bitLength, err = readMPI(r) + case PubKeyAlgoElGamal: + e.encryptedMPI1.bytes, e.encryptedMPI1.bitLength, err = readMPI(r) + if err != nil { + return + } + e.encryptedMPI2.bytes, e.encryptedMPI2.bitLength, err = readMPI(r) + } + _, err = consumeAll(r) + return +} + +func checksumKeyMaterial(key []byte) uint16 { + var checksum uint16 + for _, v := range key { + checksum += uint16(v) + } + return checksum +} + +// Decrypt decrypts an encrypted session key with the given private key. The +// private key must have been decrypted first. +// If config is nil, sensible defaults will be used. +func (e *EncryptedKey) Decrypt(priv *PrivateKey, config *Config) error { + var err error + var b []byte + + // TODO(agl): use session key decryption routines here to avoid + // padding oracle attacks. + switch priv.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: + b, err = rsa.DecryptPKCS1v15(config.Random(), priv.PrivateKey.(*rsa.PrivateKey), e.encryptedMPI1.bytes) + case PubKeyAlgoElGamal: + c1 := new(big.Int).SetBytes(e.encryptedMPI1.bytes) + c2 := new(big.Int).SetBytes(e.encryptedMPI2.bytes) + b, err = elgamal.Decrypt(priv.PrivateKey.(*elgamal.PrivateKey), c1, c2) + default: + err = errors.InvalidArgumentError("cannot decrypted encrypted session key with private key of type " + strconv.Itoa(int(priv.PubKeyAlgo))) + } + + if err != nil { + return err + } + + e.CipherFunc = CipherFunction(b[0]) + e.Key = b[1 : len(b)-2] + expectedChecksum := uint16(b[len(b)-2])<<8 | uint16(b[len(b)-1]) + checksum := checksumKeyMaterial(e.Key) + if checksum != expectedChecksum { + return errors.StructuralError("EncryptedKey checksum incorrect") + } + + return nil +} + +// Serialize writes the encrypted key packet, e, to w. +func (e *EncryptedKey) Serialize(w io.Writer) error { + var mpiLen int + switch e.Algo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: + mpiLen = 2 + len(e.encryptedMPI1.bytes) + case PubKeyAlgoElGamal: + mpiLen = 2 + len(e.encryptedMPI1.bytes) + 2 + len(e.encryptedMPI2.bytes) + default: + return errors.InvalidArgumentError("don't know how to serialize encrypted key type " + strconv.Itoa(int(e.Algo))) + } + + serializeHeader(w, packetTypeEncryptedKey, 1 /* version */ +8 /* key id */ +1 /* algo */ +mpiLen) + + w.Write([]byte{encryptedKeyVersion}) + binary.Write(w, binary.BigEndian, e.KeyId) + w.Write([]byte{byte(e.Algo)}) + + switch e.Algo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: + writeMPIs(w, e.encryptedMPI1) + case PubKeyAlgoElGamal: + writeMPIs(w, e.encryptedMPI1, e.encryptedMPI2) + default: + panic("internal error") + } + + return nil +} + +// SerializeEncryptedKey serializes an encrypted key packet to w that contains +// key, encrypted to pub. +// If config is nil, sensible defaults will be used. +func SerializeEncryptedKey(w io.Writer, pub *PublicKey, cipherFunc CipherFunction, key []byte, config *Config) error { + var buf [10]byte + buf[0] = encryptedKeyVersion + binary.BigEndian.PutUint64(buf[1:9], pub.KeyId) + buf[9] = byte(pub.PubKeyAlgo) + + keyBlock := make([]byte, 1 /* cipher type */ +len(key)+2 /* checksum */) + keyBlock[0] = byte(cipherFunc) + copy(keyBlock[1:], key) + checksum := checksumKeyMaterial(key) + keyBlock[1+len(key)] = byte(checksum >> 8) + keyBlock[1+len(key)+1] = byte(checksum) + + switch pub.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: + return serializeEncryptedKeyRSA(w, config.Random(), buf, pub.PublicKey.(*rsa.PublicKey), keyBlock) + case PubKeyAlgoElGamal: + return serializeEncryptedKeyElGamal(w, config.Random(), buf, pub.PublicKey.(*elgamal.PublicKey), keyBlock) + case PubKeyAlgoDSA, PubKeyAlgoRSASignOnly: + return errors.InvalidArgumentError("cannot encrypt to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo))) + } + + return errors.UnsupportedError("encrypting a key to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo))) +} + +func serializeEncryptedKeyRSA(w io.Writer, rand io.Reader, header [10]byte, pub *rsa.PublicKey, keyBlock []byte) error { + cipherText, err := rsa.EncryptPKCS1v15(rand, pub, keyBlock) + if err != nil { + return errors.InvalidArgumentError("RSA encryption failed: " + err.Error()) + } + + packetLen := 10 /* header length */ + 2 /* mpi size */ + len(cipherText) + + err = serializeHeader(w, packetTypeEncryptedKey, packetLen) + if err != nil { + return err + } + _, err = w.Write(header[:]) + if err != nil { + return err + } + return writeMPI(w, 8*uint16(len(cipherText)), cipherText) +} + +func serializeEncryptedKeyElGamal(w io.Writer, rand io.Reader, header [10]byte, pub *elgamal.PublicKey, keyBlock []byte) error { + c1, c2, err := elgamal.Encrypt(rand, pub, keyBlock) + if err != nil { + return errors.InvalidArgumentError("ElGamal encryption failed: " + err.Error()) + } + + packetLen := 10 /* header length */ + packetLen += 2 /* mpi size */ + (c1.BitLen()+7)/8 + packetLen += 2 /* mpi size */ + (c2.BitLen()+7)/8 + + err = serializeHeader(w, packetTypeEncryptedKey, packetLen) + if err != nil { + return err + } + _, err = w.Write(header[:]) + if err != nil { + return err + } + err = writeBig(w, c1) + if err != nil { + return err + } + return writeBig(w, c2) +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key_test.go b/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key_test.go new file mode 100644 index 0000000000000000000000000000000000000000..fee14cf3cf04edf499a430cb56b7b56c014ce455 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key_test.go @@ -0,0 +1,146 @@ +// 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 packet + +import ( + "bytes" + "crypto/rsa" + "encoding/hex" + "fmt" + "math/big" + "testing" +) + +func bigFromBase10(s string) *big.Int { + b, ok := new(big.Int).SetString(s, 10) + if !ok { + panic("bigFromBase10 failed") + } + return b +} + +var encryptedKeyPub = rsa.PublicKey{ + E: 65537, + N: bigFromBase10("115804063926007623305902631768113868327816898845124614648849934718568541074358183759250136204762053879858102352159854352727097033322663029387610959884180306668628526686121021235757016368038585212410610742029286439607686208110250133174279811431933746643015923132833417396844716207301518956640020862630546868823"), +} + +var encryptedKeyRSAPriv = &rsa.PrivateKey{ + PublicKey: encryptedKeyPub, + D: bigFromBase10("32355588668219869544751561565313228297765464314098552250409557267371233892496951383426602439009993875125222579159850054973310859166139474359774543943714622292329487391199285040721944491839695981199720170366763547754915493640685849961780092241140181198779299712578774460837139360803883139311171713302987058393"), +} + +var encryptedKeyPriv = &PrivateKey{ + PublicKey: PublicKey{ + PubKeyAlgo: PubKeyAlgoRSA, + }, + PrivateKey: encryptedKeyRSAPriv, +} + +func TestDecryptingEncryptedKey(t *testing.T) { + const encryptedKeyHex = "c18c032a67d68660df41c70104005789d0de26b6a50c985a02a13131ca829c413a35d0e6fa8d6842599252162808ac7439c72151c8c6183e76923fe3299301414d0c25a2f06a2257db3839e7df0ec964773f6e4c4ac7ff3b48c444237166dd46ba8ff443a5410dc670cb486672fdbe7c9dfafb75b4fea83af3a204fe2a7dfa86bd20122b4f3d2646cbeecb8f7be8" + const expectedKeyHex = "d930363f7e0308c333b9618617ea728963d8df993665ae7be1092d4926fd864b" + + p, err := Read(readerFromHex(encryptedKeyHex)) + if err != nil { + t.Errorf("error from Read: %s", err) + return + } + ek, ok := p.(*EncryptedKey) + if !ok { + t.Errorf("didn't parse an EncryptedKey, got %#v", p) + return + } + + if ek.KeyId != 0x2a67d68660df41c7 || ek.Algo != PubKeyAlgoRSA { + t.Errorf("unexpected EncryptedKey contents: %#v", ek) + return + } + + err = ek.Decrypt(encryptedKeyPriv, nil) + if err != nil { + t.Errorf("error from Decrypt: %s", err) + return + } + + if ek.CipherFunc != CipherAES256 { + t.Errorf("unexpected EncryptedKey contents: %#v", ek) + return + } + + keyHex := fmt.Sprintf("%x", ek.Key) + if keyHex != expectedKeyHex { + t.Errorf("bad key, got %s want %x", keyHex, expectedKeyHex) + } +} + +func TestEncryptingEncryptedKey(t *testing.T) { + key := []byte{1, 2, 3, 4} + const expectedKeyHex = "01020304" + const keyId = 42 + + pub := &PublicKey{ + PublicKey: &encryptedKeyPub, + KeyId: keyId, + PubKeyAlgo: PubKeyAlgoRSAEncryptOnly, + } + + buf := new(bytes.Buffer) + err := SerializeEncryptedKey(buf, pub, CipherAES128, key, nil) + if err != nil { + t.Errorf("error writing encrypted key packet: %s", err) + } + + p, err := Read(buf) + if err != nil { + t.Errorf("error from Read: %s", err) + return + } + ek, ok := p.(*EncryptedKey) + if !ok { + t.Errorf("didn't parse an EncryptedKey, got %#v", p) + return + } + + if ek.KeyId != keyId || ek.Algo != PubKeyAlgoRSAEncryptOnly { + t.Errorf("unexpected EncryptedKey contents: %#v", ek) + return + } + + err = ek.Decrypt(encryptedKeyPriv, nil) + if err != nil { + t.Errorf("error from Decrypt: %s", err) + return + } + + if ek.CipherFunc != CipherAES128 { + t.Errorf("unexpected EncryptedKey contents: %#v", ek) + return + } + + keyHex := fmt.Sprintf("%x", ek.Key) + if keyHex != expectedKeyHex { + t.Errorf("bad key, got %s want %x", keyHex, expectedKeyHex) + } +} + +func TestSerializingEncryptedKey(t *testing.T) { + const encryptedKeyHex = "c18c032a67d68660df41c70104005789d0de26b6a50c985a02a13131ca829c413a35d0e6fa8d6842599252162808ac7439c72151c8c6183e76923fe3299301414d0c25a2f06a2257db3839e7df0ec964773f6e4c4ac7ff3b48c444237166dd46ba8ff443a5410dc670cb486672fdbe7c9dfafb75b4fea83af3a204fe2a7dfa86bd20122b4f3d2646cbeecb8f7be8" + + p, err := Read(readerFromHex(encryptedKeyHex)) + if err != nil { + t.Fatalf("error from Read: %s", err) + } + ek, ok := p.(*EncryptedKey) + if !ok { + t.Fatalf("didn't parse an EncryptedKey, got %#v", p) + } + + var buf bytes.Buffer + ek.Serialize(&buf) + + if bufHex := hex.EncodeToString(buf.Bytes()); bufHex != encryptedKeyHex { + t.Fatalf("serialization of encrypted key differed from original. Original was %s, but reserialized as %s", encryptedKeyHex, bufHex) + } +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/literal.go b/vendor/golang.org/x/crypto/openpgp/packet/literal.go new file mode 100644 index 0000000000000000000000000000000000000000..1a9ec6e51e81d482b056e5fb26bc8b5cd6643ee6 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/literal.go @@ -0,0 +1,89 @@ +// 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 packet + +import ( + "encoding/binary" + "io" +) + +// LiteralData represents an encrypted file. See RFC 4880, section 5.9. +type LiteralData struct { + IsBinary bool + FileName string + Time uint32 // Unix epoch time. Either creation time or modification time. 0 means undefined. + Body io.Reader +} + +// ForEyesOnly returns whether the contents of the LiteralData have been marked +// as especially sensitive. +func (l *LiteralData) ForEyesOnly() bool { + return l.FileName == "_CONSOLE" +} + +func (l *LiteralData) parse(r io.Reader) (err error) { + var buf [256]byte + + _, err = readFull(r, buf[:2]) + if err != nil { + return + } + + l.IsBinary = buf[0] == 'b' + fileNameLen := int(buf[1]) + + _, err = readFull(r, buf[:fileNameLen]) + if err != nil { + return + } + + l.FileName = string(buf[:fileNameLen]) + + _, err = readFull(r, buf[:4]) + if err != nil { + return + } + + l.Time = binary.BigEndian.Uint32(buf[:4]) + l.Body = r + return +} + +// SerializeLiteral serializes a literal data packet to w and returns a +// WriteCloser to which the data itself can be written and which MUST be closed +// on completion. The fileName is truncated to 255 bytes. +func SerializeLiteral(w io.WriteCloser, isBinary bool, fileName string, time uint32) (plaintext io.WriteCloser, err error) { + var buf [4]byte + buf[0] = 't' + if isBinary { + buf[0] = 'b' + } + if len(fileName) > 255 { + fileName = fileName[:255] + } + buf[1] = byte(len(fileName)) + + inner, err := serializeStreamHeader(w, packetTypeLiteralData) + if err != nil { + return + } + + _, err = inner.Write(buf[:2]) + if err != nil { + return + } + _, err = inner.Write([]byte(fileName)) + if err != nil { + return + } + binary.BigEndian.PutUint32(buf[:], time) + _, err = inner.Write(buf[:]) + if err != nil { + return + } + + plaintext = inner + return +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/ocfb.go b/vendor/golang.org/x/crypto/openpgp/packet/ocfb.go new file mode 100644 index 0000000000000000000000000000000000000000..ce2a33a547cef97d8335958da1a18fea7df17aa5 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/ocfb.go @@ -0,0 +1,143 @@ +// 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. + +// OpenPGP CFB Mode. http://tools.ietf.org/html/rfc4880#section-13.9 + +package packet + +import ( + "crypto/cipher" +) + +type ocfbEncrypter struct { + b cipher.Block + fre []byte + outUsed int +} + +// An OCFBResyncOption determines if the "resynchronization step" of OCFB is +// performed. +type OCFBResyncOption bool + +const ( + OCFBResync OCFBResyncOption = true + OCFBNoResync OCFBResyncOption = false +) + +// NewOCFBEncrypter returns a cipher.Stream which encrypts data with OpenPGP's +// cipher feedback mode using the given cipher.Block, and an initial amount of +// ciphertext. randData must be random bytes and be the same length as the +// cipher.Block's block size. Resync determines if the "resynchronization step" +// from RFC 4880, 13.9 step 7 is performed. Different parts of OpenPGP vary on +// this point. +func NewOCFBEncrypter(block cipher.Block, randData []byte, resync OCFBResyncOption) (cipher.Stream, []byte) { + blockSize := block.BlockSize() + if len(randData) != blockSize { + return nil, nil + } + + x := &ocfbEncrypter{ + b: block, + fre: make([]byte, blockSize), + outUsed: 0, + } + prefix := make([]byte, blockSize+2) + + block.Encrypt(x.fre, x.fre) + for i := 0; i < blockSize; i++ { + prefix[i] = randData[i] ^ x.fre[i] + } + + block.Encrypt(x.fre, prefix[:blockSize]) + prefix[blockSize] = x.fre[0] ^ randData[blockSize-2] + prefix[blockSize+1] = x.fre[1] ^ randData[blockSize-1] + + if resync { + block.Encrypt(x.fre, prefix[2:]) + } else { + x.fre[0] = prefix[blockSize] + x.fre[1] = prefix[blockSize+1] + x.outUsed = 2 + } + return x, prefix +} + +func (x *ocfbEncrypter) XORKeyStream(dst, src []byte) { + for i := 0; i < len(src); i++ { + if x.outUsed == len(x.fre) { + x.b.Encrypt(x.fre, x.fre) + x.outUsed = 0 + } + + x.fre[x.outUsed] ^= src[i] + dst[i] = x.fre[x.outUsed] + x.outUsed++ + } +} + +type ocfbDecrypter struct { + b cipher.Block + fre []byte + outUsed int +} + +// NewOCFBDecrypter returns a cipher.Stream which decrypts data with OpenPGP's +// cipher feedback mode using the given cipher.Block. Prefix must be the first +// blockSize + 2 bytes of the ciphertext, where blockSize is the cipher.Block's +// block size. If an incorrect key is detected then nil is returned. On +// successful exit, blockSize+2 bytes of decrypted data are written into +// prefix. Resync determines if the "resynchronization step" from RFC 4880, +// 13.9 step 7 is performed. Different parts of OpenPGP vary on this point. +func NewOCFBDecrypter(block cipher.Block, prefix []byte, resync OCFBResyncOption) cipher.Stream { + blockSize := block.BlockSize() + if len(prefix) != blockSize+2 { + return nil + } + + x := &ocfbDecrypter{ + b: block, + fre: make([]byte, blockSize), + outUsed: 0, + } + prefixCopy := make([]byte, len(prefix)) + copy(prefixCopy, prefix) + + block.Encrypt(x.fre, x.fre) + for i := 0; i < blockSize; i++ { + prefixCopy[i] ^= x.fre[i] + } + + block.Encrypt(x.fre, prefix[:blockSize]) + prefixCopy[blockSize] ^= x.fre[0] + prefixCopy[blockSize+1] ^= x.fre[1] + + if prefixCopy[blockSize-2] != prefixCopy[blockSize] || + prefixCopy[blockSize-1] != prefixCopy[blockSize+1] { + return nil + } + + if resync { + block.Encrypt(x.fre, prefix[2:]) + } else { + x.fre[0] = prefix[blockSize] + x.fre[1] = prefix[blockSize+1] + x.outUsed = 2 + } + copy(prefix, prefixCopy) + return x +} + +func (x *ocfbDecrypter) XORKeyStream(dst, src []byte) { + for i := 0; i < len(src); i++ { + if x.outUsed == len(x.fre) { + x.b.Encrypt(x.fre, x.fre) + x.outUsed = 0 + } + + c := src[i] + dst[i] = x.fre[x.outUsed] ^ src[i] + x.fre[x.outUsed] = c + x.outUsed++ + } +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/ocfb_test.go b/vendor/golang.org/x/crypto/openpgp/packet/ocfb_test.go new file mode 100644 index 0000000000000000000000000000000000000000..91022c042d45173dfc00799e49cd9245c43b1065 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/ocfb_test.go @@ -0,0 +1,46 @@ +// 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 packet + +import ( + "bytes" + "crypto/aes" + "crypto/rand" + "testing" +) + +var commonKey128 = []byte{0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c} + +func testOCFB(t *testing.T, resync OCFBResyncOption) { + block, err := aes.NewCipher(commonKey128) + if err != nil { + t.Error(err) + return + } + + plaintext := []byte("this is the plaintext, which is long enough to span several blocks.") + randData := make([]byte, block.BlockSize()) + rand.Reader.Read(randData) + ocfb, prefix := NewOCFBEncrypter(block, randData, resync) + ciphertext := make([]byte, len(plaintext)) + ocfb.XORKeyStream(ciphertext, plaintext) + + ocfbdec := NewOCFBDecrypter(block, prefix, resync) + if ocfbdec == nil { + t.Errorf("NewOCFBDecrypter failed (resync: %t)", resync) + return + } + plaintextCopy := make([]byte, len(plaintext)) + ocfbdec.XORKeyStream(plaintextCopy, ciphertext) + + if !bytes.Equal(plaintextCopy, plaintext) { + t.Errorf("got: %x, want: %x (resync: %t)", plaintextCopy, plaintext, resync) + } +} + +func TestOCFB(t *testing.T) { + testOCFB(t, OCFBNoResync) + testOCFB(t, OCFBResync) +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/one_pass_signature.go b/vendor/golang.org/x/crypto/openpgp/packet/one_pass_signature.go new file mode 100644 index 0000000000000000000000000000000000000000..1713503395e3c89d061d270aa17a4bad151def62 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/one_pass_signature.go @@ -0,0 +1,73 @@ +// 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 packet + +import ( + "crypto" + "encoding/binary" + "golang.org/x/crypto/openpgp/errors" + "golang.org/x/crypto/openpgp/s2k" + "io" + "strconv" +) + +// OnePassSignature represents a one-pass signature packet. See RFC 4880, +// section 5.4. +type OnePassSignature struct { + SigType SignatureType + Hash crypto.Hash + PubKeyAlgo PublicKeyAlgorithm + KeyId uint64 + IsLast bool +} + +const onePassSignatureVersion = 3 + +func (ops *OnePassSignature) parse(r io.Reader) (err error) { + var buf [13]byte + + _, err = readFull(r, buf[:]) + if err != nil { + return + } + if buf[0] != onePassSignatureVersion { + err = errors.UnsupportedError("one-pass-signature packet version " + strconv.Itoa(int(buf[0]))) + } + + var ok bool + ops.Hash, ok = s2k.HashIdToHash(buf[2]) + if !ok { + return errors.UnsupportedError("hash function: " + strconv.Itoa(int(buf[2]))) + } + + ops.SigType = SignatureType(buf[1]) + ops.PubKeyAlgo = PublicKeyAlgorithm(buf[3]) + ops.KeyId = binary.BigEndian.Uint64(buf[4:12]) + ops.IsLast = buf[12] != 0 + return +} + +// Serialize marshals the given OnePassSignature to w. +func (ops *OnePassSignature) Serialize(w io.Writer) error { + var buf [13]byte + buf[0] = onePassSignatureVersion + buf[1] = uint8(ops.SigType) + var ok bool + buf[2], ok = s2k.HashToHashId(ops.Hash) + if !ok { + return errors.UnsupportedError("hash type: " + strconv.Itoa(int(ops.Hash))) + } + buf[3] = uint8(ops.PubKeyAlgo) + binary.BigEndian.PutUint64(buf[4:12], ops.KeyId) + if ops.IsLast { + buf[12] = 1 + } + + if err := serializeHeader(w, packetTypeOnePassSignature, len(buf)); err != nil { + return err + } + _, err := w.Write(buf[:]) + return err +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/opaque.go b/vendor/golang.org/x/crypto/openpgp/packet/opaque.go new file mode 100644 index 0000000000000000000000000000000000000000..456d807f255c276dce2db9e34fe965f8e45b0b62 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/opaque.go @@ -0,0 +1,162 @@ +// 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 packet + +import ( + "bytes" + "io" + "io/ioutil" + + "golang.org/x/crypto/openpgp/errors" +) + +// OpaquePacket represents an OpenPGP packet as raw, unparsed data. This is +// useful for splitting and storing the original packet contents separately, +// handling unsupported packet types or accessing parts of the packet not yet +// implemented by this package. +type OpaquePacket struct { + // Packet type + Tag uint8 + // Reason why the packet was parsed opaquely + Reason error + // Binary contents of the packet data + Contents []byte +} + +func (op *OpaquePacket) parse(r io.Reader) (err error) { + op.Contents, err = ioutil.ReadAll(r) + return +} + +// Serialize marshals the packet to a writer in its original form, including +// the packet header. +func (op *OpaquePacket) Serialize(w io.Writer) (err error) { + err = serializeHeader(w, packetType(op.Tag), len(op.Contents)) + if err == nil { + _, err = w.Write(op.Contents) + } + return +} + +// Parse attempts to parse the opaque contents into a structure supported by +// this package. If the packet is not known then the result will be another +// OpaquePacket. +func (op *OpaquePacket) Parse() (p Packet, err error) { + hdr := bytes.NewBuffer(nil) + err = serializeHeader(hdr, packetType(op.Tag), len(op.Contents)) + if err != nil { + op.Reason = err + return op, err + } + p, err = Read(io.MultiReader(hdr, bytes.NewBuffer(op.Contents))) + if err != nil { + op.Reason = err + p = op + } + return +} + +// OpaqueReader reads OpaquePackets from an io.Reader. +type OpaqueReader struct { + r io.Reader +} + +func NewOpaqueReader(r io.Reader) *OpaqueReader { + return &OpaqueReader{r: r} +} + +// Read the next OpaquePacket. +func (or *OpaqueReader) Next() (op *OpaquePacket, err error) { + tag, _, contents, err := readHeader(or.r) + if err != nil { + return + } + op = &OpaquePacket{Tag: uint8(tag), Reason: err} + err = op.parse(contents) + if err != nil { + consumeAll(contents) + } + return +} + +// OpaqueSubpacket represents an unparsed OpenPGP subpacket, +// as found in signature and user attribute packets. +type OpaqueSubpacket struct { + SubType uint8 + Contents []byte +} + +// OpaqueSubpackets extracts opaque, unparsed OpenPGP subpackets from +// their byte representation. +func OpaqueSubpackets(contents []byte) (result []*OpaqueSubpacket, err error) { + var ( + subHeaderLen int + subPacket *OpaqueSubpacket + ) + for len(contents) > 0 { + subHeaderLen, subPacket, err = nextSubpacket(contents) + if err != nil { + break + } + result = append(result, subPacket) + contents = contents[subHeaderLen+len(subPacket.Contents):] + } + return +} + +func nextSubpacket(contents []byte) (subHeaderLen int, subPacket *OpaqueSubpacket, err error) { + // RFC 4880, section 5.2.3.1 + var subLen uint32 + if len(contents) < 1 { + goto Truncated + } + subPacket = &OpaqueSubpacket{} + switch { + case contents[0] < 192: + subHeaderLen = 2 // 1 length byte, 1 subtype byte + if len(contents) < subHeaderLen { + goto Truncated + } + subLen = uint32(contents[0]) + contents = contents[1:] + case contents[0] < 255: + subHeaderLen = 3 // 2 length bytes, 1 subtype + if len(contents) < subHeaderLen { + goto Truncated + } + subLen = uint32(contents[0]-192)<<8 + uint32(contents[1]) + 192 + contents = contents[2:] + default: + subHeaderLen = 6 // 5 length bytes, 1 subtype + if len(contents) < subHeaderLen { + goto Truncated + } + subLen = uint32(contents[1])<<24 | + uint32(contents[2])<<16 | + uint32(contents[3])<<8 | + uint32(contents[4]) + contents = contents[5:] + } + if subLen > uint32(len(contents)) || subLen == 0 { + goto Truncated + } + subPacket.SubType = contents[0] + subPacket.Contents = contents[1:subLen] + return +Truncated: + err = errors.StructuralError("subpacket truncated") + return +} + +func (osp *OpaqueSubpacket) Serialize(w io.Writer) (err error) { + buf := make([]byte, 6) + n := serializeSubpacketLength(buf, len(osp.Contents)+1) + buf[n] = osp.SubType + if _, err = w.Write(buf[:n+1]); err != nil { + return + } + _, err = w.Write(osp.Contents) + return +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/opaque_test.go b/vendor/golang.org/x/crypto/openpgp/packet/opaque_test.go new file mode 100644 index 0000000000000000000000000000000000000000..f27bbfe090ba1cda1ac451229e9ef00d33c29116 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/opaque_test.go @@ -0,0 +1,67 @@ +// 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 packet + +import ( + "bytes" + "encoding/hex" + "io" + "testing" +) + +// Test packet.Read error handling in OpaquePacket.Parse, +// which attempts to re-read an OpaquePacket as a supported +// Packet type. +func TestOpaqueParseReason(t *testing.T) { + buf, err := hex.DecodeString(UnsupportedKeyHex) + if err != nil { + t.Fatal(err) + } + or := NewOpaqueReader(bytes.NewBuffer(buf)) + count := 0 + badPackets := 0 + var uid *UserId + for { + op, err := or.Next() + if err == io.EOF { + break + } else if err != nil { + t.Errorf("#%d: opaque read error: %v", count, err) + break + } + // try to parse opaque packet + p, err := op.Parse() + switch pkt := p.(type) { + case *UserId: + uid = pkt + case *OpaquePacket: + // If an OpaquePacket can't re-parse, packet.Read + // certainly had its reasons. + if pkt.Reason == nil { + t.Errorf("#%d: opaque packet, no reason", count) + } else { + badPackets++ + } + } + count++ + } + + const expectedBad = 3 + // Test post-conditions, make sure we actually parsed packets as expected. + if badPackets != expectedBad { + t.Errorf("unexpected # unparseable packets: %d (want %d)", badPackets, expectedBad) + } + if uid == nil { + t.Errorf("failed to find expected UID in unsupported keyring") + } else if uid.Id != "Armin M. Warda " { + t.Errorf("unexpected UID: %v", uid.Id) + } +} + +// This key material has public key and signature packet versions modified to +// an unsupported value (1), so that trying to parse the OpaquePacket to +// a typed packet will get an error. It also contains a GnuPG trust packet. +// (Created with: od -An -t x1 pubring.gpg | xargs | sed 's/ //g') +const UnsupportedKeyHex = `988d012e7a18a20000010400d6ac00d92b89c1f4396c243abb9b76d2e9673ad63483291fed88e22b82e255e441c078c6abbbf7d2d195e50b62eeaa915b85b0ec20c225ce2c64c167cacb6e711daf2e45da4a8356a059b8160e3b3628ac0dd8437b31f06d53d6e8ea4214d4a26406a6b63e1001406ef23e0bb3069fac9a99a91f77dfafd5de0f188a5da5e3c9000511b42741726d696e204d2e205761726461203c7761726461406e657068696c696d2e727568722e64653e8900950105102e8936c705d1eb399e58489901013f0e03ff5a0c4f421e34fcfa388129166420c08cd76987bcdec6f01bd0271459a85cc22048820dd4e44ac2c7d23908d540f54facf1b36b0d9c20488781ce9dca856531e76e2e846826e9951338020a03a09b57aa5faa82e9267458bd76105399885ac35af7dc1cbb6aaed7c39e1039f3b5beda2c0e916bd38560509bab81235d1a0ead83b0020000` diff --git a/vendor/golang.org/x/crypto/openpgp/packet/packet.go b/vendor/golang.org/x/crypto/openpgp/packet/packet.go new file mode 100644 index 0000000000000000000000000000000000000000..3eded93f042d94c6fc56592153083ec948f5ea94 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/packet.go @@ -0,0 +1,537 @@ +// 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 packet implements parsing and serialization of OpenPGP packets, as +// specified in RFC 4880. +package packet // import "golang.org/x/crypto/openpgp/packet" + +import ( + "bufio" + "crypto/aes" + "crypto/cipher" + "crypto/des" + "golang.org/x/crypto/cast5" + "golang.org/x/crypto/openpgp/errors" + "io" + "math/big" +) + +// readFull is the same as io.ReadFull except that reading zero bytes returns +// ErrUnexpectedEOF rather than EOF. +func readFull(r io.Reader, buf []byte) (n int, err error) { + n, err = io.ReadFull(r, buf) + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + return +} + +// readLength reads an OpenPGP length from r. See RFC 4880, section 4.2.2. +func readLength(r io.Reader) (length int64, isPartial bool, err error) { + var buf [4]byte + _, err = readFull(r, buf[:1]) + if err != nil { + return + } + switch { + case buf[0] < 192: + length = int64(buf[0]) + case buf[0] < 224: + length = int64(buf[0]-192) << 8 + _, err = readFull(r, buf[0:1]) + if err != nil { + return + } + length += int64(buf[0]) + 192 + case buf[0] < 255: + length = int64(1) << (buf[0] & 0x1f) + isPartial = true + default: + _, err = readFull(r, buf[0:4]) + if err != nil { + return + } + length = int64(buf[0])<<24 | + int64(buf[1])<<16 | + int64(buf[2])<<8 | + int64(buf[3]) + } + return +} + +// partialLengthReader wraps an io.Reader and handles OpenPGP partial lengths. +// The continuation lengths are parsed and removed from the stream and EOF is +// returned at the end of the packet. See RFC 4880, section 4.2.2.4. +type partialLengthReader struct { + r io.Reader + remaining int64 + isPartial bool +} + +func (r *partialLengthReader) Read(p []byte) (n int, err error) { + for r.remaining == 0 { + if !r.isPartial { + return 0, io.EOF + } + r.remaining, r.isPartial, err = readLength(r.r) + if err != nil { + return 0, err + } + } + + toRead := int64(len(p)) + if toRead > r.remaining { + toRead = r.remaining + } + + n, err = r.r.Read(p[:int(toRead)]) + r.remaining -= int64(n) + if n < int(toRead) && err == io.EOF { + err = io.ErrUnexpectedEOF + } + return +} + +// partialLengthWriter writes a stream of data using OpenPGP partial lengths. +// See RFC 4880, section 4.2.2.4. +type partialLengthWriter struct { + w io.WriteCloser + lengthByte [1]byte +} + +func (w *partialLengthWriter) Write(p []byte) (n int, err error) { + for len(p) > 0 { + for power := uint(14); power < 32; power-- { + l := 1 << power + if len(p) >= l { + w.lengthByte[0] = 224 + uint8(power) + _, err = w.w.Write(w.lengthByte[:]) + if err != nil { + return + } + var m int + m, err = w.w.Write(p[:l]) + n += m + if err != nil { + return + } + p = p[l:] + break + } + } + } + return +} + +func (w *partialLengthWriter) Close() error { + w.lengthByte[0] = 0 + _, err := w.w.Write(w.lengthByte[:]) + if err != nil { + return err + } + return w.w.Close() +} + +// A spanReader is an io.LimitReader, but it returns ErrUnexpectedEOF if the +// underlying Reader returns EOF before the limit has been reached. +type spanReader struct { + r io.Reader + n int64 +} + +func (l *spanReader) Read(p []byte) (n int, err error) { + if l.n <= 0 { + return 0, io.EOF + } + if int64(len(p)) > l.n { + p = p[0:l.n] + } + n, err = l.r.Read(p) + l.n -= int64(n) + if l.n > 0 && err == io.EOF { + err = io.ErrUnexpectedEOF + } + return +} + +// readHeader parses a packet header and returns an io.Reader which will return +// the contents of the packet. See RFC 4880, section 4.2. +func readHeader(r io.Reader) (tag packetType, length int64, contents io.Reader, err error) { + var buf [4]byte + _, err = io.ReadFull(r, buf[:1]) + if err != nil { + return + } + if buf[0]&0x80 == 0 { + err = errors.StructuralError("tag byte does not have MSB set") + return + } + if buf[0]&0x40 == 0 { + // Old format packet + tag = packetType((buf[0] & 0x3f) >> 2) + lengthType := buf[0] & 3 + if lengthType == 3 { + length = -1 + contents = r + return + } + lengthBytes := 1 << lengthType + _, err = readFull(r, buf[0:lengthBytes]) + if err != nil { + return + } + for i := 0; i < lengthBytes; i++ { + length <<= 8 + length |= int64(buf[i]) + } + contents = &spanReader{r, length} + return + } + + // New format packet + tag = packetType(buf[0] & 0x3f) + length, isPartial, err := readLength(r) + if err != nil { + return + } + if isPartial { + contents = &partialLengthReader{ + remaining: length, + isPartial: true, + r: r, + } + length = -1 + } else { + contents = &spanReader{r, length} + } + return +} + +// serializeHeader writes an OpenPGP packet header to w. See RFC 4880, section +// 4.2. +func serializeHeader(w io.Writer, ptype packetType, length int) (err error) { + var buf [6]byte + var n int + + buf[0] = 0x80 | 0x40 | byte(ptype) + if length < 192 { + buf[1] = byte(length) + n = 2 + } else if length < 8384 { + length -= 192 + buf[1] = 192 + byte(length>>8) + buf[2] = byte(length) + n = 3 + } else { + buf[1] = 255 + buf[2] = byte(length >> 24) + buf[3] = byte(length >> 16) + buf[4] = byte(length >> 8) + buf[5] = byte(length) + n = 6 + } + + _, err = w.Write(buf[:n]) + return +} + +// serializeStreamHeader writes an OpenPGP packet header to w where the +// length of the packet is unknown. It returns a io.WriteCloser which can be +// used to write the contents of the packet. See RFC 4880, section 4.2. +func serializeStreamHeader(w io.WriteCloser, ptype packetType) (out io.WriteCloser, err error) { + var buf [1]byte + buf[0] = 0x80 | 0x40 | byte(ptype) + _, err = w.Write(buf[:]) + if err != nil { + return + } + out = &partialLengthWriter{w: w} + return +} + +// Packet represents an OpenPGP packet. Users are expected to try casting +// instances of this interface to specific packet types. +type Packet interface { + parse(io.Reader) error +} + +// consumeAll reads from the given Reader until error, returning the number of +// bytes read. +func consumeAll(r io.Reader) (n int64, err error) { + var m int + var buf [1024]byte + + for { + m, err = r.Read(buf[:]) + n += int64(m) + if err == io.EOF { + err = nil + return + } + if err != nil { + return + } + } +} + +// packetType represents the numeric ids of the different OpenPGP packet types. See +// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-2 +type packetType uint8 + +const ( + packetTypeEncryptedKey packetType = 1 + packetTypeSignature packetType = 2 + packetTypeSymmetricKeyEncrypted packetType = 3 + packetTypeOnePassSignature packetType = 4 + packetTypePrivateKey packetType = 5 + packetTypePublicKey packetType = 6 + packetTypePrivateSubkey packetType = 7 + packetTypeCompressed packetType = 8 + packetTypeSymmetricallyEncrypted packetType = 9 + packetTypeLiteralData packetType = 11 + packetTypeUserId packetType = 13 + packetTypePublicSubkey packetType = 14 + packetTypeUserAttribute packetType = 17 + packetTypeSymmetricallyEncryptedMDC packetType = 18 +) + +// peekVersion detects the version of a public key packet about to +// be read. A bufio.Reader at the original position of the io.Reader +// is returned. +func peekVersion(r io.Reader) (bufr *bufio.Reader, ver byte, err error) { + bufr = bufio.NewReader(r) + var verBuf []byte + if verBuf, err = bufr.Peek(1); err != nil { + return + } + ver = verBuf[0] + return +} + +// Read reads a single OpenPGP packet from the given io.Reader. If there is an +// error parsing a packet, the whole packet is consumed from the input. +func Read(r io.Reader) (p Packet, err error) { + tag, _, contents, err := readHeader(r) + if err != nil { + return + } + + switch tag { + case packetTypeEncryptedKey: + p = new(EncryptedKey) + case packetTypeSignature: + var version byte + // Detect signature version + if contents, version, err = peekVersion(contents); err != nil { + return + } + if version < 4 { + p = new(SignatureV3) + } else { + p = new(Signature) + } + case packetTypeSymmetricKeyEncrypted: + p = new(SymmetricKeyEncrypted) + case packetTypeOnePassSignature: + p = new(OnePassSignature) + case packetTypePrivateKey, packetTypePrivateSubkey: + pk := new(PrivateKey) + if tag == packetTypePrivateSubkey { + pk.IsSubkey = true + } + p = pk + case packetTypePublicKey, packetTypePublicSubkey: + var version byte + if contents, version, err = peekVersion(contents); err != nil { + return + } + isSubkey := tag == packetTypePublicSubkey + if version < 4 { + p = &PublicKeyV3{IsSubkey: isSubkey} + } else { + p = &PublicKey{IsSubkey: isSubkey} + } + case packetTypeCompressed: + p = new(Compressed) + case packetTypeSymmetricallyEncrypted: + p = new(SymmetricallyEncrypted) + case packetTypeLiteralData: + p = new(LiteralData) + case packetTypeUserId: + p = new(UserId) + case packetTypeUserAttribute: + p = new(UserAttribute) + case packetTypeSymmetricallyEncryptedMDC: + se := new(SymmetricallyEncrypted) + se.MDC = true + p = se + default: + err = errors.UnknownPacketTypeError(tag) + } + if p != nil { + err = p.parse(contents) + } + if err != nil { + consumeAll(contents) + } + return +} + +// SignatureType represents the different semantic meanings of an OpenPGP +// signature. See RFC 4880, section 5.2.1. +type SignatureType uint8 + +const ( + SigTypeBinary SignatureType = 0 + SigTypeText = 1 + SigTypeGenericCert = 0x10 + SigTypePersonaCert = 0x11 + SigTypeCasualCert = 0x12 + SigTypePositiveCert = 0x13 + SigTypeSubkeyBinding = 0x18 + SigTypePrimaryKeyBinding = 0x19 + SigTypeDirectSignature = 0x1F + SigTypeKeyRevocation = 0x20 + SigTypeSubkeyRevocation = 0x28 +) + +// PublicKeyAlgorithm represents the different public key system specified for +// OpenPGP. See +// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-12 +type PublicKeyAlgorithm uint8 + +const ( + PubKeyAlgoRSA PublicKeyAlgorithm = 1 + PubKeyAlgoRSAEncryptOnly PublicKeyAlgorithm = 2 + PubKeyAlgoRSASignOnly PublicKeyAlgorithm = 3 + PubKeyAlgoElGamal PublicKeyAlgorithm = 16 + PubKeyAlgoDSA PublicKeyAlgorithm = 17 + // RFC 6637, Section 5. + PubKeyAlgoECDH PublicKeyAlgorithm = 18 + PubKeyAlgoECDSA PublicKeyAlgorithm = 19 +) + +// CanEncrypt returns true if it's possible to encrypt a message to a public +// key of the given type. +func (pka PublicKeyAlgorithm) CanEncrypt() bool { + switch pka { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoElGamal: + return true + } + return false +} + +// CanSign returns true if it's possible for a public key of the given type to +// sign a message. +func (pka PublicKeyAlgorithm) CanSign() bool { + switch pka { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA: + return true + } + return false +} + +// CipherFunction represents the different block ciphers specified for OpenPGP. See +// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-13 +type CipherFunction uint8 + +const ( + Cipher3DES CipherFunction = 2 + CipherCAST5 CipherFunction = 3 + CipherAES128 CipherFunction = 7 + CipherAES192 CipherFunction = 8 + CipherAES256 CipherFunction = 9 +) + +// KeySize returns the key size, in bytes, of cipher. +func (cipher CipherFunction) KeySize() int { + switch cipher { + case Cipher3DES: + return 24 + case CipherCAST5: + return cast5.KeySize + case CipherAES128: + return 16 + case CipherAES192: + return 24 + case CipherAES256: + return 32 + } + return 0 +} + +// blockSize returns the block size, in bytes, of cipher. +func (cipher CipherFunction) blockSize() int { + switch cipher { + case Cipher3DES: + return des.BlockSize + case CipherCAST5: + return 8 + case CipherAES128, CipherAES192, CipherAES256: + return 16 + } + return 0 +} + +// new returns a fresh instance of the given cipher. +func (cipher CipherFunction) new(key []byte) (block cipher.Block) { + switch cipher { + case Cipher3DES: + block, _ = des.NewTripleDESCipher(key) + case CipherCAST5: + block, _ = cast5.NewCipher(key) + case CipherAES128, CipherAES192, CipherAES256: + block, _ = aes.NewCipher(key) + } + return +} + +// readMPI reads a big integer from r. The bit length returned is the bit +// length that was specified in r. This is preserved so that the integer can be +// reserialized exactly. +func readMPI(r io.Reader) (mpi []byte, bitLength uint16, err error) { + var buf [2]byte + _, err = readFull(r, buf[0:]) + if err != nil { + return + } + bitLength = uint16(buf[0])<<8 | uint16(buf[1]) + numBytes := (int(bitLength) + 7) / 8 + mpi = make([]byte, numBytes) + _, err = readFull(r, mpi) + return +} + +// mpiLength returns the length of the given *big.Int when serialized as an +// MPI. +func mpiLength(n *big.Int) (mpiLengthInBytes int) { + mpiLengthInBytes = 2 /* MPI length */ + mpiLengthInBytes += (n.BitLen() + 7) / 8 + return +} + +// writeMPI serializes a big integer to w. +func writeMPI(w io.Writer, bitLength uint16, mpiBytes []byte) (err error) { + _, err = w.Write([]byte{byte(bitLength >> 8), byte(bitLength)}) + if err == nil { + _, err = w.Write(mpiBytes) + } + return +} + +// writeBig serializes a *big.Int to w. +func writeBig(w io.Writer, i *big.Int) error { + return writeMPI(w, uint16(i.BitLen()), i.Bytes()) +} + +// CompressionAlgo Represents the different compression algorithms +// supported by OpenPGP (except for BZIP2, which is not currently +// supported). See Section 9.3 of RFC 4880. +type CompressionAlgo uint8 + +const ( + CompressionNone CompressionAlgo = 0 + CompressionZIP CompressionAlgo = 1 + CompressionZLIB CompressionAlgo = 2 +) diff --git a/vendor/golang.org/x/crypto/openpgp/packet/packet_test.go b/vendor/golang.org/x/crypto/openpgp/packet/packet_test.go new file mode 100644 index 0000000000000000000000000000000000000000..1dab5c3d588c0686dc4dc9869f06cd6d7ea2be61 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/packet_test.go @@ -0,0 +1,255 @@ +// 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 packet + +import ( + "bytes" + "encoding/hex" + "fmt" + "golang.org/x/crypto/openpgp/errors" + "io" + "io/ioutil" + "testing" +) + +func TestReadFull(t *testing.T) { + var out [4]byte + + b := bytes.NewBufferString("foo") + n, err := readFull(b, out[:3]) + if n != 3 || err != nil { + t.Errorf("full read failed n:%d err:%s", n, err) + } + + b = bytes.NewBufferString("foo") + n, err = readFull(b, out[:4]) + if n != 3 || err != io.ErrUnexpectedEOF { + t.Errorf("partial read failed n:%d err:%s", n, err) + } + + b = bytes.NewBuffer(nil) + n, err = readFull(b, out[:3]) + if n != 0 || err != io.ErrUnexpectedEOF { + t.Errorf("empty read failed n:%d err:%s", n, err) + } +} + +func readerFromHex(s string) io.Reader { + data, err := hex.DecodeString(s) + if err != nil { + panic("readerFromHex: bad input") + } + return bytes.NewBuffer(data) +} + +var readLengthTests = []struct { + hexInput string + length int64 + isPartial bool + err error +}{ + {"", 0, false, io.ErrUnexpectedEOF}, + {"1f", 31, false, nil}, + {"c0", 0, false, io.ErrUnexpectedEOF}, + {"c101", 256 + 1 + 192, false, nil}, + {"e0", 1, true, nil}, + {"e1", 2, true, nil}, + {"e2", 4, true, nil}, + {"ff", 0, false, io.ErrUnexpectedEOF}, + {"ff00", 0, false, io.ErrUnexpectedEOF}, + {"ff0000", 0, false, io.ErrUnexpectedEOF}, + {"ff000000", 0, false, io.ErrUnexpectedEOF}, + {"ff00000000", 0, false, nil}, + {"ff01020304", 16909060, false, nil}, +} + +func TestReadLength(t *testing.T) { + for i, test := range readLengthTests { + length, isPartial, err := readLength(readerFromHex(test.hexInput)) + if test.err != nil { + if err != test.err { + t.Errorf("%d: expected different error got:%s want:%s", i, err, test.err) + } + continue + } + if err != nil { + t.Errorf("%d: unexpected error: %s", i, err) + continue + } + if length != test.length || isPartial != test.isPartial { + t.Errorf("%d: bad result got:(%d,%t) want:(%d,%t)", i, length, isPartial, test.length, test.isPartial) + } + } +} + +var partialLengthReaderTests = []struct { + hexInput string + err error + hexOutput string +}{ + {"e0", io.ErrUnexpectedEOF, ""}, + {"e001", io.ErrUnexpectedEOF, ""}, + {"e0010102", nil, "0102"}, + {"ff00000000", nil, ""}, + {"e10102e1030400", nil, "01020304"}, + {"e101", io.ErrUnexpectedEOF, ""}, +} + +func TestPartialLengthReader(t *testing.T) { + for i, test := range partialLengthReaderTests { + r := &partialLengthReader{readerFromHex(test.hexInput), 0, true} + out, err := ioutil.ReadAll(r) + if test.err != nil { + if err != test.err { + t.Errorf("%d: expected different error got:%s want:%s", i, err, test.err) + } + continue + } + if err != nil { + t.Errorf("%d: unexpected error: %s", i, err) + continue + } + + got := fmt.Sprintf("%x", out) + if got != test.hexOutput { + t.Errorf("%d: got:%s want:%s", i, test.hexOutput, got) + } + } +} + +var readHeaderTests = []struct { + hexInput string + structuralError bool + unexpectedEOF bool + tag int + length int64 + hexOutput string +}{ + {"", false, false, 0, 0, ""}, + {"7f", true, false, 0, 0, ""}, + + // Old format headers + {"80", false, true, 0, 0, ""}, + {"8001", false, true, 0, 1, ""}, + {"800102", false, false, 0, 1, "02"}, + {"81000102", false, false, 0, 1, "02"}, + {"820000000102", false, false, 0, 1, "02"}, + {"860000000102", false, false, 1, 1, "02"}, + {"83010203", false, false, 0, -1, "010203"}, + + // New format headers + {"c0", false, true, 0, 0, ""}, + {"c000", false, false, 0, 0, ""}, + {"c00102", false, false, 0, 1, "02"}, + {"c0020203", false, false, 0, 2, "0203"}, + {"c00202", false, true, 0, 2, ""}, + {"c3020203", false, false, 3, 2, "0203"}, +} + +func TestReadHeader(t *testing.T) { + for i, test := range readHeaderTests { + tag, length, contents, err := readHeader(readerFromHex(test.hexInput)) + if test.structuralError { + if _, ok := err.(errors.StructuralError); ok { + continue + } + t.Errorf("%d: expected StructuralError, got:%s", i, err) + continue + } + if err != nil { + if len(test.hexInput) == 0 && err == io.EOF { + continue + } + if !test.unexpectedEOF || err != io.ErrUnexpectedEOF { + t.Errorf("%d: unexpected error from readHeader: %s", i, err) + } + continue + } + if int(tag) != test.tag || length != test.length { + t.Errorf("%d: got:(%d,%d) want:(%d,%d)", i, int(tag), length, test.tag, test.length) + continue + } + + body, err := ioutil.ReadAll(contents) + if err != nil { + if !test.unexpectedEOF || err != io.ErrUnexpectedEOF { + t.Errorf("%d: unexpected error from contents: %s", i, err) + } + continue + } + if test.unexpectedEOF { + t.Errorf("%d: expected ErrUnexpectedEOF from contents but got no error", i) + continue + } + got := fmt.Sprintf("%x", body) + if got != test.hexOutput { + t.Errorf("%d: got:%s want:%s", i, got, test.hexOutput) + } + } +} + +func TestSerializeHeader(t *testing.T) { + tag := packetTypePublicKey + lengths := []int{0, 1, 2, 64, 192, 193, 8000, 8384, 8385, 10000} + + for _, length := range lengths { + buf := bytes.NewBuffer(nil) + serializeHeader(buf, tag, length) + tag2, length2, _, err := readHeader(buf) + if err != nil { + t.Errorf("length %d, err: %s", length, err) + } + if tag2 != tag { + t.Errorf("length %d, tag incorrect (got %d, want %d)", length, tag2, tag) + } + if int(length2) != length { + t.Errorf("length %d, length incorrect (got %d)", length, length2) + } + } +} + +func TestPartialLengths(t *testing.T) { + buf := bytes.NewBuffer(nil) + w := new(partialLengthWriter) + w.w = noOpCloser{buf} + + const maxChunkSize = 64 + + var b [maxChunkSize]byte + var n uint8 + for l := 1; l <= maxChunkSize; l++ { + for i := 0; i < l; i++ { + b[i] = n + n++ + } + m, err := w.Write(b[:l]) + if m != l { + t.Errorf("short write got: %d want: %d", m, l) + } + if err != nil { + t.Errorf("error from write: %s", err) + } + } + w.Close() + + want := (maxChunkSize * (maxChunkSize + 1)) / 2 + copyBuf := bytes.NewBuffer(nil) + r := &partialLengthReader{buf, 0, true} + m, err := io.Copy(copyBuf, r) + if m != int64(want) { + t.Errorf("short copy got: %d want: %d", m, want) + } + if err != nil { + t.Errorf("error from copy: %s", err) + } + + copyBytes := copyBuf.Bytes() + for i := 0; i < want; i++ { + if copyBytes[i] != uint8(i) { + t.Errorf("bad pattern in copy at %d", i) + break + } + } +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/private_key.go b/vendor/golang.org/x/crypto/openpgp/packet/private_key.go new file mode 100644 index 0000000000000000000000000000000000000000..34734cc63d14dec7bffc9898a47b14c8515aed79 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/private_key.go @@ -0,0 +1,380 @@ +// 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 packet + +import ( + "bytes" + "crypto" + "crypto/cipher" + "crypto/dsa" + "crypto/ecdsa" + "crypto/rsa" + "crypto/sha1" + "io" + "io/ioutil" + "math/big" + "strconv" + "time" + + "golang.org/x/crypto/openpgp/elgamal" + "golang.org/x/crypto/openpgp/errors" + "golang.org/x/crypto/openpgp/s2k" +) + +// PrivateKey represents a possibly encrypted private key. See RFC 4880, +// section 5.5.3. +type PrivateKey struct { + PublicKey + Encrypted bool // if true then the private key is unavailable until Decrypt has been called. + encryptedData []byte + cipher CipherFunction + s2k func(out, in []byte) + PrivateKey interface{} // An *{rsa|dsa|ecdsa}.PrivateKey or a crypto.Signer. + sha1Checksum bool + iv []byte +} + +func NewRSAPrivateKey(currentTime time.Time, priv *rsa.PrivateKey) *PrivateKey { + pk := new(PrivateKey) + pk.PublicKey = *NewRSAPublicKey(currentTime, &priv.PublicKey) + pk.PrivateKey = priv + return pk +} + +func NewDSAPrivateKey(currentTime time.Time, priv *dsa.PrivateKey) *PrivateKey { + pk := new(PrivateKey) + pk.PublicKey = *NewDSAPublicKey(currentTime, &priv.PublicKey) + pk.PrivateKey = priv + return pk +} + +func NewElGamalPrivateKey(currentTime time.Time, priv *elgamal.PrivateKey) *PrivateKey { + pk := new(PrivateKey) + pk.PublicKey = *NewElGamalPublicKey(currentTime, &priv.PublicKey) + pk.PrivateKey = priv + return pk +} + +func NewECDSAPrivateKey(currentTime time.Time, priv *ecdsa.PrivateKey) *PrivateKey { + pk := new(PrivateKey) + pk.PublicKey = *NewECDSAPublicKey(currentTime, &priv.PublicKey) + pk.PrivateKey = priv + return pk +} + +// NewSignerPrivateKey creates a sign-only PrivateKey from a crypto.Signer that +// implements RSA or ECDSA. +func NewSignerPrivateKey(currentTime time.Time, signer crypto.Signer) *PrivateKey { + pk := new(PrivateKey) + switch pubkey := signer.Public().(type) { + case rsa.PublicKey: + pk.PublicKey = *NewRSAPublicKey(currentTime, &pubkey) + pk.PubKeyAlgo = PubKeyAlgoRSASignOnly + case ecdsa.PublicKey: + pk.PublicKey = *NewECDSAPublicKey(currentTime, &pubkey) + default: + panic("openpgp: unknown crypto.Signer type in NewSignerPrivateKey") + } + pk.PrivateKey = signer + return pk +} + +func (pk *PrivateKey) parse(r io.Reader) (err error) { + err = (&pk.PublicKey).parse(r) + if err != nil { + return + } + var buf [1]byte + _, err = readFull(r, buf[:]) + if err != nil { + return + } + + s2kType := buf[0] + + switch s2kType { + case 0: + pk.s2k = nil + pk.Encrypted = false + case 254, 255: + _, err = readFull(r, buf[:]) + if err != nil { + return + } + pk.cipher = CipherFunction(buf[0]) + pk.Encrypted = true + pk.s2k, err = s2k.Parse(r) + if err != nil { + return + } + if s2kType == 254 { + pk.sha1Checksum = true + } + default: + return errors.UnsupportedError("deprecated s2k function in private key") + } + + if pk.Encrypted { + blockSize := pk.cipher.blockSize() + if blockSize == 0 { + return errors.UnsupportedError("unsupported cipher in private key: " + strconv.Itoa(int(pk.cipher))) + } + pk.iv = make([]byte, blockSize) + _, err = readFull(r, pk.iv) + if err != nil { + return + } + } + + pk.encryptedData, err = ioutil.ReadAll(r) + if err != nil { + return + } + + if !pk.Encrypted { + return pk.parsePrivateKey(pk.encryptedData) + } + + return +} + +func mod64kHash(d []byte) uint16 { + var h uint16 + for _, b := range d { + h += uint16(b) + } + return h +} + +func (pk *PrivateKey) Serialize(w io.Writer) (err error) { + // TODO(agl): support encrypted private keys + buf := bytes.NewBuffer(nil) + err = pk.PublicKey.serializeWithoutHeaders(buf) + if err != nil { + return + } + buf.WriteByte(0 /* no encryption */) + + privateKeyBuf := bytes.NewBuffer(nil) + + switch priv := pk.PrivateKey.(type) { + case *rsa.PrivateKey: + err = serializeRSAPrivateKey(privateKeyBuf, priv) + case *dsa.PrivateKey: + err = serializeDSAPrivateKey(privateKeyBuf, priv) + case *elgamal.PrivateKey: + err = serializeElGamalPrivateKey(privateKeyBuf, priv) + case *ecdsa.PrivateKey: + err = serializeECDSAPrivateKey(privateKeyBuf, priv) + default: + err = errors.InvalidArgumentError("unknown private key type") + } + if err != nil { + return + } + + ptype := packetTypePrivateKey + contents := buf.Bytes() + privateKeyBytes := privateKeyBuf.Bytes() + if pk.IsSubkey { + ptype = packetTypePrivateSubkey + } + err = serializeHeader(w, ptype, len(contents)+len(privateKeyBytes)+2) + if err != nil { + return + } + _, err = w.Write(contents) + if err != nil { + return + } + _, err = w.Write(privateKeyBytes) + if err != nil { + return + } + + checksum := mod64kHash(privateKeyBytes) + var checksumBytes [2]byte + checksumBytes[0] = byte(checksum >> 8) + checksumBytes[1] = byte(checksum) + _, err = w.Write(checksumBytes[:]) + + return +} + +func serializeRSAPrivateKey(w io.Writer, priv *rsa.PrivateKey) error { + err := writeBig(w, priv.D) + if err != nil { + return err + } + err = writeBig(w, priv.Primes[1]) + if err != nil { + return err + } + err = writeBig(w, priv.Primes[0]) + if err != nil { + return err + } + return writeBig(w, priv.Precomputed.Qinv) +} + +func serializeDSAPrivateKey(w io.Writer, priv *dsa.PrivateKey) error { + return writeBig(w, priv.X) +} + +func serializeElGamalPrivateKey(w io.Writer, priv *elgamal.PrivateKey) error { + return writeBig(w, priv.X) +} + +func serializeECDSAPrivateKey(w io.Writer, priv *ecdsa.PrivateKey) error { + return writeBig(w, priv.D) +} + +// Decrypt decrypts an encrypted private key using a passphrase. +func (pk *PrivateKey) Decrypt(passphrase []byte) error { + if !pk.Encrypted { + return nil + } + + key := make([]byte, pk.cipher.KeySize()) + pk.s2k(key, passphrase) + block := pk.cipher.new(key) + cfb := cipher.NewCFBDecrypter(block, pk.iv) + + data := make([]byte, len(pk.encryptedData)) + cfb.XORKeyStream(data, pk.encryptedData) + + if pk.sha1Checksum { + if len(data) < sha1.Size { + return errors.StructuralError("truncated private key data") + } + h := sha1.New() + h.Write(data[:len(data)-sha1.Size]) + sum := h.Sum(nil) + if !bytes.Equal(sum, data[len(data)-sha1.Size:]) { + return errors.StructuralError("private key checksum failure") + } + data = data[:len(data)-sha1.Size] + } else { + if len(data) < 2 { + return errors.StructuralError("truncated private key data") + } + var sum uint16 + for i := 0; i < len(data)-2; i++ { + sum += uint16(data[i]) + } + if data[len(data)-2] != uint8(sum>>8) || + data[len(data)-1] != uint8(sum) { + return errors.StructuralError("private key checksum failure") + } + data = data[:len(data)-2] + } + + return pk.parsePrivateKey(data) +} + +func (pk *PrivateKey) parsePrivateKey(data []byte) (err error) { + switch pk.PublicKey.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoRSAEncryptOnly: + return pk.parseRSAPrivateKey(data) + case PubKeyAlgoDSA: + return pk.parseDSAPrivateKey(data) + case PubKeyAlgoElGamal: + return pk.parseElGamalPrivateKey(data) + case PubKeyAlgoECDSA: + return pk.parseECDSAPrivateKey(data) + } + panic("impossible") +} + +func (pk *PrivateKey) parseRSAPrivateKey(data []byte) (err error) { + rsaPub := pk.PublicKey.PublicKey.(*rsa.PublicKey) + rsaPriv := new(rsa.PrivateKey) + rsaPriv.PublicKey = *rsaPub + + buf := bytes.NewBuffer(data) + d, _, err := readMPI(buf) + if err != nil { + return + } + p, _, err := readMPI(buf) + if err != nil { + return + } + q, _, err := readMPI(buf) + if err != nil { + return + } + + rsaPriv.D = new(big.Int).SetBytes(d) + rsaPriv.Primes = make([]*big.Int, 2) + rsaPriv.Primes[0] = new(big.Int).SetBytes(p) + rsaPriv.Primes[1] = new(big.Int).SetBytes(q) + if err := rsaPriv.Validate(); err != nil { + return err + } + rsaPriv.Precompute() + pk.PrivateKey = rsaPriv + pk.Encrypted = false + pk.encryptedData = nil + + return nil +} + +func (pk *PrivateKey) parseDSAPrivateKey(data []byte) (err error) { + dsaPub := pk.PublicKey.PublicKey.(*dsa.PublicKey) + dsaPriv := new(dsa.PrivateKey) + dsaPriv.PublicKey = *dsaPub + + buf := bytes.NewBuffer(data) + x, _, err := readMPI(buf) + if err != nil { + return + } + + dsaPriv.X = new(big.Int).SetBytes(x) + pk.PrivateKey = dsaPriv + pk.Encrypted = false + pk.encryptedData = nil + + return nil +} + +func (pk *PrivateKey) parseElGamalPrivateKey(data []byte) (err error) { + pub := pk.PublicKey.PublicKey.(*elgamal.PublicKey) + priv := new(elgamal.PrivateKey) + priv.PublicKey = *pub + + buf := bytes.NewBuffer(data) + x, _, err := readMPI(buf) + if err != nil { + return + } + + priv.X = new(big.Int).SetBytes(x) + pk.PrivateKey = priv + pk.Encrypted = false + pk.encryptedData = nil + + return nil +} + +func (pk *PrivateKey) parseECDSAPrivateKey(data []byte) (err error) { + ecdsaPub := pk.PublicKey.PublicKey.(*ecdsa.PublicKey) + + buf := bytes.NewBuffer(data) + d, _, err := readMPI(buf) + if err != nil { + return + } + + pk.PrivateKey = &ecdsa.PrivateKey{ + PublicKey: *ecdsaPub, + D: new(big.Int).SetBytes(d), + } + pk.Encrypted = false + pk.encryptedData = nil + + return nil +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/private_key_test.go b/vendor/golang.org/x/crypto/openpgp/packet/private_key_test.go new file mode 100644 index 0000000000000000000000000000000000000000..ac651d917d1acc52f308033c42b46681f04aee08 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/private_key_test.go @@ -0,0 +1,270 @@ +// 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 packet + +import ( + "bytes" + "crypto" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "encoding/hex" + "hash" + "io" + "testing" + "time" +) + +var privateKeyTests = []struct { + privateKeyHex string + creationTime time.Time +}{ + { + privKeyRSAHex, + time.Unix(0x4cc349a8, 0), + }, + { + privKeyElGamalHex, + time.Unix(0x4df9ee1a, 0), + }, +} + +func TestPrivateKeyRead(t *testing.T) { + for i, test := range privateKeyTests { + packet, err := Read(readerFromHex(test.privateKeyHex)) + if err != nil { + t.Errorf("#%d: failed to parse: %s", i, err) + continue + } + + privKey := packet.(*PrivateKey) + + if !privKey.Encrypted { + t.Errorf("#%d: private key isn't encrypted", i) + continue + } + + err = privKey.Decrypt([]byte("wrong password")) + if err == nil { + t.Errorf("#%d: decrypted with incorrect key", i) + continue + } + + err = privKey.Decrypt([]byte("testing")) + if err != nil { + t.Errorf("#%d: failed to decrypt: %s", i, err) + continue + } + + if !privKey.CreationTime.Equal(test.creationTime) || privKey.Encrypted { + t.Errorf("#%d: bad result, got: %#v", i, privKey) + } + } +} + +func populateHash(hashFunc crypto.Hash, msg []byte) (hash.Hash, error) { + h := hashFunc.New() + if _, err := h.Write(msg); err != nil { + return nil, err + } + return h, nil +} + +func TestRSAPrivateKey(t *testing.T) { + privKeyDER, _ := hex.DecodeString(pkcs1PrivKeyHex) + rsaPriv, err := x509.ParsePKCS1PrivateKey(privKeyDER) + if err != nil { + t.Fatal(err) + } + + var buf bytes.Buffer + if err := NewRSAPrivateKey(time.Now(), rsaPriv).Serialize(&buf); err != nil { + t.Fatal(err) + } + + p, err := Read(&buf) + if err != nil { + t.Fatal(err) + } + + priv, ok := p.(*PrivateKey) + if !ok { + t.Fatal("didn't parse private key") + } + + sig := &Signature{ + PubKeyAlgo: PubKeyAlgoRSA, + Hash: crypto.SHA256, + } + msg := []byte("Hello World!") + + h, err := populateHash(sig.Hash, msg) + if err != nil { + t.Fatal(err) + } + if err := sig.Sign(h, priv, nil); err != nil { + t.Fatal(err) + } + + if h, err = populateHash(sig.Hash, msg); err != nil { + t.Fatal(err) + } + if err := priv.VerifySignature(h, sig); err != nil { + t.Fatal(err) + } +} + +func TestECDSAPrivateKey(t *testing.T) { + ecdsaPriv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + t.Fatal(err) + } + + var buf bytes.Buffer + if err := NewECDSAPrivateKey(time.Now(), ecdsaPriv).Serialize(&buf); err != nil { + t.Fatal(err) + } + + p, err := Read(&buf) + if err != nil { + t.Fatal(err) + } + + priv, ok := p.(*PrivateKey) + if !ok { + t.Fatal("didn't parse private key") + } + + sig := &Signature{ + PubKeyAlgo: PubKeyAlgoECDSA, + Hash: crypto.SHA256, + } + msg := []byte("Hello World!") + + h, err := populateHash(sig.Hash, msg) + if err != nil { + t.Fatal(err) + } + if err := sig.Sign(h, priv, nil); err != nil { + t.Fatal(err) + } + + if h, err = populateHash(sig.Hash, msg); err != nil { + t.Fatal(err) + } + if err := priv.VerifySignature(h, sig); err != nil { + t.Fatal(err) + } +} + +type rsaSigner struct { + priv *rsa.PrivateKey +} + +func (s *rsaSigner) Public() crypto.PublicKey { + return s.priv.PublicKey +} + +func (s *rsaSigner) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts) ([]byte, error) { + return s.priv.Sign(rand, msg, opts) +} + +func TestRSASignerPrivateKey(t *testing.T) { + rsaPriv, err := rsa.GenerateKey(rand.Reader, 1024) + if err != nil { + t.Fatal(err) + } + + priv := NewSignerPrivateKey(time.Now(), &rsaSigner{rsaPriv}) + + if priv.PubKeyAlgo != PubKeyAlgoRSASignOnly { + t.Fatal("NewSignerPrivateKey should have made a sign-only RSA private key") + } + + sig := &Signature{ + PubKeyAlgo: PubKeyAlgoRSASignOnly, + Hash: crypto.SHA256, + } + msg := []byte("Hello World!") + + h, err := populateHash(sig.Hash, msg) + if err != nil { + t.Fatal(err) + } + if err := sig.Sign(h, priv, nil); err != nil { + t.Fatal(err) + } + + if h, err = populateHash(sig.Hash, msg); err != nil { + t.Fatal(err) + } + if err := priv.VerifySignature(h, sig); err != nil { + t.Fatal(err) + } +} + +type ecdsaSigner struct { + priv *ecdsa.PrivateKey +} + +func (s *ecdsaSigner) Public() crypto.PublicKey { + return s.priv.PublicKey +} + +func (s *ecdsaSigner) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts) ([]byte, error) { + return s.priv.Sign(rand, msg, opts) +} + +func TestECDSASignerPrivateKey(t *testing.T) { + ecdsaPriv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + t.Fatal(err) + } + + priv := NewSignerPrivateKey(time.Now(), &ecdsaSigner{ecdsaPriv}) + + if priv.PubKeyAlgo != PubKeyAlgoECDSA { + t.Fatal("NewSignerPrivateKey should have made an ECSDA private key") + } + + sig := &Signature{ + PubKeyAlgo: PubKeyAlgoECDSA, + Hash: crypto.SHA256, + } + msg := []byte("Hello World!") + + h, err := populateHash(sig.Hash, msg) + if err != nil { + t.Fatal(err) + } + if err := sig.Sign(h, priv, nil); err != nil { + t.Fatal(err) + } + + if h, err = populateHash(sig.Hash, msg); err != nil { + t.Fatal(err) + } + if err := priv.VerifySignature(h, sig); err != nil { + t.Fatal(err) + } +} + +func TestIssue11505(t *testing.T) { + // parsing a rsa private key with p or q == 1 used to panic due to a divide by zero + _, _ = Read(readerFromHex("9c3004303030300100000011303030000000000000010130303030303030303030303030303030303030303030303030303030303030303030303030303030303030")) +} + +// Generated with `gpg --export-secret-keys "Test Key 2"` +const privKeyRSAHex = "9501fe044cc349a8010400b70ca0010e98c090008d45d1ee8f9113bd5861fd57b88bacb7c68658747663f1e1a3b5a98f32fda6472373c024b97359cd2efc88ff60f77751adfbf6af5e615e6a1408cfad8bf0cea30b0d5f53aa27ad59089ba9b15b7ebc2777a25d7b436144027e3bcd203909f147d0e332b240cf63d3395f5dfe0df0a6c04e8655af7eacdf0011010001fe0303024a252e7d475fd445607de39a265472aa74a9320ba2dac395faa687e9e0336aeb7e9a7397e511b5afd9dc84557c80ac0f3d4d7bfec5ae16f20d41c8c84a04552a33870b930420e230e179564f6d19bb153145e76c33ae993886c388832b0fa042ddda7f133924f3854481533e0ede31d51278c0519b29abc3bf53da673e13e3e1214b52413d179d7f66deee35cac8eacb060f78379d70ef4af8607e68131ff529439668fc39c9ce6dfef8a5ac234d234802cbfb749a26107db26406213ae5c06d4673253a3cbee1fcbae58d6ab77e38d6e2c0e7c6317c48e054edadb5a40d0d48acb44643d998139a8a66bb820be1f3f80185bc777d14b5954b60effe2448a036d565c6bc0b915fcea518acdd20ab07bc1529f561c58cd044f723109b93f6fd99f876ff891d64306b5d08f48bab59f38695e9109c4dec34013ba3153488ce070268381ba923ee1eb77125b36afcb4347ec3478c8f2735b06ef17351d872e577fa95d0c397c88c71b59629a36aec" + +// Generated by `gpg --export-secret-keys` followed by a manual extraction of +// the ElGamal subkey from the packets. +const privKeyElGamalHex = "9d0157044df9ee1a100400eb8e136a58ec39b582629cdadf830bc64e0a94ed8103ca8bb247b27b11b46d1d25297ef4bcc3071785ba0c0bedfe89eabc5287fcc0edf81ab5896c1c8e4b20d27d79813c7aede75320b33eaeeaa586edc00fd1036c10133e6ba0ff277245d0d59d04b2b3421b7244aca5f4a8d870c6f1c1fbff9e1c26699a860b9504f35ca1d700030503fd1ededd3b840795be6d9ccbe3c51ee42e2f39233c432b831ddd9c4e72b7025a819317e47bf94f9ee316d7273b05d5fcf2999c3a681f519b1234bbfa6d359b4752bd9c3f77d6b6456cde152464763414ca130f4e91d91041432f90620fec0e6d6b5116076c2985d5aeaae13be492b9b329efcaf7ee25120159a0a30cd976b42d7afe030302dae7eb80db744d4960c4df930d57e87fe81412eaace9f900e6c839817a614ddb75ba6603b9417c33ea7b6c93967dfa2bcff3fa3c74a5ce2c962db65b03aece14c96cbd0038fc" + +// pkcs1PrivKeyHex is a PKCS#1, RSA private key. +// Generated by `openssl genrsa 1024 | openssl rsa -outform DER | xxd -p` +const pkcs1PrivKeyHex = "3082025d02010002818100e98edfa1c3b35884a54d0b36a6a603b0290fa85e49e30fa23fc94fef9c6790bc4849928607aa48d809da326fb42a969d06ad756b98b9c1a90f5d4a2b6d0ac05953c97f4da3120164a21a679793ce181c906dc01d235cc085ddcdf6ea06c389b6ab8885dfd685959e693138856a68a7e5db263337ff82a088d583a897cf2d59e9020301000102818100b6d5c9eb70b02d5369b3ee5b520a14490b5bde8a317d36f7e4c74b7460141311d1e5067735f8f01d6f5908b2b96fbd881f7a1ab9a84d82753e39e19e2d36856be960d05ac9ef8e8782ea1b6d65aee28fdfe1d61451e8cff0adfe84322f12cf455028b581cf60eb9e0e140ba5d21aeba6c2634d7c65318b9a665fc01c3191ca21024100fa5e818da3705b0fa33278bb28d4b6f6050388af2d4b75ec9375dd91ccf2e7d7068086a8b82a8f6282e4fbbdb8a7f2622eb97295249d87acea7f5f816f54d347024100eecf9406d7dc49cdfb95ab1eff4064de84c7a30f64b2798936a0d2018ba9eb52e4b636f82e96c49cc63b80b675e91e40d1b2e4017d4b9adaf33ab3d9cf1c214f024100c173704ace742c082323066226a4655226819a85304c542b9dacbeacbf5d1881ee863485fcf6f59f3a604f9b42289282067447f2b13dfeed3eab7851fc81e0550240741fc41f3fc002b382eed8730e33c5d8de40256e4accee846667f536832f711ab1d4590e7db91a8a116ac5bff3be13d3f9243ff2e976662aa9b395d907f8e9c9024046a5696c9ef882363e06c9fa4e2f5b580906452befba03f4a99d0f873697ef1f851d2226ca7934b30b7c3e80cb634a67172bbbf4781735fe3e09263e2dd723e7" diff --git a/vendor/golang.org/x/crypto/openpgp/packet/public_key.go b/vendor/golang.org/x/crypto/openpgp/packet/public_key.go new file mode 100644 index 0000000000000000000000000000000000000000..ead26233dda713fe74d5f10d138d3d6d9ac12301 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/public_key.go @@ -0,0 +1,748 @@ +// 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 packet + +import ( + "bytes" + "crypto" + "crypto/dsa" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rsa" + "crypto/sha1" + _ "crypto/sha256" + _ "crypto/sha512" + "encoding/binary" + "fmt" + "hash" + "io" + "math/big" + "strconv" + "time" + + "golang.org/x/crypto/openpgp/elgamal" + "golang.org/x/crypto/openpgp/errors" +) + +var ( + // NIST curve P-256 + oidCurveP256 []byte = []byte{0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07} + // NIST curve P-384 + oidCurveP384 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x22} + // NIST curve P-521 + oidCurveP521 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x23} +) + +const maxOIDLength = 8 + +// ecdsaKey stores the algorithm-specific fields for ECDSA keys. +// as defined in RFC 6637, Section 9. +type ecdsaKey struct { + // oid contains the OID byte sequence identifying the elliptic curve used + oid []byte + // p contains the elliptic curve point that represents the public key + p parsedMPI +} + +// parseOID reads the OID for the curve as defined in RFC 6637, Section 9. +func parseOID(r io.Reader) (oid []byte, err error) { + buf := make([]byte, maxOIDLength) + if _, err = readFull(r, buf[:1]); err != nil { + return + } + oidLen := buf[0] + if int(oidLen) > len(buf) { + err = errors.UnsupportedError("invalid oid length: " + strconv.Itoa(int(oidLen))) + return + } + oid = buf[:oidLen] + _, err = readFull(r, oid) + return +} + +func (f *ecdsaKey) parse(r io.Reader) (err error) { + if f.oid, err = parseOID(r); err != nil { + return err + } + f.p.bytes, f.p.bitLength, err = readMPI(r) + return +} + +func (f *ecdsaKey) serialize(w io.Writer) (err error) { + buf := make([]byte, maxOIDLength+1) + buf[0] = byte(len(f.oid)) + copy(buf[1:], f.oid) + if _, err = w.Write(buf[:len(f.oid)+1]); err != nil { + return + } + return writeMPIs(w, f.p) +} + +func (f *ecdsaKey) newECDSA() (*ecdsa.PublicKey, error) { + var c elliptic.Curve + if bytes.Equal(f.oid, oidCurveP256) { + c = elliptic.P256() + } else if bytes.Equal(f.oid, oidCurveP384) { + c = elliptic.P384() + } else if bytes.Equal(f.oid, oidCurveP521) { + c = elliptic.P521() + } else { + return nil, errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", f.oid)) + } + x, y := elliptic.Unmarshal(c, f.p.bytes) + if x == nil { + return nil, errors.UnsupportedError("failed to parse EC point") + } + return &ecdsa.PublicKey{Curve: c, X: x, Y: y}, nil +} + +func (f *ecdsaKey) byteLen() int { + return 1 + len(f.oid) + 2 + len(f.p.bytes) +} + +type kdfHashFunction byte +type kdfAlgorithm byte + +// ecdhKdf stores key derivation function parameters +// used for ECDH encryption. See RFC 6637, Section 9. +type ecdhKdf struct { + KdfHash kdfHashFunction + KdfAlgo kdfAlgorithm +} + +func (f *ecdhKdf) parse(r io.Reader) (err error) { + buf := make([]byte, 1) + if _, err = readFull(r, buf); err != nil { + return + } + kdfLen := int(buf[0]) + if kdfLen < 3 { + return errors.UnsupportedError("Unsupported ECDH KDF length: " + strconv.Itoa(kdfLen)) + } + buf = make([]byte, kdfLen) + if _, err = readFull(r, buf); err != nil { + return + } + reserved := int(buf[0]) + f.KdfHash = kdfHashFunction(buf[1]) + f.KdfAlgo = kdfAlgorithm(buf[2]) + if reserved != 0x01 { + return errors.UnsupportedError("Unsupported KDF reserved field: " + strconv.Itoa(reserved)) + } + return +} + +func (f *ecdhKdf) serialize(w io.Writer) (err error) { + buf := make([]byte, 4) + // See RFC 6637, Section 9, Algorithm-Specific Fields for ECDH keys. + buf[0] = byte(0x03) // Length of the following fields + buf[1] = byte(0x01) // Reserved for future extensions, must be 1 for now + buf[2] = byte(f.KdfHash) + buf[3] = byte(f.KdfAlgo) + _, err = w.Write(buf[:]) + return +} + +func (f *ecdhKdf) byteLen() int { + return 4 +} + +// PublicKey represents an OpenPGP public key. See RFC 4880, section 5.5.2. +type PublicKey struct { + CreationTime time.Time + PubKeyAlgo PublicKeyAlgorithm + PublicKey interface{} // *rsa.PublicKey, *dsa.PublicKey or *ecdsa.PublicKey + Fingerprint [20]byte + KeyId uint64 + IsSubkey bool + + n, e, p, q, g, y parsedMPI + + // RFC 6637 fields + ec *ecdsaKey + ecdh *ecdhKdf +} + +// signingKey provides a convenient abstraction over signature verification +// for v3 and v4 public keys. +type signingKey interface { + SerializeSignaturePrefix(io.Writer) + serializeWithoutHeaders(io.Writer) error +} + +func fromBig(n *big.Int) parsedMPI { + return parsedMPI{ + bytes: n.Bytes(), + bitLength: uint16(n.BitLen()), + } +} + +// NewRSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey. +func NewRSAPublicKey(creationTime time.Time, pub *rsa.PublicKey) *PublicKey { + pk := &PublicKey{ + CreationTime: creationTime, + PubKeyAlgo: PubKeyAlgoRSA, + PublicKey: pub, + n: fromBig(pub.N), + e: fromBig(big.NewInt(int64(pub.E))), + } + + pk.setFingerPrintAndKeyId() + return pk +} + +// NewDSAPublicKey returns a PublicKey that wraps the given dsa.PublicKey. +func NewDSAPublicKey(creationTime time.Time, pub *dsa.PublicKey) *PublicKey { + pk := &PublicKey{ + CreationTime: creationTime, + PubKeyAlgo: PubKeyAlgoDSA, + PublicKey: pub, + p: fromBig(pub.P), + q: fromBig(pub.Q), + g: fromBig(pub.G), + y: fromBig(pub.Y), + } + + pk.setFingerPrintAndKeyId() + return pk +} + +// NewElGamalPublicKey returns a PublicKey that wraps the given elgamal.PublicKey. +func NewElGamalPublicKey(creationTime time.Time, pub *elgamal.PublicKey) *PublicKey { + pk := &PublicKey{ + CreationTime: creationTime, + PubKeyAlgo: PubKeyAlgoElGamal, + PublicKey: pub, + p: fromBig(pub.P), + g: fromBig(pub.G), + y: fromBig(pub.Y), + } + + pk.setFingerPrintAndKeyId() + return pk +} + +func NewECDSAPublicKey(creationTime time.Time, pub *ecdsa.PublicKey) *PublicKey { + pk := &PublicKey{ + CreationTime: creationTime, + PubKeyAlgo: PubKeyAlgoECDSA, + PublicKey: pub, + ec: new(ecdsaKey), + } + + switch pub.Curve { + case elliptic.P256(): + pk.ec.oid = oidCurveP256 + case elliptic.P384(): + pk.ec.oid = oidCurveP384 + case elliptic.P521(): + pk.ec.oid = oidCurveP521 + default: + panic("unknown elliptic curve") + } + + pk.ec.p.bytes = elliptic.Marshal(pub.Curve, pub.X, pub.Y) + pk.ec.p.bitLength = uint16(8 * len(pk.ec.p.bytes)) + + pk.setFingerPrintAndKeyId() + return pk +} + +func (pk *PublicKey) parse(r io.Reader) (err error) { + // RFC 4880, section 5.5.2 + var buf [6]byte + _, err = readFull(r, buf[:]) + if err != nil { + return + } + if buf[0] != 4 { + return errors.UnsupportedError("public key version") + } + pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0) + pk.PubKeyAlgo = PublicKeyAlgorithm(buf[5]) + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: + err = pk.parseRSA(r) + case PubKeyAlgoDSA: + err = pk.parseDSA(r) + case PubKeyAlgoElGamal: + err = pk.parseElGamal(r) + case PubKeyAlgoECDSA: + pk.ec = new(ecdsaKey) + if err = pk.ec.parse(r); err != nil { + return err + } + pk.PublicKey, err = pk.ec.newECDSA() + case PubKeyAlgoECDH: + pk.ec = new(ecdsaKey) + if err = pk.ec.parse(r); err != nil { + return + } + pk.ecdh = new(ecdhKdf) + if err = pk.ecdh.parse(r); err != nil { + return + } + // The ECDH key is stored in an ecdsa.PublicKey for convenience. + pk.PublicKey, err = pk.ec.newECDSA() + default: + err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo))) + } + if err != nil { + return + } + + pk.setFingerPrintAndKeyId() + return +} + +func (pk *PublicKey) setFingerPrintAndKeyId() { + // RFC 4880, section 12.2 + fingerPrint := sha1.New() + pk.SerializeSignaturePrefix(fingerPrint) + pk.serializeWithoutHeaders(fingerPrint) + copy(pk.Fingerprint[:], fingerPrint.Sum(nil)) + pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[12:20]) +} + +// parseRSA parses RSA public key material from the given Reader. See RFC 4880, +// section 5.5.2. +func (pk *PublicKey) parseRSA(r io.Reader) (err error) { + pk.n.bytes, pk.n.bitLength, err = readMPI(r) + if err != nil { + return + } + pk.e.bytes, pk.e.bitLength, err = readMPI(r) + if err != nil { + return + } + + if len(pk.e.bytes) > 3 { + err = errors.UnsupportedError("large public exponent") + return + } + rsa := &rsa.PublicKey{ + N: new(big.Int).SetBytes(pk.n.bytes), + E: 0, + } + for i := 0; i < len(pk.e.bytes); i++ { + rsa.E <<= 8 + rsa.E |= int(pk.e.bytes[i]) + } + pk.PublicKey = rsa + return +} + +// parseDSA parses DSA public key material from the given Reader. See RFC 4880, +// section 5.5.2. +func (pk *PublicKey) parseDSA(r io.Reader) (err error) { + pk.p.bytes, pk.p.bitLength, err = readMPI(r) + if err != nil { + return + } + pk.q.bytes, pk.q.bitLength, err = readMPI(r) + if err != nil { + return + } + pk.g.bytes, pk.g.bitLength, err = readMPI(r) + if err != nil { + return + } + pk.y.bytes, pk.y.bitLength, err = readMPI(r) + if err != nil { + return + } + + dsa := new(dsa.PublicKey) + dsa.P = new(big.Int).SetBytes(pk.p.bytes) + dsa.Q = new(big.Int).SetBytes(pk.q.bytes) + dsa.G = new(big.Int).SetBytes(pk.g.bytes) + dsa.Y = new(big.Int).SetBytes(pk.y.bytes) + pk.PublicKey = dsa + return +} + +// parseElGamal parses ElGamal public key material from the given Reader. See +// RFC 4880, section 5.5.2. +func (pk *PublicKey) parseElGamal(r io.Reader) (err error) { + pk.p.bytes, pk.p.bitLength, err = readMPI(r) + if err != nil { + return + } + pk.g.bytes, pk.g.bitLength, err = readMPI(r) + if err != nil { + return + } + pk.y.bytes, pk.y.bitLength, err = readMPI(r) + if err != nil { + return + } + + elgamal := new(elgamal.PublicKey) + elgamal.P = new(big.Int).SetBytes(pk.p.bytes) + elgamal.G = new(big.Int).SetBytes(pk.g.bytes) + elgamal.Y = new(big.Int).SetBytes(pk.y.bytes) + pk.PublicKey = elgamal + return +} + +// SerializeSignaturePrefix writes the prefix for this public key to the given Writer. +// The prefix is used when calculating a signature over this public key. See +// RFC 4880, section 5.2.4. +func (pk *PublicKey) SerializeSignaturePrefix(h io.Writer) { + var pLength uint16 + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: + pLength += 2 + uint16(len(pk.n.bytes)) + pLength += 2 + uint16(len(pk.e.bytes)) + case PubKeyAlgoDSA: + pLength += 2 + uint16(len(pk.p.bytes)) + pLength += 2 + uint16(len(pk.q.bytes)) + pLength += 2 + uint16(len(pk.g.bytes)) + pLength += 2 + uint16(len(pk.y.bytes)) + case PubKeyAlgoElGamal: + pLength += 2 + uint16(len(pk.p.bytes)) + pLength += 2 + uint16(len(pk.g.bytes)) + pLength += 2 + uint16(len(pk.y.bytes)) + case PubKeyAlgoECDSA: + pLength += uint16(pk.ec.byteLen()) + case PubKeyAlgoECDH: + pLength += uint16(pk.ec.byteLen()) + pLength += uint16(pk.ecdh.byteLen()) + default: + panic("unknown public key algorithm") + } + pLength += 6 + h.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)}) + return +} + +func (pk *PublicKey) Serialize(w io.Writer) (err error) { + length := 6 // 6 byte header + + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: + length += 2 + len(pk.n.bytes) + length += 2 + len(pk.e.bytes) + case PubKeyAlgoDSA: + length += 2 + len(pk.p.bytes) + length += 2 + len(pk.q.bytes) + length += 2 + len(pk.g.bytes) + length += 2 + len(pk.y.bytes) + case PubKeyAlgoElGamal: + length += 2 + len(pk.p.bytes) + length += 2 + len(pk.g.bytes) + length += 2 + len(pk.y.bytes) + case PubKeyAlgoECDSA: + length += pk.ec.byteLen() + case PubKeyAlgoECDH: + length += pk.ec.byteLen() + length += pk.ecdh.byteLen() + default: + panic("unknown public key algorithm") + } + + packetType := packetTypePublicKey + if pk.IsSubkey { + packetType = packetTypePublicSubkey + } + err = serializeHeader(w, packetType, length) + if err != nil { + return + } + return pk.serializeWithoutHeaders(w) +} + +// serializeWithoutHeaders marshals the PublicKey to w in the form of an +// OpenPGP public key packet, not including the packet header. +func (pk *PublicKey) serializeWithoutHeaders(w io.Writer) (err error) { + var buf [6]byte + buf[0] = 4 + t := uint32(pk.CreationTime.Unix()) + buf[1] = byte(t >> 24) + buf[2] = byte(t >> 16) + buf[3] = byte(t >> 8) + buf[4] = byte(t) + buf[5] = byte(pk.PubKeyAlgo) + + _, err = w.Write(buf[:]) + if err != nil { + return + } + + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: + return writeMPIs(w, pk.n, pk.e) + case PubKeyAlgoDSA: + return writeMPIs(w, pk.p, pk.q, pk.g, pk.y) + case PubKeyAlgoElGamal: + return writeMPIs(w, pk.p, pk.g, pk.y) + case PubKeyAlgoECDSA: + return pk.ec.serialize(w) + case PubKeyAlgoECDH: + if err = pk.ec.serialize(w); err != nil { + return + } + return pk.ecdh.serialize(w) + } + return errors.InvalidArgumentError("bad public-key algorithm") +} + +// CanSign returns true iff this public key can generate signatures +func (pk *PublicKey) CanSign() bool { + return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly && pk.PubKeyAlgo != PubKeyAlgoElGamal +} + +// VerifySignature returns nil iff sig is a valid signature, made by this +// public key, of the data hashed into signed. signed is mutated by this call. +func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err error) { + if !pk.CanSign() { + return errors.InvalidArgumentError("public key cannot generate signatures") + } + + signed.Write(sig.HashSuffix) + hashBytes := signed.Sum(nil) + + if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] { + return errors.SignatureError("hash tag doesn't match") + } + + if pk.PubKeyAlgo != sig.PubKeyAlgo { + return errors.InvalidArgumentError("public key and signature use different algorithms") + } + + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: + rsaPublicKey, _ := pk.PublicKey.(*rsa.PublicKey) + err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes) + if err != nil { + return errors.SignatureError("RSA verification failure") + } + return nil + case PubKeyAlgoDSA: + dsaPublicKey, _ := pk.PublicKey.(*dsa.PublicKey) + // Need to truncate hashBytes to match FIPS 186-3 section 4.6. + subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8 + if len(hashBytes) > subgroupSize { + hashBytes = hashBytes[:subgroupSize] + } + if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) { + return errors.SignatureError("DSA verification failure") + } + return nil + case PubKeyAlgoECDSA: + ecdsaPublicKey := pk.PublicKey.(*ecdsa.PublicKey) + if !ecdsa.Verify(ecdsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.ECDSASigR.bytes), new(big.Int).SetBytes(sig.ECDSASigS.bytes)) { + return errors.SignatureError("ECDSA verification failure") + } + return nil + default: + return errors.SignatureError("Unsupported public key algorithm used in signature") + } +} + +// VerifySignatureV3 returns nil iff sig is a valid signature, made by this +// public key, of the data hashed into signed. signed is mutated by this call. +func (pk *PublicKey) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err error) { + if !pk.CanSign() { + return errors.InvalidArgumentError("public key cannot generate signatures") + } + + suffix := make([]byte, 5) + suffix[0] = byte(sig.SigType) + binary.BigEndian.PutUint32(suffix[1:], uint32(sig.CreationTime.Unix())) + signed.Write(suffix) + hashBytes := signed.Sum(nil) + + if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] { + return errors.SignatureError("hash tag doesn't match") + } + + if pk.PubKeyAlgo != sig.PubKeyAlgo { + return errors.InvalidArgumentError("public key and signature use different algorithms") + } + + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: + rsaPublicKey := pk.PublicKey.(*rsa.PublicKey) + if err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes); err != nil { + return errors.SignatureError("RSA verification failure") + } + return + case PubKeyAlgoDSA: + dsaPublicKey := pk.PublicKey.(*dsa.PublicKey) + // Need to truncate hashBytes to match FIPS 186-3 section 4.6. + subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8 + if len(hashBytes) > subgroupSize { + hashBytes = hashBytes[:subgroupSize] + } + if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) { + return errors.SignatureError("DSA verification failure") + } + return nil + default: + panic("shouldn't happen") + } +} + +// keySignatureHash returns a Hash of the message that needs to be signed for +// pk to assert a subkey relationship to signed. +func keySignatureHash(pk, signed signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) { + if !hashFunc.Available() { + return nil, errors.UnsupportedError("hash function") + } + h = hashFunc.New() + + // RFC 4880, section 5.2.4 + pk.SerializeSignaturePrefix(h) + pk.serializeWithoutHeaders(h) + signed.SerializeSignaturePrefix(h) + signed.serializeWithoutHeaders(h) + return +} + +// VerifyKeySignature returns nil iff sig is a valid signature, made by this +// public key, of signed. +func (pk *PublicKey) VerifyKeySignature(signed *PublicKey, sig *Signature) error { + h, err := keySignatureHash(pk, signed, sig.Hash) + if err != nil { + return err + } + if err = pk.VerifySignature(h, sig); err != nil { + return err + } + + if sig.FlagSign { + // Signing subkeys must be cross-signed. See + // https://www.gnupg.org/faq/subkey-cross-certify.html. + if sig.EmbeddedSignature == nil { + return errors.StructuralError("signing subkey is missing cross-signature") + } + // Verify the cross-signature. This is calculated over the same + // data as the main signature, so we cannot just recursively + // call signed.VerifyKeySignature(...) + if h, err = keySignatureHash(pk, signed, sig.EmbeddedSignature.Hash); err != nil { + return errors.StructuralError("error while hashing for cross-signature: " + err.Error()) + } + if err := signed.VerifySignature(h, sig.EmbeddedSignature); err != nil { + return errors.StructuralError("error while verifying cross-signature: " + err.Error()) + } + } + + return nil +} + +func keyRevocationHash(pk signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) { + if !hashFunc.Available() { + return nil, errors.UnsupportedError("hash function") + } + h = hashFunc.New() + + // RFC 4880, section 5.2.4 + pk.SerializeSignaturePrefix(h) + pk.serializeWithoutHeaders(h) + + return +} + +// VerifyRevocationSignature returns nil iff sig is a valid signature, made by this +// public key. +func (pk *PublicKey) VerifyRevocationSignature(sig *Signature) (err error) { + h, err := keyRevocationHash(pk, sig.Hash) + if err != nil { + return err + } + return pk.VerifySignature(h, sig) +} + +// userIdSignatureHash returns a Hash of the message that needs to be signed +// to assert that pk is a valid key for id. +func userIdSignatureHash(id string, pk *PublicKey, hashFunc crypto.Hash) (h hash.Hash, err error) { + if !hashFunc.Available() { + return nil, errors.UnsupportedError("hash function") + } + h = hashFunc.New() + + // RFC 4880, section 5.2.4 + pk.SerializeSignaturePrefix(h) + pk.serializeWithoutHeaders(h) + + var buf [5]byte + buf[0] = 0xb4 + buf[1] = byte(len(id) >> 24) + buf[2] = byte(len(id) >> 16) + buf[3] = byte(len(id) >> 8) + buf[4] = byte(len(id)) + h.Write(buf[:]) + h.Write([]byte(id)) + + return +} + +// VerifyUserIdSignature returns nil iff sig is a valid signature, made by this +// public key, that id is the identity of pub. +func (pk *PublicKey) VerifyUserIdSignature(id string, pub *PublicKey, sig *Signature) (err error) { + h, err := userIdSignatureHash(id, pub, sig.Hash) + if err != nil { + return err + } + return pk.VerifySignature(h, sig) +} + +// VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this +// public key, that id is the identity of pub. +func (pk *PublicKey) VerifyUserIdSignatureV3(id string, pub *PublicKey, sig *SignatureV3) (err error) { + h, err := userIdSignatureV3Hash(id, pub, sig.Hash) + if err != nil { + return err + } + return pk.VerifySignatureV3(h, sig) +} + +// KeyIdString returns the public key's fingerprint in capital hex +// (e.g. "6C7EE1B8621CC013"). +func (pk *PublicKey) KeyIdString() string { + return fmt.Sprintf("%X", pk.Fingerprint[12:20]) +} + +// KeyIdShortString returns the short form of public key's fingerprint +// in capital hex, as shown by gpg --list-keys (e.g. "621CC013"). +func (pk *PublicKey) KeyIdShortString() string { + return fmt.Sprintf("%X", pk.Fingerprint[16:20]) +} + +// A parsedMPI is used to store the contents of a big integer, along with the +// bit length that was specified in the original input. This allows the MPI to +// be reserialized exactly. +type parsedMPI struct { + bytes []byte + bitLength uint16 +} + +// writeMPIs is a utility function for serializing several big integers to the +// given Writer. +func writeMPIs(w io.Writer, mpis ...parsedMPI) (err error) { + for _, mpi := range mpis { + err = writeMPI(w, mpi.bitLength, mpi.bytes) + if err != nil { + return + } + } + return +} + +// BitLength returns the bit length for the given public key. +func (pk *PublicKey) BitLength() (bitLength uint16, err error) { + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: + bitLength = pk.n.bitLength + case PubKeyAlgoDSA: + bitLength = pk.p.bitLength + case PubKeyAlgoElGamal: + bitLength = pk.p.bitLength + default: + err = errors.InvalidArgumentError("bad public-key algorithm") + } + return +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/public_key_test.go b/vendor/golang.org/x/crypto/openpgp/packet/public_key_test.go new file mode 100644 index 0000000000000000000000000000000000000000..7ad7d91856d86fdd3c98e1fe7bc11a3dd5d6cf3c --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/public_key_test.go @@ -0,0 +1,202 @@ +// 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 packet + +import ( + "bytes" + "encoding/hex" + "testing" + "time" +) + +var pubKeyTests = []struct { + hexData string + hexFingerprint string + creationTime time.Time + pubKeyAlgo PublicKeyAlgorithm + keyId uint64 + keyIdString string + keyIdShort string +}{ + {rsaPkDataHex, rsaFingerprintHex, time.Unix(0x4d3c5c10, 0), PubKeyAlgoRSA, 0xa34d7e18c20c31bb, "A34D7E18C20C31BB", "C20C31BB"}, + {dsaPkDataHex, dsaFingerprintHex, time.Unix(0x4d432f89, 0), PubKeyAlgoDSA, 0x8e8fbe54062f19ed, "8E8FBE54062F19ED", "062F19ED"}, + {ecdsaPkDataHex, ecdsaFingerprintHex, time.Unix(0x5071c294, 0), PubKeyAlgoECDSA, 0x43fe956c542ca00b, "43FE956C542CA00B", "542CA00B"}, +} + +func TestPublicKeyRead(t *testing.T) { + for i, test := range pubKeyTests { + packet, err := Read(readerFromHex(test.hexData)) + if err != nil { + t.Errorf("#%d: Read error: %s", i, err) + continue + } + pk, ok := packet.(*PublicKey) + if !ok { + t.Errorf("#%d: failed to parse, got: %#v", i, packet) + continue + } + if pk.PubKeyAlgo != test.pubKeyAlgo { + t.Errorf("#%d: bad public key algorithm got:%x want:%x", i, pk.PubKeyAlgo, test.pubKeyAlgo) + } + if !pk.CreationTime.Equal(test.creationTime) { + t.Errorf("#%d: bad creation time got:%v want:%v", i, pk.CreationTime, test.creationTime) + } + expectedFingerprint, _ := hex.DecodeString(test.hexFingerprint) + if !bytes.Equal(expectedFingerprint, pk.Fingerprint[:]) { + t.Errorf("#%d: bad fingerprint got:%x want:%x", i, pk.Fingerprint[:], expectedFingerprint) + } + if pk.KeyId != test.keyId { + t.Errorf("#%d: bad keyid got:%x want:%x", i, pk.KeyId, test.keyId) + } + if g, e := pk.KeyIdString(), test.keyIdString; g != e { + t.Errorf("#%d: bad KeyIdString got:%q want:%q", i, g, e) + } + if g, e := pk.KeyIdShortString(), test.keyIdShort; g != e { + t.Errorf("#%d: bad KeyIdShortString got:%q want:%q", i, g, e) + } + } +} + +func TestPublicKeySerialize(t *testing.T) { + for i, test := range pubKeyTests { + packet, err := Read(readerFromHex(test.hexData)) + if err != nil { + t.Errorf("#%d: Read error: %s", i, err) + continue + } + pk, ok := packet.(*PublicKey) + if !ok { + t.Errorf("#%d: failed to parse, got: %#v", i, packet) + continue + } + serializeBuf := bytes.NewBuffer(nil) + err = pk.Serialize(serializeBuf) + if err != nil { + t.Errorf("#%d: failed to serialize: %s", i, err) + continue + } + + packet, err = Read(serializeBuf) + if err != nil { + t.Errorf("#%d: Read error (from serialized data): %s", i, err) + continue + } + pk, ok = packet.(*PublicKey) + if !ok { + t.Errorf("#%d: failed to parse serialized data, got: %#v", i, packet) + continue + } + } +} + +func TestEcc384Serialize(t *testing.T) { + r := readerFromHex(ecc384PubHex) + var w bytes.Buffer + for i := 0; i < 2; i++ { + // Public key + p, err := Read(r) + if err != nil { + t.Error(err) + } + pubkey := p.(*PublicKey) + if !bytes.Equal(pubkey.ec.oid, []byte{0x2b, 0x81, 0x04, 0x00, 0x22}) { + t.Errorf("Unexpected pubkey OID: %x", pubkey.ec.oid) + } + if !bytes.Equal(pubkey.ec.p.bytes[:5], []byte{0x04, 0xf6, 0xb8, 0xc5, 0xac}) { + t.Errorf("Unexpected pubkey P[:5]: %x", pubkey.ec.p.bytes) + } + if pubkey.KeyId != 0x098033880F54719F { + t.Errorf("Unexpected pubkey ID: %x", pubkey.KeyId) + } + err = pubkey.Serialize(&w) + if err != nil { + t.Error(err) + } + // User ID + p, err = Read(r) + if err != nil { + t.Error(err) + } + uid := p.(*UserId) + if uid.Id != "ec_dsa_dh_384 " { + t.Error("Unexpected UID:", uid.Id) + } + err = uid.Serialize(&w) + if err != nil { + t.Error(err) + } + // User ID Sig + p, err = Read(r) + if err != nil { + t.Error(err) + } + uidSig := p.(*Signature) + err = pubkey.VerifyUserIdSignature(uid.Id, pubkey, uidSig) + if err != nil { + t.Error(err, ": UID") + } + err = uidSig.Serialize(&w) + if err != nil { + t.Error(err) + } + // Subkey + p, err = Read(r) + if err != nil { + t.Error(err) + } + subkey := p.(*PublicKey) + if !bytes.Equal(subkey.ec.oid, []byte{0x2b, 0x81, 0x04, 0x00, 0x22}) { + t.Errorf("Unexpected subkey OID: %x", subkey.ec.oid) + } + if !bytes.Equal(subkey.ec.p.bytes[:5], []byte{0x04, 0x2f, 0xaa, 0x84, 0x02}) { + t.Errorf("Unexpected subkey P[:5]: %x", subkey.ec.p.bytes) + } + if subkey.ecdh.KdfHash != 0x09 { + t.Error("Expected KDF hash function SHA384 (0x09), got", subkey.ecdh.KdfHash) + } + if subkey.ecdh.KdfAlgo != 0x09 { + t.Error("Expected KDF symmetric alg AES256 (0x09), got", subkey.ecdh.KdfAlgo) + } + if subkey.KeyId != 0xAA8B938F9A201946 { + t.Errorf("Unexpected subkey ID: %x", subkey.KeyId) + } + err = subkey.Serialize(&w) + if err != nil { + t.Error(err) + } + // Subkey Sig + p, err = Read(r) + if err != nil { + t.Error(err) + } + subkeySig := p.(*Signature) + err = pubkey.VerifyKeySignature(subkey, subkeySig) + if err != nil { + t.Error(err) + } + err = subkeySig.Serialize(&w) + if err != nil { + t.Error(err) + } + // Now read back what we've written again + r = bytes.NewBuffer(w.Bytes()) + w.Reset() + } +} + +const rsaFingerprintHex = "5fb74b1d03b1e3cb31bc2f8aa34d7e18c20c31bb" + +const rsaPkDataHex = "988d044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd0011010001" + +const dsaFingerprintHex = "eece4c094db002103714c63c8e8fbe54062f19ed" + +const dsaPkDataHex = "9901a2044d432f89110400cd581334f0d7a1e1bdc8b9d6d8c0baf68793632735d2bb0903224cbaa1dfbf35a60ee7a13b92643421e1eb41aa8d79bea19a115a677f6b8ba3c7818ce53a6c2a24a1608bd8b8d6e55c5090cbde09dd26e356267465ae25e69ec8bdd57c7bbb2623e4d73336f73a0a9098f7f16da2e25252130fd694c0e8070c55a812a423ae7f00a0ebf50e70c2f19c3520a551bd4b08d30f23530d3d03ff7d0bf4a53a64a09dc5e6e6e35854b7d70c882b0c60293401958b1bd9e40abec3ea05ba87cf64899299d4bd6aa7f459c201d3fbbd6c82004bdc5e8a9eb8082d12054cc90fa9d4ec251a843236a588bf49552441817436c4f43326966fe85447d4e6d0acf8fa1ef0f014730770603ad7634c3088dc52501c237328417c31c89ed70400b2f1a98b0bf42f11fefc430704bebbaa41d9f355600c3facee1e490f64208e0e094ea55e3a598a219a58500bf78ac677b670a14f4e47e9cf8eab4f368cc1ddcaa18cc59309d4cc62dd4f680e73e6cc3e1ce87a84d0925efbcb26c575c093fc42eecf45135fabf6403a25c2016e1774c0484e440a18319072c617cc97ac0a3bb0" + +const ecdsaFingerprintHex = "9892270b38b8980b05c8d56d43fe956c542ca00b" + +const ecdsaPkDataHex = "9893045071c29413052b8104002304230401f4867769cedfa52c325018896245443968e52e51d0c2df8d939949cb5b330f2921711fbee1c9b9dddb95d15cb0255e99badeddda7cc23d9ddcaacbc290969b9f24019375d61c2e4e3b36953a28d8b2bc95f78c3f1d592fb24499be348656a7b17e3963187b4361afe497bc5f9f81213f04069f8e1fb9e6a6290ae295ca1a92b894396cb4" + +// Source: https://sites.google.com/site/brainhub/pgpecckeys#TOC-ECC-NIST-P-384-key +const ecc384PubHex = `99006f044d53059213052b81040022030304f6b8c5aced5b84ef9f4a209db2e4a9dfb70d28cb8c10ecd57674a9fa5a67389942b62d5e51367df4c7bfd3f8e500feecf07ed265a621a8ebbbe53e947ec78c677eba143bd1533c2b350e1c29f82313e1e1108eba063be1e64b10e6950e799c2db42465635f6473615f64685f333834203c6f70656e70677040627261696e6875622e6f72673e8900cb04101309005305024d530592301480000000002000077072656665727265642d656d61696c2d656e636f64696e67407067702e636f6d7067706d696d65040b090807021901051b03000000021602051e010000000415090a08000a0910098033880f54719fca2b0180aa37350968bd5f115afd8ce7bc7b103822152dbff06d0afcda835329510905b98cb469ba208faab87c7412b799e7b633017f58364ea480e8a1a3f253a0c5f22c446e8be9a9fce6210136ee30811abbd49139de28b5bdf8dc36d06ae748579e9ff503b90073044d53059212052b810400220303042faa84024a20b6735c4897efa5bfb41bf85b7eefeab5ca0cb9ffc8ea04a46acb25534a577694f9e25340a4ab5223a9dd1eda530c8aa2e6718db10d7e672558c7736fe09369ea5739a2a3554bf16d41faa50562f11c6d39bbd5dffb6b9a9ec9180301090989008404181309000c05024d530592051b0c000000000a0910098033880f54719f80970180eee7a6d8fcee41ee4f9289df17f9bcf9d955dca25c583b94336f3a2b2d4986dc5cf417b8d2dc86f741a9e1a6d236c0e3017d1c76575458a0cfb93ae8a2b274fcc65ceecd7a91eec83656ba13219969f06945b48c56bd04152c3a0553c5f2f4bd1267` diff --git a/vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go b/vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go new file mode 100644 index 0000000000000000000000000000000000000000..5daf7b6cfd4a06f57ce7fbbd9f5805dadb6a44b5 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go @@ -0,0 +1,279 @@ +// 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. + +package packet + +import ( + "crypto" + "crypto/md5" + "crypto/rsa" + "encoding/binary" + "fmt" + "hash" + "io" + "math/big" + "strconv" + "time" + + "golang.org/x/crypto/openpgp/errors" +) + +// PublicKeyV3 represents older, version 3 public keys. These keys are less secure and +// should not be used for signing or encrypting. They are supported here only for +// parsing version 3 key material and validating signatures. +// See RFC 4880, section 5.5.2. +type PublicKeyV3 struct { + CreationTime time.Time + DaysToExpire uint16 + PubKeyAlgo PublicKeyAlgorithm + PublicKey *rsa.PublicKey + Fingerprint [16]byte + KeyId uint64 + IsSubkey bool + + n, e parsedMPI +} + +// newRSAPublicKeyV3 returns a PublicKey that wraps the given rsa.PublicKey. +// Included here for testing purposes only. RFC 4880, section 5.5.2: +// "an implementation MUST NOT generate a V3 key, but MAY accept it." +func newRSAPublicKeyV3(creationTime time.Time, pub *rsa.PublicKey) *PublicKeyV3 { + pk := &PublicKeyV3{ + CreationTime: creationTime, + PublicKey: pub, + n: fromBig(pub.N), + e: fromBig(big.NewInt(int64(pub.E))), + } + + pk.setFingerPrintAndKeyId() + return pk +} + +func (pk *PublicKeyV3) parse(r io.Reader) (err error) { + // RFC 4880, section 5.5.2 + var buf [8]byte + if _, err = readFull(r, buf[:]); err != nil { + return + } + if buf[0] < 2 || buf[0] > 3 { + return errors.UnsupportedError("public key version") + } + pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0) + pk.DaysToExpire = binary.BigEndian.Uint16(buf[5:7]) + pk.PubKeyAlgo = PublicKeyAlgorithm(buf[7]) + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: + err = pk.parseRSA(r) + default: + err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo))) + } + if err != nil { + return + } + + pk.setFingerPrintAndKeyId() + return +} + +func (pk *PublicKeyV3) setFingerPrintAndKeyId() { + // RFC 4880, section 12.2 + fingerPrint := md5.New() + fingerPrint.Write(pk.n.bytes) + fingerPrint.Write(pk.e.bytes) + fingerPrint.Sum(pk.Fingerprint[:0]) + pk.KeyId = binary.BigEndian.Uint64(pk.n.bytes[len(pk.n.bytes)-8:]) +} + +// parseRSA parses RSA public key material from the given Reader. See RFC 4880, +// section 5.5.2. +func (pk *PublicKeyV3) parseRSA(r io.Reader) (err error) { + if pk.n.bytes, pk.n.bitLength, err = readMPI(r); err != nil { + return + } + if pk.e.bytes, pk.e.bitLength, err = readMPI(r); err != nil { + return + } + + // RFC 4880 Section 12.2 requires the low 8 bytes of the + // modulus to form the key id. + if len(pk.n.bytes) < 8 { + return errors.StructuralError("v3 public key modulus is too short") + } + if len(pk.e.bytes) > 3 { + err = errors.UnsupportedError("large public exponent") + return + } + rsa := &rsa.PublicKey{N: new(big.Int).SetBytes(pk.n.bytes)} + for i := 0; i < len(pk.e.bytes); i++ { + rsa.E <<= 8 + rsa.E |= int(pk.e.bytes[i]) + } + pk.PublicKey = rsa + return +} + +// SerializeSignaturePrefix writes the prefix for this public key to the given Writer. +// The prefix is used when calculating a signature over this public key. See +// RFC 4880, section 5.2.4. +func (pk *PublicKeyV3) SerializeSignaturePrefix(w io.Writer) { + var pLength uint16 + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: + pLength += 2 + uint16(len(pk.n.bytes)) + pLength += 2 + uint16(len(pk.e.bytes)) + default: + panic("unknown public key algorithm") + } + pLength += 6 + w.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)}) + return +} + +func (pk *PublicKeyV3) Serialize(w io.Writer) (err error) { + length := 8 // 8 byte header + + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: + length += 2 + len(pk.n.bytes) + length += 2 + len(pk.e.bytes) + default: + panic("unknown public key algorithm") + } + + packetType := packetTypePublicKey + if pk.IsSubkey { + packetType = packetTypePublicSubkey + } + if err = serializeHeader(w, packetType, length); err != nil { + return + } + return pk.serializeWithoutHeaders(w) +} + +// serializeWithoutHeaders marshals the PublicKey to w in the form of an +// OpenPGP public key packet, not including the packet header. +func (pk *PublicKeyV3) serializeWithoutHeaders(w io.Writer) (err error) { + var buf [8]byte + // Version 3 + buf[0] = 3 + // Creation time + t := uint32(pk.CreationTime.Unix()) + buf[1] = byte(t >> 24) + buf[2] = byte(t >> 16) + buf[3] = byte(t >> 8) + buf[4] = byte(t) + // Days to expire + buf[5] = byte(pk.DaysToExpire >> 8) + buf[6] = byte(pk.DaysToExpire) + // Public key algorithm + buf[7] = byte(pk.PubKeyAlgo) + + if _, err = w.Write(buf[:]); err != nil { + return + } + + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: + return writeMPIs(w, pk.n, pk.e) + } + return errors.InvalidArgumentError("bad public-key algorithm") +} + +// CanSign returns true iff this public key can generate signatures +func (pk *PublicKeyV3) CanSign() bool { + return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly +} + +// VerifySignatureV3 returns nil iff sig is a valid signature, made by this +// public key, of the data hashed into signed. signed is mutated by this call. +func (pk *PublicKeyV3) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err error) { + if !pk.CanSign() { + return errors.InvalidArgumentError("public key cannot generate signatures") + } + + suffix := make([]byte, 5) + suffix[0] = byte(sig.SigType) + binary.BigEndian.PutUint32(suffix[1:], uint32(sig.CreationTime.Unix())) + signed.Write(suffix) + hashBytes := signed.Sum(nil) + + if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] { + return errors.SignatureError("hash tag doesn't match") + } + + if pk.PubKeyAlgo != sig.PubKeyAlgo { + return errors.InvalidArgumentError("public key and signature use different algorithms") + } + + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: + if err = rsa.VerifyPKCS1v15(pk.PublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes); err != nil { + return errors.SignatureError("RSA verification failure") + } + return + default: + // V3 public keys only support RSA. + panic("shouldn't happen") + } +} + +// VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this +// public key, that id is the identity of pub. +func (pk *PublicKeyV3) VerifyUserIdSignatureV3(id string, pub *PublicKeyV3, sig *SignatureV3) (err error) { + h, err := userIdSignatureV3Hash(id, pk, sig.Hash) + if err != nil { + return err + } + return pk.VerifySignatureV3(h, sig) +} + +// VerifyKeySignatureV3 returns nil iff sig is a valid signature, made by this +// public key, of signed. +func (pk *PublicKeyV3) VerifyKeySignatureV3(signed *PublicKeyV3, sig *SignatureV3) (err error) { + h, err := keySignatureHash(pk, signed, sig.Hash) + if err != nil { + return err + } + return pk.VerifySignatureV3(h, sig) +} + +// userIdSignatureV3Hash returns a Hash of the message that needs to be signed +// to assert that pk is a valid key for id. +func userIdSignatureV3Hash(id string, pk signingKey, hfn crypto.Hash) (h hash.Hash, err error) { + if !hfn.Available() { + return nil, errors.UnsupportedError("hash function") + } + h = hfn.New() + + // RFC 4880, section 5.2.4 + pk.SerializeSignaturePrefix(h) + pk.serializeWithoutHeaders(h) + + h.Write([]byte(id)) + + return +} + +// KeyIdString returns the public key's fingerprint in capital hex +// (e.g. "6C7EE1B8621CC013"). +func (pk *PublicKeyV3) KeyIdString() string { + return fmt.Sprintf("%X", pk.KeyId) +} + +// KeyIdShortString returns the short form of public key's fingerprint +// in capital hex, as shown by gpg --list-keys (e.g. "621CC013"). +func (pk *PublicKeyV3) KeyIdShortString() string { + return fmt.Sprintf("%X", pk.KeyId&0xFFFFFFFF) +} + +// BitLength returns the bit length for the given public key. +func (pk *PublicKeyV3) BitLength() (bitLength uint16, err error) { + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: + bitLength = pk.n.bitLength + default: + err = errors.InvalidArgumentError("bad public-key algorithm") + } + return +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/public_key_v3_test.go b/vendor/golang.org/x/crypto/openpgp/packet/public_key_v3_test.go new file mode 100644 index 0000000000000000000000000000000000000000..e06405904b3e3b2875ba2d58815b7f76705304c2 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/public_key_v3_test.go @@ -0,0 +1,82 @@ +// 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. + +package packet + +import ( + "bytes" + "encoding/hex" + "testing" + "time" +) + +var pubKeyV3Test = struct { + hexFingerprint string + creationTime time.Time + pubKeyAlgo PublicKeyAlgorithm + keyId uint64 + keyIdString string + keyIdShort string +}{ + "103BECF5BD1E837C89D19E98487767F7", + time.Unix(779753634, 0), + PubKeyAlgoRSA, + 0xDE0F188A5DA5E3C9, + "DE0F188A5DA5E3C9", + "5DA5E3C9"} + +func TestPublicKeyV3Read(t *testing.T) { + i, test := 0, pubKeyV3Test + packet, err := Read(v3KeyReader(t)) + if err != nil { + t.Fatalf("#%d: Read error: %s", i, err) + } + pk, ok := packet.(*PublicKeyV3) + if !ok { + t.Fatalf("#%d: failed to parse, got: %#v", i, packet) + } + if pk.PubKeyAlgo != test.pubKeyAlgo { + t.Errorf("#%d: bad public key algorithm got:%x want:%x", i, pk.PubKeyAlgo, test.pubKeyAlgo) + } + if !pk.CreationTime.Equal(test.creationTime) { + t.Errorf("#%d: bad creation time got:%v want:%v", i, pk.CreationTime, test.creationTime) + } + expectedFingerprint, _ := hex.DecodeString(test.hexFingerprint) + if !bytes.Equal(expectedFingerprint, pk.Fingerprint[:]) { + t.Errorf("#%d: bad fingerprint got:%x want:%x", i, pk.Fingerprint[:], expectedFingerprint) + } + if pk.KeyId != test.keyId { + t.Errorf("#%d: bad keyid got:%x want:%x", i, pk.KeyId, test.keyId) + } + if g, e := pk.KeyIdString(), test.keyIdString; g != e { + t.Errorf("#%d: bad KeyIdString got:%q want:%q", i, g, e) + } + if g, e := pk.KeyIdShortString(), test.keyIdShort; g != e { + t.Errorf("#%d: bad KeyIdShortString got:%q want:%q", i, g, e) + } +} + +func TestPublicKeyV3Serialize(t *testing.T) { + //for i, test := range pubKeyV3Tests { + i := 0 + packet, err := Read(v3KeyReader(t)) + if err != nil { + t.Fatalf("#%d: Read error: %s", i, err) + } + pk, ok := packet.(*PublicKeyV3) + if !ok { + t.Fatalf("#%d: failed to parse, got: %#v", i, packet) + } + var serializeBuf bytes.Buffer + if err = pk.Serialize(&serializeBuf); err != nil { + t.Fatalf("#%d: failed to serialize: %s", i, err) + } + + if packet, err = Read(bytes.NewBuffer(serializeBuf.Bytes())); err != nil { + t.Fatalf("#%d: Read error (from serialized data): %s", i, err) + } + if pk, ok = packet.(*PublicKeyV3); !ok { + t.Fatalf("#%d: failed to parse serialized data, got: %#v", i, packet) + } +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/reader.go b/vendor/golang.org/x/crypto/openpgp/packet/reader.go new file mode 100644 index 0000000000000000000000000000000000000000..34bc7c613e6e236b24b7bf97f246fceef37c8b29 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/reader.go @@ -0,0 +1,76 @@ +// 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 packet + +import ( + "golang.org/x/crypto/openpgp/errors" + "io" +) + +// Reader reads packets from an io.Reader and allows packets to be 'unread' so +// that they result from the next call to Next. +type Reader struct { + q []Packet + readers []io.Reader +} + +// New io.Readers are pushed when a compressed or encrypted packet is processed +// and recursively treated as a new source of packets. However, a carefully +// crafted packet can trigger an infinite recursive sequence of packets. See +// http://mumble.net/~campbell/misc/pgp-quine +// https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2013-4402 +// This constant limits the number of recursive packets that may be pushed. +const maxReaders = 32 + +// Next returns the most recently unread Packet, or reads another packet from +// the top-most io.Reader. Unknown packet types are skipped. +func (r *Reader) Next() (p Packet, err error) { + if len(r.q) > 0 { + p = r.q[len(r.q)-1] + r.q = r.q[:len(r.q)-1] + return + } + + for len(r.readers) > 0 { + p, err = Read(r.readers[len(r.readers)-1]) + if err == nil { + return + } + if err == io.EOF { + r.readers = r.readers[:len(r.readers)-1] + continue + } + if _, ok := err.(errors.UnknownPacketTypeError); !ok { + return nil, err + } + } + + return nil, io.EOF +} + +// Push causes the Reader to start reading from a new io.Reader. When an EOF +// error is seen from the new io.Reader, it is popped and the Reader continues +// to read from the next most recent io.Reader. Push returns a StructuralError +// if pushing the reader would exceed the maximum recursion level, otherwise it +// returns nil. +func (r *Reader) Push(reader io.Reader) (err error) { + if len(r.readers) >= maxReaders { + return errors.StructuralError("too many layers of packets") + } + r.readers = append(r.readers, reader) + return nil +} + +// Unread causes the given Packet to be returned from the next call to Next. +func (r *Reader) Unread(p Packet) { + r.q = append(r.q, p) +} + +func NewReader(r io.Reader) *Reader { + return &Reader{ + q: nil, + readers: []io.Reader{r}, + } +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/signature.go b/vendor/golang.org/x/crypto/openpgp/packet/signature.go new file mode 100644 index 0000000000000000000000000000000000000000..6ce0cbedbeae429bb23809b52bfbe283ff847acc --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/signature.go @@ -0,0 +1,731 @@ +// 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 packet + +import ( + "bytes" + "crypto" + "crypto/dsa" + "crypto/ecdsa" + "encoding/asn1" + "encoding/binary" + "hash" + "io" + "math/big" + "strconv" + "time" + + "golang.org/x/crypto/openpgp/errors" + "golang.org/x/crypto/openpgp/s2k" +) + +const ( + // See RFC 4880, section 5.2.3.21 for details. + KeyFlagCertify = 1 << iota + KeyFlagSign + KeyFlagEncryptCommunications + KeyFlagEncryptStorage +) + +// Signature represents a signature. See RFC 4880, section 5.2. +type Signature struct { + SigType SignatureType + PubKeyAlgo PublicKeyAlgorithm + Hash crypto.Hash + + // HashSuffix is extra data that is hashed in after the signed data. + HashSuffix []byte + // HashTag contains the first two bytes of the hash for fast rejection + // of bad signed data. + HashTag [2]byte + CreationTime time.Time + + RSASignature parsedMPI + DSASigR, DSASigS parsedMPI + ECDSASigR, ECDSASigS parsedMPI + + // rawSubpackets contains the unparsed subpackets, in order. + rawSubpackets []outputSubpacket + + // The following are optional so are nil when not included in the + // signature. + + SigLifetimeSecs, KeyLifetimeSecs *uint32 + PreferredSymmetric, PreferredHash, PreferredCompression []uint8 + IssuerKeyId *uint64 + IsPrimaryId *bool + + // FlagsValid is set if any flags were given. See RFC 4880, section + // 5.2.3.21 for details. + FlagsValid bool + FlagCertify, FlagSign, FlagEncryptCommunications, FlagEncryptStorage bool + + // RevocationReason is set if this signature has been revoked. + // See RFC 4880, section 5.2.3.23 for details. + RevocationReason *uint8 + RevocationReasonText string + + // MDC is set if this signature has a feature packet that indicates + // support for MDC subpackets. + MDC bool + + // EmbeddedSignature, if non-nil, is a signature of the parent key, by + // this key. This prevents an attacker from claiming another's signing + // subkey as their own. + EmbeddedSignature *Signature + + outSubpackets []outputSubpacket +} + +func (sig *Signature) parse(r io.Reader) (err error) { + // RFC 4880, section 5.2.3 + var buf [5]byte + _, err = readFull(r, buf[:1]) + if err != nil { + return + } + if buf[0] != 4 { + err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0]))) + return + } + + _, err = readFull(r, buf[:5]) + if err != nil { + return + } + sig.SigType = SignatureType(buf[0]) + sig.PubKeyAlgo = PublicKeyAlgorithm(buf[1]) + switch sig.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA: + default: + err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo))) + return + } + + var ok bool + sig.Hash, ok = s2k.HashIdToHash(buf[2]) + if !ok { + return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2]))) + } + + hashedSubpacketsLength := int(buf[3])<<8 | int(buf[4]) + l := 6 + hashedSubpacketsLength + sig.HashSuffix = make([]byte, l+6) + sig.HashSuffix[0] = 4 + copy(sig.HashSuffix[1:], buf[:5]) + hashedSubpackets := sig.HashSuffix[6:l] + _, err = readFull(r, hashedSubpackets) + if err != nil { + return + } + // See RFC 4880, section 5.2.4 + trailer := sig.HashSuffix[l:] + trailer[0] = 4 + trailer[1] = 0xff + trailer[2] = uint8(l >> 24) + trailer[3] = uint8(l >> 16) + trailer[4] = uint8(l >> 8) + trailer[5] = uint8(l) + + err = parseSignatureSubpackets(sig, hashedSubpackets, true) + if err != nil { + return + } + + _, err = readFull(r, buf[:2]) + if err != nil { + return + } + unhashedSubpacketsLength := int(buf[0])<<8 | int(buf[1]) + unhashedSubpackets := make([]byte, unhashedSubpacketsLength) + _, err = readFull(r, unhashedSubpackets) + if err != nil { + return + } + err = parseSignatureSubpackets(sig, unhashedSubpackets, false) + if err != nil { + return + } + + _, err = readFull(r, sig.HashTag[:2]) + if err != nil { + return + } + + switch sig.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: + sig.RSASignature.bytes, sig.RSASignature.bitLength, err = readMPI(r) + case PubKeyAlgoDSA: + sig.DSASigR.bytes, sig.DSASigR.bitLength, err = readMPI(r) + if err == nil { + sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r) + } + case PubKeyAlgoECDSA: + sig.ECDSASigR.bytes, sig.ECDSASigR.bitLength, err = readMPI(r) + if err == nil { + sig.ECDSASigS.bytes, sig.ECDSASigS.bitLength, err = readMPI(r) + } + default: + panic("unreachable") + } + return +} + +// parseSignatureSubpackets parses subpackets of the main signature packet. See +// RFC 4880, section 5.2.3.1. +func parseSignatureSubpackets(sig *Signature, subpackets []byte, isHashed bool) (err error) { + for len(subpackets) > 0 { + subpackets, err = parseSignatureSubpacket(sig, subpackets, isHashed) + if err != nil { + return + } + } + + if sig.CreationTime.IsZero() { + err = errors.StructuralError("no creation time in signature") + } + + return +} + +type signatureSubpacketType uint8 + +const ( + creationTimeSubpacket signatureSubpacketType = 2 + signatureExpirationSubpacket signatureSubpacketType = 3 + keyExpirationSubpacket signatureSubpacketType = 9 + prefSymmetricAlgosSubpacket signatureSubpacketType = 11 + issuerSubpacket signatureSubpacketType = 16 + prefHashAlgosSubpacket signatureSubpacketType = 21 + prefCompressionSubpacket signatureSubpacketType = 22 + primaryUserIdSubpacket signatureSubpacketType = 25 + keyFlagsSubpacket signatureSubpacketType = 27 + reasonForRevocationSubpacket signatureSubpacketType = 29 + featuresSubpacket signatureSubpacketType = 30 + embeddedSignatureSubpacket signatureSubpacketType = 32 +) + +// parseSignatureSubpacket parses a single subpacket. len(subpacket) is >= 1. +func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (rest []byte, err error) { + // RFC 4880, section 5.2.3.1 + var ( + length uint32 + packetType signatureSubpacketType + isCritical bool + ) + switch { + case subpacket[0] < 192: + length = uint32(subpacket[0]) + subpacket = subpacket[1:] + case subpacket[0] < 255: + if len(subpacket) < 2 { + goto Truncated + } + length = uint32(subpacket[0]-192)<<8 + uint32(subpacket[1]) + 192 + subpacket = subpacket[2:] + default: + if len(subpacket) < 5 { + goto Truncated + } + length = uint32(subpacket[1])<<24 | + uint32(subpacket[2])<<16 | + uint32(subpacket[3])<<8 | + uint32(subpacket[4]) + subpacket = subpacket[5:] + } + if length > uint32(len(subpacket)) { + goto Truncated + } + rest = subpacket[length:] + subpacket = subpacket[:length] + if len(subpacket) == 0 { + err = errors.StructuralError("zero length signature subpacket") + return + } + packetType = signatureSubpacketType(subpacket[0] & 0x7f) + isCritical = subpacket[0]&0x80 == 0x80 + subpacket = subpacket[1:] + sig.rawSubpackets = append(sig.rawSubpackets, outputSubpacket{isHashed, packetType, isCritical, subpacket}) + switch packetType { + case creationTimeSubpacket: + if !isHashed { + err = errors.StructuralError("signature creation time in non-hashed area") + return + } + if len(subpacket) != 4 { + err = errors.StructuralError("signature creation time not four bytes") + return + } + t := binary.BigEndian.Uint32(subpacket) + sig.CreationTime = time.Unix(int64(t), 0) + case signatureExpirationSubpacket: + // Signature expiration time, section 5.2.3.10 + if !isHashed { + return + } + if len(subpacket) != 4 { + err = errors.StructuralError("expiration subpacket with bad length") + return + } + sig.SigLifetimeSecs = new(uint32) + *sig.SigLifetimeSecs = binary.BigEndian.Uint32(subpacket) + case keyExpirationSubpacket: + // Key expiration time, section 5.2.3.6 + if !isHashed { + return + } + if len(subpacket) != 4 { + err = errors.StructuralError("key expiration subpacket with bad length") + return + } + sig.KeyLifetimeSecs = new(uint32) + *sig.KeyLifetimeSecs = binary.BigEndian.Uint32(subpacket) + case prefSymmetricAlgosSubpacket: + // Preferred symmetric algorithms, section 5.2.3.7 + if !isHashed { + return + } + sig.PreferredSymmetric = make([]byte, len(subpacket)) + copy(sig.PreferredSymmetric, subpacket) + case issuerSubpacket: + // Issuer, section 5.2.3.5 + if len(subpacket) != 8 { + err = errors.StructuralError("issuer subpacket with bad length") + return + } + sig.IssuerKeyId = new(uint64) + *sig.IssuerKeyId = binary.BigEndian.Uint64(subpacket) + case prefHashAlgosSubpacket: + // Preferred hash algorithms, section 5.2.3.8 + if !isHashed { + return + } + sig.PreferredHash = make([]byte, len(subpacket)) + copy(sig.PreferredHash, subpacket) + case prefCompressionSubpacket: + // Preferred compression algorithms, section 5.2.3.9 + if !isHashed { + return + } + sig.PreferredCompression = make([]byte, len(subpacket)) + copy(sig.PreferredCompression, subpacket) + case primaryUserIdSubpacket: + // Primary User ID, section 5.2.3.19 + if !isHashed { + return + } + if len(subpacket) != 1 { + err = errors.StructuralError("primary user id subpacket with bad length") + return + } + sig.IsPrimaryId = new(bool) + if subpacket[0] > 0 { + *sig.IsPrimaryId = true + } + case keyFlagsSubpacket: + // Key flags, section 5.2.3.21 + if !isHashed { + return + } + if len(subpacket) == 0 { + err = errors.StructuralError("empty key flags subpacket") + return + } + sig.FlagsValid = true + if subpacket[0]&KeyFlagCertify != 0 { + sig.FlagCertify = true + } + if subpacket[0]&KeyFlagSign != 0 { + sig.FlagSign = true + } + if subpacket[0]&KeyFlagEncryptCommunications != 0 { + sig.FlagEncryptCommunications = true + } + if subpacket[0]&KeyFlagEncryptStorage != 0 { + sig.FlagEncryptStorage = true + } + case reasonForRevocationSubpacket: + // Reason For Revocation, section 5.2.3.23 + if !isHashed { + return + } + if len(subpacket) == 0 { + err = errors.StructuralError("empty revocation reason subpacket") + return + } + sig.RevocationReason = new(uint8) + *sig.RevocationReason = subpacket[0] + sig.RevocationReasonText = string(subpacket[1:]) + case featuresSubpacket: + // Features subpacket, section 5.2.3.24 specifies a very general + // mechanism for OpenPGP implementations to signal support for new + // features. In practice, the subpacket is used exclusively to + // indicate support for MDC-protected encryption. + sig.MDC = len(subpacket) >= 1 && subpacket[0]&1 == 1 + case embeddedSignatureSubpacket: + // Only usage is in signatures that cross-certify + // signing subkeys. section 5.2.3.26 describes the + // format, with its usage described in section 11.1 + if sig.EmbeddedSignature != nil { + err = errors.StructuralError("Cannot have multiple embedded signatures") + return + } + sig.EmbeddedSignature = new(Signature) + // Embedded signatures are required to be v4 signatures see + // section 12.1. However, we only parse v4 signatures in this + // file anyway. + if err := sig.EmbeddedSignature.parse(bytes.NewBuffer(subpacket)); err != nil { + return nil, err + } + if sigType := sig.EmbeddedSignature.SigType; sigType != SigTypePrimaryKeyBinding { + return nil, errors.StructuralError("cross-signature has unexpected type " + strconv.Itoa(int(sigType))) + } + default: + if isCritical { + err = errors.UnsupportedError("unknown critical signature subpacket type " + strconv.Itoa(int(packetType))) + return + } + } + return + +Truncated: + err = errors.StructuralError("signature subpacket truncated") + return +} + +// subpacketLengthLength returns the length, in bytes, of an encoded length value. +func subpacketLengthLength(length int) int { + if length < 192 { + return 1 + } + if length < 16320 { + return 2 + } + return 5 +} + +// serializeSubpacketLength marshals the given length into to. +func serializeSubpacketLength(to []byte, length int) int { + // RFC 4880, Section 4.2.2. + if length < 192 { + to[0] = byte(length) + return 1 + } + if length < 16320 { + length -= 192 + to[0] = byte((length >> 8) + 192) + to[1] = byte(length) + return 2 + } + to[0] = 255 + to[1] = byte(length >> 24) + to[2] = byte(length >> 16) + to[3] = byte(length >> 8) + to[4] = byte(length) + return 5 +} + +// subpacketsLength returns the serialized length, in bytes, of the given +// subpackets. +func subpacketsLength(subpackets []outputSubpacket, hashed bool) (length int) { + for _, subpacket := range subpackets { + if subpacket.hashed == hashed { + length += subpacketLengthLength(len(subpacket.contents) + 1) + length += 1 // type byte + length += len(subpacket.contents) + } + } + return +} + +// serializeSubpackets marshals the given subpackets into to. +func serializeSubpackets(to []byte, subpackets []outputSubpacket, hashed bool) { + for _, subpacket := range subpackets { + if subpacket.hashed == hashed { + n := serializeSubpacketLength(to, len(subpacket.contents)+1) + to[n] = byte(subpacket.subpacketType) + to = to[1+n:] + n = copy(to, subpacket.contents) + to = to[n:] + } + } + return +} + +// KeyExpired returns whether sig is a self-signature of a key that has +// expired. +func (sig *Signature) KeyExpired(currentTime time.Time) bool { + if sig.KeyLifetimeSecs == nil { + return false + } + expiry := sig.CreationTime.Add(time.Duration(*sig.KeyLifetimeSecs) * time.Second) + return currentTime.After(expiry) +} + +// buildHashSuffix constructs the HashSuffix member of sig in preparation for signing. +func (sig *Signature) buildHashSuffix() (err error) { + hashedSubpacketsLen := subpacketsLength(sig.outSubpackets, true) + + var ok bool + l := 6 + hashedSubpacketsLen + sig.HashSuffix = make([]byte, l+6) + sig.HashSuffix[0] = 4 + sig.HashSuffix[1] = uint8(sig.SigType) + sig.HashSuffix[2] = uint8(sig.PubKeyAlgo) + sig.HashSuffix[3], ok = s2k.HashToHashId(sig.Hash) + if !ok { + sig.HashSuffix = nil + return errors.InvalidArgumentError("hash cannot be represented in OpenPGP: " + strconv.Itoa(int(sig.Hash))) + } + sig.HashSuffix[4] = byte(hashedSubpacketsLen >> 8) + sig.HashSuffix[5] = byte(hashedSubpacketsLen) + serializeSubpackets(sig.HashSuffix[6:l], sig.outSubpackets, true) + trailer := sig.HashSuffix[l:] + trailer[0] = 4 + trailer[1] = 0xff + trailer[2] = byte(l >> 24) + trailer[3] = byte(l >> 16) + trailer[4] = byte(l >> 8) + trailer[5] = byte(l) + return +} + +func (sig *Signature) signPrepareHash(h hash.Hash) (digest []byte, err error) { + err = sig.buildHashSuffix() + if err != nil { + return + } + + h.Write(sig.HashSuffix) + digest = h.Sum(nil) + copy(sig.HashTag[:], digest) + return +} + +// Sign signs a message with a private key. The hash, h, must contain +// the hash of the message to be signed and will be mutated by this function. +// On success, the signature is stored in sig. Call Serialize to write it out. +// If config is nil, sensible defaults will be used. +func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err error) { + sig.outSubpackets = sig.buildSubpackets() + digest, err := sig.signPrepareHash(h) + if err != nil { + return + } + + switch priv.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: + // supports both *rsa.PrivateKey and crypto.Signer + sig.RSASignature.bytes, err = priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, sig.Hash) + sig.RSASignature.bitLength = uint16(8 * len(sig.RSASignature.bytes)) + case PubKeyAlgoDSA: + dsaPriv := priv.PrivateKey.(*dsa.PrivateKey) + + // Need to truncate hashBytes to match FIPS 186-3 section 4.6. + subgroupSize := (dsaPriv.Q.BitLen() + 7) / 8 + if len(digest) > subgroupSize { + digest = digest[:subgroupSize] + } + r, s, err := dsa.Sign(config.Random(), dsaPriv, digest) + if err == nil { + sig.DSASigR.bytes = r.Bytes() + sig.DSASigR.bitLength = uint16(8 * len(sig.DSASigR.bytes)) + sig.DSASigS.bytes = s.Bytes() + sig.DSASigS.bitLength = uint16(8 * len(sig.DSASigS.bytes)) + } + case PubKeyAlgoECDSA: + var r, s *big.Int + if pk, ok := priv.PrivateKey.(*ecdsa.PrivateKey); ok { + // direct support, avoid asn1 wrapping/unwrapping + r, s, err = ecdsa.Sign(config.Random(), pk, digest) + } else { + var b []byte + b, err = priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, nil) + if err == nil { + r, s, err = unwrapECDSASig(b) + } + } + if err == nil { + sig.ECDSASigR = fromBig(r) + sig.ECDSASigS = fromBig(s) + } + default: + err = errors.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo))) + } + + return +} + +// unwrapECDSASig parses the two integer components of an ASN.1-encoded ECDSA +// signature. +func unwrapECDSASig(b []byte) (r, s *big.Int, err error) { + var ecsdaSig struct { + R, S *big.Int + } + _, err = asn1.Unmarshal(b, &ecsdaSig) + if err != nil { + return + } + return ecsdaSig.R, ecsdaSig.S, nil +} + +// SignUserId computes a signature from priv, asserting that pub is a valid +// key for the identity id. On success, the signature is stored in sig. Call +// Serialize to write it out. +// If config is nil, sensible defaults will be used. +func (sig *Signature) SignUserId(id string, pub *PublicKey, priv *PrivateKey, config *Config) error { + h, err := userIdSignatureHash(id, pub, sig.Hash) + if err != nil { + return err + } + return sig.Sign(h, priv, config) +} + +// SignKey computes a signature from priv, asserting that pub is a subkey. On +// success, the signature is stored in sig. Call Serialize to write it out. +// If config is nil, sensible defaults will be used. +func (sig *Signature) SignKey(pub *PublicKey, priv *PrivateKey, config *Config) error { + h, err := keySignatureHash(&priv.PublicKey, pub, sig.Hash) + if err != nil { + return err + } + return sig.Sign(h, priv, config) +} + +// Serialize marshals sig to w. Sign, SignUserId or SignKey must have been +// called first. +func (sig *Signature) Serialize(w io.Writer) (err error) { + if len(sig.outSubpackets) == 0 { + sig.outSubpackets = sig.rawSubpackets + } + if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil && sig.ECDSASigR.bytes == nil { + return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize") + } + + sigLength := 0 + switch sig.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: + sigLength = 2 + len(sig.RSASignature.bytes) + case PubKeyAlgoDSA: + sigLength = 2 + len(sig.DSASigR.bytes) + sigLength += 2 + len(sig.DSASigS.bytes) + case PubKeyAlgoECDSA: + sigLength = 2 + len(sig.ECDSASigR.bytes) + sigLength += 2 + len(sig.ECDSASigS.bytes) + default: + panic("impossible") + } + + unhashedSubpacketsLen := subpacketsLength(sig.outSubpackets, false) + length := len(sig.HashSuffix) - 6 /* trailer not included */ + + 2 /* length of unhashed subpackets */ + unhashedSubpacketsLen + + 2 /* hash tag */ + sigLength + err = serializeHeader(w, packetTypeSignature, length) + if err != nil { + return + } + + _, err = w.Write(sig.HashSuffix[:len(sig.HashSuffix)-6]) + if err != nil { + return + } + + unhashedSubpackets := make([]byte, 2+unhashedSubpacketsLen) + unhashedSubpackets[0] = byte(unhashedSubpacketsLen >> 8) + unhashedSubpackets[1] = byte(unhashedSubpacketsLen) + serializeSubpackets(unhashedSubpackets[2:], sig.outSubpackets, false) + + _, err = w.Write(unhashedSubpackets) + if err != nil { + return + } + _, err = w.Write(sig.HashTag[:]) + if err != nil { + return + } + + switch sig.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: + err = writeMPIs(w, sig.RSASignature) + case PubKeyAlgoDSA: + err = writeMPIs(w, sig.DSASigR, sig.DSASigS) + case PubKeyAlgoECDSA: + err = writeMPIs(w, sig.ECDSASigR, sig.ECDSASigS) + default: + panic("impossible") + } + return +} + +// outputSubpacket represents a subpacket to be marshaled. +type outputSubpacket struct { + hashed bool // true if this subpacket is in the hashed area. + subpacketType signatureSubpacketType + isCritical bool + contents []byte +} + +func (sig *Signature) buildSubpackets() (subpackets []outputSubpacket) { + creationTime := make([]byte, 4) + binary.BigEndian.PutUint32(creationTime, uint32(sig.CreationTime.Unix())) + subpackets = append(subpackets, outputSubpacket{true, creationTimeSubpacket, false, creationTime}) + + if sig.IssuerKeyId != nil { + keyId := make([]byte, 8) + binary.BigEndian.PutUint64(keyId, *sig.IssuerKeyId) + subpackets = append(subpackets, outputSubpacket{true, issuerSubpacket, false, keyId}) + } + + if sig.SigLifetimeSecs != nil && *sig.SigLifetimeSecs != 0 { + sigLifetime := make([]byte, 4) + binary.BigEndian.PutUint32(sigLifetime, *sig.SigLifetimeSecs) + subpackets = append(subpackets, outputSubpacket{true, signatureExpirationSubpacket, true, sigLifetime}) + } + + // Key flags may only appear in self-signatures or certification signatures. + + if sig.FlagsValid { + var flags byte + if sig.FlagCertify { + flags |= KeyFlagCertify + } + if sig.FlagSign { + flags |= KeyFlagSign + } + if sig.FlagEncryptCommunications { + flags |= KeyFlagEncryptCommunications + } + if sig.FlagEncryptStorage { + flags |= KeyFlagEncryptStorage + } + subpackets = append(subpackets, outputSubpacket{true, keyFlagsSubpacket, false, []byte{flags}}) + } + + // The following subpackets may only appear in self-signatures + + if sig.KeyLifetimeSecs != nil && *sig.KeyLifetimeSecs != 0 { + keyLifetime := make([]byte, 4) + binary.BigEndian.PutUint32(keyLifetime, *sig.KeyLifetimeSecs) + subpackets = append(subpackets, outputSubpacket{true, keyExpirationSubpacket, true, keyLifetime}) + } + + if sig.IsPrimaryId != nil && *sig.IsPrimaryId { + subpackets = append(subpackets, outputSubpacket{true, primaryUserIdSubpacket, false, []byte{1}}) + } + + if len(sig.PreferredSymmetric) > 0 { + subpackets = append(subpackets, outputSubpacket{true, prefSymmetricAlgosSubpacket, false, sig.PreferredSymmetric}) + } + + if len(sig.PreferredHash) > 0 { + subpackets = append(subpackets, outputSubpacket{true, prefHashAlgosSubpacket, false, sig.PreferredHash}) + } + + if len(sig.PreferredCompression) > 0 { + subpackets = append(subpackets, outputSubpacket{true, prefCompressionSubpacket, false, sig.PreferredCompression}) + } + + return +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/signature_test.go b/vendor/golang.org/x/crypto/openpgp/packet/signature_test.go new file mode 100644 index 0000000000000000000000000000000000000000..56e761179d0cf8b81dcd49b573830e58b6e0b994 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/signature_test.go @@ -0,0 +1,78 @@ +// 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 packet + +import ( + "bytes" + "crypto" + "encoding/hex" + "testing" +) + +func TestSignatureRead(t *testing.T) { + packet, err := Read(readerFromHex(signatureDataHex)) + if err != nil { + t.Error(err) + return + } + sig, ok := packet.(*Signature) + if !ok || sig.SigType != SigTypeBinary || sig.PubKeyAlgo != PubKeyAlgoRSA || sig.Hash != crypto.SHA1 { + t.Errorf("failed to parse, got: %#v", packet) + } +} + +func TestSignatureReserialize(t *testing.T) { + packet, _ := Read(readerFromHex(signatureDataHex)) + sig := packet.(*Signature) + out := new(bytes.Buffer) + err := sig.Serialize(out) + if err != nil { + t.Errorf("error reserializing: %s", err) + return + } + + expected, _ := hex.DecodeString(signatureDataHex) + if !bytes.Equal(expected, out.Bytes()) { + t.Errorf("output doesn't match input (got vs expected):\n%s\n%s", hex.Dump(out.Bytes()), hex.Dump(expected)) + } +} + +func TestSignUserId(t *testing.T) { + sig := &Signature{ + SigType: SigTypeGenericCert, + PubKeyAlgo: PubKeyAlgoRSA, + Hash: 0, // invalid hash function + } + + packet, err := Read(readerFromHex(rsaPkDataHex)) + if err != nil { + t.Fatalf("failed to deserialize public key: %v", err) + } + pubKey := packet.(*PublicKey) + + packet, err = Read(readerFromHex(privKeyRSAHex)) + if err != nil { + t.Fatalf("failed to deserialize private key: %v", err) + } + privKey := packet.(*PrivateKey) + + err = sig.SignUserId("", pubKey, privKey, nil) + if err == nil { + t.Errorf("did not receive an error when expected") + } + + sig.Hash = crypto.SHA256 + err = privKey.Decrypt([]byte("testing")) + if err != nil { + t.Fatalf("failed to decrypt private key: %v", err) + } + + err = sig.SignUserId("", pubKey, privKey, nil) + if err != nil { + t.Errorf("failed to sign user id: %v", err) + } +} + +const signatureDataHex = "c2c05c04000102000605024cb45112000a0910ab105c91af38fb158f8d07ff5596ea368c5efe015bed6e78348c0f033c931d5f2ce5db54ce7f2a7e4b4ad64db758d65a7a71773edeab7ba2a9e0908e6a94a1175edd86c1d843279f045b021a6971a72702fcbd650efc393c5474d5b59a15f96d2eaad4c4c426797e0dcca2803ef41c6ff234d403eec38f31d610c344c06f2401c262f0993b2e66cad8a81ebc4322c723e0d4ba09fe917e8777658307ad8329adacba821420741009dfe87f007759f0982275d028a392c6ed983a0d846f890b36148c7358bdb8a516007fac760261ecd06076813831a36d0459075d1befa245ae7f7fb103d92ca759e9498fe60ef8078a39a3beda510deea251ea9f0a7f0df6ef42060f20780360686f3e400e" diff --git a/vendor/golang.org/x/crypto/openpgp/packet/signature_v3.go b/vendor/golang.org/x/crypto/openpgp/packet/signature_v3.go new file mode 100644 index 0000000000000000000000000000000000000000..6edff889349b3f50df3f866c82c55277b0b07565 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/signature_v3.go @@ -0,0 +1,146 @@ +// 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. + +package packet + +import ( + "crypto" + "encoding/binary" + "fmt" + "io" + "strconv" + "time" + + "golang.org/x/crypto/openpgp/errors" + "golang.org/x/crypto/openpgp/s2k" +) + +// SignatureV3 represents older version 3 signatures. These signatures are less secure +// than version 4 and should not be used to create new signatures. They are included +// here for backwards compatibility to read and validate with older key material. +// See RFC 4880, section 5.2.2. +type SignatureV3 struct { + SigType SignatureType + CreationTime time.Time + IssuerKeyId uint64 + PubKeyAlgo PublicKeyAlgorithm + Hash crypto.Hash + HashTag [2]byte + + RSASignature parsedMPI + DSASigR, DSASigS parsedMPI +} + +func (sig *SignatureV3) parse(r io.Reader) (err error) { + // RFC 4880, section 5.2.2 + var buf [8]byte + if _, err = readFull(r, buf[:1]); err != nil { + return + } + if buf[0] < 2 || buf[0] > 3 { + err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0]))) + return + } + if _, err = readFull(r, buf[:1]); err != nil { + return + } + if buf[0] != 5 { + err = errors.UnsupportedError( + "invalid hashed material length " + strconv.Itoa(int(buf[0]))) + return + } + + // Read hashed material: signature type + creation time + if _, err = readFull(r, buf[:5]); err != nil { + return + } + sig.SigType = SignatureType(buf[0]) + t := binary.BigEndian.Uint32(buf[1:5]) + sig.CreationTime = time.Unix(int64(t), 0) + + // Eight-octet Key ID of signer. + if _, err = readFull(r, buf[:8]); err != nil { + return + } + sig.IssuerKeyId = binary.BigEndian.Uint64(buf[:]) + + // Public-key and hash algorithm + if _, err = readFull(r, buf[:2]); err != nil { + return + } + sig.PubKeyAlgo = PublicKeyAlgorithm(buf[0]) + switch sig.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA: + default: + err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo))) + return + } + var ok bool + if sig.Hash, ok = s2k.HashIdToHash(buf[1]); !ok { + return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2]))) + } + + // Two-octet field holding left 16 bits of signed hash value. + if _, err = readFull(r, sig.HashTag[:2]); err != nil { + return + } + + switch sig.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: + sig.RSASignature.bytes, sig.RSASignature.bitLength, err = readMPI(r) + case PubKeyAlgoDSA: + if sig.DSASigR.bytes, sig.DSASigR.bitLength, err = readMPI(r); err != nil { + return + } + sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r) + default: + panic("unreachable") + } + return +} + +// Serialize marshals sig to w. Sign, SignUserId or SignKey must have been +// called first. +func (sig *SignatureV3) Serialize(w io.Writer) (err error) { + buf := make([]byte, 8) + + // Write the sig type and creation time + buf[0] = byte(sig.SigType) + binary.BigEndian.PutUint32(buf[1:5], uint32(sig.CreationTime.Unix())) + if _, err = w.Write(buf[:5]); err != nil { + return + } + + // Write the issuer long key ID + binary.BigEndian.PutUint64(buf[:8], sig.IssuerKeyId) + if _, err = w.Write(buf[:8]); err != nil { + return + } + + // Write public key algorithm, hash ID, and hash value + buf[0] = byte(sig.PubKeyAlgo) + hashId, ok := s2k.HashToHashId(sig.Hash) + if !ok { + return errors.UnsupportedError(fmt.Sprintf("hash function %v", sig.Hash)) + } + buf[1] = hashId + copy(buf[2:4], sig.HashTag[:]) + if _, err = w.Write(buf[:4]); err != nil { + return + } + + if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil { + return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize") + } + + switch sig.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: + err = writeMPIs(w, sig.RSASignature) + case PubKeyAlgoDSA: + err = writeMPIs(w, sig.DSASigR, sig.DSASigS) + default: + panic("impossible") + } + return +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/signature_v3_test.go b/vendor/golang.org/x/crypto/openpgp/packet/signature_v3_test.go new file mode 100644 index 0000000000000000000000000000000000000000..ad7b62ac193598260cb9a225b1d19b9251d2c6a9 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/signature_v3_test.go @@ -0,0 +1,92 @@ +// 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. + +package packet + +import ( + "bytes" + "crypto" + "encoding/hex" + "io" + "io/ioutil" + "testing" + + "golang.org/x/crypto/openpgp/armor" +) + +func TestSignatureV3Read(t *testing.T) { + r := v3KeyReader(t) + Read(r) // Skip public key + Read(r) // Skip uid + packet, err := Read(r) // Signature + if err != nil { + t.Error(err) + return + } + sig, ok := packet.(*SignatureV3) + if !ok || sig.SigType != SigTypeGenericCert || sig.PubKeyAlgo != PubKeyAlgoRSA || sig.Hash != crypto.MD5 { + t.Errorf("failed to parse, got: %#v", packet) + } +} + +func TestSignatureV3Reserialize(t *testing.T) { + r := v3KeyReader(t) + Read(r) // Skip public key + Read(r) // Skip uid + packet, err := Read(r) + if err != nil { + t.Error(err) + return + } + sig := packet.(*SignatureV3) + out := new(bytes.Buffer) + if err = sig.Serialize(out); err != nil { + t.Errorf("error reserializing: %s", err) + return + } + expected, err := ioutil.ReadAll(v3KeyReader(t)) + if err != nil { + t.Error(err) + return + } + expected = expected[4+141+4+39:] // See pgpdump offsets below, this is where the sig starts + if !bytes.Equal(expected, out.Bytes()) { + t.Errorf("output doesn't match input (got vs expected):\n%s\n%s", hex.Dump(out.Bytes()), hex.Dump(expected)) + } +} + +func v3KeyReader(t *testing.T) io.Reader { + armorBlock, err := armor.Decode(bytes.NewBufferString(keySigV3Armor)) + if err != nil { + t.Fatalf("armor Decode failed: %v", err) + } + return armorBlock.Body +} + +// keySigV3Armor is some V3 public key I found in an SKS dump. +// Old: Public Key Packet(tag 6)(141 bytes) +// Ver 4 - new +// Public key creation time - Fri Sep 16 17:13:54 CDT 1994 +// Pub alg - unknown(pub 0) +// Unknown public key(pub 0) +// Old: User ID Packet(tag 13)(39 bytes) +// User ID - Armin M. Warda +// Old: Signature Packet(tag 2)(149 bytes) +// Ver 4 - new +// Sig type - unknown(05) +// Pub alg - ElGamal Encrypt-Only(pub 16) +// Hash alg - unknown(hash 46) +// Hashed Sub: unknown(sub 81, critical)(1988 bytes) +const keySigV3Armor = `-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: SKS 1.0.10 + +mI0CLnoYogAAAQQA1qwA2SuJwfQ5bCQ6u5t20ulnOtY0gykf7YjiK4LiVeRBwHjGq7v30tGV +5Qti7qqRW4Ww7CDCJc4sZMFnystucR2vLkXaSoNWoFm4Fg47NiisDdhDezHwbVPW6OpCFNSi +ZAamtj4QAUBu8j4LswafrJqZqR9336/V3g8Yil2l48kABRG0J0FybWluIE0uIFdhcmRhIDx3 +YXJkYUBuZXBoaWxpbS5ydWhyLmRlPoiVAgUQLok2xwXR6zmeWEiZAQE/DgP/WgxPQh40/Po4 +gSkWZCDAjNdph7zexvAb0CcUWahcwiBIgg3U5ErCx9I5CNVA9U+s8bNrDZwgSIeBzp3KhWUx +524uhGgm6ZUTOAIKA6CbV6pfqoLpJnRYvXYQU5mIWsNa99wcu2qu18OeEDnztb7aLA6Ra9OF +YFCbq4EjXRoOrYM= +=LPjs +-----END PGP PUBLIC KEY BLOCK-----` diff --git a/vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go b/vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go new file mode 100644 index 0000000000000000000000000000000000000000..744c2d2c42dc5ee54f541ebf612548cc97d8a02c --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go @@ -0,0 +1,155 @@ +// 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 packet + +import ( + "bytes" + "crypto/cipher" + "io" + "strconv" + + "golang.org/x/crypto/openpgp/errors" + "golang.org/x/crypto/openpgp/s2k" +) + +// This is the largest session key that we'll support. Since no 512-bit cipher +// has even been seriously used, this is comfortably large. +const maxSessionKeySizeInBytes = 64 + +// SymmetricKeyEncrypted represents a passphrase protected session key. See RFC +// 4880, section 5.3. +type SymmetricKeyEncrypted struct { + CipherFunc CipherFunction + s2k func(out, in []byte) + encryptedKey []byte +} + +const symmetricKeyEncryptedVersion = 4 + +func (ske *SymmetricKeyEncrypted) parse(r io.Reader) error { + // RFC 4880, section 5.3. + var buf [2]byte + if _, err := readFull(r, buf[:]); err != nil { + return err + } + if buf[0] != symmetricKeyEncryptedVersion { + return errors.UnsupportedError("SymmetricKeyEncrypted version") + } + ske.CipherFunc = CipherFunction(buf[1]) + + if ske.CipherFunc.KeySize() == 0 { + return errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(buf[1]))) + } + + var err error + ske.s2k, err = s2k.Parse(r) + if err != nil { + return err + } + + encryptedKey := make([]byte, maxSessionKeySizeInBytes) + // The session key may follow. We just have to try and read to find + // out. If it exists then we limit it to maxSessionKeySizeInBytes. + n, err := readFull(r, encryptedKey) + if err != nil && err != io.ErrUnexpectedEOF { + return err + } + + if n != 0 { + if n == maxSessionKeySizeInBytes { + return errors.UnsupportedError("oversized encrypted session key") + } + ske.encryptedKey = encryptedKey[:n] + } + + return nil +} + +// Decrypt attempts to decrypt an encrypted session key and returns the key and +// the cipher to use when decrypting a subsequent Symmetrically Encrypted Data +// packet. +func (ske *SymmetricKeyEncrypted) Decrypt(passphrase []byte) ([]byte, CipherFunction, error) { + key := make([]byte, ske.CipherFunc.KeySize()) + ske.s2k(key, passphrase) + + if len(ske.encryptedKey) == 0 { + return key, ske.CipherFunc, nil + } + + // the IV is all zeros + iv := make([]byte, ske.CipherFunc.blockSize()) + c := cipher.NewCFBDecrypter(ske.CipherFunc.new(key), iv) + plaintextKey := make([]byte, len(ske.encryptedKey)) + c.XORKeyStream(plaintextKey, ske.encryptedKey) + cipherFunc := CipherFunction(plaintextKey[0]) + if cipherFunc.blockSize() == 0 { + return nil, ske.CipherFunc, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc))) + } + plaintextKey = plaintextKey[1:] + if l, cipherKeySize := len(plaintextKey), cipherFunc.KeySize(); l != cipherFunc.KeySize() { + return nil, cipherFunc, errors.StructuralError("length of decrypted key (" + strconv.Itoa(l) + ") " + + "not equal to cipher keysize (" + strconv.Itoa(cipherKeySize) + ")") + } + return plaintextKey, cipherFunc, nil +} + +// SerializeSymmetricKeyEncrypted serializes a symmetric key packet to w. The +// packet contains a random session key, encrypted by a key derived from the +// given passphrase. The session key is returned and must be passed to +// SerializeSymmetricallyEncrypted. +// If config is nil, sensible defaults will be used. +func SerializeSymmetricKeyEncrypted(w io.Writer, passphrase []byte, config *Config) (key []byte, err error) { + cipherFunc := config.Cipher() + keySize := cipherFunc.KeySize() + if keySize == 0 { + return nil, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc))) + } + + s2kBuf := new(bytes.Buffer) + keyEncryptingKey := make([]byte, keySize) + // s2k.Serialize salts and stretches the passphrase, and writes the + // resulting key to keyEncryptingKey and the s2k descriptor to s2kBuf. + err = s2k.Serialize(s2kBuf, keyEncryptingKey, config.Random(), passphrase, &s2k.Config{Hash: config.Hash(), S2KCount: config.PasswordHashIterations()}) + if err != nil { + return + } + s2kBytes := s2kBuf.Bytes() + + packetLength := 2 /* header */ + len(s2kBytes) + 1 /* cipher type */ + keySize + err = serializeHeader(w, packetTypeSymmetricKeyEncrypted, packetLength) + if err != nil { + return + } + + var buf [2]byte + buf[0] = symmetricKeyEncryptedVersion + buf[1] = byte(cipherFunc) + _, err = w.Write(buf[:]) + if err != nil { + return + } + _, err = w.Write(s2kBytes) + if err != nil { + return + } + + sessionKey := make([]byte, keySize) + _, err = io.ReadFull(config.Random(), sessionKey) + if err != nil { + return + } + iv := make([]byte, cipherFunc.blockSize()) + c := cipher.NewCFBEncrypter(cipherFunc.new(keyEncryptingKey), iv) + encryptedCipherAndKey := make([]byte, keySize+1) + c.XORKeyStream(encryptedCipherAndKey, buf[1:]) + c.XORKeyStream(encryptedCipherAndKey[1:], sessionKey) + _, err = w.Write(encryptedCipherAndKey) + if err != nil { + return + } + + key = sessionKey + return +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted_test.go b/vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted_test.go new file mode 100644 index 0000000000000000000000000000000000000000..e1d52c122e9cff9fc6ce46d0f8857ce33384d9b7 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted_test.go @@ -0,0 +1,117 @@ +// 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 packet + +import ( + "bytes" + "encoding/hex" + "io" + "io/ioutil" + "testing" +) + +func TestSymmetricKeyEncrypted(t *testing.T) { + buf := readerFromHex(symmetricallyEncryptedHex) + packet, err := Read(buf) + if err != nil { + t.Errorf("failed to read SymmetricKeyEncrypted: %s", err) + return + } + ske, ok := packet.(*SymmetricKeyEncrypted) + if !ok { + t.Error("didn't find SymmetricKeyEncrypted packet") + return + } + key, cipherFunc, err := ske.Decrypt([]byte("password")) + if err != nil { + t.Error(err) + return + } + + packet, err = Read(buf) + if err != nil { + t.Errorf("failed to read SymmetricallyEncrypted: %s", err) + return + } + se, ok := packet.(*SymmetricallyEncrypted) + if !ok { + t.Error("didn't find SymmetricallyEncrypted packet") + return + } + r, err := se.Decrypt(cipherFunc, key) + if err != nil { + t.Error(err) + return + } + + contents, err := ioutil.ReadAll(r) + if err != nil && err != io.EOF { + t.Error(err) + return + } + + expectedContents, _ := hex.DecodeString(symmetricallyEncryptedContentsHex) + if !bytes.Equal(expectedContents, contents) { + t.Errorf("bad contents got:%x want:%x", contents, expectedContents) + } +} + +const symmetricallyEncryptedHex = "8c0d04030302371a0b38d884f02060c91cf97c9973b8e58e028e9501708ccfe618fb92afef7fa2d80ddadd93cf" +const symmetricallyEncryptedContentsHex = "cb1062004d14c4df636f6e74656e74732e0a" + +func TestSerializeSymmetricKeyEncryptedCiphers(t *testing.T) { + tests := [...]struct { + cipherFunc CipherFunction + name string + }{ + {Cipher3DES, "Cipher3DES"}, + {CipherCAST5, "CipherCAST5"}, + {CipherAES128, "CipherAES128"}, + {CipherAES192, "CipherAES192"}, + {CipherAES256, "CipherAES256"}, + } + + for _, test := range tests { + var buf bytes.Buffer + passphrase := []byte("testing") + config := &Config{ + DefaultCipher: test.cipherFunc, + } + + key, err := SerializeSymmetricKeyEncrypted(&buf, passphrase, config) + if err != nil { + t.Errorf("cipher(%s) failed to serialize: %s", test.name, err) + continue + } + + p, err := Read(&buf) + if err != nil { + t.Errorf("cipher(%s) failed to reparse: %s", test.name, err) + continue + } + + ske, ok := p.(*SymmetricKeyEncrypted) + if !ok { + t.Errorf("cipher(%s) parsed a different packet type: %#v", test.name, p) + continue + } + + if ske.CipherFunc != config.DefaultCipher { + t.Errorf("cipher(%s) SKE cipher function is %d (expected %d)", test.name, ske.CipherFunc, config.DefaultCipher) + } + parsedKey, parsedCipherFunc, err := ske.Decrypt(passphrase) + if err != nil { + t.Errorf("cipher(%s) failed to decrypt reparsed SKE: %s", test.name, err) + continue + } + if !bytes.Equal(key, parsedKey) { + t.Errorf("cipher(%s) keys don't match after Decrypt: %x (original) vs %x (parsed)", test.name, key, parsedKey) + } + if parsedCipherFunc != test.cipherFunc { + t.Errorf("cipher(%s) cipher function doesn't match after Decrypt: %d (original) vs %d (parsed)", + test.name, test.cipherFunc, parsedCipherFunc) + } + } +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go b/vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go new file mode 100644 index 0000000000000000000000000000000000000000..6126030eb9035d5b9717a8c07945727b7ddb94d5 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go @@ -0,0 +1,290 @@ +// 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 packet + +import ( + "crypto/cipher" + "crypto/sha1" + "crypto/subtle" + "golang.org/x/crypto/openpgp/errors" + "hash" + "io" + "strconv" +) + +// SymmetricallyEncrypted represents a symmetrically encrypted byte string. The +// encrypted contents will consist of more OpenPGP packets. See RFC 4880, +// sections 5.7 and 5.13. +type SymmetricallyEncrypted struct { + MDC bool // true iff this is a type 18 packet and thus has an embedded MAC. + contents io.Reader + prefix []byte +} + +const symmetricallyEncryptedVersion = 1 + +func (se *SymmetricallyEncrypted) parse(r io.Reader) error { + if se.MDC { + // See RFC 4880, section 5.13. + var buf [1]byte + _, err := readFull(r, buf[:]) + if err != nil { + return err + } + if buf[0] != symmetricallyEncryptedVersion { + return errors.UnsupportedError("unknown SymmetricallyEncrypted version") + } + } + se.contents = r + return nil +} + +// Decrypt returns a ReadCloser, from which the decrypted contents of the +// packet can be read. An incorrect key can, with high probability, be detected +// immediately and this will result in a KeyIncorrect error being returned. +func (se *SymmetricallyEncrypted) Decrypt(c CipherFunction, key []byte) (io.ReadCloser, error) { + keySize := c.KeySize() + if keySize == 0 { + return nil, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(c))) + } + if len(key) != keySize { + return nil, errors.InvalidArgumentError("SymmetricallyEncrypted: incorrect key length") + } + + if se.prefix == nil { + se.prefix = make([]byte, c.blockSize()+2) + _, err := readFull(se.contents, se.prefix) + if err != nil { + return nil, err + } + } else if len(se.prefix) != c.blockSize()+2 { + return nil, errors.InvalidArgumentError("can't try ciphers with different block lengths") + } + + ocfbResync := OCFBResync + if se.MDC { + // MDC packets use a different form of OCFB mode. + ocfbResync = OCFBNoResync + } + + s := NewOCFBDecrypter(c.new(key), se.prefix, ocfbResync) + if s == nil { + return nil, errors.ErrKeyIncorrect + } + + plaintext := cipher.StreamReader{S: s, R: se.contents} + + if se.MDC { + // MDC packets have an embedded hash that we need to check. + h := sha1.New() + h.Write(se.prefix) + return &seMDCReader{in: plaintext, h: h}, nil + } + + // Otherwise, we just need to wrap plaintext so that it's a valid ReadCloser. + return seReader{plaintext}, nil +} + +// seReader wraps an io.Reader with a no-op Close method. +type seReader struct { + in io.Reader +} + +func (ser seReader) Read(buf []byte) (int, error) { + return ser.in.Read(buf) +} + +func (ser seReader) Close() error { + return nil +} + +const mdcTrailerSize = 1 /* tag byte */ + 1 /* length byte */ + sha1.Size + +// An seMDCReader wraps an io.Reader, maintains a running hash and keeps hold +// of the most recent 22 bytes (mdcTrailerSize). Upon EOF, those bytes form an +// MDC packet containing a hash of the previous contents which is checked +// against the running hash. See RFC 4880, section 5.13. +type seMDCReader struct { + in io.Reader + h hash.Hash + trailer [mdcTrailerSize]byte + scratch [mdcTrailerSize]byte + trailerUsed int + error bool + eof bool +} + +func (ser *seMDCReader) Read(buf []byte) (n int, err error) { + if ser.error { + err = io.ErrUnexpectedEOF + return + } + if ser.eof { + err = io.EOF + return + } + + // If we haven't yet filled the trailer buffer then we must do that + // first. + for ser.trailerUsed < mdcTrailerSize { + n, err = ser.in.Read(ser.trailer[ser.trailerUsed:]) + ser.trailerUsed += n + if err == io.EOF { + if ser.trailerUsed != mdcTrailerSize { + n = 0 + err = io.ErrUnexpectedEOF + ser.error = true + return + } + ser.eof = true + n = 0 + return + } + + if err != nil { + n = 0 + return + } + } + + // If it's a short read then we read into a temporary buffer and shift + // the data into the caller's buffer. + if len(buf) <= mdcTrailerSize { + n, err = readFull(ser.in, ser.scratch[:len(buf)]) + copy(buf, ser.trailer[:n]) + ser.h.Write(buf[:n]) + copy(ser.trailer[:], ser.trailer[n:]) + copy(ser.trailer[mdcTrailerSize-n:], ser.scratch[:]) + if n < len(buf) { + ser.eof = true + err = io.EOF + } + return + } + + n, err = ser.in.Read(buf[mdcTrailerSize:]) + copy(buf, ser.trailer[:]) + ser.h.Write(buf[:n]) + copy(ser.trailer[:], buf[n:]) + + if err == io.EOF { + ser.eof = true + } + return +} + +// This is a new-format packet tag byte for a type 19 (MDC) packet. +const mdcPacketTagByte = byte(0x80) | 0x40 | 19 + +func (ser *seMDCReader) Close() error { + if ser.error { + return errors.SignatureError("error during reading") + } + + for !ser.eof { + // We haven't seen EOF so we need to read to the end + var buf [1024]byte + _, err := ser.Read(buf[:]) + if err == io.EOF { + break + } + if err != nil { + return errors.SignatureError("error during reading") + } + } + + if ser.trailer[0] != mdcPacketTagByte || ser.trailer[1] != sha1.Size { + return errors.SignatureError("MDC packet not found") + } + ser.h.Write(ser.trailer[:2]) + + final := ser.h.Sum(nil) + if subtle.ConstantTimeCompare(final, ser.trailer[2:]) != 1 { + return errors.SignatureError("hash mismatch") + } + return nil +} + +// An seMDCWriter writes through to an io.WriteCloser while maintains a running +// hash of the data written. On close, it emits an MDC packet containing the +// running hash. +type seMDCWriter struct { + w io.WriteCloser + h hash.Hash +} + +func (w *seMDCWriter) Write(buf []byte) (n int, err error) { + w.h.Write(buf) + return w.w.Write(buf) +} + +func (w *seMDCWriter) Close() (err error) { + var buf [mdcTrailerSize]byte + + buf[0] = mdcPacketTagByte + buf[1] = sha1.Size + w.h.Write(buf[:2]) + digest := w.h.Sum(nil) + copy(buf[2:], digest) + + _, err = w.w.Write(buf[:]) + if err != nil { + return + } + return w.w.Close() +} + +// noOpCloser is like an ioutil.NopCloser, but for an io.Writer. +type noOpCloser struct { + w io.Writer +} + +func (c noOpCloser) Write(data []byte) (n int, err error) { + return c.w.Write(data) +} + +func (c noOpCloser) Close() error { + return nil +} + +// SerializeSymmetricallyEncrypted serializes a symmetrically encrypted packet +// to w and returns a WriteCloser to which the to-be-encrypted packets can be +// written. +// If config is nil, sensible defaults will be used. +func SerializeSymmetricallyEncrypted(w io.Writer, c CipherFunction, key []byte, config *Config) (contents io.WriteCloser, err error) { + if c.KeySize() != len(key) { + return nil, errors.InvalidArgumentError("SymmetricallyEncrypted.Serialize: bad key length") + } + writeCloser := noOpCloser{w} + ciphertext, err := serializeStreamHeader(writeCloser, packetTypeSymmetricallyEncryptedMDC) + if err != nil { + return + } + + _, err = ciphertext.Write([]byte{symmetricallyEncryptedVersion}) + if err != nil { + return + } + + block := c.new(key) + blockSize := block.BlockSize() + iv := make([]byte, blockSize) + _, err = config.Random().Read(iv) + if err != nil { + return + } + s, prefix := NewOCFBEncrypter(block, iv, OCFBNoResync) + _, err = ciphertext.Write(prefix) + if err != nil { + return + } + plaintext := cipher.StreamWriter{S: s, W: ciphertext} + + h := sha1.New() + h.Write(iv) + h.Write(iv[blockSize-2:]) + contents = &seMDCWriter{w: plaintext, h: h} + return +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted_test.go b/vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted_test.go new file mode 100644 index 0000000000000000000000000000000000000000..c5c00f7b9c399efa58cf984c8c8549087f911d5b --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted_test.go @@ -0,0 +1,123 @@ +// 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 packet + +import ( + "bytes" + "crypto/sha1" + "encoding/hex" + "golang.org/x/crypto/openpgp/errors" + "io" + "io/ioutil" + "testing" +) + +// TestReader wraps a []byte and returns reads of a specific length. +type testReader struct { + data []byte + stride int +} + +func (t *testReader) Read(buf []byte) (n int, err error) { + n = t.stride + if n > len(t.data) { + n = len(t.data) + } + if n > len(buf) { + n = len(buf) + } + copy(buf, t.data) + t.data = t.data[n:] + if len(t.data) == 0 { + err = io.EOF + } + return +} + +func testMDCReader(t *testing.T) { + mdcPlaintext, _ := hex.DecodeString(mdcPlaintextHex) + + for stride := 1; stride < len(mdcPlaintext)/2; stride++ { + r := &testReader{data: mdcPlaintext, stride: stride} + mdcReader := &seMDCReader{in: r, h: sha1.New()} + body, err := ioutil.ReadAll(mdcReader) + if err != nil { + t.Errorf("stride: %d, error: %s", stride, err) + continue + } + if !bytes.Equal(body, mdcPlaintext[:len(mdcPlaintext)-22]) { + t.Errorf("stride: %d: bad contents %x", stride, body) + continue + } + + err = mdcReader.Close() + if err != nil { + t.Errorf("stride: %d, error on Close: %s", stride, err) + } + } + + mdcPlaintext[15] ^= 80 + + r := &testReader{data: mdcPlaintext, stride: 2} + mdcReader := &seMDCReader{in: r, h: sha1.New()} + _, err := ioutil.ReadAll(mdcReader) + if err != nil { + t.Errorf("corruption test, error: %s", err) + return + } + err = mdcReader.Close() + if err == nil { + t.Error("corruption: no error") + } else if _, ok := err.(*errors.SignatureError); !ok { + t.Errorf("corruption: expected SignatureError, got: %s", err) + } +} + +const mdcPlaintextHex = "a302789c3b2d93c4e0eb9aba22283539b3203335af44a134afb800c849cb4c4de10200aff40b45d31432c80cb384299a0655966d6939dfdeed1dddf980" + +func TestSerialize(t *testing.T) { + buf := bytes.NewBuffer(nil) + c := CipherAES128 + key := make([]byte, c.KeySize()) + + w, err := SerializeSymmetricallyEncrypted(buf, c, key, nil) + if err != nil { + t.Errorf("error from SerializeSymmetricallyEncrypted: %s", err) + return + } + + contents := []byte("hello world\n") + + w.Write(contents) + w.Close() + + p, err := Read(buf) + if err != nil { + t.Errorf("error from Read: %s", err) + return + } + + se, ok := p.(*SymmetricallyEncrypted) + if !ok { + t.Errorf("didn't read a *SymmetricallyEncrypted") + return + } + + r, err := se.Decrypt(c, key) + if err != nil { + t.Errorf("error from Decrypt: %s", err) + return + } + + contentsCopy := bytes.NewBuffer(nil) + _, err = io.Copy(contentsCopy, r) + if err != nil { + t.Errorf("error from io.Copy: %s", err) + return + } + if !bytes.Equal(contentsCopy.Bytes(), contents) { + t.Errorf("contents not equal got: %x want: %x", contentsCopy.Bytes(), contents) + } +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/userattribute.go b/vendor/golang.org/x/crypto/openpgp/packet/userattribute.go new file mode 100644 index 0000000000000000000000000000000000000000..96a2b382a1de036fd13217c846b5b6bd795330c9 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/userattribute.go @@ -0,0 +1,91 @@ +// 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. + +package packet + +import ( + "bytes" + "image" + "image/jpeg" + "io" + "io/ioutil" +) + +const UserAttrImageSubpacket = 1 + +// UserAttribute is capable of storing other types of data about a user +// beyond name, email and a text comment. In practice, user attributes are typically used +// to store a signed thumbnail photo JPEG image of the user. +// See RFC 4880, section 5.12. +type UserAttribute struct { + Contents []*OpaqueSubpacket +} + +// NewUserAttributePhoto creates a user attribute packet +// containing the given images. +func NewUserAttributePhoto(photos ...image.Image) (uat *UserAttribute, err error) { + uat = new(UserAttribute) + for _, photo := range photos { + var buf bytes.Buffer + // RFC 4880, Section 5.12.1. + data := []byte{ + 0x10, 0x00, // Little-endian image header length (16 bytes) + 0x01, // Image header version 1 + 0x01, // JPEG + 0, 0, 0, 0, // 12 reserved octets, must be all zero. + 0, 0, 0, 0, + 0, 0, 0, 0} + if _, err = buf.Write(data); err != nil { + return + } + if err = jpeg.Encode(&buf, photo, nil); err != nil { + return + } + uat.Contents = append(uat.Contents, &OpaqueSubpacket{ + SubType: UserAttrImageSubpacket, + Contents: buf.Bytes()}) + } + return +} + +// NewUserAttribute creates a new user attribute packet containing the given subpackets. +func NewUserAttribute(contents ...*OpaqueSubpacket) *UserAttribute { + return &UserAttribute{Contents: contents} +} + +func (uat *UserAttribute) parse(r io.Reader) (err error) { + // RFC 4880, section 5.13 + b, err := ioutil.ReadAll(r) + if err != nil { + return + } + uat.Contents, err = OpaqueSubpackets(b) + return +} + +// Serialize marshals the user attribute to w in the form of an OpenPGP packet, including +// header. +func (uat *UserAttribute) Serialize(w io.Writer) (err error) { + var buf bytes.Buffer + for _, sp := range uat.Contents { + sp.Serialize(&buf) + } + if err = serializeHeader(w, packetTypeUserAttribute, buf.Len()); err != nil { + return err + } + _, err = w.Write(buf.Bytes()) + return +} + +// ImageData returns zero or more byte slices, each containing +// JPEG File Interchange Format (JFIF), for each photo in the +// the user attribute packet. +func (uat *UserAttribute) ImageData() (imageData [][]byte) { + for _, sp := range uat.Contents { + if sp.SubType == UserAttrImageSubpacket && len(sp.Contents) > 16 { + imageData = append(imageData, sp.Contents[16:]) + } + } + return +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/userattribute_test.go b/vendor/golang.org/x/crypto/openpgp/packet/userattribute_test.go new file mode 100644 index 0000000000000000000000000000000000000000..13ca5143cee62c871409db2a045937b3021e351a --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/userattribute_test.go @@ -0,0 +1,109 @@ +// 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 packet + +import ( + "bytes" + "encoding/base64" + "image/color" + "image/jpeg" + "testing" +) + +func TestParseUserAttribute(t *testing.T) { + r := base64.NewDecoder(base64.StdEncoding, bytes.NewBufferString(userAttributePacket)) + for i := 0; i < 2; i++ { + p, err := Read(r) + if err != nil { + t.Fatal(err) + } + uat := p.(*UserAttribute) + imgs := uat.ImageData() + if len(imgs) != 1 { + t.Errorf("Unexpected number of images in user attribute packet: %d", len(imgs)) + } + if len(imgs[0]) != 3395 { + t.Errorf("Unexpected JPEG image size: %d", len(imgs[0])) + } + img, err := jpeg.Decode(bytes.NewBuffer(imgs[0])) + if err != nil { + t.Errorf("Error decoding JPEG image: %v", err) + } + // A pixel in my right eye. + pixel := color.NRGBAModel.Convert(img.At(56, 36)) + ref := color.NRGBA{R: 157, G: 128, B: 124, A: 255} + if pixel != ref { + t.Errorf("Unexpected pixel color: %v", pixel) + } + w := bytes.NewBuffer(nil) + err = uat.Serialize(w) + if err != nil { + t.Errorf("Error writing user attribute: %v", err) + } + r = bytes.NewBuffer(w.Bytes()) + } +} + +const userAttributePacket = ` +0cyWzJQBEAABAQAAAAAAAAAAAAAAAP/Y/+AAEEpGSUYAAQIAAAEAAQAA/9sAQwAFAwQEBAMFBAQE +BQUFBgcMCAcHBwcPCgsJDBEPEhIRDxEQExYcFxMUGhUQERghGBocHR8fHxMXIiQiHiQcHh8e/9sA +QwEFBQUHBgcOCAgOHhQRFB4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4e +Hh4eHh4eHh4e/8AAEQgAZABkAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYH +CAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHw +JDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6 +g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk +5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIB +AgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEX +GBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKT +lJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX2 +9/j5+v/aAAwDAQACEQMRAD8A5uGP06VehQ4pIox04q5EnHSvAep+hIIl4zVuMHGPWmRrUWtalaaN +pU2oXsgSGJSxPr6ClvoitErs0Itqjc7BQOpPAFYmrfEnwjojtHNqaXEynBjtx5hH4jj9a8B8d+Od +W8UXZjWR4LJT+7t0Jwfc+prnIdO1CWZEW2mZ3HyDactXXDB3V5s8evm1namj6r0H4weCLtxG+ova +ueP30RA/MV6not1bX0Ed1ZzxzwyDKvGwZSPqK+Ff+ES8R8t/ZV2oHUmM10Hgbxp4m8BatEfNnWBH +/eWshOxx9Kmpg4te49RUM1kn+8Wh9zQ4P1FaMC7l465rjPh14y0fxnoseoaXOpfaPOgJ+eI98j09 +67W19M15bi4uzPSqTU480WXkjZkAyAR61DPE6OCSOalWRRgZxjvTb598sfU4FBwx5uY4T4feIm8P +TeJbAgc65NIM+8cX+FFeLfF3Vr3SfiNrMFrMypJMJcDPUqP8KK+kpVFyLU+ar037SXqX4hxVpMY7 +1UhPpVlT2rybKx9smWYz3NeH/EDVLzxt40j8O6bITaQybPlbKkjq39K9O8fasdH8IahfKxWQRFIy +Ou9uB/OuE/Z/0y3j1d9TuyoZCMs5xjuea1pLli5nn46q240l13PcfhN8EvDNtpcEl/CklyVBLuMk +mvU/Dfwo0BL/AO13FjEDD/qyV7Vn+CvGPg8zRpJrVm8ikLtEg6+1ew2dxZ3EQaJgysuQPasH7eXW +1zzsbVhT92kk/PsYieEND+zlPs6c/wCyAPyryH4wfCPRtW0u6j+xRLOxLxSoADkDpXY+MPjJ4c0S +9k082d3O8ZKkxw5XI96ytK+IGk+IpFjRpod+Qq3C7QT6A1E6NenaXbqRg6rlLlqS0fRnxjpd1r/w +w8afa7GWRPKbZLGeBKmeVNfZngLxNaeKfDdprVjxHcLlkJ5Vh1H5185/tDad9h8XOsqAw3Cb0cjq +CfX61P8AsveKf7L8T3fhe5nxa3g324YniQdh9R/KuivTdSmp9TXB1/Z1nRlsfU249QBx1pWfcwI7 +Cq6u2Ovamb9rYz16V5x7Psz5q/aJhZfibcupIElvE3H+7j+lFbXx9szP45jlUfeso8/99OKK9elL +3EeNVopzZVharCtxVRGGMk02S5JyFOB69zWTieypnL/GksfB+0cr9oQt69awPhPpD69Y3Ky3DWth +CWluGU4LAdq3vibGs/g68BJygVxjrwRW5+ztoRv/AAs8EeCZnO/J/hzz/Kumi4wp3kePjlOdZKPY +ml8Mvo6WM9ppi7J0EkQYMzkb1X0wW+bJHGACa+ivg14huZPCkjXUO6SImIYOQAP6UQ2sGneHmiWF +CYoSAAuM8etXfhBpMr+EZ3SSNRcMx6ZxWdes6ytBGSwkMNFuo7pnP614Ut9Zn1C4uLySKcwObGFA +Qnm4+XcR71h+CfDHiKCQWuv2YWFtw+bBZQD8rcE8n2Ney+GbGGQSM6I7xvtI681rXdp8hKRRp6t3 +FYPE1VDlsY1nQjWdl+J8w/tOeDZZ/AMd/EGefTHyxxyYjwfyODXg3waRh8UtEcFh+8Jb8FNfZPxh +Ak8J6nbPIsiyW7LnseK+Ofh99ptPHFnf2lu0y2twGcKuSEPB/Q1WHk50miq1o14TXU+xop+On61H +NMC6Nis1LgsAcUTSt1APFcXJZn0EqmhyvxA037friTYziBV6f7Tf40Vr3k4aXLx5OMZIzRXZB2ik +efJXbPHJJcnaD9aN2R1qoGO8/WkuLlIV+YjdjpXSonQ5lTxfiTwzqCnkeQxx9BWx+zPrQsrBFYja +zEfrXL6lfie3khcjY6lSPUGud+G3iA6FrY0uQ/KJsA9gCa0jSvFpnBi6tpKSPu++nsIfDFxeXciR +qIicscY4rxTwB8RUkn1axsPEf2LTYx85kTGzqCUP8VcJ47+JOs+I0Hhq1njjt/ufIeSvq1VtE+Gs +eoaUbSHUrkHdu3WtuX5Ix81XRh7OL5jirVpV5Whdn0F8C/iX4auVn0i612T7bASoe8wjTAd89K9g +vtSt5NMa4t5lkRhgOh3Dn6V8aaz8KZrIR3OlQ6r56LySmSxxz06Vo/CHx34h0rxBP4XvJ5AjK2RP +nEbAEj6ZxjPrWM6fMmoswqJxqJ1VZnqHxn1NLPwveqWHmNC2BnnNcD8DfDkGi+CH1m+ijN1qMzNA +4GSIiAMf+hVxPxU8Tapc3c0F9MGCn5GU5BX0Pau3+HmrT3XgXSIJCBHDGdgAx1NYSpezha52Yauq +1dya2Wh2onAIwTj1p0lxxWWLkhRyCKWa5O3ORXOos9KVQluZm83j0oqi84JyWH50Vdmc7ep43d3I +t1Z2Iz2FYdxeSTsxyRnvTdVuDNcNluM9KrKcg817NOnZGNbEXdkNckjrXGeIIprPxFFdRHAlIwem +COtdmxrG8Q2cd/ZNExw45RvQ1bVjim+dWNzw7eaTD4mN3dndCQCo6hmI5zXpj/Ea/wBHjkh0kwRW +xXEfl4yTxXzXZalJDL9nuWKMmRnHcV2Hh3WreCyYXW2SWQhd5P3F6n+lS43d2cTm6d7Ox9EWPxH1 +ODQxPqWpCaSU/ukUc4z3/WvKW8UhviAdaMewYZG98gj9c1ymoa8LyWOJHwkTDaVPb0qpr+q2m6Nb +cfvNo349az9mou9iZVXNWbub3jm98/Vza2ReV7lsJg/e3dsV654UR9N0K0sZP9ZDGFbHr3rzL4P+ +H7rXfEEWr3I3W1qf3IYdW9fwqDxf4k8UeH/G95p08kscHmk25dPlZT0we9YTj7SXKjpw1aNG8mj3 +FLv5ccU959ycnmvKPDnxB82YQarGsZPAlTp+IrvIr1ZIgySKwIyCOhFYTpyg9T0qWIhVV4svzPvf +IdhgY4orPachj81FRdmtzxqdiZmJ9aQEgdqZcPtmbJ71DJcAZ5r20kkeXJtsfPIQDwPzrG1a+S3i +LyHAHvmp7y7HOD1rlNdm+1T7Acovf3o+J2RMpezjzMvrob67pX9o2ShZlYgg/wAWKxZLLWLZ/Ke3 +mVh14yK9M+BMC3dre2ko3LHKCB7EV7EngeGQJdQ7HyBkMKS0djgq1W3c+XtK03U522RwzsTwNiEk +ntXoHgf4calql9El/G8UZbLfLyfr7V9FeGvh+s+0Lbxxcglu2K1NW1nwN4Gk/wBLuI57tV5jjwzE +/QVNS+0dWYRqNvXRFv4eeCodKsY1ggVIY1G3K4z714h+1Jqul3GpwaXYeXJLbzgyyrg4b+6D+HNb +vjz436zq9m+naHF/ZdkeGfOZXH17V4Vqt2b29K+ZuOc5bnce5zWdPBShL2lTfojSeJhy+zp/NjVz +1Bwa6DSfFGq6fbJFDKrov8DjPFcu97ZxsUe4jVhwVJ5Bpp1mwQiLewJPXacVq6fNpYyjOUXdHoKf +EG8VQHsInbuVcgflRXnt5fIs2FYHgcgUVi8LG+xusdW/mN7U2KgEVkTzPt60UVfQ9eHxGHrV1MGi +iD4V25x1qvdgLAMd6KK0pbHm4x++dp8FtUubLxJ5EIjMc+A4Za+qfD8pe1JZVOBmiinW3RyRPMfi +R8QPE638+k2l6LK0Hylbddhb6nOa80mlkcmWR2kcnlnOSaKK7qCXKcNdu5narcSrAoBxvODWJIga +VckjDdqKKwq/EaQ0gUdbjQ6mr7QGBUcd6tPBC6gtGpOOuKKKie5qn7qIpEXd0HSiiimSf//Z` diff --git a/vendor/golang.org/x/crypto/openpgp/packet/userid.go b/vendor/golang.org/x/crypto/openpgp/packet/userid.go new file mode 100644 index 0000000000000000000000000000000000000000..d6bea7d4acc076fa2fc8753af6724e0fb0095e2f --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/userid.go @@ -0,0 +1,160 @@ +// 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 packet + +import ( + "io" + "io/ioutil" + "strings" +) + +// UserId contains text that is intended to represent the name and email +// address of the key holder. See RFC 4880, section 5.11. By convention, this +// takes the form "Full Name (Comment) " +type UserId struct { + Id string // By convention, this takes the form "Full Name (Comment) " which is split out in the fields below. + + Name, Comment, Email string +} + +func hasInvalidCharacters(s string) bool { + for _, c := range s { + switch c { + case '(', ')', '<', '>', 0: + return true + } + } + return false +} + +// NewUserId returns a UserId or nil if any of the arguments contain invalid +// characters. The invalid characters are '\x00', '(', ')', '<' and '>' +func NewUserId(name, comment, email string) *UserId { + // RFC 4880 doesn't deal with the structure of userid strings; the + // name, comment and email form is just a convention. However, there's + // no convention about escaping the metacharacters and GPG just refuses + // to create user ids where, say, the name contains a '('. We mirror + // this behaviour. + + if hasInvalidCharacters(name) || hasInvalidCharacters(comment) || hasInvalidCharacters(email) { + return nil + } + + uid := new(UserId) + uid.Name, uid.Comment, uid.Email = name, comment, email + uid.Id = name + if len(comment) > 0 { + if len(uid.Id) > 0 { + uid.Id += " " + } + uid.Id += "(" + uid.Id += comment + uid.Id += ")" + } + if len(email) > 0 { + if len(uid.Id) > 0 { + uid.Id += " " + } + uid.Id += "<" + uid.Id += email + uid.Id += ">" + } + return uid +} + +func (uid *UserId) parse(r io.Reader) (err error) { + // RFC 4880, section 5.11 + b, err := ioutil.ReadAll(r) + if err != nil { + return + } + uid.Id = string(b) + uid.Name, uid.Comment, uid.Email = parseUserId(uid.Id) + return +} + +// Serialize marshals uid to w in the form of an OpenPGP packet, including +// header. +func (uid *UserId) Serialize(w io.Writer) error { + err := serializeHeader(w, packetTypeUserId, len(uid.Id)) + if err != nil { + return err + } + _, err = w.Write([]byte(uid.Id)) + return err +} + +// parseUserId extracts the name, comment and email from a user id string that +// is formatted as "Full Name (Comment) ". +func parseUserId(id string) (name, comment, email string) { + var n, c, e struct { + start, end int + } + var state int + + for offset, rune := range id { + switch state { + case 0: + // Entering name + n.start = offset + state = 1 + fallthrough + case 1: + // In name + if rune == '(' { + state = 2 + n.end = offset + } else if rune == '<' { + state = 5 + n.end = offset + } + case 2: + // Entering comment + c.start = offset + state = 3 + fallthrough + case 3: + // In comment + if rune == ')' { + state = 4 + c.end = offset + } + case 4: + // Between comment and email + if rune == '<' { + state = 5 + } + case 5: + // Entering email + e.start = offset + state = 6 + fallthrough + case 6: + // In email + if rune == '>' { + state = 7 + e.end = offset + } + default: + // After email + } + } + switch state { + case 1: + // ended in the name + n.end = len(id) + case 3: + // ended in comment + c.end = len(id) + case 6: + // ended in email + e.end = len(id) + } + + name = strings.TrimSpace(id[n.start:n.end]) + comment = strings.TrimSpace(id[c.start:c.end]) + email = strings.TrimSpace(id[e.start:e.end]) + return +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/userid_test.go b/vendor/golang.org/x/crypto/openpgp/packet/userid_test.go new file mode 100644 index 0000000000000000000000000000000000000000..29681938938c687b9e6ef78b17761925042d8cad --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/userid_test.go @@ -0,0 +1,87 @@ +// 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 packet + +import ( + "testing" +) + +var userIdTests = []struct { + id string + name, comment, email string +}{ + {"", "", "", ""}, + {"John Smith", "John Smith", "", ""}, + {"John Smith ()", "John Smith", "", ""}, + {"John Smith () <>", "John Smith", "", ""}, + {"(comment", "", "comment", ""}, + {"(comment)", "", "comment", ""}, + {" sdfk", "", "", "email"}, + {" John Smith ( Comment ) asdkflj < email > lksdfj", "John Smith", "Comment", "email"}, + {" John Smith < email > lksdfj", "John Smith", "", "email"}, + {"("}, + {"foo", "bar", "", "foo (bar)"}, + {"foo", "", "baz", "foo "}, + {"", "bar", "baz", "(bar) "}, + {"foo", "bar", "baz", "foo (bar) "}, +} + +func TestNewUserId(t *testing.T) { + for i, test := range newUserIdTests { + uid := NewUserId(test.name, test.comment, test.email) + if uid == nil { + t.Errorf("#%d: returned nil", i) + continue + } + if uid.Id != test.id { + t.Errorf("#%d: got '%s', want '%s'", i, uid.Id, test.id) + } + } +} + +var invalidNewUserIdTests = []struct { + name, comment, email string +}{ + {"foo(", "", ""}, + {"foo<", "", ""}, + {"", "bar)", ""}, + {"", "bar<", ""}, + {"", "", "baz>"}, + {"", "", "baz)"}, + {"", "", "baz\x00"}, +} + +func TestNewUserIdWithInvalidInput(t *testing.T) { + for i, test := range invalidNewUserIdTests { + if uid := NewUserId(test.name, test.comment, test.email); uid != nil { + t.Errorf("#%d: returned non-nil value: %#v", i, uid) + } + } +} diff --git a/vendor/golang.org/x/crypto/openpgp/read.go b/vendor/golang.org/x/crypto/openpgp/read.go new file mode 100644 index 0000000000000000000000000000000000000000..6ec664f44a1723905fb1140d4a7cc0010297b691 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/read.go @@ -0,0 +1,442 @@ +// 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 openpgp implements high level operations on OpenPGP messages. +package openpgp // import "golang.org/x/crypto/openpgp" + +import ( + "crypto" + _ "crypto/sha256" + "hash" + "io" + "strconv" + + "golang.org/x/crypto/openpgp/armor" + "golang.org/x/crypto/openpgp/errors" + "golang.org/x/crypto/openpgp/packet" +) + +// SignatureType is the armor type for a PGP signature. +var SignatureType = "PGP SIGNATURE" + +// readArmored reads an armored block with the given type. +func readArmored(r io.Reader, expectedType string) (body io.Reader, err error) { + block, err := armor.Decode(r) + if err != nil { + return + } + + if block.Type != expectedType { + return nil, errors.InvalidArgumentError("expected '" + expectedType + "', got: " + block.Type) + } + + return block.Body, nil +} + +// MessageDetails contains the result of parsing an OpenPGP encrypted and/or +// signed message. +type MessageDetails struct { + IsEncrypted bool // true if the message was encrypted. + EncryptedToKeyIds []uint64 // the list of recipient key ids. + IsSymmetricallyEncrypted bool // true if a passphrase could have decrypted the message. + DecryptedWith Key // the private key used to decrypt the message, if any. + IsSigned bool // true if the message is signed. + SignedByKeyId uint64 // the key id of the signer, if any. + SignedBy *Key // the key of the signer, if available. + LiteralData *packet.LiteralData // the metadata of the contents + UnverifiedBody io.Reader // the contents of the message. + + // If IsSigned is true and SignedBy is non-zero then the signature will + // be verified as UnverifiedBody is read. The signature cannot be + // checked until the whole of UnverifiedBody is read so UnverifiedBody + // must be consumed until EOF before the data can be trusted. Even if a + // message isn't signed (or the signer is unknown) the data may contain + // an authentication code that is only checked once UnverifiedBody has + // been consumed. Once EOF has been seen, the following fields are + // valid. (An authentication code failure is reported as a + // SignatureError error when reading from UnverifiedBody.) + SignatureError error // nil if the signature is good. + Signature *packet.Signature // the signature packet itself, if v4 (default) + SignatureV3 *packet.SignatureV3 // the signature packet if it is a v2 or v3 signature + + decrypted io.ReadCloser +} + +// A PromptFunction is used as a callback by functions that may need to decrypt +// a private key, or prompt for a passphrase. It is called with a list of +// acceptable, encrypted private keys and a boolean that indicates whether a +// passphrase is usable. It should either decrypt a private key or return a +// passphrase to try. If the decrypted private key or given passphrase isn't +// correct, the function will be called again, forever. Any error returned will +// be passed up. +type PromptFunction func(keys []Key, symmetric bool) ([]byte, error) + +// A keyEnvelopePair is used to store a private key with the envelope that +// contains a symmetric key, encrypted with that key. +type keyEnvelopePair struct { + key Key + encryptedKey *packet.EncryptedKey +} + +// ReadMessage parses an OpenPGP message that may be signed and/or encrypted. +// The given KeyRing should contain both public keys (for signature +// verification) and, possibly encrypted, private keys for decrypting. +// If config is nil, sensible defaults will be used. +func ReadMessage(r io.Reader, keyring KeyRing, prompt PromptFunction, config *packet.Config) (md *MessageDetails, err error) { + var p packet.Packet + + var symKeys []*packet.SymmetricKeyEncrypted + var pubKeys []keyEnvelopePair + var se *packet.SymmetricallyEncrypted + + packets := packet.NewReader(r) + md = new(MessageDetails) + md.IsEncrypted = true + + // The message, if encrypted, starts with a number of packets + // containing an encrypted decryption key. The decryption key is either + // encrypted to a public key, or with a passphrase. This loop + // collects these packets. +ParsePackets: + for { + p, err = packets.Next() + if err != nil { + return nil, err + } + switch p := p.(type) { + case *packet.SymmetricKeyEncrypted: + // This packet contains the decryption key encrypted with a passphrase. + md.IsSymmetricallyEncrypted = true + symKeys = append(symKeys, p) + case *packet.EncryptedKey: + // This packet contains the decryption key encrypted to a public key. + md.EncryptedToKeyIds = append(md.EncryptedToKeyIds, p.KeyId) + switch p.Algo { + case packet.PubKeyAlgoRSA, packet.PubKeyAlgoRSAEncryptOnly, packet.PubKeyAlgoElGamal: + break + default: + continue + } + var keys []Key + if p.KeyId == 0 { + keys = keyring.DecryptionKeys() + } else { + keys = keyring.KeysById(p.KeyId) + } + for _, k := range keys { + pubKeys = append(pubKeys, keyEnvelopePair{k, p}) + } + case *packet.SymmetricallyEncrypted: + se = p + break ParsePackets + case *packet.Compressed, *packet.LiteralData, *packet.OnePassSignature: + // This message isn't encrypted. + if len(symKeys) != 0 || len(pubKeys) != 0 { + return nil, errors.StructuralError("key material not followed by encrypted message") + } + packets.Unread(p) + return readSignedMessage(packets, nil, keyring) + } + } + + var candidates []Key + var decrypted io.ReadCloser + + // Now that we have the list of encrypted keys we need to decrypt at + // least one of them or, if we cannot, we need to call the prompt + // function so that it can decrypt a key or give us a passphrase. +FindKey: + for { + // See if any of the keys already have a private key available + candidates = candidates[:0] + candidateFingerprints := make(map[string]bool) + + for _, pk := range pubKeys { + if pk.key.PrivateKey == nil { + continue + } + if !pk.key.PrivateKey.Encrypted { + if len(pk.encryptedKey.Key) == 0 { + pk.encryptedKey.Decrypt(pk.key.PrivateKey, config) + } + if len(pk.encryptedKey.Key) == 0 { + continue + } + decrypted, err = se.Decrypt(pk.encryptedKey.CipherFunc, pk.encryptedKey.Key) + if err != nil && err != errors.ErrKeyIncorrect { + return nil, err + } + if decrypted != nil { + md.DecryptedWith = pk.key + break FindKey + } + } else { + fpr := string(pk.key.PublicKey.Fingerprint[:]) + if v := candidateFingerprints[fpr]; v { + continue + } + candidates = append(candidates, pk.key) + candidateFingerprints[fpr] = true + } + } + + if len(candidates) == 0 && len(symKeys) == 0 { + return nil, errors.ErrKeyIncorrect + } + + if prompt == nil { + return nil, errors.ErrKeyIncorrect + } + + passphrase, err := prompt(candidates, len(symKeys) != 0) + if err != nil { + return nil, err + } + + // Try the symmetric passphrase first + if len(symKeys) != 0 && passphrase != nil { + for _, s := range symKeys { + key, cipherFunc, err := s.Decrypt(passphrase) + if err == nil { + decrypted, err = se.Decrypt(cipherFunc, key) + if err != nil && err != errors.ErrKeyIncorrect { + return nil, err + } + if decrypted != nil { + break FindKey + } + } + + } + } + } + + md.decrypted = decrypted + if err := packets.Push(decrypted); err != nil { + return nil, err + } + return readSignedMessage(packets, md, keyring) +} + +// readSignedMessage reads a possibly signed message if mdin is non-zero then +// that structure is updated and returned. Otherwise a fresh MessageDetails is +// used. +func readSignedMessage(packets *packet.Reader, mdin *MessageDetails, keyring KeyRing) (md *MessageDetails, err error) { + if mdin == nil { + mdin = new(MessageDetails) + } + md = mdin + + var p packet.Packet + var h hash.Hash + var wrappedHash hash.Hash +FindLiteralData: + for { + p, err = packets.Next() + if err != nil { + return nil, err + } + switch p := p.(type) { + case *packet.Compressed: + if err := packets.Push(p.Body); err != nil { + return nil, err + } + case *packet.OnePassSignature: + if !p.IsLast { + return nil, errors.UnsupportedError("nested signatures") + } + + h, wrappedHash, err = hashForSignature(p.Hash, p.SigType) + if err != nil { + md = nil + return + } + + md.IsSigned = true + md.SignedByKeyId = p.KeyId + keys := keyring.KeysByIdUsage(p.KeyId, packet.KeyFlagSign) + if len(keys) > 0 { + md.SignedBy = &keys[0] + } + case *packet.LiteralData: + md.LiteralData = p + break FindLiteralData + } + } + + if md.SignedBy != nil { + md.UnverifiedBody = &signatureCheckReader{packets, h, wrappedHash, md} + } else if md.decrypted != nil { + md.UnverifiedBody = checkReader{md} + } else { + md.UnverifiedBody = md.LiteralData.Body + } + + return md, nil +} + +// hashForSignature returns a pair of hashes that can be used to verify a +// signature. The signature may specify that the contents of the signed message +// should be preprocessed (i.e. to normalize line endings). Thus this function +// returns two hashes. The second should be used to hash the message itself and +// performs any needed preprocessing. +func hashForSignature(hashId crypto.Hash, sigType packet.SignatureType) (hash.Hash, hash.Hash, error) { + if !hashId.Available() { + return nil, nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hashId))) + } + h := hashId.New() + + switch sigType { + case packet.SigTypeBinary: + return h, h, nil + case packet.SigTypeText: + return h, NewCanonicalTextHash(h), nil + } + + return nil, nil, errors.UnsupportedError("unsupported signature type: " + strconv.Itoa(int(sigType))) +} + +// checkReader wraps an io.Reader from a LiteralData packet. When it sees EOF +// it closes the ReadCloser from any SymmetricallyEncrypted packet to trigger +// MDC checks. +type checkReader struct { + md *MessageDetails +} + +func (cr checkReader) Read(buf []byte) (n int, err error) { + n, err = cr.md.LiteralData.Body.Read(buf) + if err == io.EOF { + mdcErr := cr.md.decrypted.Close() + if mdcErr != nil { + err = mdcErr + } + } + return +} + +// signatureCheckReader wraps an io.Reader from a LiteralData packet and hashes +// the data as it is read. When it sees an EOF from the underlying io.Reader +// it parses and checks a trailing Signature packet and triggers any MDC checks. +type signatureCheckReader struct { + packets *packet.Reader + h, wrappedHash hash.Hash + md *MessageDetails +} + +func (scr *signatureCheckReader) Read(buf []byte) (n int, err error) { + n, err = scr.md.LiteralData.Body.Read(buf) + scr.wrappedHash.Write(buf[:n]) + if err == io.EOF { + var p packet.Packet + p, scr.md.SignatureError = scr.packets.Next() + if scr.md.SignatureError != nil { + return + } + + var ok bool + if scr.md.Signature, ok = p.(*packet.Signature); ok { + scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignature(scr.h, scr.md.Signature) + } else if scr.md.SignatureV3, ok = p.(*packet.SignatureV3); ok { + scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignatureV3(scr.h, scr.md.SignatureV3) + } else { + scr.md.SignatureError = errors.StructuralError("LiteralData not followed by Signature") + return + } + + // The SymmetricallyEncrypted packet, if any, might have an + // unsigned hash of its own. In order to check this we need to + // close that Reader. + if scr.md.decrypted != nil { + mdcErr := scr.md.decrypted.Close() + if mdcErr != nil { + err = mdcErr + } + } + } + return +} + +// CheckDetachedSignature takes a signed file and a detached signature and +// returns the signer if the signature is valid. If the signer isn't known, +// ErrUnknownIssuer is returned. +func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err error) { + var issuerKeyId uint64 + var hashFunc crypto.Hash + var sigType packet.SignatureType + var keys []Key + var p packet.Packet + + packets := packet.NewReader(signature) + for { + p, err = packets.Next() + if err == io.EOF { + return nil, errors.ErrUnknownIssuer + } + if err != nil { + return nil, err + } + + switch sig := p.(type) { + case *packet.Signature: + if sig.IssuerKeyId == nil { + return nil, errors.StructuralError("signature doesn't have an issuer") + } + issuerKeyId = *sig.IssuerKeyId + hashFunc = sig.Hash + sigType = sig.SigType + case *packet.SignatureV3: + issuerKeyId = sig.IssuerKeyId + hashFunc = sig.Hash + sigType = sig.SigType + default: + return nil, errors.StructuralError("non signature packet found") + } + + keys = keyring.KeysByIdUsage(issuerKeyId, packet.KeyFlagSign) + if len(keys) > 0 { + break + } + } + + if len(keys) == 0 { + panic("unreachable") + } + + h, wrappedHash, err := hashForSignature(hashFunc, sigType) + if err != nil { + return nil, err + } + + if _, err := io.Copy(wrappedHash, signed); err != nil && err != io.EOF { + return nil, err + } + + for _, key := range keys { + switch sig := p.(type) { + case *packet.Signature: + err = key.PublicKey.VerifySignature(h, sig) + case *packet.SignatureV3: + err = key.PublicKey.VerifySignatureV3(h, sig) + default: + panic("unreachable") + } + + if err == nil { + return key.Entity, nil + } + } + + return nil, err +} + +// CheckArmoredDetachedSignature performs the same actions as +// CheckDetachedSignature but expects the signature to be armored. +func CheckArmoredDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err error) { + body, err := readArmored(signature, SignatureType) + if err != nil { + return + } + + return CheckDetachedSignature(keyring, signed, body) +} diff --git a/vendor/golang.org/x/crypto/openpgp/read_test.go b/vendor/golang.org/x/crypto/openpgp/read_test.go new file mode 100644 index 0000000000000000000000000000000000000000..1fbfbac4ce097ef08f59edeb81988dfe6ced6dc3 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/read_test.go @@ -0,0 +1,613 @@ +// 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 openpgp + +import ( + "bytes" + _ "crypto/sha512" + "encoding/hex" + "io" + "io/ioutil" + "strings" + "testing" + + "golang.org/x/crypto/openpgp/armor" + "golang.org/x/crypto/openpgp/errors" +) + +func readerFromHex(s string) io.Reader { + data, err := hex.DecodeString(s) + if err != nil { + panic("readerFromHex: bad input") + } + return bytes.NewBuffer(data) +} + +func TestReadKeyRing(t *testing.T) { + kring, err := ReadKeyRing(readerFromHex(testKeys1And2Hex)) + if err != nil { + t.Error(err) + return + } + if len(kring) != 2 || uint32(kring[0].PrimaryKey.KeyId) != 0xC20C31BB || uint32(kring[1].PrimaryKey.KeyId) != 0x1E35246B { + t.Errorf("bad keyring: %#v", kring) + } +} + +func TestRereadKeyRing(t *testing.T) { + kring, err := ReadKeyRing(readerFromHex(testKeys1And2Hex)) + if err != nil { + t.Errorf("error in initial parse: %s", err) + return + } + out := new(bytes.Buffer) + err = kring[0].Serialize(out) + if err != nil { + t.Errorf("error in serialization: %s", err) + return + } + kring, err = ReadKeyRing(out) + if err != nil { + t.Errorf("error in second parse: %s", err) + return + } + + if len(kring) != 1 || uint32(kring[0].PrimaryKey.KeyId) != 0xC20C31BB { + t.Errorf("bad keyring: %#v", kring) + } +} + +func TestReadPrivateKeyRing(t *testing.T) { + kring, err := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex)) + if err != nil { + t.Error(err) + return + } + if len(kring) != 2 || uint32(kring[0].PrimaryKey.KeyId) != 0xC20C31BB || uint32(kring[1].PrimaryKey.KeyId) != 0x1E35246B || kring[0].PrimaryKey == nil { + t.Errorf("bad keyring: %#v", kring) + } +} + +func TestReadDSAKey(t *testing.T) { + kring, err := ReadKeyRing(readerFromHex(dsaTestKeyHex)) + if err != nil { + t.Error(err) + return + } + if len(kring) != 1 || uint32(kring[0].PrimaryKey.KeyId) != 0x0CCC0360 { + t.Errorf("bad parse: %#v", kring) + } +} + +func TestReadP256Key(t *testing.T) { + kring, err := ReadKeyRing(readerFromHex(p256TestKeyHex)) + if err != nil { + t.Error(err) + return + } + if len(kring) != 1 || uint32(kring[0].PrimaryKey.KeyId) != 0x5918513E { + t.Errorf("bad parse: %#v", kring) + } +} + +func TestDSAHashTruncatation(t *testing.T) { + // dsaKeyWithSHA512 was generated with GnuPG and --cert-digest-algo + // SHA512 in order to require DSA hash truncation to verify correctly. + _, err := ReadKeyRing(readerFromHex(dsaKeyWithSHA512)) + if err != nil { + t.Error(err) + } +} + +func TestGetKeyById(t *testing.T) { + kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex)) + + keys := kring.KeysById(0xa34d7e18c20c31bb) + if len(keys) != 1 || keys[0].Entity != kring[0] { + t.Errorf("bad result for 0xa34d7e18c20c31bb: %#v", keys) + } + + keys = kring.KeysById(0xfd94408d4543314f) + if len(keys) != 1 || keys[0].Entity != kring[0] { + t.Errorf("bad result for 0xa34d7e18c20c31bb: %#v", keys) + } +} + +func checkSignedMessage(t *testing.T, signedHex, expected string) { + kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex)) + + md, err := ReadMessage(readerFromHex(signedHex), kring, nil, nil) + if err != nil { + t.Error(err) + return + } + + if !md.IsSigned || md.SignedByKeyId != 0xa34d7e18c20c31bb || md.SignedBy == nil || md.IsEncrypted || md.IsSymmetricallyEncrypted || len(md.EncryptedToKeyIds) != 0 || md.IsSymmetricallyEncrypted { + t.Errorf("bad MessageDetails: %#v", md) + } + + contents, err := ioutil.ReadAll(md.UnverifiedBody) + if err != nil { + t.Errorf("error reading UnverifiedBody: %s", err) + } + if string(contents) != expected { + t.Errorf("bad UnverifiedBody got:%s want:%s", string(contents), expected) + } + if md.SignatureError != nil || md.Signature == nil { + t.Errorf("failed to validate: %s", md.SignatureError) + } +} + +func TestSignedMessage(t *testing.T) { + checkSignedMessage(t, signedMessageHex, signedInput) +} + +func TestTextSignedMessage(t *testing.T) { + checkSignedMessage(t, signedTextMessageHex, signedTextInput) +} + +// The reader should detect "compressed quines", which are compressed +// packets that expand into themselves and cause an infinite recursive +// parsing loop. +// The packet in this test case comes from Taylor R. Campbell at +// http://mumble.net/~campbell/misc/pgp-quine/ +func TestCampbellQuine(t *testing.T) { + md, err := ReadMessage(readerFromHex(campbellQuine), nil, nil, nil) + if md != nil { + t.Errorf("Reading a compressed quine should not return any data: %#v", md) + } + structural, ok := err.(errors.StructuralError) + if !ok { + t.Fatalf("Unexpected class of error: %T", err) + } + if !strings.Contains(string(structural), "too many layers of packets") { + t.Fatalf("Unexpected error: %s", err) + } +} + +var signedEncryptedMessageTests = []struct { + keyRingHex string + messageHex string + signedByKeyId uint64 + encryptedToKeyId uint64 +}{ + { + testKeys1And2PrivateHex, + signedEncryptedMessageHex, + 0xa34d7e18c20c31bb, + 0x2a67d68660df41c7, + }, + { + dsaElGamalTestKeysHex, + signedEncryptedMessage2Hex, + 0x33af447ccd759b09, + 0xcf6a7abcd43e3673, + }, +} + +func TestSignedEncryptedMessage(t *testing.T) { + for i, test := range signedEncryptedMessageTests { + expected := "Signed and encrypted message\n" + kring, _ := ReadKeyRing(readerFromHex(test.keyRingHex)) + prompt := func(keys []Key, symmetric bool) ([]byte, error) { + if symmetric { + t.Errorf("prompt: message was marked as symmetrically encrypted") + return nil, errors.ErrKeyIncorrect + } + + if len(keys) == 0 { + t.Error("prompt: no keys requested") + return nil, errors.ErrKeyIncorrect + } + + err := keys[0].PrivateKey.Decrypt([]byte("passphrase")) + if err != nil { + t.Errorf("prompt: error decrypting key: %s", err) + return nil, errors.ErrKeyIncorrect + } + + return nil, nil + } + + md, err := ReadMessage(readerFromHex(test.messageHex), kring, prompt, nil) + if err != nil { + t.Errorf("#%d: error reading message: %s", i, err) + return + } + + if !md.IsSigned || md.SignedByKeyId != test.signedByKeyId || md.SignedBy == nil || !md.IsEncrypted || md.IsSymmetricallyEncrypted || len(md.EncryptedToKeyIds) == 0 || md.EncryptedToKeyIds[0] != test.encryptedToKeyId { + t.Errorf("#%d: bad MessageDetails: %#v", i, md) + } + + contents, err := ioutil.ReadAll(md.UnverifiedBody) + if err != nil { + t.Errorf("#%d: error reading UnverifiedBody: %s", i, err) + } + if string(contents) != expected { + t.Errorf("#%d: bad UnverifiedBody got:%s want:%s", i, string(contents), expected) + } + + if md.SignatureError != nil || md.Signature == nil { + t.Errorf("#%d: failed to validate: %s", i, md.SignatureError) + } + } +} + +func TestUnspecifiedRecipient(t *testing.T) { + expected := "Recipient unspecified\n" + kring, _ := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex)) + + md, err := ReadMessage(readerFromHex(recipientUnspecifiedHex), kring, nil, nil) + if err != nil { + t.Errorf("error reading message: %s", err) + return + } + + contents, err := ioutil.ReadAll(md.UnverifiedBody) + if err != nil { + t.Errorf("error reading UnverifiedBody: %s", err) + } + if string(contents) != expected { + t.Errorf("bad UnverifiedBody got:%s want:%s", string(contents), expected) + } +} + +func TestSymmetricallyEncrypted(t *testing.T) { + firstTimeCalled := true + + prompt := func(keys []Key, symmetric bool) ([]byte, error) { + if len(keys) != 0 { + t.Errorf("prompt: len(keys) = %d (want 0)", len(keys)) + } + + if !symmetric { + t.Errorf("symmetric is not set") + } + + if firstTimeCalled { + firstTimeCalled = false + return []byte("wrongpassword"), nil + } + + return []byte("password"), nil + } + + md, err := ReadMessage(readerFromHex(symmetricallyEncryptedCompressedHex), nil, prompt, nil) + if err != nil { + t.Errorf("ReadMessage: %s", err) + return + } + + contents, err := ioutil.ReadAll(md.UnverifiedBody) + if err != nil { + t.Errorf("ReadAll: %s", err) + } + + expectedCreationTime := uint32(1295992998) + if md.LiteralData.Time != expectedCreationTime { + t.Errorf("LiteralData.Time is %d, want %d", md.LiteralData.Time, expectedCreationTime) + } + + const expected = "Symmetrically encrypted.\n" + if string(contents) != expected { + t.Errorf("contents got: %s want: %s", string(contents), expected) + } +} + +func testDetachedSignature(t *testing.T, kring KeyRing, signature io.Reader, sigInput, tag string, expectedSignerKeyId uint64) { + signed := bytes.NewBufferString(sigInput) + signer, err := CheckDetachedSignature(kring, signed, signature) + if err != nil { + t.Errorf("%s: signature error: %s", tag, err) + return + } + if signer == nil { + t.Errorf("%s: signer is nil", tag) + return + } + if signer.PrimaryKey.KeyId != expectedSignerKeyId { + t.Errorf("%s: wrong signer got:%x want:%x", tag, signer.PrimaryKey.KeyId, expectedSignerKeyId) + } +} + +func TestDetachedSignature(t *testing.T) { + kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex)) + testDetachedSignature(t, kring, readerFromHex(detachedSignatureHex), signedInput, "binary", testKey1KeyId) + testDetachedSignature(t, kring, readerFromHex(detachedSignatureTextHex), signedInput, "text", testKey1KeyId) + testDetachedSignature(t, kring, readerFromHex(detachedSignatureV3TextHex), signedInput, "v3", testKey1KeyId) + + incorrectSignedInput := signedInput + "X" + _, err := CheckDetachedSignature(kring, bytes.NewBufferString(incorrectSignedInput), readerFromHex(detachedSignatureHex)) + if err == nil { + t.Fatal("CheckDetachedSignature returned without error for bad signature") + } + if err == errors.ErrUnknownIssuer { + t.Fatal("CheckDetachedSignature returned ErrUnknownIssuer when the signer was known, but the signature invalid") + } +} + +func TestDetachedSignatureDSA(t *testing.T) { + kring, _ := ReadKeyRing(readerFromHex(dsaTestKeyHex)) + testDetachedSignature(t, kring, readerFromHex(detachedSignatureDSAHex), signedInput, "binary", testKey3KeyId) +} + +func TestMultipleSignaturePacketsDSA(t *testing.T) { + kring, _ := ReadKeyRing(readerFromHex(dsaTestKeyHex)) + testDetachedSignature(t, kring, readerFromHex(missingHashFunctionHex+detachedSignatureDSAHex), signedInput, "binary", testKey3KeyId) +} + +func TestDetachedSignatureP256(t *testing.T) { + kring, _ := ReadKeyRing(readerFromHex(p256TestKeyHex)) + testDetachedSignature(t, kring, readerFromHex(detachedSignatureP256Hex), signedInput, "binary", testKeyP256KeyId) +} + +func testHashFunctionError(t *testing.T, signatureHex string) { + kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex)) + _, err := CheckDetachedSignature(kring, nil, readerFromHex(signatureHex)) + if err == nil { + t.Fatal("Packet with bad hash type was correctly parsed") + } + unsupported, ok := err.(errors.UnsupportedError) + if !ok { + t.Fatalf("Unexpected class of error: %s", err) + } + if !strings.Contains(string(unsupported), "hash ") { + t.Fatalf("Unexpected error: %s", err) + } +} + +func TestUnknownHashFunction(t *testing.T) { + // unknownHashFunctionHex contains a signature packet with hash + // function type 153 (which isn't a real hash function id). + testHashFunctionError(t, unknownHashFunctionHex) +} + +func TestMissingHashFunction(t *testing.T) { + // missingHashFunctionHex contains a signature packet that uses + // RIPEMD160, which isn't compiled in. Since that's the only signature + // packet we don't find any suitable packets and end up with ErrUnknownIssuer + kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex)) + _, err := CheckDetachedSignature(kring, nil, readerFromHex(missingHashFunctionHex)) + if err == nil { + t.Fatal("Packet with missing hash type was correctly parsed") + } + if err != errors.ErrUnknownIssuer { + t.Fatalf("Unexpected class of error: %s", err) + } +} + +func TestReadingArmoredPrivateKey(t *testing.T) { + el, err := ReadArmoredKeyRing(bytes.NewBufferString(armoredPrivateKeyBlock)) + if err != nil { + t.Error(err) + } + if len(el) != 1 { + t.Errorf("got %d entities, wanted 1\n", len(el)) + } +} + +func TestReadingArmoredPublicKey(t *testing.T) { + el, err := ReadArmoredKeyRing(bytes.NewBufferString(e2ePublicKey)) + if err != nil { + t.Error(err) + } + if len(el) != 1 { + t.Errorf("didn't get a valid entity") + } +} + +func TestNoArmoredData(t *testing.T) { + _, err := ReadArmoredKeyRing(bytes.NewBufferString("foo")) + if _, ok := err.(errors.InvalidArgumentError); !ok { + t.Errorf("error was not an InvalidArgumentError: %s", err) + } +} + +func testReadMessageError(t *testing.T, messageHex string) { + buf, err := hex.DecodeString(messageHex) + if err != nil { + t.Errorf("hex.DecodeString(): %v", err) + } + + kr, err := ReadKeyRing(new(bytes.Buffer)) + if err != nil { + t.Errorf("ReadKeyring(): %v", err) + } + + _, err = ReadMessage(bytes.NewBuffer(buf), kr, + func([]Key, bool) ([]byte, error) { + return []byte("insecure"), nil + }, nil) + + if err == nil { + t.Errorf("ReadMessage(): Unexpected nil error") + } +} + +func TestIssue11503(t *testing.T) { + testReadMessageError(t, "8c040402000aa430aa8228b9248b01fc899a91197130303030") +} + +func TestIssue11504(t *testing.T) { + testReadMessageError(t, "9303000130303030303030303030983002303030303030030000000130") +} + +// TestSignatureV3Message tests the verification of V3 signature, generated +// with a modern V4-style key. Some people have their clients set to generate +// V3 signatures, so it's useful to be able to verify them. +func TestSignatureV3Message(t *testing.T) { + sig, err := armor.Decode(strings.NewReader(signedMessageV3)) + if err != nil { + t.Error(err) + return + } + key, err := ReadArmoredKeyRing(strings.NewReader(keyV4forVerifyingSignedMessageV3)) + if err != nil { + t.Error(err) + return + } + md, err := ReadMessage(sig.Body, key, nil, nil) + if err != nil { + t.Error(err) + return + } + + _, err = ioutil.ReadAll(md.UnverifiedBody) + if err != nil { + t.Error(err) + return + } + + // We'll see a sig error here after reading in the UnverifiedBody above, + // if there was one to see. + if err = md.SignatureError; err != nil { + t.Error(err) + return + } + + if md.SignatureV3 == nil { + t.Errorf("No available signature after checking signature") + return + } + if md.Signature != nil { + t.Errorf("Did not expect a signature V4 back") + return + } + return +} + +const testKey1KeyId = 0xA34D7E18C20C31BB +const testKey3KeyId = 0x338934250CCC0360 +const testKeyP256KeyId = 0xd44a2c495918513e + +const signedInput = "Signed message\nline 2\nline 3\n" +const signedTextInput = "Signed message\r\nline 2\r\nline 3\r\n" + +const recipientUnspecifiedHex = "848c0300000000000000000103ff62d4d578d03cf40c3da998dfe216c074fa6ddec5e31c197c9666ba292830d91d18716a80f699f9d897389a90e6d62d0238f5f07a5248073c0f24920e4bc4a30c2d17ee4e0cae7c3d4aaa4e8dced50e3010a80ee692175fa0385f62ecca4b56ee6e9980aa3ec51b61b077096ac9e800edaf161268593eedb6cc7027ff5cb32745d250010d407a6221ae22ef18469b444f2822478c4d190b24d36371a95cb40087cdd42d9399c3d06a53c0673349bfb607927f20d1e122bde1e2bf3aa6cae6edf489629bcaa0689539ae3b718914d88ededc3b" + +const detachedSignatureHex = "889c04000102000605024d449cd1000a0910a34d7e18c20c31bb167603ff57718d09f28a519fdc7b5a68b6a3336da04df85e38c5cd5d5bd2092fa4629848a33d85b1729402a2aab39c3ac19f9d573f773cc62c264dc924c067a79dfd8a863ae06c7c8686120760749f5fd9b1e03a64d20a7df3446ddc8f0aeadeaeba7cbaee5c1e366d65b6a0c6cc749bcb912d2f15013f812795c2e29eb7f7b77f39ce77" + +const detachedSignatureTextHex = "889c04010102000605024d449d21000a0910a34d7e18c20c31bbc8c60400a24fbef7342603a41cb1165767bd18985d015fb72fe05db42db36cfb2f1d455967f1e491194fbf6cf88146222b23bf6ffbd50d17598d976a0417d3192ff9cc0034fd00f287b02e90418bbefe609484b09231e4e7a5f3562e199bf39909ab5276c4d37382fe088f6b5c3426fc1052865da8b3ab158672d58b6264b10823dc4b39" + +const detachedSignatureV3TextHex = "8900950305005255c25ca34d7e18c20c31bb0102bb3f04009f6589ef8a028d6e54f6eaf25432e590d31c3a41f4710897585e10c31e5e332c7f9f409af8512adceaff24d0da1474ab07aa7bce4f674610b010fccc5b579ae5eb00a127f272fb799f988ab8e4574c141da6dbfecfef7e6b2c478d9a3d2551ba741f260ee22bec762812f0053e05380bfdd55ad0f22d8cdf71b233fe51ae8a24" + +const detachedSignatureDSAHex = "884604001102000605024d6c4eac000a0910338934250ccc0360f18d00a087d743d6405ed7b87755476629600b8b694a39e900a0abff8126f46faf1547c1743c37b21b4ea15b8f83" + +const detachedSignatureP256Hex = "885e0400130a0006050256e5bb00000a0910d44a2c495918513edef001009841a4f792beb0befccb35c8838a6a87d9b936beaa86db6745ddc7b045eee0cf00fd1ac1f78306b17e965935dd3f8bae4587a76587e4af231efe19cc4011a8434817" + +const testKeys1And2Hex = "988d044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd0011010001b41054657374204b6579203120285253412988b804130102002205024d3c5c10021b03060b090807030206150802090a0b0416020301021e01021780000a0910a34d7e18c20c31bbb5b304009cc45fe610b641a2c146331be94dade0a396e73ca725e1b25c21708d9cab46ecca5ccebc23055879df8f99eea39b377962a400f2ebdc36a7c99c333d74aeba346315137c3ff9d0a09b0273299090343048afb8107cf94cbd1400e3026f0ccac7ecebbc4d78588eb3e478fe2754d3ca664bcf3eac96ca4a6b0c8d7df5102f60f6b0020003b88d044d3c5c10010400b201df61d67487301f11879d514f4248ade90c8f68c7af1284c161098de4c28c2850f1ec7b8e30f959793e571542ffc6532189409cb51c3d30dad78c4ad5165eda18b20d9826d8707d0f742e2ab492103a85bbd9ddf4f5720f6de7064feb0d39ee002219765bb07bcfb8b877f47abe270ddeda4f676108cecb6b9bb2ad484a4f0011010001889f04180102000905024d3c5c10021b0c000a0910a34d7e18c20c31bb1a03040085c8d62e16d05dc4e9dad64953c8a2eed8b6c12f92b1575eeaa6dcf7be9473dd5b24b37b6dffbb4e7c99ed1bd3cb11634be19b3e6e207bed7505c7ca111ccf47cb323bf1f8851eb6360e8034cbff8dd149993c959de89f8f77f38e7e98b8e3076323aa719328e2b408db5ec0d03936efd57422ba04f925cdc7b4c1af7590e40ab0020003988d044d3c5c33010400b488c3e5f83f4d561f317817538d9d0397981e9aef1321ca68ebfae1cf8b7d388e19f4b5a24a82e2fbbf1c6c26557a6c5845307a03d815756f564ac7325b02bc83e87d5480a8fae848f07cb891f2d51ce7df83dcafdc12324517c86d472cc0ee10d47a68fd1d9ae49a6c19bbd36d82af597a0d88cc9c49de9df4e696fc1f0b5d0011010001b42754657374204b6579203220285253412c20656e637279707465642070726976617465206b65792988b804130102002205024d3c5c33021b03060b090807030206150802090a0b0416020301021e01021780000a0910d4984f961e35246b98940400908a73b6a6169f700434f076c6c79015a49bee37130eaf23aaa3cfa9ce60bfe4acaa7bc95f1146ada5867e0079babb38804891f4f0b8ebca57a86b249dee786161a755b7a342e68ccf3f78ed6440a93a6626beb9a37aa66afcd4f888790cb4bb46d94a4ae3eb3d7d3e6b00f6bfec940303e89ec5b32a1eaaacce66497d539328b0020003b88d044d3c5c33010400a4e913f9442abcc7f1804ccab27d2f787ffa592077ca935a8bb23165bd8d57576acac647cc596b2c3f814518cc8c82953c7a4478f32e0cf645630a5ba38d9618ef2bc3add69d459ae3dece5cab778938d988239f8c5ae437807075e06c828019959c644ff05ef6a5a1dab72227c98e3a040b0cf219026640698d7a13d8538a570011010001889f04180102000905024d3c5c33021b0c000a0910d4984f961e35246b26c703ff7ee29ef53bc1ae1ead533c408fa136db508434e233d6e62be621e031e5940bbd4c08142aed0f82217e7c3e1ec8de574bc06ccf3c36633be41ad78a9eacd209f861cae7b064100758545cc9dd83db71806dc1cfd5fb9ae5c7474bba0c19c44034ae61bae5eca379383339dece94ff56ff7aa44a582f3e5c38f45763af577c0934b0020003" + +const testKeys1And2PrivateHex = "9501d8044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd00110100010003ff4d91393b9a8e3430b14d6209df42f98dc927425b881f1209f319220841273a802a97c7bdb8b3a7740b3ab5866c4d1d308ad0d3a79bd1e883aacf1ac92dfe720285d10d08752a7efe3c609b1d00f17f2805b217be53999a7da7e493bfc3e9618fd17018991b8128aea70a05dbce30e4fbe626aa45775fa255dd9177aabf4df7cf0200c1ded12566e4bc2bb590455e5becfb2e2c9796482270a943343a7835de41080582c2be3caf5981aa838140e97afa40ad652a0b544f83eb1833b0957dce26e47b0200eacd6046741e9ce2ec5beb6fb5e6335457844fb09477f83b050a96be7da043e17f3a9523567ed40e7a521f818813a8b8a72209f1442844843ccc7eb9805442570200bdafe0438d97ac36e773c7162028d65844c4d463e2420aa2228c6e50dc2743c3d6c72d0d782a5173fe7be2169c8a9f4ef8a7cf3e37165e8c61b89c346cdc6c1799d2b41054657374204b6579203120285253412988b804130102002205024d3c5c10021b03060b090807030206150802090a0b0416020301021e01021780000a0910a34d7e18c20c31bbb5b304009cc45fe610b641a2c146331be94dade0a396e73ca725e1b25c21708d9cab46ecca5ccebc23055879df8f99eea39b377962a400f2ebdc36a7c99c333d74aeba346315137c3ff9d0a09b0273299090343048afb8107cf94cbd1400e3026f0ccac7ecebbc4d78588eb3e478fe2754d3ca664bcf3eac96ca4a6b0c8d7df5102f60f6b00200009d01d8044d3c5c10010400b201df61d67487301f11879d514f4248ade90c8f68c7af1284c161098de4c28c2850f1ec7b8e30f959793e571542ffc6532189409cb51c3d30dad78c4ad5165eda18b20d9826d8707d0f742e2ab492103a85bbd9ddf4f5720f6de7064feb0d39ee002219765bb07bcfb8b877f47abe270ddeda4f676108cecb6b9bb2ad484a4f00110100010003fd17a7490c22a79c59281fb7b20f5e6553ec0c1637ae382e8adaea295f50241037f8997cf42c1ce26417e015091451b15424b2c59eb8d4161b0975630408e394d3b00f88d4b4e18e2cc85e8251d4753a27c639c83f5ad4a571c4f19d7cd460b9b73c25ade730c99df09637bd173d8e3e981ac64432078263bb6dc30d3e974150dd0200d0ee05be3d4604d2146fb0457f31ba17c057560785aa804e8ca5530a7cd81d3440d0f4ba6851efcfd3954b7e68908fc0ba47f7ac37bf559c6c168b70d3a7c8cd0200da1c677c4bce06a068070f2b3733b0a714e88d62aa3f9a26c6f5216d48d5c2b5624144f3807c0df30be66b3268eeeca4df1fbded58faf49fc95dc3c35f134f8b01fd1396b6c0fc1b6c4f0eb8f5e44b8eace1e6073e20d0b8bc5385f86f1cf3f050f66af789f3ef1fc107b7f4421e19e0349c730c68f0a226981f4e889054fdb4dc149e8e889f04180102000905024d3c5c10021b0c000a0910a34d7e18c20c31bb1a03040085c8d62e16d05dc4e9dad64953c8a2eed8b6c12f92b1575eeaa6dcf7be9473dd5b24b37b6dffbb4e7c99ed1bd3cb11634be19b3e6e207bed7505c7ca111ccf47cb323bf1f8851eb6360e8034cbff8dd149993c959de89f8f77f38e7e98b8e3076323aa719328e2b408db5ec0d03936efd57422ba04f925cdc7b4c1af7590e40ab00200009501fe044d3c5c33010400b488c3e5f83f4d561f317817538d9d0397981e9aef1321ca68ebfae1cf8b7d388e19f4b5a24a82e2fbbf1c6c26557a6c5845307a03d815756f564ac7325b02bc83e87d5480a8fae848f07cb891f2d51ce7df83dcafdc12324517c86d472cc0ee10d47a68fd1d9ae49a6c19bbd36d82af597a0d88cc9c49de9df4e696fc1f0b5d0011010001fe030302e9030f3c783e14856063f16938530e148bc57a7aa3f3e4f90df9dceccdc779bc0835e1ad3d006e4a8d7b36d08b8e0de5a0d947254ecfbd22037e6572b426bcfdc517796b224b0036ff90bc574b5509bede85512f2eefb520fb4b02aa523ba739bff424a6fe81c5041f253f8d757e69a503d3563a104d0d49e9e890b9d0c26f96b55b743883b472caa7050c4acfd4a21f875bdf1258d88bd61224d303dc9df77f743137d51e6d5246b88c406780528fd9a3e15bab5452e5b93970d9dcc79f48b38651b9f15bfbcf6da452837e9cc70683d1bdca94507870f743e4ad902005812488dd342f836e72869afd00ce1850eea4cfa53ce10e3608e13d3c149394ee3cbd0e23d018fcbcb6e2ec5a1a22972d1d462ca05355d0d290dd2751e550d5efb38c6c89686344df64852bf4ff86638708f644e8ec6bd4af9b50d8541cb91891a431326ab2e332faa7ae86cfb6e0540aa63160c1e5cdd5a4add518b303fff0a20117c6bc77f7cfbaf36b04c865c6c2b42754657374204b6579203220285253412c20656e637279707465642070726976617465206b65792988b804130102002205024d3c5c33021b03060b090807030206150802090a0b0416020301021e01021780000a0910d4984f961e35246b98940400908a73b6a6169f700434f076c6c79015a49bee37130eaf23aaa3cfa9ce60bfe4acaa7bc95f1146ada5867e0079babb38804891f4f0b8ebca57a86b249dee786161a755b7a342e68ccf3f78ed6440a93a6626beb9a37aa66afcd4f888790cb4bb46d94a4ae3eb3d7d3e6b00f6bfec940303e89ec5b32a1eaaacce66497d539328b00200009d01fe044d3c5c33010400a4e913f9442abcc7f1804ccab27d2f787ffa592077ca935a8bb23165bd8d57576acac647cc596b2c3f814518cc8c82953c7a4478f32e0cf645630a5ba38d9618ef2bc3add69d459ae3dece5cab778938d988239f8c5ae437807075e06c828019959c644ff05ef6a5a1dab72227c98e3a040b0cf219026640698d7a13d8538a570011010001fe030302e9030f3c783e148560f936097339ae381d63116efcf802ff8b1c9360767db5219cc987375702a4123fd8657d3e22700f23f95020d1b261eda5257e9a72f9a918e8ef22dd5b3323ae03bbc1923dd224db988cadc16acc04b120a9f8b7e84da9716c53e0334d7b66586ddb9014df604b41be1e960dcfcbc96f4ed150a1a0dd070b9eb14276b9b6be413a769a75b519a53d3ecc0c220e85cd91ca354d57e7344517e64b43b6e29823cbd87eae26e2b2e78e6dedfbb76e3e9f77bcb844f9a8932eb3db2c3f9e44316e6f5d60e9e2a56e46b72abe6b06dc9a31cc63f10023d1f5e12d2a3ee93b675c96f504af0001220991c88db759e231b3320dcedf814dcf723fd9857e3d72d66a0f2af26950b915abdf56c1596f46a325bf17ad4810d3535fb02a259b247ac3dbd4cc3ecf9c51b6c07cebb009c1506fba0a89321ec8683e3fd009a6e551d50243e2d5092fefb3321083a4bad91320dc624bd6b5dddf93553e3d53924c05bfebec1fb4bd47e89a1a889f04180102000905024d3c5c33021b0c000a0910d4984f961e35246b26c703ff7ee29ef53bc1ae1ead533c408fa136db508434e233d6e62be621e031e5940bbd4c08142aed0f82217e7c3e1ec8de574bc06ccf3c36633be41ad78a9eacd209f861cae7b064100758545cc9dd83db71806dc1cfd5fb9ae5c7474bba0c19c44034ae61bae5eca379383339dece94ff56ff7aa44a582f3e5c38f45763af577c0934b0020000" + +const dsaElGamalTestKeysHex = "9501e1044dfcb16a110400aa3e5c1a1f43dd28c2ffae8abf5cfce555ee874134d8ba0a0f7b868ce2214beddc74e5e1e21ded354a95d18acdaf69e5e342371a71fbb9093162e0c5f3427de413a7f2c157d83f5cd2f9d791256dc4f6f0e13f13c3302af27f2384075ab3021dff7a050e14854bbde0a1094174855fc02f0bae8e00a340d94a1f22b32e48485700a0cec672ac21258fb95f61de2ce1af74b2c4fa3e6703ff698edc9be22c02ae4d916e4fa223f819d46582c0516235848a77b577ea49018dcd5e9e15cff9dbb4663a1ae6dd7580fa40946d40c05f72814b0f88481207e6c0832c3bded4853ebba0a7e3bd8e8c66df33d5a537cd4acf946d1080e7a3dcea679cb2b11a72a33a2b6a9dc85f466ad2ddf4c3db6283fa645343286971e3dd700703fc0c4e290d45767f370831a90187e74e9972aae5bff488eeff7d620af0362bfb95c1a6c3413ab5d15a2e4139e5d07a54d72583914661ed6a87cce810be28a0aa8879a2dd39e52fb6fe800f4f181ac7e328f740cde3d09a05cecf9483e4cca4253e60d4429ffd679d9996a520012aad119878c941e3cf151459873bdfc2a9563472fe0303027a728f9feb3b864260a1babe83925ce794710cfd642ee4ae0e5b9d74cee49e9c67b6cd0ea5dfbb582132195a121356a1513e1bca73e5b80c58c7ccb4164453412f456c47616d616c2054657374204b65792031886204131102002205024dfcb16a021b03060b090807030206150802090a0b0416020301021e01021780000a091033af447ccd759b09fadd00a0b8fd6f5a790bad7e9f2dbb7632046dc4493588db009c087c6a9ba9f7f49fab221587a74788c00db4889ab00200009d0157044dfcb16a1004008dec3f9291205255ccff8c532318133a6840739dd68b03ba942676f9038612071447bf07d00d559c5c0875724ea16a4c774f80d8338b55fca691a0522e530e604215b467bbc9ccfd483a1da99d7bc2648b4318fdbd27766fc8bfad3fddb37c62b8ae7ccfe9577e9b8d1e77c1d417ed2c2ef02d52f4da11600d85d3229607943700030503ff506c94c87c8cab778e963b76cf63770f0a79bf48fb49d3b4e52234620fc9f7657f9f8d56c96a2b7c7826ae6b57ebb2221a3fe154b03b6637cea7e6d98e3e45d87cf8dc432f723d3d71f89c5192ac8d7290684d2c25ce55846a80c9a7823f6acd9bb29fa6cd71f20bc90eccfca20451d0c976e460e672b000df49466408d527affe0303027a728f9feb3b864260abd761730327bca2aaa4ea0525c175e92bf240682a0e83b226f97ecb2e935b62c9a133858ce31b271fa8eb41f6a1b3cd72a63025ce1a75ee4180dcc284884904181102000905024dfcb16a021b0c000a091033af447ccd759b09dd0b009e3c3e7296092c81bee5a19929462caaf2fff3ae26009e218c437a2340e7ea628149af1ec98ec091a43992b00200009501e1044dfcb1be1104009f61faa61aa43df75d128cbe53de528c4aec49ce9360c992e70c77072ad5623de0a3a6212771b66b39a30dad6781799e92608316900518ec01184a85d872365b7d2ba4bacfb5882ea3c2473d3750dc6178cc1cf82147fb58caa28b28e9f12f6d1efcb0534abed644156c91cca4ab78834268495160b2400bc422beb37d237c2300a0cac94911b6d493bda1e1fbc6feeca7cb7421d34b03fe22cec6ccb39675bb7b94a335c2b7be888fd3906a1125f33301d8aa6ec6ee6878f46f73961c8d57a3e9544d8ef2a2cbfd4d52da665b1266928cfe4cb347a58c412815f3b2d2369dec04b41ac9a71cc9547426d5ab941cccf3b18575637ccfb42df1a802df3cfe0a999f9e7109331170e3a221991bf868543960f8c816c28097e503fe319db10fb98049f3a57d7c80c420da66d56f3644371631fad3f0ff4040a19a4fedc2d07727a1b27576f75a4d28c47d8246f27071e12d7a8de62aad216ddbae6aa02efd6b8a3e2818cda48526549791ab277e447b3a36c57cefe9b592f5eab73959743fcc8e83cbefec03a329b55018b53eec196765ae40ef9e20521a603c551efe0303020950d53a146bf9c66034d00c23130cce95576a2ff78016ca471276e8227fb30b1ffbd92e61804fb0c3eff9e30b1a826ee8f3e4730b4d86273ca977b4164453412f456c47616d616c2054657374204b65792032886204131102002205024dfcb1be021b03060b090807030206150802090a0b0416020301021e01021780000a0910a86bf526325b21b22bd9009e34511620415c974750a20df5cb56b182f3b48e6600a0a9466cb1a1305a84953445f77d461593f1d42bc1b00200009d0157044dfcb1be1004009565a951da1ee87119d600c077198f1c1bceb0f7aa54552489298e41ff788fa8f0d43a69871f0f6f77ebdfb14a4260cf9fbeb65d5844b4272a1904dd95136d06c3da745dc46327dd44a0f16f60135914368c8039a34033862261806bb2c5ce1152e2840254697872c85441ccb7321431d75a747a4bfb1d2c66362b51ce76311700030503fc0ea76601c196768070b7365a200e6ddb09307f262d5f39eec467b5f5784e22abdf1aa49226f59ab37cb49969d8f5230ea65caf56015abda62604544ed526c5c522bf92bed178a078789f6c807b6d34885688024a5bed9e9f8c58d11d4b82487b44c5f470c5606806a0443b79cadb45e0f897a561a53f724e5349b9267c75ca17fe0303020950d53a146bf9c660bc5f4ce8f072465e2d2466434320c1e712272fafc20e342fe7608101580fa1a1a367e60486a7cd1246b7ef5586cf5e10b32762b710a30144f12dd17dd4884904181102000905024dfcb1be021b0c000a0910a86bf526325b21b2904c00a0b2b66b4b39ccffda1d10f3ea8d58f827e30a8b8e009f4255b2d8112a184e40cde43a34e8655ca7809370b0020000" + +const signedMessageHex = "a3019bc0cbccc0c4b8d8b74ee2108fe16ec6d3ca490cbe362d3f8333d3f352531472538b8b13d353b97232f352158c20943157c71c16064626063656269052062e4e01987e9b6fccff4b7df3a34c534b23e679cbec3bc0f8f6e64dfb4b55fe3f8efa9ce110ddb5cd79faf1d753c51aecfa669f7e7aa043436596cccc3359cb7dd6bbe9ecaa69e5989d9e57209571edc0b2fa7f57b9b79a64ee6e99ce1371395fee92fec2796f7b15a77c386ff668ee27f6d38f0baa6c438b561657377bf6acff3c5947befd7bf4c196252f1d6e5c524d0300" + +const signedTextMessageHex = "a3019bc0cbccc8c4b8d8b74ee2108fe16ec6d36a250cbece0c178233d3f352531472538b8b13d35379b97232f352158ca0b4312f57c71c1646462606365626906a062e4e019811591798ff99bf8afee860b0d8a8c2a85c3387e3bcf0bb3b17987f2bbcfab2aa526d930cbfd3d98757184df3995c9f3e7790e36e3e9779f06089d4c64e9e47dd6202cb6e9bc73c5d11bb59fbaf89d22d8dc7cf199ddf17af96e77c5f65f9bbed56f427bd8db7af37f6c9984bf9385efaf5f184f986fb3e6adb0ecfe35bbf92d16a7aa2a344fb0bc52fb7624f0200" + +const signedEncryptedMessageHex = "848c032a67d68660df41c70103ff5789d0de26b6a50c985a02a13131ca829c413a35d0e6fa8d6842599252162808ac7439c72151c8c6183e76923fe3299301414d0c25a2f06a2257db3839e7df0ec964773f6e4c4ac7ff3b48c444237166dd46ba8ff443a5410dc670cb486672fdbe7c9dfafb75b4fea83af3a204fe2a7dfa86bd20122b4f3d2646cbeecb8f7be8d2c03b018bd210b1d3791e1aba74b0f1034e122ab72e760492c192383cf5e20b5628bd043272d63df9b923f147eb6091cd897553204832aba48fec54aa447547bb16305a1024713b90e77fd0065f1918271947549205af3c74891af22ee0b56cd29bfec6d6e351901cd4ab3ece7c486f1e32a792d4e474aed98ee84b3f591c7dff37b64e0ecd68fd036d517e412dcadf85840ce184ad7921ad446c4ee28db80447aea1ca8d4f574db4d4e37688158ddd19e14ee2eab4873d46947d65d14a23e788d912cf9a19624ca7352469b72a83866b7c23cb5ace3deab3c7018061b0ba0f39ed2befe27163e5083cf9b8271e3e3d52cc7ad6e2a3bd81d4c3d7022f8d" + +const signedEncryptedMessage2Hex = "85010e03cf6a7abcd43e36731003fb057f5495b79db367e277cdbe4ab90d924ddee0c0381494112ff8c1238fb0184af35d1731573b01bc4c55ecacd2aafbe2003d36310487d1ecc9ac994f3fada7f9f7f5c3a64248ab7782906c82c6ff1303b69a84d9a9529c31ecafbcdb9ba87e05439897d87e8a2a3dec55e14df19bba7f7bd316291c002ae2efd24f83f9e3441203fc081c0c23dc3092a454ca8a082b27f631abf73aca341686982e8fbda7e0e7d863941d68f3de4a755c2964407f4b5e0477b3196b8c93d551dd23c8beef7d0f03fbb1b6066f78907faf4bf1677d8fcec72651124080e0b7feae6b476e72ab207d38d90b958759fdedfc3c6c35717c9dbfc979b3cfbbff0a76d24a5e57056bb88acbd2a901ef64bc6e4db02adc05b6250ff378de81dca18c1910ab257dff1b9771b85bb9bbe0a69f5989e6d1710a35e6dfcceb7d8fb5ccea8db3932b3d9ff3fe0d327597c68b3622aec8e3716c83a6c93f497543b459b58ba504ed6bcaa747d37d2ca746fe49ae0a6ce4a8b694234e941b5159ff8bd34b9023da2814076163b86f40eed7c9472f81b551452d5ab87004a373c0172ec87ea6ce42ccfa7dbdad66b745496c4873d8019e8c28d6b3" + +const symmetricallyEncryptedCompressedHex = "8c0d04030302eb4a03808145d0d260c92f714339e13de5a79881216431925bf67ee2898ea61815f07894cd0703c50d0a76ef64d482196f47a8bc729af9b80bb6" + +const dsaTestKeyHex = "9901a2044d6c49de110400cb5ce438cf9250907ac2ba5bf6547931270b89f7c4b53d9d09f4d0213a5ef2ec1f26806d3d259960f872a4a102ef1581ea3f6d6882d15134f21ef6a84de933cc34c47cc9106efe3bd84c6aec12e78523661e29bc1a61f0aab17fa58a627fd5fd33f5149153fbe8cd70edf3d963bc287ef875270ff14b5bfdd1bca4483793923b00a0fe46d76cb6e4cbdc568435cd5480af3266d610d303fe33ae8273f30a96d4d34f42fa28ce1112d425b2e3bf7ea553d526e2db6b9255e9dc7419045ce817214d1a0056dbc8d5289956a4b1b69f20f1105124096e6a438f41f2e2495923b0f34b70642607d45559595c7fe94d7fa85fc41bf7d68c1fd509ebeaa5f315f6059a446b9369c277597e4f474a9591535354c7e7f4fd98a08aa60400b130c24ff20bdfbf683313f5daebf1c9b34b3bdadfc77f2ddd72ee1fb17e56c473664bc21d66467655dd74b9005e3a2bacce446f1920cd7017231ae447b67036c9b431b8179deacd5120262d894c26bc015bffe3d827ba7087ad9b700d2ca1f6d16cc1786581e5dd065f293c31209300f9b0afcc3f7c08dd26d0a22d87580b4db41054657374204b65792033202844534129886204131102002205024d6c49de021b03060b090807030206150802090a0b0416020301021e01021780000a0910338934250ccc03607e0400a0bdb9193e8a6b96fc2dfc108ae848914b504481f100a09c4dc148cb693293a67af24dd40d2b13a9e36794" + +const dsaTestKeyPrivateHex = "9501bb044d6c49de110400cb5ce438cf9250907ac2ba5bf6547931270b89f7c4b53d9d09f4d0213a5ef2ec1f26806d3d259960f872a4a102ef1581ea3f6d6882d15134f21ef6a84de933cc34c47cc9106efe3bd84c6aec12e78523661e29bc1a61f0aab17fa58a627fd5fd33f5149153fbe8cd70edf3d963bc287ef875270ff14b5bfdd1bca4483793923b00a0fe46d76cb6e4cbdc568435cd5480af3266d610d303fe33ae8273f30a96d4d34f42fa28ce1112d425b2e3bf7ea553d526e2db6b9255e9dc7419045ce817214d1a0056dbc8d5289956a4b1b69f20f1105124096e6a438f41f2e2495923b0f34b70642607d45559595c7fe94d7fa85fc41bf7d68c1fd509ebeaa5f315f6059a446b9369c277597e4f474a9591535354c7e7f4fd98a08aa60400b130c24ff20bdfbf683313f5daebf1c9b34b3bdadfc77f2ddd72ee1fb17e56c473664bc21d66467655dd74b9005e3a2bacce446f1920cd7017231ae447b67036c9b431b8179deacd5120262d894c26bc015bffe3d827ba7087ad9b700d2ca1f6d16cc1786581e5dd065f293c31209300f9b0afcc3f7c08dd26d0a22d87580b4d00009f592e0619d823953577d4503061706843317e4fee083db41054657374204b65792033202844534129886204131102002205024d6c49de021b03060b090807030206150802090a0b0416020301021e01021780000a0910338934250ccc03607e0400a0bdb9193e8a6b96fc2dfc108ae848914b504481f100a09c4dc148cb693293a67af24dd40d2b13a9e36794" + +const p256TestKeyHex = "98520456e5b83813082a8648ce3d030107020304a2072cd6d21321266c758cc5b83fab0510f751cb8d91897cddb7047d8d6f185546e2107111b0a95cb8ef063c33245502af7a65f004d5919d93ee74eb71a66253b424502d3235362054657374204b6579203c696e76616c6964406578616d706c652e636f6d3e8879041313080021050256e5b838021b03050b09080702061508090a0b020416020301021e01021780000a0910d44a2c495918513e54e50100dfa64f97d9b47766fc1943c6314ba3f2b2a103d71ad286dc5b1efb96a345b0c80100dbc8150b54241f559da6ef4baacea6d31902b4f4b1bdc09b34bf0502334b7754b8560456e5b83812082a8648ce3d030107020304bfe3cea9cee13486f8d518aa487fecab451f25467d2bf08e58f63e5fa525d5482133e6a79299c274b068ef0be448152ad65cf11cf764348588ca4f6a0bcf22b6030108078861041813080009050256e5b838021b0c000a0910d44a2c495918513e4a4800ff49d589fa64024ad30be363a032e3a0e0e6f5db56ba4c73db850518bf0121b8f20100fd78e065f4c70ea5be9df319ea67e493b936fc78da834a71828043d3154af56e" + +const p256TestKeyPrivateHex = "94a50456e5b83813082a8648ce3d030107020304a2072cd6d21321266c758cc5b83fab0510f751cb8d91897cddb7047d8d6f185546e2107111b0a95cb8ef063c33245502af7a65f004d5919d93ee74eb71a66253fe070302f0c2bfb0b6c30f87ee1599472b8636477eab23ced13b271886a4b50ed34c9d8436af5af5b8f88921f0efba6ef8c37c459bbb88bc1c6a13bbd25c4ce9b1e97679569ee77645d469bf4b43de637f5561b424502d3235362054657374204b6579203c696e76616c6964406578616d706c652e636f6d3e8879041313080021050256e5b838021b03050b09080702061508090a0b020416020301021e01021780000a0910d44a2c495918513e54e50100dfa64f97d9b47766fc1943c6314ba3f2b2a103d71ad286dc5b1efb96a345b0c80100dbc8150b54241f559da6ef4baacea6d31902b4f4b1bdc09b34bf0502334b77549ca90456e5b83812082a8648ce3d030107020304bfe3cea9cee13486f8d518aa487fecab451f25467d2bf08e58f63e5fa525d5482133e6a79299c274b068ef0be448152ad65cf11cf764348588ca4f6a0bcf22b603010807fe0703027510012471a603cfee2968dce19f732721ddf03e966fd133b4e3c7a685b788705cbc46fb026dc94724b830c9edbaecd2fb2c662f23169516cacd1fe423f0475c364ecc10abcabcfd4bbbda1a36a1bd8861041813080009050256e5b838021b0c000a0910d44a2c495918513e4a4800ff49d589fa64024ad30be363a032e3a0e0e6f5db56ba4c73db850518bf0121b8f20100fd78e065f4c70ea5be9df319ea67e493b936fc78da834a71828043d3154af56e" + +const armoredPrivateKeyBlock = `-----BEGIN PGP PRIVATE KEY BLOCK----- +Version: GnuPG v1.4.10 (GNU/Linux) + +lQHYBE2rFNoBBADFwqWQIW/DSqcB4yCQqnAFTJ27qS5AnB46ccAdw3u4Greeu3Bp +idpoHdjULy7zSKlwR1EA873dO/k/e11Ml3dlAFUinWeejWaK2ugFP6JjiieSsrKn +vWNicdCS4HTWn0X4sjl0ZiAygw6GNhqEQ3cpLeL0g8E9hnYzJKQ0LWJa0QARAQAB +AAP/TB81EIo2VYNmTq0pK1ZXwUpxCrvAAIG3hwKjEzHcbQznsjNvPUihZ+NZQ6+X +0HCfPAdPkGDCLCb6NavcSW+iNnLTrdDnSI6+3BbIONqWWdRDYJhqZCkqmG6zqSfL +IdkJgCw94taUg5BWP/AAeQrhzjChvpMQTVKQL5mnuZbUCeMCAN5qrYMP2S9iKdnk +VANIFj7656ARKt/nf4CBzxcpHTyB8+d2CtPDKCmlJP6vL8t58Jmih+kHJMvC0dzn +gr5f5+sCAOOe5gt9e0am7AvQWhdbHVfJU0TQJx+m2OiCJAqGTB1nvtBLHdJnfdC9 +TnXXQ6ZXibqLyBies/xeY2sCKL5qtTMCAKnX9+9d/5yQxRyrQUHt1NYhaXZnJbHx +q4ytu0eWz+5i68IYUSK69jJ1NWPM0T6SkqpB3KCAIv68VFm9PxqG1KmhSrQIVGVz +dCBLZXmIuAQTAQIAIgUCTasU2gIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AA +CgkQO9o98PRieSoLhgQAkLEZex02Qt7vGhZzMwuN0R22w3VwyYyjBx+fM3JFETy1 +ut4xcLJoJfIaF5ZS38UplgakHG0FQ+b49i8dMij0aZmDqGxrew1m4kBfjXw9B/v+ +eIqpODryb6cOSwyQFH0lQkXC040pjq9YqDsO5w0WYNXYKDnzRV0p4H1pweo2VDid +AdgETasU2gEEAN46UPeWRqKHvA99arOxee38fBt2CI08iiWyI8T3J6ivtFGixSqV +bRcPxYO/qLpVe5l84Nb3X71GfVXlc9hyv7CD6tcowL59hg1E/DC5ydI8K8iEpUmK +/UnHdIY5h8/kqgGxkY/T/hgp5fRQgW1ZoZxLajVlMRZ8W4tFtT0DeA+JABEBAAEA +A/0bE1jaaZKj6ndqcw86jd+QtD1SF+Cf21CWRNeLKnUds4FRRvclzTyUMuWPkUeX +TaNNsUOFqBsf6QQ2oHUBBK4VCHffHCW4ZEX2cd6umz7mpHW6XzN4DECEzOVksXtc +lUC1j4UB91DC/RNQqwX1IV2QLSwssVotPMPqhOi0ZLNY7wIA3n7DWKInxYZZ4K+6 +rQ+POsz6brEoRHwr8x6XlHenq1Oki855pSa1yXIARoTrSJkBtn5oI+f8AzrnN0BN +oyeQAwIA/7E++3HDi5aweWrViiul9cd3rcsS0dEnksPhvS0ozCJiHsq/6GFmy7J8 +QSHZPteedBnZyNp5jR+H7cIfVN3KgwH/Skq4PsuPhDq5TKK6i8Pc1WW8MA6DXTdU +nLkX7RGmMwjC0DBf7KWAlPjFaONAX3a8ndnz//fy1q7u2l9AZwrj1qa1iJ8EGAEC +AAkFAk2rFNoCGwwACgkQO9o98PRieSo2/QP/WTzr4ioINVsvN1akKuekmEMI3LAp +BfHwatufxxP1U+3Si/6YIk7kuPB9Hs+pRqCXzbvPRrI8NHZBmc8qIGthishdCYad +AHcVnXjtxrULkQFGbGvhKURLvS9WnzD/m1K2zzwxzkPTzT9/Yf06O6Mal5AdugPL +VrM0m72/jnpKo04= +=zNCn +-----END PGP PRIVATE KEY BLOCK-----` + +const e2ePublicKey = `-----BEGIN PGP PUBLIC KEY BLOCK----- +Charset: UTF-8 + +xv8AAABSBAAAAAATCCqGSM49AwEHAgME1LRoXSpOxtHXDUdmuvzchyg6005qIBJ4 +sfaSxX7QgH9RV2ONUhC+WiayCNADq+UMzuR/vunSr4aQffXvuGnR383/AAAAFDxk +Z2lsQHlhaG9vLWluYy5jb20+wv8AAACGBBATCAA4/wAAAAWCVGvAG/8AAAACiwn/ +AAAACZC2VkQCOjdvYf8AAAAFlQgJCgv/AAAAA5YBAv8AAAACngEAAE1BAP0X8veD +24IjmI5/C6ZAfVNXxgZZFhTAACFX75jUA3oD6AEAzoSwKf1aqH6oq62qhCN/pekX ++WAsVMBhNwzLpqtCRjLO/wAAAFYEAAAAABIIKoZIzj0DAQcCAwT50ain7vXiIRv8 +B1DO3x3cE/aattZ5sHNixJzRCXi2vQIA5QmOxZ6b5jjUekNbdHG3SZi1a2Ak5mfX +fRxC/5VGAwEIB8L/AAAAZQQYEwgAGP8AAAAFglRrwBz/AAAACZC2VkQCOjdvYQAA +FJAA9isX3xtGyMLYwp2F3nXm7QEdY5bq5VUcD/RJlj792VwA/1wH0pCzVLl4Q9F9 +ex7En5r7rHR5xwX82Msc+Rq9dSyO +=7MrZ +-----END PGP PUBLIC KEY BLOCK-----` + +const dsaKeyWithSHA512 = `9901a2044f04b07f110400db244efecc7316553ee08d179972aab87bb1214de7692593fcf5b6feb1c80fba268722dd464748539b85b81d574cd2d7ad0ca2444de4d849b8756bad7768c486c83a824f9bba4af773d11742bdfb4ac3b89ef8cc9452d4aad31a37e4b630d33927bff68e879284a1672659b8b298222fc68f370f3e24dccacc4a862442b9438b00a0ea444a24088dc23e26df7daf8f43cba3bffc4fe703fe3d6cd7fdca199d54ed8ae501c30e3ec7871ea9cdd4cf63cfe6fc82281d70a5b8bb493f922cd99fba5f088935596af087c8d818d5ec4d0b9afa7f070b3d7c1dd32a84fca08d8280b4890c8da1dde334de8e3cad8450eed2a4a4fcc2db7b8e5528b869a74a7f0189e11ef097ef1253582348de072bb07a9fa8ab838e993cef0ee203ff49298723e2d1f549b00559f886cd417a41692ce58d0ac1307dc71d85a8af21b0cf6eaa14baf2922d3a70389bedf17cc514ba0febbd107675a372fe84b90162a9e88b14d4b1c6be855b96b33fb198c46f058568817780435b6936167ebb3724b680f32bf27382ada2e37a879b3d9de2abe0c3f399350afd1ad438883f4791e2e3b4184453412068617368207472756e636174696f6e207465737488620413110a002205024f04b07f021b03060b090807030206150802090a0b0416020301021e01021780000a0910ef20e0cefca131581318009e2bf3bf047a44d75a9bacd00161ee04d435522397009a03a60d51bd8a568c6c021c8d7cf1be8d990d6417b0020003` + +const unknownHashFunctionHex = `8a00000040040001990006050253863c24000a09103b4fe6acc0b21f32ffff01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101` + +const missingHashFunctionHex = `8a00000040040001030006050253863c24000a09103b4fe6acc0b21f32ffff0101010101010101010101010101010101010101010101010101010101010101010101010101` + +const campbellQuine = `a0b001000300fcffa0b001000d00f2ff000300fcffa0b001000d00f2ff8270a01c00000500faff8270a01c00000500faff000500faff001400ebff8270a01c00000500faff000500faff001400ebff428821c400001400ebff428821c400001400ebff428821c400001400ebff428821c400001400ebff428821c400000000ffff000000ffff000b00f4ff428821c400000000ffff000000ffff000b00f4ff0233214c40000100feff000233214c40000100feff0000` + +const keyV4forVerifyingSignedMessageV3 = `-----BEGIN PGP PUBLIC KEY BLOCK----- +Comment: GPGTools - https://gpgtools.org + +mI0EVfxoFQEEAMBIqmbDfYygcvP6Phr1wr1XI41IF7Qixqybs/foBF8qqblD9gIY +BKpXjnBOtbkcVOJ0nljd3/sQIfH4E0vQwK5/4YRQSI59eKOqd6Fx+fWQOLG+uu6z +tewpeCj9LLHvibx/Sc7VWRnrznia6ftrXxJ/wHMezSab3tnGC0YPVdGNABEBAAG0 +JEdvY3J5cHRvIFRlc3QgS2V5IDx0aGVtYXhAZ21haWwuY29tPoi5BBMBCgAjBQJV +/GgVAhsDBwsJCAcDAgEGFQgCCQoLBBYCAwECHgECF4AACgkQeXnQmhdGW9PFVAP+ +K7TU0qX5ArvIONIxh/WAweyOk884c5cE8f+3NOPOOCRGyVy0FId5A7MmD5GOQh4H +JseOZVEVCqlmngEvtHZb3U1VYtVGE5WZ+6rQhGsMcWP5qaT4soYwMBlSYxgYwQcx +YhN9qOr292f9j2Y//TTIJmZT4Oa+lMxhWdqTfX+qMgG4jQRV/GgVAQQArhFSiij1 +b+hT3dnapbEU+23Z1yTu1DfF6zsxQ4XQWEV3eR8v+8mEDDNcz8oyyF56k6UQ3rXi +UMTIwRDg4V6SbZmaFbZYCOwp/EmXJ3rfhm7z7yzXj2OFN22luuqbyVhuL7LRdB0M +pxgmjXb4tTvfgKd26x34S+QqUJ7W6uprY4sAEQEAAYifBBgBCgAJBQJV/GgVAhsM +AAoJEHl50JoXRlvT7y8D/02ckx4OMkKBZo7viyrBw0MLG92i+DC2bs35PooHR6zz +786mitjOp5z2QWNLBvxC70S0qVfCIz8jKupO1J6rq6Z8CcbLF3qjm6h1omUBf8Nd +EfXKD2/2HV6zMKVknnKzIEzauh+eCKS2CeJUSSSryap/QLVAjRnckaES/OsEWhNB +=RZia +-----END PGP PUBLIC KEY BLOCK----- +` + +const signedMessageV3 = `-----BEGIN PGP MESSAGE----- +Comment: GPGTools - https://gpgtools.org + +owGbwMvMwMVYWXlhlrhb9GXG03JJDKF/MtxDMjKLFYAoUaEktbhEITe1uDgxPVWP +q5NhKjMrWAVcC9evD8z/bF/uWNjqtk/X3y5/38XGRQHm/57rrDRYuGnTw597Xqka +uM3137/hH3Os+Jf2dc0fXOITKwJvXJvecPVs0ta+Vg7ZO1MLn8w58Xx+6L58mbka +DGHyU9yTueZE8D+QF/Tz28Y78dqtF56R1VPn9Xw4uJqrWYdd7b3vIZ1V6R4Nh05d +iT57d/OhWwA= +=hG7R +-----END PGP MESSAGE----- +` diff --git a/vendor/golang.org/x/crypto/openpgp/s2k/s2k.go b/vendor/golang.org/x/crypto/openpgp/s2k/s2k.go new file mode 100644 index 0000000000000000000000000000000000000000..4b9a44ca26d65abf31236ce61638fb9f37d688d6 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/s2k/s2k.go @@ -0,0 +1,273 @@ +// 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 s2k implements the various OpenPGP string-to-key transforms as +// specified in RFC 4800 section 3.7.1. +package s2k // import "golang.org/x/crypto/openpgp/s2k" + +import ( + "crypto" + "hash" + "io" + "strconv" + + "golang.org/x/crypto/openpgp/errors" +) + +// Config collects configuration parameters for s2k key-stretching +// transformatioms. A nil *Config is valid and results in all default +// values. Currently, Config is used only by the Serialize function in +// this package. +type Config struct { + // Hash is the default hash function to be used. If + // nil, SHA1 is used. + Hash crypto.Hash + // S2KCount is only used for symmetric encryption. It + // determines the strength of the passphrase stretching when + // the said passphrase is hashed to produce a key. S2KCount + // should be between 1024 and 65011712, inclusive. If Config + // is nil or S2KCount is 0, the value 65536 used. Not all + // values in the above range can be represented. S2KCount will + // be rounded up to the next representable value if it cannot + // be encoded exactly. When set, it is strongly encrouraged to + // use a value that is at least 65536. See RFC 4880 Section + // 3.7.1.3. + S2KCount int +} + +func (c *Config) hash() crypto.Hash { + if c == nil || uint(c.Hash) == 0 { + // SHA1 is the historical default in this package. + return crypto.SHA1 + } + + return c.Hash +} + +func (c *Config) encodedCount() uint8 { + if c == nil || c.S2KCount == 0 { + return 96 // The common case. Correspoding to 65536 + } + + i := c.S2KCount + switch { + // Behave like GPG. Should we make 65536 the lowest value used? + case i < 1024: + i = 1024 + case i > 65011712: + i = 65011712 + } + + return encodeCount(i) +} + +// encodeCount converts an iterative "count" in the range 1024 to +// 65011712, inclusive, to an encoded count. The return value is the +// octet that is actually stored in the GPG file. encodeCount panics +// if i is not in the above range (encodedCount above takes care to +// pass i in the correct range). See RFC 4880 Section 3.7.7.1. +func encodeCount(i int) uint8 { + if i < 1024 || i > 65011712 { + panic("count arg i outside the required range") + } + + for encoded := 0; encoded < 256; encoded++ { + count := decodeCount(uint8(encoded)) + if count >= i { + return uint8(encoded) + } + } + + return 255 +} + +// decodeCount returns the s2k mode 3 iterative "count" corresponding to +// the encoded octet c. +func decodeCount(c uint8) int { + return (16 + int(c&15)) << (uint32(c>>4) + 6) +} + +// Simple writes to out the result of computing the Simple S2K function (RFC +// 4880, section 3.7.1.1) using the given hash and input passphrase. +func Simple(out []byte, h hash.Hash, in []byte) { + Salted(out, h, in, nil) +} + +var zero [1]byte + +// Salted writes to out the result of computing the Salted S2K function (RFC +// 4880, section 3.7.1.2) using the given hash, input passphrase and salt. +func Salted(out []byte, h hash.Hash, in []byte, salt []byte) { + done := 0 + var digest []byte + + for i := 0; done < len(out); i++ { + h.Reset() + for j := 0; j < i; j++ { + h.Write(zero[:]) + } + h.Write(salt) + h.Write(in) + digest = h.Sum(digest[:0]) + n := copy(out[done:], digest) + done += n + } +} + +// Iterated writes to out the result of computing the Iterated and Salted S2K +// function (RFC 4880, section 3.7.1.3) using the given hash, input passphrase, +// salt and iteration count. +func Iterated(out []byte, h hash.Hash, in []byte, salt []byte, count int) { + combined := make([]byte, len(in)+len(salt)) + copy(combined, salt) + copy(combined[len(salt):], in) + + if count < len(combined) { + count = len(combined) + } + + done := 0 + var digest []byte + for i := 0; done < len(out); i++ { + h.Reset() + for j := 0; j < i; j++ { + h.Write(zero[:]) + } + written := 0 + for written < count { + if written+len(combined) > count { + todo := count - written + h.Write(combined[:todo]) + written = count + } else { + h.Write(combined) + written += len(combined) + } + } + digest = h.Sum(digest[:0]) + n := copy(out[done:], digest) + done += n + } +} + +// Parse reads a binary specification for a string-to-key transformation from r +// and returns a function which performs that transform. +func Parse(r io.Reader) (f func(out, in []byte), err error) { + var buf [9]byte + + _, err = io.ReadFull(r, buf[:2]) + if err != nil { + return + } + + hash, ok := HashIdToHash(buf[1]) + if !ok { + return nil, errors.UnsupportedError("hash for S2K function: " + strconv.Itoa(int(buf[1]))) + } + if !hash.Available() { + return nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hash))) + } + h := hash.New() + + switch buf[0] { + case 0: + f := func(out, in []byte) { + Simple(out, h, in) + } + return f, nil + case 1: + _, err = io.ReadFull(r, buf[:8]) + if err != nil { + return + } + f := func(out, in []byte) { + Salted(out, h, in, buf[:8]) + } + return f, nil + case 3: + _, err = io.ReadFull(r, buf[:9]) + if err != nil { + return + } + count := decodeCount(buf[8]) + f := func(out, in []byte) { + Iterated(out, h, in, buf[:8], count) + } + return f, nil + } + + return nil, errors.UnsupportedError("S2K function") +} + +// Serialize salts and stretches the given passphrase and writes the +// resulting key into key. It also serializes an S2K descriptor to +// w. The key stretching can be configured with c, which may be +// nil. In that case, sensible defaults will be used. +func Serialize(w io.Writer, key []byte, rand io.Reader, passphrase []byte, c *Config) error { + var buf [11]byte + buf[0] = 3 /* iterated and salted */ + buf[1], _ = HashToHashId(c.hash()) + salt := buf[2:10] + if _, err := io.ReadFull(rand, salt); err != nil { + return err + } + encodedCount := c.encodedCount() + count := decodeCount(encodedCount) + buf[10] = encodedCount + if _, err := w.Write(buf[:]); err != nil { + return err + } + + Iterated(key, c.hash().New(), passphrase, salt, count) + return nil +} + +// hashToHashIdMapping contains pairs relating OpenPGP's hash identifier with +// Go's crypto.Hash type. See RFC 4880, section 9.4. +var hashToHashIdMapping = []struct { + id byte + hash crypto.Hash + name string +}{ + {1, crypto.MD5, "MD5"}, + {2, crypto.SHA1, "SHA1"}, + {3, crypto.RIPEMD160, "RIPEMD160"}, + {8, crypto.SHA256, "SHA256"}, + {9, crypto.SHA384, "SHA384"}, + {10, crypto.SHA512, "SHA512"}, + {11, crypto.SHA224, "SHA224"}, +} + +// HashIdToHash returns a crypto.Hash which corresponds to the given OpenPGP +// hash id. +func HashIdToHash(id byte) (h crypto.Hash, ok bool) { + for _, m := range hashToHashIdMapping { + if m.id == id { + return m.hash, true + } + } + return 0, false +} + +// HashIdToString returns the name of the hash function corresponding to the +// given OpenPGP hash id. +func HashIdToString(id byte) (name string, ok bool) { + for _, m := range hashToHashIdMapping { + if m.id == id { + return m.name, true + } + } + + return "", false +} + +// HashIdToHash returns an OpenPGP hash id which corresponds the given Hash. +func HashToHashId(h crypto.Hash) (id byte, ok bool) { + for _, m := range hashToHashIdMapping { + if m.hash == h { + return m.id, true + } + } + return 0, false +} diff --git a/vendor/golang.org/x/crypto/openpgp/s2k/s2k_test.go b/vendor/golang.org/x/crypto/openpgp/s2k/s2k_test.go new file mode 100644 index 0000000000000000000000000000000000000000..183d26056b11e412f5f7b59af0dfaacfaec3b781 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/s2k/s2k_test.go @@ -0,0 +1,137 @@ +// 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 s2k + +import ( + "bytes" + "crypto" + _ "crypto/md5" + "crypto/rand" + "crypto/sha1" + _ "crypto/sha256" + _ "crypto/sha512" + "encoding/hex" + "testing" + + _ "golang.org/x/crypto/ripemd160" +) + +var saltedTests = []struct { + in, out string +}{ + {"hello", "10295ac1"}, + {"world", "ac587a5e"}, + {"foo", "4dda8077"}, + {"bar", "bd8aac6b9ea9cae04eae6a91c6133b58b5d9a61c14f355516ed9370456"}, + {"x", "f1d3f289"}, + {"xxxxxxxxxxxxxxxxxxxxxxx", "e00d7b45"}, +} + +func TestSalted(t *testing.T) { + h := sha1.New() + salt := [4]byte{1, 2, 3, 4} + + for i, test := range saltedTests { + expected, _ := hex.DecodeString(test.out) + out := make([]byte, len(expected)) + Salted(out, h, []byte(test.in), salt[:]) + if !bytes.Equal(expected, out) { + t.Errorf("#%d, got: %x want: %x", i, out, expected) + } + } +} + +var iteratedTests = []struct { + in, out string +}{ + {"hello", "83126105"}, + {"world", "6fa317f9"}, + {"foo", "8fbc35b9"}, + {"bar", "2af5a99b54f093789fd657f19bd245af7604d0f6ae06f66602a46a08ae"}, + {"x", "5a684dfe"}, + {"xxxxxxxxxxxxxxxxxxxxxxx", "18955174"}, +} + +func TestIterated(t *testing.T) { + h := sha1.New() + salt := [4]byte{4, 3, 2, 1} + + for i, test := range iteratedTests { + expected, _ := hex.DecodeString(test.out) + out := make([]byte, len(expected)) + Iterated(out, h, []byte(test.in), salt[:], 31) + if !bytes.Equal(expected, out) { + t.Errorf("#%d, got: %x want: %x", i, out, expected) + } + } +} + +var parseTests = []struct { + spec, in, out string +}{ + /* Simple with SHA1 */ + {"0002", "hello", "aaf4c61d"}, + /* Salted with SHA1 */ + {"01020102030405060708", "hello", "f4f7d67e"}, + /* Iterated with SHA1 */ + {"03020102030405060708f1", "hello", "f2a57b7c"}, +} + +func TestParse(t *testing.T) { + for i, test := range parseTests { + spec, _ := hex.DecodeString(test.spec) + buf := bytes.NewBuffer(spec) + f, err := Parse(buf) + if err != nil { + t.Errorf("%d: Parse returned error: %s", i, err) + continue + } + + expected, _ := hex.DecodeString(test.out) + out := make([]byte, len(expected)) + f(out, []byte(test.in)) + if !bytes.Equal(out, expected) { + t.Errorf("%d: output got: %x want: %x", i, out, expected) + } + if testing.Short() { + break + } + } +} + +func TestSerialize(t *testing.T) { + hashes := []crypto.Hash{crypto.MD5, crypto.SHA1, crypto.RIPEMD160, + crypto.SHA256, crypto.SHA384, crypto.SHA512, crypto.SHA224} + testCounts := []int{-1, 0, 1024, 65536, 4063232, 65011712} + for _, h := range hashes { + for _, c := range testCounts { + testSerializeConfig(t, &Config{Hash: h, S2KCount: c}) + } + } +} + +func testSerializeConfig(t *testing.T, c *Config) { + t.Logf("Running testSerializeConfig() with config: %+v", c) + + buf := bytes.NewBuffer(nil) + key := make([]byte, 16) + passphrase := []byte("testing") + err := Serialize(buf, key, rand.Reader, passphrase, c) + if err != nil { + t.Errorf("failed to serialize: %s", err) + return + } + + f, err := Parse(buf) + if err != nil { + t.Errorf("failed to reparse: %s", err) + return + } + key2 := make([]byte, len(key)) + f(key2, passphrase) + if !bytes.Equal(key2, key) { + t.Errorf("keys don't match: %x (serialied) vs %x (parsed)", key, key2) + } +} diff --git a/vendor/golang.org/x/crypto/openpgp/write.go b/vendor/golang.org/x/crypto/openpgp/write.go new file mode 100644 index 0000000000000000000000000000000000000000..65a304cc8679662991f1e865a97bf7976f62410f --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/write.go @@ -0,0 +1,378 @@ +// 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 openpgp + +import ( + "crypto" + "hash" + "io" + "strconv" + "time" + + "golang.org/x/crypto/openpgp/armor" + "golang.org/x/crypto/openpgp/errors" + "golang.org/x/crypto/openpgp/packet" + "golang.org/x/crypto/openpgp/s2k" +) + +// DetachSign signs message with the private key from signer (which must +// already have been decrypted) and writes the signature to w. +// If config is nil, sensible defaults will be used. +func DetachSign(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error { + return detachSign(w, signer, message, packet.SigTypeBinary, config) +} + +// ArmoredDetachSign signs message with the private key from signer (which +// must already have been decrypted) and writes an armored signature to w. +// If config is nil, sensible defaults will be used. +func ArmoredDetachSign(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) (err error) { + return armoredDetachSign(w, signer, message, packet.SigTypeBinary, config) +} + +// DetachSignText signs message (after canonicalising the line endings) with +// the private key from signer (which must already have been decrypted) and +// writes the signature to w. +// If config is nil, sensible defaults will be used. +func DetachSignText(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error { + return detachSign(w, signer, message, packet.SigTypeText, config) +} + +// ArmoredDetachSignText signs message (after canonicalising the line endings) +// with the private key from signer (which must already have been decrypted) +// and writes an armored signature to w. +// If config is nil, sensible defaults will be used. +func ArmoredDetachSignText(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error { + return armoredDetachSign(w, signer, message, packet.SigTypeText, config) +} + +func armoredDetachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType, config *packet.Config) (err error) { + out, err := armor.Encode(w, SignatureType, nil) + if err != nil { + return + } + err = detachSign(out, signer, message, sigType, config) + if err != nil { + return + } + return out.Close() +} + +func detachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType, config *packet.Config) (err error) { + if signer.PrivateKey == nil { + return errors.InvalidArgumentError("signing key doesn't have a private key") + } + if signer.PrivateKey.Encrypted { + return errors.InvalidArgumentError("signing key is encrypted") + } + + sig := new(packet.Signature) + sig.SigType = sigType + sig.PubKeyAlgo = signer.PrivateKey.PubKeyAlgo + sig.Hash = config.Hash() + sig.CreationTime = config.Now() + sig.IssuerKeyId = &signer.PrivateKey.KeyId + + h, wrappedHash, err := hashForSignature(sig.Hash, sig.SigType) + if err != nil { + return + } + io.Copy(wrappedHash, message) + + err = sig.Sign(h, signer.PrivateKey, config) + if err != nil { + return + } + + return sig.Serialize(w) +} + +// FileHints contains metadata about encrypted files. This metadata is, itself, +// encrypted. +type FileHints struct { + // IsBinary can be set to hint that the contents are binary data. + IsBinary bool + // FileName hints at the name of the file that should be written. It's + // truncated to 255 bytes if longer. It may be empty to suggest that the + // file should not be written to disk. It may be equal to "_CONSOLE" to + // suggest the data should not be written to disk. + FileName string + // ModTime contains the modification time of the file, or the zero time if not applicable. + ModTime time.Time +} + +// SymmetricallyEncrypt acts like gpg -c: it encrypts a file with a passphrase. +// The resulting WriteCloser must be closed after the contents of the file have +// been written. +// If config is nil, sensible defaults will be used. +func SymmetricallyEncrypt(ciphertext io.Writer, passphrase []byte, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) { + if hints == nil { + hints = &FileHints{} + } + + key, err := packet.SerializeSymmetricKeyEncrypted(ciphertext, passphrase, config) + if err != nil { + return + } + w, err := packet.SerializeSymmetricallyEncrypted(ciphertext, config.Cipher(), key, config) + if err != nil { + return + } + + literaldata := w + if algo := config.Compression(); algo != packet.CompressionNone { + var compConfig *packet.CompressionConfig + if config != nil { + compConfig = config.CompressionConfig + } + literaldata, err = packet.SerializeCompressed(w, algo, compConfig) + if err != nil { + return + } + } + + var epochSeconds uint32 + if !hints.ModTime.IsZero() { + epochSeconds = uint32(hints.ModTime.Unix()) + } + return packet.SerializeLiteral(literaldata, hints.IsBinary, hints.FileName, epochSeconds) +} + +// intersectPreferences mutates and returns a prefix of a that contains only +// the values in the intersection of a and b. The order of a is preserved. +func intersectPreferences(a []uint8, b []uint8) (intersection []uint8) { + var j int + for _, v := range a { + for _, v2 := range b { + if v == v2 { + a[j] = v + j++ + break + } + } + } + + return a[:j] +} + +func hashToHashId(h crypto.Hash) uint8 { + v, ok := s2k.HashToHashId(h) + if !ok { + panic("tried to convert unknown hash") + } + return v +} + +// Encrypt encrypts a message to a number of recipients and, optionally, signs +// it. hints contains optional information, that is also encrypted, that aids +// the recipients in processing the message. The resulting WriteCloser must +// be closed after the contents of the file have been written. +// If config is nil, sensible defaults will be used. +func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) { + var signer *packet.PrivateKey + if signed != nil { + signKey, ok := signed.signingKey(config.Now()) + if !ok { + return nil, errors.InvalidArgumentError("no valid signing keys") + } + signer = signKey.PrivateKey + if signer == nil { + return nil, errors.InvalidArgumentError("no private key in signing key") + } + if signer.Encrypted { + return nil, errors.InvalidArgumentError("signing key must be decrypted") + } + } + + // These are the possible ciphers that we'll use for the message. + candidateCiphers := []uint8{ + uint8(packet.CipherAES128), + uint8(packet.CipherAES256), + uint8(packet.CipherCAST5), + } + // These are the possible hash functions that we'll use for the signature. + candidateHashes := []uint8{ + hashToHashId(crypto.SHA256), + hashToHashId(crypto.SHA512), + hashToHashId(crypto.SHA1), + hashToHashId(crypto.RIPEMD160), + } + // In the event that a recipient doesn't specify any supported ciphers + // or hash functions, these are the ones that we assume that every + // implementation supports. + defaultCiphers := candidateCiphers[len(candidateCiphers)-1:] + defaultHashes := candidateHashes[len(candidateHashes)-1:] + + encryptKeys := make([]Key, len(to)) + for i := range to { + var ok bool + encryptKeys[i], ok = to[i].encryptionKey(config.Now()) + if !ok { + return nil, errors.InvalidArgumentError("cannot encrypt a message to key id " + strconv.FormatUint(to[i].PrimaryKey.KeyId, 16) + " because it has no encryption keys") + } + + sig := to[i].primaryIdentity().SelfSignature + + preferredSymmetric := sig.PreferredSymmetric + if len(preferredSymmetric) == 0 { + preferredSymmetric = defaultCiphers + } + preferredHashes := sig.PreferredHash + if len(preferredHashes) == 0 { + preferredHashes = defaultHashes + } + candidateCiphers = intersectPreferences(candidateCiphers, preferredSymmetric) + candidateHashes = intersectPreferences(candidateHashes, preferredHashes) + } + + if len(candidateCiphers) == 0 || len(candidateHashes) == 0 { + return nil, errors.InvalidArgumentError("cannot encrypt because recipient set shares no common algorithms") + } + + cipher := packet.CipherFunction(candidateCiphers[0]) + // If the cipher specified by config is a candidate, we'll use that. + configuredCipher := config.Cipher() + for _, c := range candidateCiphers { + cipherFunc := packet.CipherFunction(c) + if cipherFunc == configuredCipher { + cipher = cipherFunc + break + } + } + + var hash crypto.Hash + for _, hashId := range candidateHashes { + if h, ok := s2k.HashIdToHash(hashId); ok && h.Available() { + hash = h + break + } + } + + // If the hash specified by config is a candidate, we'll use that. + if configuredHash := config.Hash(); configuredHash.Available() { + for _, hashId := range candidateHashes { + if h, ok := s2k.HashIdToHash(hashId); ok && h == configuredHash { + hash = h + break + } + } + } + + if hash == 0 { + hashId := candidateHashes[0] + name, ok := s2k.HashIdToString(hashId) + if !ok { + name = "#" + strconv.Itoa(int(hashId)) + } + return nil, errors.InvalidArgumentError("cannot encrypt because no candidate hash functions are compiled in. (Wanted " + name + " in this case.)") + } + + symKey := make([]byte, cipher.KeySize()) + if _, err := io.ReadFull(config.Random(), symKey); err != nil { + return nil, err + } + + for _, key := range encryptKeys { + if err := packet.SerializeEncryptedKey(ciphertext, key.PublicKey, cipher, symKey, config); err != nil { + return nil, err + } + } + + encryptedData, err := packet.SerializeSymmetricallyEncrypted(ciphertext, cipher, symKey, config) + if err != nil { + return + } + + if signer != nil { + ops := &packet.OnePassSignature{ + SigType: packet.SigTypeBinary, + Hash: hash, + PubKeyAlgo: signer.PubKeyAlgo, + KeyId: signer.KeyId, + IsLast: true, + } + if err := ops.Serialize(encryptedData); err != nil { + return nil, err + } + } + + if hints == nil { + hints = &FileHints{} + } + + w := encryptedData + if signer != nil { + // If we need to write a signature packet after the literal + // data then we need to stop literalData from closing + // encryptedData. + w = noOpCloser{encryptedData} + + } + var epochSeconds uint32 + if !hints.ModTime.IsZero() { + epochSeconds = uint32(hints.ModTime.Unix()) + } + literalData, err := packet.SerializeLiteral(w, hints.IsBinary, hints.FileName, epochSeconds) + if err != nil { + return nil, err + } + + if signer != nil { + return signatureWriter{encryptedData, literalData, hash, hash.New(), signer, config}, nil + } + return literalData, nil +} + +// signatureWriter hashes the contents of a message while passing it along to +// literalData. When closed, it closes literalData, writes a signature packet +// to encryptedData and then also closes encryptedData. +type signatureWriter struct { + encryptedData io.WriteCloser + literalData io.WriteCloser + hashType crypto.Hash + h hash.Hash + signer *packet.PrivateKey + config *packet.Config +} + +func (s signatureWriter) Write(data []byte) (int, error) { + s.h.Write(data) + return s.literalData.Write(data) +} + +func (s signatureWriter) Close() error { + sig := &packet.Signature{ + SigType: packet.SigTypeBinary, + PubKeyAlgo: s.signer.PubKeyAlgo, + Hash: s.hashType, + CreationTime: s.config.Now(), + IssuerKeyId: &s.signer.KeyId, + } + + if err := sig.Sign(s.h, s.signer, s.config); err != nil { + return err + } + if err := s.literalData.Close(); err != nil { + return err + } + if err := sig.Serialize(s.encryptedData); err != nil { + return err + } + return s.encryptedData.Close() +} + +// noOpCloser is like an ioutil.NopCloser, but for an io.Writer. +// TODO: we have two of these in OpenPGP packages alone. This probably needs +// to be promoted somewhere more common. +type noOpCloser struct { + w io.Writer +} + +func (c noOpCloser) Write(data []byte) (n int, err error) { + return c.w.Write(data) +} + +func (c noOpCloser) Close() error { + return nil +} diff --git a/vendor/golang.org/x/crypto/openpgp/write_test.go b/vendor/golang.org/x/crypto/openpgp/write_test.go new file mode 100644 index 0000000000000000000000000000000000000000..f2d50a0cff069342d00469588f258c27589cd342 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/write_test.go @@ -0,0 +1,273 @@ +// 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 openpgp + +import ( + "bytes" + "io" + "io/ioutil" + "testing" + "time" + + "golang.org/x/crypto/openpgp/packet" +) + +func TestSignDetached(t *testing.T) { + kring, _ := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex)) + out := bytes.NewBuffer(nil) + message := bytes.NewBufferString(signedInput) + err := DetachSign(out, kring[0], message, nil) + if err != nil { + t.Error(err) + } + + testDetachedSignature(t, kring, out, signedInput, "check", testKey1KeyId) +} + +func TestSignTextDetached(t *testing.T) { + kring, _ := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex)) + out := bytes.NewBuffer(nil) + message := bytes.NewBufferString(signedInput) + err := DetachSignText(out, kring[0], message, nil) + if err != nil { + t.Error(err) + } + + testDetachedSignature(t, kring, out, signedInput, "check", testKey1KeyId) +} + +func TestSignDetachedDSA(t *testing.T) { + kring, _ := ReadKeyRing(readerFromHex(dsaTestKeyPrivateHex)) + out := bytes.NewBuffer(nil) + message := bytes.NewBufferString(signedInput) + err := DetachSign(out, kring[0], message, nil) + if err != nil { + t.Error(err) + } + + testDetachedSignature(t, kring, out, signedInput, "check", testKey3KeyId) +} + +func TestSignDetachedP256(t *testing.T) { + kring, _ := ReadKeyRing(readerFromHex(p256TestKeyPrivateHex)) + kring[0].PrivateKey.Decrypt([]byte("passphrase")) + + out := bytes.NewBuffer(nil) + message := bytes.NewBufferString(signedInput) + err := DetachSign(out, kring[0], message, nil) + if err != nil { + t.Error(err) + } + + testDetachedSignature(t, kring, out, signedInput, "check", testKeyP256KeyId) +} + +func TestNewEntity(t *testing.T) { + if testing.Short() { + return + } + + // Check bit-length with no config. + e, err := NewEntity("Test User", "test", "test@example.com", nil) + if err != nil { + t.Errorf("failed to create entity: %s", err) + return + } + bl, err := e.PrimaryKey.BitLength() + if err != nil { + t.Errorf("failed to find bit length: %s", err) + } + if int(bl) != defaultRSAKeyBits { + t.Errorf("BitLength %v, expected %v", int(bl), defaultRSAKeyBits) + } + + // Check bit-length with a config. + cfg := &packet.Config{RSABits: 1024} + e, err = NewEntity("Test User", "test", "test@example.com", cfg) + if err != nil { + t.Errorf("failed to create entity: %s", err) + return + } + bl, err = e.PrimaryKey.BitLength() + if err != nil { + t.Errorf("failed to find bit length: %s", err) + } + if int(bl) != cfg.RSABits { + t.Errorf("BitLength %v, expected %v", bl, cfg.RSABits) + } + + w := bytes.NewBuffer(nil) + if err := e.SerializePrivate(w, nil); err != nil { + t.Errorf("failed to serialize entity: %s", err) + return + } + serialized := w.Bytes() + + el, err := ReadKeyRing(w) + if err != nil { + t.Errorf("failed to reparse entity: %s", err) + return + } + + if len(el) != 1 { + t.Errorf("wrong number of entities found, got %d, want 1", len(el)) + } + + w = bytes.NewBuffer(nil) + if err := e.SerializePrivate(w, nil); err != nil { + t.Errorf("failed to serialize entity second time: %s", err) + return + } + + if !bytes.Equal(w.Bytes(), serialized) { + t.Errorf("results differed") + } +} + +func TestSymmetricEncryption(t *testing.T) { + buf := new(bytes.Buffer) + plaintext, err := SymmetricallyEncrypt(buf, []byte("testing"), nil, nil) + if err != nil { + t.Errorf("error writing headers: %s", err) + return + } + message := []byte("hello world\n") + _, err = plaintext.Write(message) + if err != nil { + t.Errorf("error writing to plaintext writer: %s", err) + } + err = plaintext.Close() + if err != nil { + t.Errorf("error closing plaintext writer: %s", err) + } + + md, err := ReadMessage(buf, nil, func(keys []Key, symmetric bool) ([]byte, error) { + return []byte("testing"), nil + }, nil) + if err != nil { + t.Errorf("error rereading message: %s", err) + } + messageBuf := bytes.NewBuffer(nil) + _, err = io.Copy(messageBuf, md.UnverifiedBody) + if err != nil { + t.Errorf("error rereading message: %s", err) + } + if !bytes.Equal(message, messageBuf.Bytes()) { + t.Errorf("recovered message incorrect got '%s', want '%s'", messageBuf.Bytes(), message) + } +} + +var testEncryptionTests = []struct { + keyRingHex string + isSigned bool +}{ + { + testKeys1And2PrivateHex, + false, + }, + { + testKeys1And2PrivateHex, + true, + }, + { + dsaElGamalTestKeysHex, + false, + }, + { + dsaElGamalTestKeysHex, + true, + }, +} + +func TestEncryption(t *testing.T) { + for i, test := range testEncryptionTests { + kring, _ := ReadKeyRing(readerFromHex(test.keyRingHex)) + + passphrase := []byte("passphrase") + for _, entity := range kring { + if entity.PrivateKey != nil && entity.PrivateKey.Encrypted { + err := entity.PrivateKey.Decrypt(passphrase) + if err != nil { + t.Errorf("#%d: failed to decrypt key", i) + } + } + for _, subkey := range entity.Subkeys { + if subkey.PrivateKey != nil && subkey.PrivateKey.Encrypted { + err := subkey.PrivateKey.Decrypt(passphrase) + if err != nil { + t.Errorf("#%d: failed to decrypt subkey", i) + } + } + } + } + + var signed *Entity + if test.isSigned { + signed = kring[0] + } + + buf := new(bytes.Buffer) + w, err := Encrypt(buf, kring[:1], signed, nil /* no hints */, nil) + if err != nil { + t.Errorf("#%d: error in Encrypt: %s", i, err) + continue + } + + const message = "testing" + _, err = w.Write([]byte(message)) + if err != nil { + t.Errorf("#%d: error writing plaintext: %s", i, err) + continue + } + err = w.Close() + if err != nil { + t.Errorf("#%d: error closing WriteCloser: %s", i, err) + continue + } + + md, err := ReadMessage(buf, kring, nil /* no prompt */, nil) + if err != nil { + t.Errorf("#%d: error reading message: %s", i, err) + continue + } + + testTime, _ := time.Parse("2006-01-02", "2013-07-01") + if test.isSigned { + signKey, _ := kring[0].signingKey(testTime) + expectedKeyId := signKey.PublicKey.KeyId + if md.SignedByKeyId != expectedKeyId { + t.Errorf("#%d: message signed by wrong key id, got: %v, want: %v", i, *md.SignedBy, expectedKeyId) + } + if md.SignedBy == nil { + t.Errorf("#%d: failed to find the signing Entity", i) + } + } + + plaintext, err := ioutil.ReadAll(md.UnverifiedBody) + if err != nil { + t.Errorf("#%d: error reading encrypted contents: %s", i, err) + continue + } + + encryptKey, _ := kring[0].encryptionKey(testTime) + expectedKeyId := encryptKey.PublicKey.KeyId + if len(md.EncryptedToKeyIds) != 1 || md.EncryptedToKeyIds[0] != expectedKeyId { + t.Errorf("#%d: expected message to be encrypted to %v, but got %#v", i, expectedKeyId, md.EncryptedToKeyIds) + } + + if string(plaintext) != message { + t.Errorf("#%d: got: %s, want: %s", i, string(plaintext), message) + } + + if test.isSigned { + if md.SignatureError != nil { + t.Errorf("#%d: signature error: %s", i, md.SignatureError) + } + if md.Signature == nil { + t.Error("signature missing") + } + } + } +} diff --git a/vendor/golang.org/x/crypto/otr/libotr_test_helper.c b/vendor/golang.org/x/crypto/otr/libotr_test_helper.c new file mode 100644 index 0000000000000000000000000000000000000000..b3ca072d4809242735229ad737dd452c6284d406 --- /dev/null +++ b/vendor/golang.org/x/crypto/otr/libotr_test_helper.c @@ -0,0 +1,197 @@ +// 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 can be compiled and used to test the otr package against libotr. +// See otr_test.go. + +// +build ignore + +#include +#include +#include + +#include +#include +#include + +static int g_session_established = 0; + +OtrlPolicy policy(void *opdata, ConnContext *context) { + return OTRL_POLICY_ALWAYS; +} + +int is_logged_in(void *opdata, const char *accountname, const char *protocol, + const char *recipient) { + return 1; +} + +void inject_message(void *opdata, const char *accountname, const char *protocol, + const char *recipient, const char *message) { + printf("%s\n", message); + fflush(stdout); + fprintf(stderr, "libotr helper sent: %s\n", message); +} + +void update_context_list(void *opdata) {} + +void new_fingerprint(void *opdata, OtrlUserState us, const char *accountname, + const char *protocol, const char *username, + unsigned char fingerprint[20]) { + fprintf(stderr, "NEW FINGERPRINT\n"); + g_session_established = 1; +} + +void write_fingerprints(void *opdata) {} + +void gone_secure(void *opdata, ConnContext *context) {} + +void gone_insecure(void *opdata, ConnContext *context) {} + +void still_secure(void *opdata, ConnContext *context, int is_reply) {} + +int max_message_size(void *opdata, ConnContext *context) { return 99999; } + +const char *account_name(void *opdata, const char *account, + const char *protocol) { + return "ACCOUNT"; +} + +void account_name_free(void *opdata, const char *account_name) {} + +const char *error_message(void *opdata, ConnContext *context, + OtrlErrorCode err_code) { + return "ERR"; +} + +void error_message_free(void *opdata, const char *msg) {} + +void resent_msg_prefix_free(void *opdata, const char *prefix) {} + +void handle_smp_event(void *opdata, OtrlSMPEvent smp_event, + ConnContext *context, unsigned short progress_event, + char *question) {} + +void handle_msg_event(void *opdata, OtrlMessageEvent msg_event, + ConnContext *context, const char *message, + gcry_error_t err) { + fprintf(stderr, "msg event: %d %s\n", msg_event, message); +} + +OtrlMessageAppOps uiops = { + policy, + NULL, + is_logged_in, + inject_message, + update_context_list, + new_fingerprint, + write_fingerprints, + gone_secure, + gone_insecure, + still_secure, + max_message_size, + account_name, + account_name_free, + NULL, /* received_symkey */ + error_message, + error_message_free, + NULL, /* resent_msg_prefix */ + resent_msg_prefix_free, + handle_smp_event, + handle_msg_event, + NULL /* create_instag */, + NULL /* convert_msg */, + NULL /* convert_free */, + NULL /* timer_control */, +}; + +static const char kPrivateKeyData[] = + "(privkeys (account (name \"account\") (protocol proto) (private-key (dsa " + "(p " + "#00FC07ABCF0DC916AFF6E9AE47BEF60C7AB9B4D6B2469E436630E36F8A489BE812486A09F" + "30B71224508654940A835301ACC525A4FF133FC152CC53DCC59D65C30A54F1993FE13FE63E" + "5823D4C746DB21B90F9B9C00B49EC7404AB1D929BA7FBA12F2E45C6E0A651689750E8528AB" + "8C031D3561FECEE72EBB4A090D450A9B7A857#) (q " + "#00997BD266EF7B1F60A5C23F3A741F2AEFD07A2081#) (g " + "#535E360E8A95EBA46A4F7DE50AD6E9B2A6DB785A66B64EB9F20338D2A3E8FB0E94725848F" + "1AA6CC567CB83A1CC517EC806F2E92EAE71457E80B2210A189B91250779434B41FC8A8873F" + "6DB94BEA7D177F5D59E7E114EE10A49CFD9CEF88AE43387023B672927BA74B04EB6BBB5E57" + "597766A2F9CE3857D7ACE3E1E3BC1FC6F26#) (y " + "#0AC8670AD767D7A8D9D14CC1AC6744CD7D76F993B77FFD9E39DF01E5A6536EF65E775FCEF" + "2A983E2A19BD6415500F6979715D9FD1257E1FE2B6F5E1E74B333079E7C880D39868462A93" + "454B41877BE62E5EF0A041C2EE9C9E76BD1E12AE25D9628DECB097025DD625EF49C3258A1A" + "3C0FF501E3DC673B76D7BABF349009B6ECF#) (x " + "#14D0345A3562C480A039E3C72764F72D79043216#)))))\n"; + +int main() { + OTRL_INIT; + + // We have to write the private key information to a file because the libotr + // API demands a filename to read from. + const char *tmpdir = "/tmp"; + if (getenv("TMP")) { + tmpdir = getenv("TMP"); + } + + char private_key_file[256]; + snprintf(private_key_file, sizeof(private_key_file), + "%s/libotr_test_helper_privatekeys-XXXXXX", tmpdir); + int fd = mkstemp(private_key_file); + if (fd == -1) { + perror("creating temp file"); + } + write(fd, kPrivateKeyData, sizeof(kPrivateKeyData) - 1); + close(fd); + + OtrlUserState userstate = otrl_userstate_create(); + otrl_privkey_read(userstate, private_key_file); + unlink(private_key_file); + + fprintf(stderr, "libotr helper started\n"); + + char buf[4096]; + + for (;;) { + char *message = fgets(buf, sizeof(buf), stdin); + if (strlen(message) == 0) { + break; + } + message[strlen(message) - 1] = 0; + fprintf(stderr, "libotr helper got: %s\n", message); + + char *newmessage = NULL; + OtrlTLV *tlvs; + int ignore_message = otrl_message_receiving( + userstate, &uiops, NULL, "account", "proto", "peer", message, + &newmessage, &tlvs, NULL, NULL, NULL); + if (tlvs) { + otrl_tlv_free(tlvs); + } + + if (newmessage != NULL) { + fprintf(stderr, "libotr got: %s\n", newmessage); + otrl_message_free(newmessage); + + gcry_error_t err; + char *newmessage = NULL; + + err = otrl_message_sending(userstate, &uiops, NULL, "account", "proto", + "peer", 0, "test message", NULL, &newmessage, + OTRL_FRAGMENT_SEND_SKIP, NULL, NULL, NULL); + if (newmessage == NULL) { + fprintf(stderr, "libotr didn't encrypt message\n"); + return 1; + } + write(1, newmessage, strlen(newmessage)); + write(1, "\n", 1); + fprintf(stderr, "libotr sent: %s\n", newmessage); + otrl_message_free(newmessage); + + g_session_established = 0; + write(1, "?OTRv2?\n", 8); + fprintf(stderr, "libotr sent: ?OTRv2\n"); + } + } + + return 0; +} diff --git a/vendor/golang.org/x/crypto/otr/otr.go b/vendor/golang.org/x/crypto/otr/otr.go new file mode 100644 index 0000000000000000000000000000000000000000..173b753dbd34f7b57b58617350a1f710be324e96 --- /dev/null +++ b/vendor/golang.org/x/crypto/otr/otr.go @@ -0,0 +1,1415 @@ +// 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 otr implements the Off The Record protocol as specified in +// http://www.cypherpunks.ca/otr/Protocol-v2-3.1.0.html +package otr // import "golang.org/x/crypto/otr" + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" + "crypto/dsa" + "crypto/hmac" + "crypto/rand" + "crypto/sha1" + "crypto/sha256" + "crypto/subtle" + "encoding/base64" + "encoding/hex" + "errors" + "hash" + "io" + "math/big" + "strconv" +) + +// SecurityChange describes a change in the security state of a Conversation. +type SecurityChange int + +const ( + NoChange SecurityChange = iota + // NewKeys indicates that a key exchange has completed. This occurs + // when a conversation first becomes encrypted, and when the keys are + // renegotiated within an encrypted conversation. + NewKeys + // SMPSecretNeeded indicates that the peer has started an + // authentication and that we need to supply a secret. Call SMPQuestion + // to get the optional, human readable challenge and then Authenticate + // to supply the matching secret. + SMPSecretNeeded + // SMPComplete indicates that an authentication completed. The identity + // of the peer has now been confirmed. + SMPComplete + // SMPFailed indicates that an authentication failed. + SMPFailed + // ConversationEnded indicates that the peer ended the secure + // conversation. + ConversationEnded +) + +// QueryMessage can be sent to a peer to start an OTR conversation. +var QueryMessage = "?OTRv2?" + +// ErrorPrefix can be used to make an OTR error by appending an error message +// to it. +var ErrorPrefix = "?OTR Error:" + +var ( + fragmentPartSeparator = []byte(",") + fragmentPrefix = []byte("?OTR,") + msgPrefix = []byte("?OTR:") + queryMarker = []byte("?OTR") +) + +// isQuery attempts to parse an OTR query from msg and returns the greatest +// common version, or 0 if msg is not an OTR query. +func isQuery(msg []byte) (greatestCommonVersion int) { + pos := bytes.Index(msg, queryMarker) + if pos == -1 { + return 0 + } + for i, c := range msg[pos+len(queryMarker):] { + if i == 0 { + if c == '?' { + // Indicates support for version 1, but we don't + // implement that. + continue + } + + if c != 'v' { + // Invalid message + return 0 + } + + continue + } + + if c == '?' { + // End of message + return + } + + if c == ' ' || c == '\t' { + // Probably an invalid message + return 0 + } + + if c == '2' { + greatestCommonVersion = 2 + } + } + + return 0 +} + +const ( + statePlaintext = iota + stateEncrypted + stateFinished +) + +const ( + authStateNone = iota + authStateAwaitingDHKey + authStateAwaitingRevealSig + authStateAwaitingSig +) + +const ( + msgTypeDHCommit = 2 + msgTypeData = 3 + msgTypeDHKey = 10 + msgTypeRevealSig = 17 + msgTypeSig = 18 +) + +const ( + // If the requested fragment size is less than this, it will be ignored. + minFragmentSize = 18 + // Messages are padded to a multiple of this number of bytes. + paddingGranularity = 256 + // The number of bytes in a Diffie-Hellman private value (320-bits). + dhPrivateBytes = 40 + // The number of bytes needed to represent an element of the DSA + // subgroup (160-bits). + dsaSubgroupBytes = 20 + // The number of bytes of the MAC that are sent on the wire (160-bits). + macPrefixBytes = 20 +) + +// These are the global, common group parameters for OTR. +var ( + p *big.Int // group prime + g *big.Int // group generator + q *big.Int // group order + pMinus2 *big.Int +) + +func init() { + p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF", 16) + q, _ = new(big.Int).SetString("7FFFFFFFFFFFFFFFE487ED5110B4611A62633145C06E0E68948127044533E63A0105DF531D89CD9128A5043CC71A026EF7CA8CD9E69D218D98158536F92F8A1BA7F09AB6B6A8E122F242DABB312F3F637A262174D31BF6B585FFAE5B7A035BF6F71C35FDAD44CFD2D74F9208BE258FF324943328F6722D9EE1003E5C50B1DF82CC6D241B0E2AE9CD348B1FD47E9267AFC1B2AE91EE51D6CB0E3179AB1042A95DCF6A9483B84B4B36B3861AA7255E4C0278BA36046511B993FFFFFFFFFFFFFFFF", 16) + g = new(big.Int).SetInt64(2) + pMinus2 = new(big.Int).Sub(p, g) +} + +// Conversation represents a relation with a peer. The zero value is a valid +// Conversation, although PrivateKey must be set. +// +// When communicating with a peer, all inbound messages should be passed to +// Conversation.Receive and all outbound messages to Conversation.Send. The +// Conversation will take care of maintaining the encryption state and +// negotiating encryption as needed. +type Conversation struct { + // PrivateKey contains the private key to use to sign key exchanges. + PrivateKey *PrivateKey + + // Rand can be set to override the entropy source. Otherwise, + // crypto/rand will be used. + Rand io.Reader + // If FragmentSize is set, all messages produced by Receive and Send + // will be fragmented into messages of, at most, this number of bytes. + FragmentSize int + + // Once Receive has returned NewKeys once, the following fields are + // valid. + SSID [8]byte + TheirPublicKey PublicKey + + state, authState int + + r [16]byte + x, y *big.Int + gx, gy *big.Int + gxBytes []byte + digest [sha256.Size]byte + + revealKeys, sigKeys akeKeys + + myKeyId uint32 + myCurrentDHPub *big.Int + myCurrentDHPriv *big.Int + myLastDHPub *big.Int + myLastDHPriv *big.Int + + theirKeyId uint32 + theirCurrentDHPub *big.Int + theirLastDHPub *big.Int + + keySlots [4]keySlot + + myCounter [8]byte + theirLastCtr [8]byte + oldMACs []byte + + k, n int // fragment state + frag []byte + + smp smpState +} + +// A keySlot contains key material for a specific (their keyid, my keyid) pair. +type keySlot struct { + // used is true if this slot is valid. If false, it's free for reuse. + used bool + theirKeyId uint32 + myKeyId uint32 + sendAESKey, recvAESKey []byte + sendMACKey, recvMACKey []byte + theirLastCtr [8]byte +} + +// akeKeys are generated during key exchange. There's one set for the reveal +// signature message and another for the signature message. In the protocol +// spec the latter are indicated with a prime mark. +type akeKeys struct { + c [16]byte + m1, m2 [32]byte +} + +func (c *Conversation) rand() io.Reader { + if c.Rand != nil { + return c.Rand + } + return rand.Reader +} + +func (c *Conversation) randMPI(buf []byte) *big.Int { + _, err := io.ReadFull(c.rand(), buf) + if err != nil { + panic("otr: short read from random source") + } + + return new(big.Int).SetBytes(buf) +} + +// tlv represents the type-length value from the protocol. +type tlv struct { + typ, length uint16 + data []byte +} + +const ( + tlvTypePadding = 0 + tlvTypeDisconnected = 1 + tlvTypeSMP1 = 2 + tlvTypeSMP2 = 3 + tlvTypeSMP3 = 4 + tlvTypeSMP4 = 5 + tlvTypeSMPAbort = 6 + tlvTypeSMP1WithQuestion = 7 +) + +// Receive handles a message from a peer. It returns a human readable message, +// an indicator of whether that message was encrypted, a hint about the +// encryption state and zero or more messages to send back to the peer. +// These messages do not need to be passed to Send before transmission. +func (c *Conversation) Receive(in []byte) (out []byte, encrypted bool, change SecurityChange, toSend [][]byte, err error) { + if bytes.HasPrefix(in, fragmentPrefix) { + in, err = c.processFragment(in) + if in == nil || err != nil { + return + } + } + + if bytes.HasPrefix(in, msgPrefix) && in[len(in)-1] == '.' { + in = in[len(msgPrefix) : len(in)-1] + } else if version := isQuery(in); version > 0 { + c.authState = authStateAwaitingDHKey + c.reset() + toSend = c.encode(c.generateDHCommit()) + return + } else { + // plaintext message + out = in + return + } + + msg := make([]byte, base64.StdEncoding.DecodedLen(len(in))) + msgLen, err := base64.StdEncoding.Decode(msg, in) + if err != nil { + err = errors.New("otr: invalid base64 encoding in message") + return + } + msg = msg[:msgLen] + + // The first two bytes are the protocol version (2) + if len(msg) < 3 || msg[0] != 0 || msg[1] != 2 { + err = errors.New("otr: invalid OTR message") + return + } + + msgType := int(msg[2]) + msg = msg[3:] + + switch msgType { + case msgTypeDHCommit: + switch c.authState { + case authStateNone: + c.authState = authStateAwaitingRevealSig + if err = c.processDHCommit(msg); err != nil { + return + } + c.reset() + toSend = c.encode(c.generateDHKey()) + return + case authStateAwaitingDHKey: + // This is a 'SYN-crossing'. The greater digest wins. + var cmp int + if cmp, err = c.compareToDHCommit(msg); err != nil { + return + } + if cmp > 0 { + // We win. Retransmit DH commit. + toSend = c.encode(c.serializeDHCommit()) + return + } else { + // They win. We forget about our DH commit. + c.authState = authStateAwaitingRevealSig + if err = c.processDHCommit(msg); err != nil { + return + } + c.reset() + toSend = c.encode(c.generateDHKey()) + return + } + case authStateAwaitingRevealSig: + if err = c.processDHCommit(msg); err != nil { + return + } + toSend = c.encode(c.serializeDHKey()) + case authStateAwaitingSig: + if err = c.processDHCommit(msg); err != nil { + return + } + c.reset() + toSend = c.encode(c.generateDHKey()) + c.authState = authStateAwaitingRevealSig + default: + panic("bad state") + } + case msgTypeDHKey: + switch c.authState { + case authStateAwaitingDHKey: + var isSame bool + if isSame, err = c.processDHKey(msg); err != nil { + return + } + if isSame { + err = errors.New("otr: unexpected duplicate DH key") + return + } + toSend = c.encode(c.generateRevealSig()) + c.authState = authStateAwaitingSig + case authStateAwaitingSig: + var isSame bool + if isSame, err = c.processDHKey(msg); err != nil { + return + } + if isSame { + toSend = c.encode(c.serializeDHKey()) + } + } + case msgTypeRevealSig: + if c.authState != authStateAwaitingRevealSig { + return + } + if err = c.processRevealSig(msg); err != nil { + return + } + toSend = c.encode(c.generateSig()) + c.authState = authStateNone + c.state = stateEncrypted + change = NewKeys + case msgTypeSig: + if c.authState != authStateAwaitingSig { + return + } + if err = c.processSig(msg); err != nil { + return + } + c.authState = authStateNone + c.state = stateEncrypted + change = NewKeys + case msgTypeData: + if c.state != stateEncrypted { + err = errors.New("otr: encrypted message received without encrypted session established") + return + } + var tlvs []tlv + out, tlvs, err = c.processData(msg) + encrypted = true + + EachTLV: + for _, inTLV := range tlvs { + switch inTLV.typ { + case tlvTypeDisconnected: + change = ConversationEnded + c.state = stateFinished + break EachTLV + case tlvTypeSMP1, tlvTypeSMP2, tlvTypeSMP3, tlvTypeSMP4, tlvTypeSMPAbort, tlvTypeSMP1WithQuestion: + var reply tlv + var complete bool + reply, complete, err = c.processSMP(inTLV) + if err == smpSecretMissingError { + err = nil + change = SMPSecretNeeded + c.smp.saved = &inTLV + return + } + if err == smpFailureError { + err = nil + change = SMPFailed + } else if complete { + change = SMPComplete + } + if reply.typ != 0 { + toSend = c.encode(c.generateData(nil, &reply)) + } + break EachTLV + default: + // skip unknown TLVs + } + } + default: + err = errors.New("otr: unknown message type " + strconv.Itoa(msgType)) + } + + return +} + +// Send takes a human readable message from the local user, possibly encrypts +// it and returns zero one or more messages to send to the peer. +func (c *Conversation) Send(msg []byte) ([][]byte, error) { + switch c.state { + case statePlaintext: + return [][]byte{msg}, nil + case stateEncrypted: + return c.encode(c.generateData(msg, nil)), nil + case stateFinished: + return nil, errors.New("otr: cannot send message because secure conversation has finished") + } + + return nil, errors.New("otr: cannot send message in current state") +} + +// SMPQuestion returns the human readable challenge question from the peer. +// It's only valid after Receive has returned SMPSecretNeeded. +func (c *Conversation) SMPQuestion() string { + return c.smp.question +} + +// Authenticate begins an authentication with the peer. Authentication involves +// an optional challenge message and a shared secret. The authentication +// proceeds until either Receive returns SMPComplete, SMPSecretNeeded (which +// indicates that a new authentication is happening and thus this one was +// aborted) or SMPFailed. +func (c *Conversation) Authenticate(question string, mutualSecret []byte) (toSend [][]byte, err error) { + if c.state != stateEncrypted { + err = errors.New("otr: can't authenticate a peer without a secure conversation established") + return + } + + if c.smp.saved != nil { + c.calcSMPSecret(mutualSecret, false /* they started it */) + + var out tlv + var complete bool + out, complete, err = c.processSMP(*c.smp.saved) + if complete { + panic("SMP completed on the first message") + } + c.smp.saved = nil + if out.typ != 0 { + toSend = c.encode(c.generateData(nil, &out)) + } + return + } + + c.calcSMPSecret(mutualSecret, true /* we started it */) + outs := c.startSMP(question) + for _, out := range outs { + toSend = append(toSend, c.encode(c.generateData(nil, &out))...) + } + return +} + +// End ends a secure conversation by generating a termination message for +// the peer and switches to unencrypted communication. +func (c *Conversation) End() (toSend [][]byte) { + switch c.state { + case statePlaintext: + return nil + case stateEncrypted: + c.state = statePlaintext + return c.encode(c.generateData(nil, &tlv{typ: tlvTypeDisconnected})) + case stateFinished: + c.state = statePlaintext + return nil + } + panic("unreachable") +} + +// IsEncrypted returns true if a message passed to Send would be encrypted +// before transmission. This result remains valid until the next call to +// Receive or End, which may change the state of the Conversation. +func (c *Conversation) IsEncrypted() bool { + return c.state == stateEncrypted +} + +var fragmentError = errors.New("otr: invalid OTR fragment") + +// processFragment processes a fragmented OTR message and possibly returns a +// complete message. Fragmented messages look like "?OTR,k,n,msg," where k is +// the fragment number (starting from 1), n is the number of fragments in this +// message and msg is a substring of the base64 encoded message. +func (c *Conversation) processFragment(in []byte) (out []byte, err error) { + in = in[len(fragmentPrefix):] // remove "?OTR," + parts := bytes.Split(in, fragmentPartSeparator) + if len(parts) != 4 || len(parts[3]) != 0 { + return nil, fragmentError + } + + k, err := strconv.Atoi(string(parts[0])) + if err != nil { + return nil, fragmentError + } + + n, err := strconv.Atoi(string(parts[1])) + if err != nil { + return nil, fragmentError + } + + if k < 1 || n < 1 || k > n { + return nil, fragmentError + } + + if k == 1 { + c.frag = append(c.frag[:0], parts[2]...) + c.k, c.n = k, n + } else if n == c.n && k == c.k+1 { + c.frag = append(c.frag, parts[2]...) + c.k++ + } else { + c.frag = c.frag[:0] + c.n, c.k = 0, 0 + } + + if c.n > 0 && c.k == c.n { + c.n, c.k = 0, 0 + return c.frag, nil + } + + return nil, nil +} + +func (c *Conversation) generateDHCommit() []byte { + _, err := io.ReadFull(c.rand(), c.r[:]) + if err != nil { + panic("otr: short read from random source") + } + + var xBytes [dhPrivateBytes]byte + c.x = c.randMPI(xBytes[:]) + c.gx = new(big.Int).Exp(g, c.x, p) + c.gy = nil + c.gxBytes = appendMPI(nil, c.gx) + + h := sha256.New() + h.Write(c.gxBytes) + h.Sum(c.digest[:0]) + + aesCipher, err := aes.NewCipher(c.r[:]) + if err != nil { + panic(err.Error()) + } + + var iv [aes.BlockSize]byte + ctr := cipher.NewCTR(aesCipher, iv[:]) + ctr.XORKeyStream(c.gxBytes, c.gxBytes) + + return c.serializeDHCommit() +} + +func (c *Conversation) serializeDHCommit() []byte { + var ret []byte + ret = appendU16(ret, 2) // protocol version + ret = append(ret, msgTypeDHCommit) + ret = appendData(ret, c.gxBytes) + ret = appendData(ret, c.digest[:]) + return ret +} + +func (c *Conversation) processDHCommit(in []byte) error { + var ok1, ok2 bool + c.gxBytes, in, ok1 = getData(in) + digest, in, ok2 := getData(in) + if !ok1 || !ok2 || len(in) > 0 { + return errors.New("otr: corrupt DH commit message") + } + copy(c.digest[:], digest) + return nil +} + +func (c *Conversation) compareToDHCommit(in []byte) (int, error) { + _, in, ok1 := getData(in) + digest, in, ok2 := getData(in) + if !ok1 || !ok2 || len(in) > 0 { + return 0, errors.New("otr: corrupt DH commit message") + } + return bytes.Compare(c.digest[:], digest), nil +} + +func (c *Conversation) generateDHKey() []byte { + var yBytes [dhPrivateBytes]byte + c.y = c.randMPI(yBytes[:]) + c.gy = new(big.Int).Exp(g, c.y, p) + return c.serializeDHKey() +} + +func (c *Conversation) serializeDHKey() []byte { + var ret []byte + ret = appendU16(ret, 2) // protocol version + ret = append(ret, msgTypeDHKey) + ret = appendMPI(ret, c.gy) + return ret +} + +func (c *Conversation) processDHKey(in []byte) (isSame bool, err error) { + gy, in, ok := getMPI(in) + if !ok { + err = errors.New("otr: corrupt DH key message") + return + } + if gy.Cmp(g) < 0 || gy.Cmp(pMinus2) > 0 { + err = errors.New("otr: DH value out of range") + return + } + if c.gy != nil { + isSame = c.gy.Cmp(gy) == 0 + return + } + c.gy = gy + return +} + +func (c *Conversation) generateEncryptedSignature(keys *akeKeys, xFirst bool) ([]byte, []byte) { + var xb []byte + xb = c.PrivateKey.PublicKey.Serialize(xb) + + var verifyData []byte + if xFirst { + verifyData = appendMPI(verifyData, c.gx) + verifyData = appendMPI(verifyData, c.gy) + } else { + verifyData = appendMPI(verifyData, c.gy) + verifyData = appendMPI(verifyData, c.gx) + } + verifyData = append(verifyData, xb...) + verifyData = appendU32(verifyData, c.myKeyId) + + mac := hmac.New(sha256.New, keys.m1[:]) + mac.Write(verifyData) + mb := mac.Sum(nil) + + xb = appendU32(xb, c.myKeyId) + xb = append(xb, c.PrivateKey.Sign(c.rand(), mb)...) + + aesCipher, err := aes.NewCipher(keys.c[:]) + if err != nil { + panic(err.Error()) + } + var iv [aes.BlockSize]byte + ctr := cipher.NewCTR(aesCipher, iv[:]) + ctr.XORKeyStream(xb, xb) + + mac = hmac.New(sha256.New, keys.m2[:]) + encryptedSig := appendData(nil, xb) + mac.Write(encryptedSig) + + return encryptedSig, mac.Sum(nil) +} + +func (c *Conversation) generateRevealSig() []byte { + s := new(big.Int).Exp(c.gy, c.x, p) + c.calcAKEKeys(s) + c.myKeyId++ + + encryptedSig, mac := c.generateEncryptedSignature(&c.revealKeys, true /* gx comes first */) + + c.myCurrentDHPub = c.gx + c.myCurrentDHPriv = c.x + c.rotateDHKeys() + incCounter(&c.myCounter) + + var ret []byte + ret = appendU16(ret, 2) + ret = append(ret, msgTypeRevealSig) + ret = appendData(ret, c.r[:]) + ret = append(ret, encryptedSig...) + ret = append(ret, mac[:20]...) + return ret +} + +func (c *Conversation) processEncryptedSig(encryptedSig, theirMAC []byte, keys *akeKeys, xFirst bool) error { + mac := hmac.New(sha256.New, keys.m2[:]) + mac.Write(appendData(nil, encryptedSig)) + myMAC := mac.Sum(nil)[:20] + + if len(myMAC) != len(theirMAC) || subtle.ConstantTimeCompare(myMAC, theirMAC) == 0 { + return errors.New("bad signature MAC in encrypted signature") + } + + aesCipher, err := aes.NewCipher(keys.c[:]) + if err != nil { + panic(err.Error()) + } + var iv [aes.BlockSize]byte + ctr := cipher.NewCTR(aesCipher, iv[:]) + ctr.XORKeyStream(encryptedSig, encryptedSig) + + sig := encryptedSig + sig, ok1 := c.TheirPublicKey.Parse(sig) + keyId, sig, ok2 := getU32(sig) + if !ok1 || !ok2 { + return errors.New("otr: corrupt encrypted signature") + } + + var verifyData []byte + if xFirst { + verifyData = appendMPI(verifyData, c.gx) + verifyData = appendMPI(verifyData, c.gy) + } else { + verifyData = appendMPI(verifyData, c.gy) + verifyData = appendMPI(verifyData, c.gx) + } + verifyData = c.TheirPublicKey.Serialize(verifyData) + verifyData = appendU32(verifyData, keyId) + + mac = hmac.New(sha256.New, keys.m1[:]) + mac.Write(verifyData) + mb := mac.Sum(nil) + + sig, ok1 = c.TheirPublicKey.Verify(mb, sig) + if !ok1 { + return errors.New("bad signature in encrypted signature") + } + if len(sig) > 0 { + return errors.New("corrupt encrypted signature") + } + + c.theirKeyId = keyId + zero(c.theirLastCtr[:]) + return nil +} + +func (c *Conversation) processRevealSig(in []byte) error { + r, in, ok1 := getData(in) + encryptedSig, in, ok2 := getData(in) + theirMAC := in + if !ok1 || !ok2 || len(theirMAC) != 20 { + return errors.New("otr: corrupt reveal signature message") + } + + aesCipher, err := aes.NewCipher(r) + if err != nil { + return errors.New("otr: cannot create AES cipher from reveal signature message: " + err.Error()) + } + var iv [aes.BlockSize]byte + ctr := cipher.NewCTR(aesCipher, iv[:]) + ctr.XORKeyStream(c.gxBytes, c.gxBytes) + h := sha256.New() + h.Write(c.gxBytes) + digest := h.Sum(nil) + if len(digest) != len(c.digest) || subtle.ConstantTimeCompare(digest, c.digest[:]) == 0 { + return errors.New("otr: bad commit MAC in reveal signature message") + } + var rest []byte + c.gx, rest, ok1 = getMPI(c.gxBytes) + if !ok1 || len(rest) > 0 { + return errors.New("otr: gx corrupt after decryption") + } + if c.gx.Cmp(g) < 0 || c.gx.Cmp(pMinus2) > 0 { + return errors.New("otr: DH value out of range") + } + s := new(big.Int).Exp(c.gx, c.y, p) + c.calcAKEKeys(s) + + if err := c.processEncryptedSig(encryptedSig, theirMAC, &c.revealKeys, true /* gx comes first */); err != nil { + return errors.New("otr: in reveal signature message: " + err.Error()) + } + + c.theirCurrentDHPub = c.gx + c.theirLastDHPub = nil + + return nil +} + +func (c *Conversation) generateSig() []byte { + c.myKeyId++ + + encryptedSig, mac := c.generateEncryptedSignature(&c.sigKeys, false /* gy comes first */) + + c.myCurrentDHPub = c.gy + c.myCurrentDHPriv = c.y + c.rotateDHKeys() + incCounter(&c.myCounter) + + var ret []byte + ret = appendU16(ret, 2) + ret = append(ret, msgTypeSig) + ret = append(ret, encryptedSig...) + ret = append(ret, mac[:macPrefixBytes]...) + return ret +} + +func (c *Conversation) processSig(in []byte) error { + encryptedSig, in, ok1 := getData(in) + theirMAC := in + if !ok1 || len(theirMAC) != macPrefixBytes { + return errors.New("otr: corrupt signature message") + } + + if err := c.processEncryptedSig(encryptedSig, theirMAC, &c.sigKeys, false /* gy comes first */); err != nil { + return errors.New("otr: in signature message: " + err.Error()) + } + + c.theirCurrentDHPub = c.gy + c.theirLastDHPub = nil + + return nil +} + +func (c *Conversation) rotateDHKeys() { + // evict slots using our retired key id + for i := range c.keySlots { + slot := &c.keySlots[i] + if slot.used && slot.myKeyId == c.myKeyId-1 { + slot.used = false + c.oldMACs = append(c.oldMACs, slot.recvMACKey...) + } + } + + c.myLastDHPriv = c.myCurrentDHPriv + c.myLastDHPub = c.myCurrentDHPub + + var xBytes [dhPrivateBytes]byte + c.myCurrentDHPriv = c.randMPI(xBytes[:]) + c.myCurrentDHPub = new(big.Int).Exp(g, c.myCurrentDHPriv, p) + c.myKeyId++ +} + +func (c *Conversation) processData(in []byte) (out []byte, tlvs []tlv, err error) { + origIn := in + flags, in, ok1 := getU8(in) + theirKeyId, in, ok2 := getU32(in) + myKeyId, in, ok3 := getU32(in) + y, in, ok4 := getMPI(in) + counter, in, ok5 := getNBytes(in, 8) + encrypted, in, ok6 := getData(in) + macedData := origIn[:len(origIn)-len(in)] + theirMAC, in, ok7 := getNBytes(in, macPrefixBytes) + _, in, ok8 := getData(in) + if !ok1 || !ok2 || !ok3 || !ok4 || !ok5 || !ok6 || !ok7 || !ok8 || len(in) > 0 { + err = errors.New("otr: corrupt data message") + return + } + + ignoreErrors := flags&1 != 0 + + slot, err := c.calcDataKeys(myKeyId, theirKeyId) + if err != nil { + if ignoreErrors { + err = nil + } + return + } + + mac := hmac.New(sha1.New, slot.recvMACKey) + mac.Write([]byte{0, 2, 3}) + mac.Write(macedData) + myMAC := mac.Sum(nil) + if len(myMAC) != len(theirMAC) || subtle.ConstantTimeCompare(myMAC, theirMAC) == 0 { + if !ignoreErrors { + err = errors.New("otr: bad MAC on data message") + } + return + } + + if bytes.Compare(counter, slot.theirLastCtr[:]) <= 0 { + err = errors.New("otr: counter regressed") + return + } + copy(slot.theirLastCtr[:], counter) + + var iv [aes.BlockSize]byte + copy(iv[:], counter) + aesCipher, err := aes.NewCipher(slot.recvAESKey) + if err != nil { + panic(err.Error()) + } + ctr := cipher.NewCTR(aesCipher, iv[:]) + ctr.XORKeyStream(encrypted, encrypted) + decrypted := encrypted + + if myKeyId == c.myKeyId { + c.rotateDHKeys() + } + if theirKeyId == c.theirKeyId { + // evict slots using their retired key id + for i := range c.keySlots { + slot := &c.keySlots[i] + if slot.used && slot.theirKeyId == theirKeyId-1 { + slot.used = false + c.oldMACs = append(c.oldMACs, slot.recvMACKey...) + } + } + + c.theirLastDHPub = c.theirCurrentDHPub + c.theirKeyId++ + c.theirCurrentDHPub = y + } + + if nulPos := bytes.IndexByte(decrypted, 0); nulPos >= 0 { + out = decrypted[:nulPos] + tlvData := decrypted[nulPos+1:] + for len(tlvData) > 0 { + var t tlv + var ok1, ok2, ok3 bool + + t.typ, tlvData, ok1 = getU16(tlvData) + t.length, tlvData, ok2 = getU16(tlvData) + t.data, tlvData, ok3 = getNBytes(tlvData, int(t.length)) + if !ok1 || !ok2 || !ok3 { + err = errors.New("otr: corrupt tlv data") + return + } + tlvs = append(tlvs, t) + } + } else { + out = decrypted + } + + return +} + +func (c *Conversation) generateData(msg []byte, extra *tlv) []byte { + slot, err := c.calcDataKeys(c.myKeyId-1, c.theirKeyId) + if err != nil { + panic("otr: failed to generate sending keys: " + err.Error()) + } + + var plaintext []byte + plaintext = append(plaintext, msg...) + plaintext = append(plaintext, 0) + + padding := paddingGranularity - ((len(plaintext) + 4) % paddingGranularity) + plaintext = appendU16(plaintext, tlvTypePadding) + plaintext = appendU16(plaintext, uint16(padding)) + for i := 0; i < padding; i++ { + plaintext = append(plaintext, 0) + } + + if extra != nil { + plaintext = appendU16(plaintext, extra.typ) + plaintext = appendU16(plaintext, uint16(len(extra.data))) + plaintext = append(plaintext, extra.data...) + } + + encrypted := make([]byte, len(plaintext)) + + var iv [aes.BlockSize]byte + copy(iv[:], c.myCounter[:]) + aesCipher, err := aes.NewCipher(slot.sendAESKey) + if err != nil { + panic(err.Error()) + } + ctr := cipher.NewCTR(aesCipher, iv[:]) + ctr.XORKeyStream(encrypted, plaintext) + + var ret []byte + ret = appendU16(ret, 2) + ret = append(ret, msgTypeData) + ret = append(ret, 0 /* flags */) + ret = appendU32(ret, c.myKeyId-1) + ret = appendU32(ret, c.theirKeyId) + ret = appendMPI(ret, c.myCurrentDHPub) + ret = append(ret, c.myCounter[:]...) + ret = appendData(ret, encrypted) + + mac := hmac.New(sha1.New, slot.sendMACKey) + mac.Write(ret) + ret = append(ret, mac.Sum(nil)[:macPrefixBytes]...) + ret = appendData(ret, c.oldMACs) + c.oldMACs = nil + incCounter(&c.myCounter) + + return ret +} + +func incCounter(counter *[8]byte) { + for i := 7; i >= 0; i-- { + counter[i]++ + if counter[i] > 0 { + break + } + } +} + +// calcDataKeys computes the keys used to encrypt a data message given the key +// IDs. +func (c *Conversation) calcDataKeys(myKeyId, theirKeyId uint32) (slot *keySlot, err error) { + // Check for a cache hit. + for i := range c.keySlots { + slot = &c.keySlots[i] + if slot.used && slot.theirKeyId == theirKeyId && slot.myKeyId == myKeyId { + return + } + } + + // Find an empty slot to write into. + slot = nil + for i := range c.keySlots { + if !c.keySlots[i].used { + slot = &c.keySlots[i] + break + } + } + if slot == nil { + return nil, errors.New("otr: internal error: no more key slots") + } + + var myPriv, myPub, theirPub *big.Int + + if myKeyId == c.myKeyId { + myPriv = c.myCurrentDHPriv + myPub = c.myCurrentDHPub + } else if myKeyId == c.myKeyId-1 { + myPriv = c.myLastDHPriv + myPub = c.myLastDHPub + } else { + err = errors.New("otr: peer requested keyid " + strconv.FormatUint(uint64(myKeyId), 10) + " when I'm on " + strconv.FormatUint(uint64(c.myKeyId), 10)) + return + } + + if theirKeyId == c.theirKeyId { + theirPub = c.theirCurrentDHPub + } else if theirKeyId == c.theirKeyId-1 && c.theirLastDHPub != nil { + theirPub = c.theirLastDHPub + } else { + err = errors.New("otr: peer requested keyid " + strconv.FormatUint(uint64(myKeyId), 10) + " when they're on " + strconv.FormatUint(uint64(c.myKeyId), 10)) + return + } + + var sendPrefixByte, recvPrefixByte [1]byte + + if myPub.Cmp(theirPub) > 0 { + // we're the high end + sendPrefixByte[0], recvPrefixByte[0] = 1, 2 + } else { + // we're the low end + sendPrefixByte[0], recvPrefixByte[0] = 2, 1 + } + + s := new(big.Int).Exp(theirPub, myPriv, p) + sBytes := appendMPI(nil, s) + + h := sha1.New() + h.Write(sendPrefixByte[:]) + h.Write(sBytes) + slot.sendAESKey = h.Sum(slot.sendAESKey[:0])[:16] + + h.Reset() + h.Write(slot.sendAESKey) + slot.sendMACKey = h.Sum(slot.sendMACKey[:0]) + + h.Reset() + h.Write(recvPrefixByte[:]) + h.Write(sBytes) + slot.recvAESKey = h.Sum(slot.recvAESKey[:0])[:16] + + h.Reset() + h.Write(slot.recvAESKey) + slot.recvMACKey = h.Sum(slot.recvMACKey[:0]) + + slot.theirKeyId = theirKeyId + slot.myKeyId = myKeyId + slot.used = true + + zero(slot.theirLastCtr[:]) + return +} + +func (c *Conversation) calcAKEKeys(s *big.Int) { + mpi := appendMPI(nil, s) + h := sha256.New() + + var cBytes [32]byte + hashWithPrefix(c.SSID[:], 0, mpi, h) + + hashWithPrefix(cBytes[:], 1, mpi, h) + copy(c.revealKeys.c[:], cBytes[:16]) + copy(c.sigKeys.c[:], cBytes[16:]) + + hashWithPrefix(c.revealKeys.m1[:], 2, mpi, h) + hashWithPrefix(c.revealKeys.m2[:], 3, mpi, h) + hashWithPrefix(c.sigKeys.m1[:], 4, mpi, h) + hashWithPrefix(c.sigKeys.m2[:], 5, mpi, h) +} + +func hashWithPrefix(out []byte, prefix byte, in []byte, h hash.Hash) { + h.Reset() + var p [1]byte + p[0] = prefix + h.Write(p[:]) + h.Write(in) + if len(out) == h.Size() { + h.Sum(out[:0]) + } else { + digest := h.Sum(nil) + copy(out, digest) + } +} + +func (c *Conversation) encode(msg []byte) [][]byte { + b64 := make([]byte, base64.StdEncoding.EncodedLen(len(msg))+len(msgPrefix)+1) + base64.StdEncoding.Encode(b64[len(msgPrefix):], msg) + copy(b64, msgPrefix) + b64[len(b64)-1] = '.' + + if c.FragmentSize < minFragmentSize || len(b64) <= c.FragmentSize { + // We can encode this in a single fragment. + return [][]byte{b64} + } + + // We have to fragment this message. + var ret [][]byte + bytesPerFragment := c.FragmentSize - minFragmentSize + numFragments := (len(b64) + bytesPerFragment) / bytesPerFragment + + for i := 0; i < numFragments; i++ { + frag := []byte("?OTR," + strconv.Itoa(i+1) + "," + strconv.Itoa(numFragments) + ",") + todo := bytesPerFragment + if todo > len(b64) { + todo = len(b64) + } + frag = append(frag, b64[:todo]...) + b64 = b64[todo:] + frag = append(frag, ',') + ret = append(ret, frag) + } + + return ret +} + +func (c *Conversation) reset() { + c.myKeyId = 0 + + for i := range c.keySlots { + c.keySlots[i].used = false + } +} + +type PublicKey struct { + dsa.PublicKey +} + +func (pk *PublicKey) Parse(in []byte) ([]byte, bool) { + var ok bool + var pubKeyType uint16 + + if pubKeyType, in, ok = getU16(in); !ok || pubKeyType != 0 { + return nil, false + } + if pk.P, in, ok = getMPI(in); !ok { + return nil, false + } + if pk.Q, in, ok = getMPI(in); !ok { + return nil, false + } + if pk.G, in, ok = getMPI(in); !ok { + return nil, false + } + if pk.Y, in, ok = getMPI(in); !ok { + return nil, false + } + + return in, true +} + +func (pk *PublicKey) Serialize(in []byte) []byte { + in = appendU16(in, 0) + in = appendMPI(in, pk.P) + in = appendMPI(in, pk.Q) + in = appendMPI(in, pk.G) + in = appendMPI(in, pk.Y) + return in +} + +// Fingerprint returns the 20-byte, binary fingerprint of the PublicKey. +func (pk *PublicKey) Fingerprint() []byte { + b := pk.Serialize(nil) + h := sha1.New() + h.Write(b[2:]) + return h.Sum(nil) +} + +func (pk *PublicKey) Verify(hashed, sig []byte) ([]byte, bool) { + if len(sig) != 2*dsaSubgroupBytes { + return nil, false + } + r := new(big.Int).SetBytes(sig[:dsaSubgroupBytes]) + s := new(big.Int).SetBytes(sig[dsaSubgroupBytes:]) + ok := dsa.Verify(&pk.PublicKey, hashed, r, s) + return sig[dsaSubgroupBytes*2:], ok +} + +type PrivateKey struct { + PublicKey + dsa.PrivateKey +} + +func (priv *PrivateKey) Sign(rand io.Reader, hashed []byte) []byte { + r, s, err := dsa.Sign(rand, &priv.PrivateKey, hashed) + if err != nil { + panic(err.Error()) + } + rBytes := r.Bytes() + sBytes := s.Bytes() + if len(rBytes) > dsaSubgroupBytes || len(sBytes) > dsaSubgroupBytes { + panic("DSA signature too large") + } + + out := make([]byte, 2*dsaSubgroupBytes) + copy(out[dsaSubgroupBytes-len(rBytes):], rBytes) + copy(out[len(out)-len(sBytes):], sBytes) + return out +} + +func (priv *PrivateKey) Serialize(in []byte) []byte { + in = priv.PublicKey.Serialize(in) + in = appendMPI(in, priv.PrivateKey.X) + return in +} + +func (priv *PrivateKey) Parse(in []byte) ([]byte, bool) { + in, ok := priv.PublicKey.Parse(in) + if !ok { + return in, ok + } + priv.PrivateKey.PublicKey = priv.PublicKey.PublicKey + priv.PrivateKey.X, in, ok = getMPI(in) + return in, ok +} + +func (priv *PrivateKey) Generate(rand io.Reader) { + if err := dsa.GenerateParameters(&priv.PrivateKey.PublicKey.Parameters, rand, dsa.L1024N160); err != nil { + panic(err.Error()) + } + if err := dsa.GenerateKey(&priv.PrivateKey, rand); err != nil { + panic(err.Error()) + } + priv.PublicKey.PublicKey = priv.PrivateKey.PublicKey +} + +func notHex(r rune) bool { + if r >= '0' && r <= '9' || + r >= 'a' && r <= 'f' || + r >= 'A' && r <= 'F' { + return false + } + + return true +} + +// Import parses the contents of a libotr private key file. +func (priv *PrivateKey) Import(in []byte) bool { + mpiStart := []byte(" #") + + mpis := make([]*big.Int, 5) + + for i := 0; i < len(mpis); i++ { + start := bytes.Index(in, mpiStart) + if start == -1 { + return false + } + in = in[start+len(mpiStart):] + end := bytes.IndexFunc(in, notHex) + if end == -1 { + return false + } + hexBytes := in[:end] + in = in[end:] + + if len(hexBytes)&1 != 0 { + return false + } + + mpiBytes := make([]byte, len(hexBytes)/2) + if _, err := hex.Decode(mpiBytes, hexBytes); err != nil { + return false + } + + mpis[i] = new(big.Int).SetBytes(mpiBytes) + } + + for _, mpi := range mpis { + if mpi.Sign() <= 0 { + return false + } + } + + priv.PrivateKey.P = mpis[0] + priv.PrivateKey.Q = mpis[1] + priv.PrivateKey.G = mpis[2] + priv.PrivateKey.Y = mpis[3] + priv.PrivateKey.X = mpis[4] + priv.PublicKey.PublicKey = priv.PrivateKey.PublicKey + + a := new(big.Int).Exp(priv.PrivateKey.G, priv.PrivateKey.X, priv.PrivateKey.P) + return a.Cmp(priv.PrivateKey.Y) == 0 +} + +func getU8(in []byte) (uint8, []byte, bool) { + if len(in) < 1 { + return 0, in, false + } + return in[0], in[1:], true +} + +func getU16(in []byte) (uint16, []byte, bool) { + if len(in) < 2 { + return 0, in, false + } + r := uint16(in[0])<<8 | uint16(in[1]) + return r, in[2:], true +} + +func getU32(in []byte) (uint32, []byte, bool) { + if len(in) < 4 { + return 0, in, false + } + r := uint32(in[0])<<24 | uint32(in[1])<<16 | uint32(in[2])<<8 | uint32(in[3]) + return r, in[4:], true +} + +func getMPI(in []byte) (*big.Int, []byte, bool) { + l, in, ok := getU32(in) + if !ok || uint32(len(in)) < l { + return nil, in, false + } + r := new(big.Int).SetBytes(in[:l]) + return r, in[l:], true +} + +func getData(in []byte) ([]byte, []byte, bool) { + l, in, ok := getU32(in) + if !ok || uint32(len(in)) < l { + return nil, in, false + } + return in[:l], in[l:], true +} + +func getNBytes(in []byte, n int) ([]byte, []byte, bool) { + if len(in) < n { + return nil, in, false + } + return in[:n], in[n:], true +} + +func appendU16(out []byte, v uint16) []byte { + out = append(out, byte(v>>8), byte(v)) + return out +} + +func appendU32(out []byte, v uint32) []byte { + out = append(out, byte(v>>24), byte(v>>16), byte(v>>8), byte(v)) + return out +} + +func appendData(out, v []byte) []byte { + out = appendU32(out, uint32(len(v))) + out = append(out, v...) + return out +} + +func appendMPI(out []byte, v *big.Int) []byte { + vBytes := v.Bytes() + out = appendU32(out, uint32(len(vBytes))) + out = append(out, vBytes...) + return out +} + +func appendMPIs(out []byte, mpis ...*big.Int) []byte { + for _, mpi := range mpis { + out = appendMPI(out, mpi) + } + return out +} + +func zero(b []byte) { + for i := range b { + b[i] = 0 + } +} diff --git a/vendor/golang.org/x/crypto/otr/otr_test.go b/vendor/golang.org/x/crypto/otr/otr_test.go new file mode 100644 index 0000000000000000000000000000000000000000..cfcd062b27450719e656374f0d9637787c44d5ff --- /dev/null +++ b/vendor/golang.org/x/crypto/otr/otr_test.go @@ -0,0 +1,470 @@ +// 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 otr + +import ( + "bufio" + "bytes" + "crypto/rand" + "encoding/hex" + "math/big" + "os" + "os/exec" + "testing" +) + +var isQueryTests = []struct { + msg string + expectedVersion int +}{ + {"foo", 0}, + {"?OtR", 0}, + {"?OtR?", 0}, + {"?OTR?", 0}, + {"?OTRv?", 0}, + {"?OTRv1?", 0}, + {"?OTR?v1?", 0}, + {"?OTR?v?", 0}, + {"?OTR?v2?", 2}, + {"?OTRv2?", 2}, + {"?OTRv23?", 2}, + {"?OTRv23 ?", 0}, +} + +func TestIsQuery(t *testing.T) { + for i, test := range isQueryTests { + version := isQuery([]byte(test.msg)) + if version != test.expectedVersion { + t.Errorf("#%d: got %d, want %d", i, version, test.expectedVersion) + } + } +} + +var alicePrivateKeyHex = "000000000080c81c2cb2eb729b7e6fd48e975a932c638b3a9055478583afa46755683e30102447f6da2d8bec9f386bbb5da6403b0040fee8650b6ab2d7f32c55ab017ae9b6aec8c324ab5844784e9a80e194830d548fb7f09a0410df2c4d5c8bc2b3e9ad484e65412be689cf0834694e0839fb2954021521ffdffb8f5c32c14dbf2020b3ce7500000014da4591d58def96de61aea7b04a8405fe1609308d000000808ddd5cb0b9d66956e3dea5a915d9aba9d8a6e7053b74dadb2fc52f9fe4e5bcc487d2305485ed95fed026ad93f06ebb8c9e8baf693b7887132c7ffdd3b0f72f4002ff4ed56583ca7c54458f8c068ca3e8a4dfa309d1dd5d34e2a4b68e6f4338835e5e0fb4317c9e4c7e4806dafda3ef459cd563775a586dd91b1319f72621bf3f00000080b8147e74d8c45e6318c37731b8b33b984a795b3653c2cd1d65cc99efe097cb7eb2fa49569bab5aab6e8a1c261a27d0f7840a5e80b317e6683042b59b6dceca2879c6ffc877a465be690c15e4a42f9a7588e79b10faac11b1ce3741fcef7aba8ce05327a2c16d279ee1b3d77eb783fb10e3356caa25635331e26dd42b8396c4d00000001420bec691fea37ecea58a5c717142f0b804452f57" + +var aliceFingerprintHex = "0bb01c360424522e94ee9c346ce877a1a4288b2f" + +var bobPrivateKeyHex = "000000000080a5138eb3d3eb9c1d85716faecadb718f87d31aaed1157671d7fee7e488f95e8e0ba60ad449ec732710a7dec5190f7182af2e2f98312d98497221dff160fd68033dd4f3a33b7c078d0d9f66e26847e76ca7447d4bab35486045090572863d9e4454777f24d6706f63e02548dfec2d0a620af37bbc1d24f884708a212c343b480d00000014e9c58f0ea21a5e4dfd9f44b6a9f7f6a9961a8fa9000000803c4d111aebd62d3c50c2889d420a32cdf1e98b70affcc1fcf44d59cca2eb019f6b774ef88153fb9b9615441a5fe25ea2d11b74ce922ca0232bd81b3c0fcac2a95b20cb6e6c0c5c1ace2e26f65dc43c751af0edbb10d669890e8ab6beea91410b8b2187af1a8347627a06ecea7e0f772c28aae9461301e83884860c9b656c722f0000008065af8625a555ea0e008cd04743671a3cda21162e83af045725db2eb2bb52712708dc0cc1a84c08b3649b88a966974bde27d8612c2861792ec9f08786a246fcadd6d8d3a81a32287745f309238f47618c2bd7612cb8b02d940571e0f30b96420bcd462ff542901b46109b1e5ad6423744448d20a57818a8cbb1647d0fea3b664e0000001440f9f2eb554cb00d45a5826b54bfa419b6980e48" + +func TestKeySerialization(t *testing.T) { + var priv PrivateKey + alicePrivateKey, _ := hex.DecodeString(alicePrivateKeyHex) + rest, ok := priv.Parse(alicePrivateKey) + if !ok { + t.Error("failed to parse private key") + } + if len(rest) > 0 { + t.Error("data remaining after parsing private key") + } + + out := priv.Serialize(nil) + if !bytes.Equal(alicePrivateKey, out) { + t.Errorf("serialization (%x) is not equal to original (%x)", out, alicePrivateKey) + } + + aliceFingerprint, _ := hex.DecodeString(aliceFingerprintHex) + fingerprint := priv.PublicKey.Fingerprint() + if !bytes.Equal(aliceFingerprint, fingerprint) { + t.Errorf("fingerprint (%x) is not equal to expected value (%x)", fingerprint, aliceFingerprint) + } +} + +const libOTRPrivateKey = `(privkeys + (account +(name "foo@example.com") +(protocol prpl-jabber) +(private-key + (dsa + (p #00FC07ABCF0DC916AFF6E9AE47BEF60C7AB9B4D6B2469E436630E36F8A489BE812486A09F30B71224508654940A835301ACC525A4FF133FC152CC53DCC59D65C30A54F1993FE13FE63E5823D4C746DB21B90F9B9C00B49EC7404AB1D929BA7FBA12F2E45C6E0A651689750E8528AB8C031D3561FECEE72EBB4A090D450A9B7A857#) + (q #00997BD266EF7B1F60A5C23F3A741F2AEFD07A2081#) + (g #535E360E8A95EBA46A4F7DE50AD6E9B2A6DB785A66B64EB9F20338D2A3E8FB0E94725848F1AA6CC567CB83A1CC517EC806F2E92EAE71457E80B2210A189B91250779434B41FC8A8873F6DB94BEA7D177F5D59E7E114EE10A49CFD9CEF88AE43387023B672927BA74B04EB6BBB5E57597766A2F9CE3857D7ACE3E1E3BC1FC6F26#) + (y #0AC8670AD767D7A8D9D14CC1AC6744CD7D76F993B77FFD9E39DF01E5A6536EF65E775FCEF2A983E2A19BD6415500F6979715D9FD1257E1FE2B6F5E1E74B333079E7C880D39868462A93454B41877BE62E5EF0A041C2EE9C9E76BD1E12AE25D9628DECB097025DD625EF49C3258A1A3C0FF501E3DC673B76D7BABF349009B6ECF#) + (x #14D0345A3562C480A039E3C72764F72D79043216#) + ) + ) + ) +)` + +func TestParseLibOTRPrivateKey(t *testing.T) { + var priv PrivateKey + + if !priv.Import([]byte(libOTRPrivateKey)) { + t.Fatalf("Failed to import sample private key") + } +} + +func TestSignVerify(t *testing.T) { + var priv PrivateKey + alicePrivateKey, _ := hex.DecodeString(alicePrivateKeyHex) + _, ok := priv.Parse(alicePrivateKey) + if !ok { + t.Error("failed to parse private key") + } + + var msg [32]byte + rand.Reader.Read(msg[:]) + + sig := priv.Sign(rand.Reader, msg[:]) + rest, ok := priv.PublicKey.Verify(msg[:], sig) + if !ok { + t.Errorf("signature (%x) of %x failed to verify", sig, msg[:]) + } else if len(rest) > 0 { + t.Error("signature data remains after verification") + } + + sig[10] ^= 80 + _, ok = priv.PublicKey.Verify(msg[:], sig) + if ok { + t.Errorf("corrupted signature (%x) of %x verified", sig, msg[:]) + } +} + +func setupConversation(t *testing.T) (alice, bob *Conversation) { + alicePrivateKey, _ := hex.DecodeString(alicePrivateKeyHex) + bobPrivateKey, _ := hex.DecodeString(bobPrivateKeyHex) + + alice, bob = new(Conversation), new(Conversation) + + alice.PrivateKey = new(PrivateKey) + bob.PrivateKey = new(PrivateKey) + alice.PrivateKey.Parse(alicePrivateKey) + bob.PrivateKey.Parse(bobPrivateKey) + alice.FragmentSize = 100 + bob.FragmentSize = 100 + + if alice.IsEncrypted() { + t.Error("Alice believes that the conversation is secure before we've started") + } + if bob.IsEncrypted() { + t.Error("Bob believes that the conversation is secure before we've started") + } + + performHandshake(t, alice, bob) + return alice, bob +} + +func performHandshake(t *testing.T, alice, bob *Conversation) { + var alicesMessage, bobsMessage [][]byte + var out []byte + var aliceChange, bobChange SecurityChange + var err error + alicesMessage = append(alicesMessage, []byte(QueryMessage)) + + for round := 0; len(alicesMessage) > 0 || len(bobsMessage) > 0; round++ { + bobsMessage = nil + for i, msg := range alicesMessage { + out, _, bobChange, bobsMessage, err = bob.Receive(msg) + if len(out) > 0 { + t.Errorf("Bob generated output during key exchange, round %d, message %d", round, i) + } + if err != nil { + t.Fatalf("Bob returned an error, round %d, message %d (%x): %s", round, i, msg, err) + } + if len(bobsMessage) > 0 && i != len(alicesMessage)-1 { + t.Errorf("Bob produced output while processing a fragment, round %d, message %d", round, i) + } + } + + alicesMessage = nil + for i, msg := range bobsMessage { + out, _, aliceChange, alicesMessage, err = alice.Receive(msg) + if len(out) > 0 { + t.Errorf("Alice generated output during key exchange, round %d, message %d", round, i) + } + if err != nil { + t.Fatalf("Alice returned an error, round %d, message %d (%x): %s", round, i, msg, err) + } + if len(alicesMessage) > 0 && i != len(bobsMessage)-1 { + t.Errorf("Alice produced output while processing a fragment, round %d, message %d", round, i) + } + } + } + + if aliceChange != NewKeys { + t.Errorf("Alice terminated without signaling new keys") + } + if bobChange != NewKeys { + t.Errorf("Bob terminated without signaling new keys") + } + + if !bytes.Equal(alice.SSID[:], bob.SSID[:]) { + t.Errorf("Session identifiers don't match. Alice has %x, Bob has %x", alice.SSID[:], bob.SSID[:]) + } + + if !alice.IsEncrypted() { + t.Error("Alice doesn't believe that the conversation is secure") + } + if !bob.IsEncrypted() { + t.Error("Bob doesn't believe that the conversation is secure") + } +} + +const ( + firstRoundTrip = iota + subsequentRoundTrip + noMACKeyCheck +) + +func roundTrip(t *testing.T, alice, bob *Conversation, message []byte, macKeyCheck int) { + alicesMessage, err := alice.Send(message) + if err != nil { + t.Errorf("Error from Alice sending message: %s", err) + } + + if len(alice.oldMACs) != 0 { + t.Errorf("Alice has not revealed all MAC keys") + } + + for i, msg := range alicesMessage { + out, encrypted, _, _, err := bob.Receive(msg) + + if err != nil { + t.Errorf("Error generated while processing test message: %s", err.Error()) + } + if len(out) > 0 { + if i != len(alicesMessage)-1 { + t.Fatal("Bob produced a message while processing a fragment of Alice's") + } + if !encrypted { + t.Errorf("Message was not marked as encrypted") + } + if !bytes.Equal(out, message) { + t.Errorf("Message corrupted: got %x, want %x", out, message) + } + } + } + + switch macKeyCheck { + case firstRoundTrip: + if len(bob.oldMACs) != 0 { + t.Errorf("Bob should not have MAC keys to reveal") + } + case subsequentRoundTrip: + if len(bob.oldMACs) != 40 { + t.Errorf("Bob has %d bytes of MAC keys to reveal, but should have 40", len(bob.oldMACs)) + } + } + + bobsMessage, err := bob.Send(message) + if err != nil { + t.Errorf("Error from Bob sending message: %s", err) + } + + if len(bob.oldMACs) != 0 { + t.Errorf("Bob has not revealed all MAC keys") + } + + for i, msg := range bobsMessage { + out, encrypted, _, _, err := alice.Receive(msg) + + if err != nil { + t.Errorf("Error generated while processing test message: %s", err.Error()) + } + if len(out) > 0 { + if i != len(bobsMessage)-1 { + t.Fatal("Alice produced a message while processing a fragment of Bob's") + } + if !encrypted { + t.Errorf("Message was not marked as encrypted") + } + if !bytes.Equal(out, message) { + t.Errorf("Message corrupted: got %x, want %x", out, message) + } + } + } + + switch macKeyCheck { + case firstRoundTrip: + if len(alice.oldMACs) != 20 { + t.Errorf("Alice has %d bytes of MAC keys to reveal, but should have 20", len(alice.oldMACs)) + } + case subsequentRoundTrip: + if len(alice.oldMACs) != 40 { + t.Errorf("Alice has %d bytes of MAC keys to reveal, but should have 40", len(alice.oldMACs)) + } + } +} + +func TestConversation(t *testing.T) { + alice, bob := setupConversation(t) + + var testMessages = [][]byte{ + []byte("hello"), []byte("bye"), + } + + roundTripType := firstRoundTrip + + for _, testMessage := range testMessages { + roundTrip(t, alice, bob, testMessage, roundTripType) + roundTripType = subsequentRoundTrip + } +} + +func TestGoodSMP(t *testing.T) { + var alice, bob Conversation + + alice.smp.secret = new(big.Int).SetInt64(42) + bob.smp.secret = alice.smp.secret + + var alicesMessages, bobsMessages []tlv + var aliceComplete, bobComplete bool + var err error + var out tlv + + alicesMessages = alice.startSMP("") + for round := 0; len(alicesMessages) > 0 || len(bobsMessages) > 0; round++ { + bobsMessages = bobsMessages[:0] + for i, msg := range alicesMessages { + out, bobComplete, err = bob.processSMP(msg) + if err != nil { + t.Errorf("Error from Bob in round %d: %s", round, err) + } + if bobComplete && i != len(alicesMessages)-1 { + t.Errorf("Bob returned a completed signal before processing all of Alice's messages in round %d", round) + } + if out.typ != 0 { + bobsMessages = append(bobsMessages, out) + } + } + + alicesMessages = alicesMessages[:0] + for i, msg := range bobsMessages { + out, aliceComplete, err = alice.processSMP(msg) + if err != nil { + t.Errorf("Error from Alice in round %d: %s", round, err) + } + if aliceComplete && i != len(bobsMessages)-1 { + t.Errorf("Alice returned a completed signal before processing all of Bob's messages in round %d", round) + } + if out.typ != 0 { + alicesMessages = append(alicesMessages, out) + } + } + } + + if !aliceComplete || !bobComplete { + t.Errorf("SMP completed without both sides reporting success: alice: %v, bob: %v\n", aliceComplete, bobComplete) + } +} + +func TestBadSMP(t *testing.T) { + var alice, bob Conversation + + alice.smp.secret = new(big.Int).SetInt64(42) + bob.smp.secret = new(big.Int).SetInt64(43) + + var alicesMessages, bobsMessages []tlv + + alicesMessages = alice.startSMP("") + for round := 0; len(alicesMessages) > 0 || len(bobsMessages) > 0; round++ { + bobsMessages = bobsMessages[:0] + for _, msg := range alicesMessages { + out, complete, _ := bob.processSMP(msg) + if complete { + t.Errorf("Bob signaled completion in round %d", round) + } + if out.typ != 0 { + bobsMessages = append(bobsMessages, out) + } + } + + alicesMessages = alicesMessages[:0] + for _, msg := range bobsMessages { + out, complete, _ := alice.processSMP(msg) + if complete { + t.Errorf("Alice signaled completion in round %d", round) + } + if out.typ != 0 { + alicesMessages = append(alicesMessages, out) + } + } + } +} + +func TestRehandshaking(t *testing.T) { + alice, bob := setupConversation(t) + roundTrip(t, alice, bob, []byte("test"), firstRoundTrip) + roundTrip(t, alice, bob, []byte("test 2"), subsequentRoundTrip) + roundTrip(t, alice, bob, []byte("test 3"), subsequentRoundTrip) + roundTrip(t, alice, bob, []byte("test 4"), subsequentRoundTrip) + roundTrip(t, alice, bob, []byte("test 5"), subsequentRoundTrip) + roundTrip(t, alice, bob, []byte("test 6"), subsequentRoundTrip) + roundTrip(t, alice, bob, []byte("test 7"), subsequentRoundTrip) + roundTrip(t, alice, bob, []byte("test 8"), subsequentRoundTrip) + performHandshake(t, alice, bob) + roundTrip(t, alice, bob, []byte("test"), noMACKeyCheck) + roundTrip(t, alice, bob, []byte("test 2"), noMACKeyCheck) +} + +func TestAgainstLibOTR(t *testing.T) { + // This test requires otr.c.test to be built as /tmp/a.out. + // If enabled, this tests runs forever performing OTR handshakes in a + // loop. + return + + alicePrivateKey, _ := hex.DecodeString(alicePrivateKeyHex) + var alice Conversation + alice.PrivateKey = new(PrivateKey) + alice.PrivateKey.Parse(alicePrivateKey) + + cmd := exec.Command("/tmp/a.out") + cmd.Stderr = os.Stderr + + out, err := cmd.StdinPipe() + if err != nil { + t.Fatal(err) + } + defer out.Close() + stdout, err := cmd.StdoutPipe() + if err != nil { + t.Fatal(err) + } + in := bufio.NewReader(stdout) + + if err := cmd.Start(); err != nil { + t.Fatal(err) + } + + out.Write([]byte(QueryMessage)) + out.Write([]byte("\n")) + var expectedText = []byte("test message") + + for { + line, isPrefix, err := in.ReadLine() + if isPrefix { + t.Fatal("line from subprocess too long") + } + if err != nil { + t.Fatal(err) + } + text, encrypted, change, alicesMessage, err := alice.Receive(line) + if err != nil { + t.Fatal(err) + } + for _, msg := range alicesMessage { + out.Write(msg) + out.Write([]byte("\n")) + } + if change == NewKeys { + alicesMessage, err := alice.Send([]byte("Go -> libotr test message")) + if err != nil { + t.Fatalf("error sending message: %s", err.Error()) + } else { + for _, msg := range alicesMessage { + out.Write(msg) + out.Write([]byte("\n")) + } + } + } + if len(text) > 0 { + if !bytes.Equal(text, expectedText) { + t.Fatalf("expected %x, but got %x", expectedText, text) + } + if !encrypted { + t.Fatal("message wasn't encrypted") + } + } + } +} diff --git a/vendor/golang.org/x/crypto/otr/smp.go b/vendor/golang.org/x/crypto/otr/smp.go new file mode 100644 index 0000000000000000000000000000000000000000..dc6de4ee0eb74d0a92a5240ef63a76e63af7eaab --- /dev/null +++ b/vendor/golang.org/x/crypto/otr/smp.go @@ -0,0 +1,572 @@ +// 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 file implements the Socialist Millionaires Protocol as described in +// http://www.cypherpunks.ca/otr/Protocol-v2-3.1.0.html. The protocol +// specification is required in order to understand this code and, where +// possible, the variable names in the code match up with the spec. + +package otr + +import ( + "bytes" + "crypto/sha256" + "errors" + "hash" + "math/big" +) + +type smpFailure string + +func (s smpFailure) Error() string { + return string(s) +} + +var smpFailureError = smpFailure("otr: SMP protocol failed") +var smpSecretMissingError = smpFailure("otr: mutual secret needed") + +const smpVersion = 1 + +const ( + smpState1 = iota + smpState2 + smpState3 + smpState4 +) + +type smpState struct { + state int + a2, a3, b2, b3, pb, qb *big.Int + g2a, g3a *big.Int + g2, g3 *big.Int + g3b, papb, qaqb, ra *big.Int + saved *tlv + secret *big.Int + question string +} + +func (c *Conversation) startSMP(question string) (tlvs []tlv) { + if c.smp.state != smpState1 { + tlvs = append(tlvs, c.generateSMPAbort()) + } + tlvs = append(tlvs, c.generateSMP1(question)) + c.smp.question = "" + c.smp.state = smpState2 + return +} + +func (c *Conversation) resetSMP() { + c.smp.state = smpState1 + c.smp.secret = nil + c.smp.question = "" +} + +func (c *Conversation) processSMP(in tlv) (out tlv, complete bool, err error) { + data := in.data + + switch in.typ { + case tlvTypeSMPAbort: + if c.smp.state != smpState1 { + err = smpFailureError + } + c.resetSMP() + return + case tlvTypeSMP1WithQuestion: + // We preprocess this into a SMP1 message. + nulPos := bytes.IndexByte(data, 0) + if nulPos == -1 { + err = errors.New("otr: SMP message with question didn't contain a NUL byte") + return + } + c.smp.question = string(data[:nulPos]) + data = data[nulPos+1:] + } + + numMPIs, data, ok := getU32(data) + if !ok || numMPIs > 20 { + err = errors.New("otr: corrupt SMP message") + return + } + + mpis := make([]*big.Int, numMPIs) + for i := range mpis { + var ok bool + mpis[i], data, ok = getMPI(data) + if !ok { + err = errors.New("otr: corrupt SMP message") + return + } + } + + switch in.typ { + case tlvTypeSMP1, tlvTypeSMP1WithQuestion: + if c.smp.state != smpState1 { + c.resetSMP() + out = c.generateSMPAbort() + return + } + if c.smp.secret == nil { + err = smpSecretMissingError + return + } + if err = c.processSMP1(mpis); err != nil { + return + } + c.smp.state = smpState3 + out = c.generateSMP2() + case tlvTypeSMP2: + if c.smp.state != smpState2 { + c.resetSMP() + out = c.generateSMPAbort() + return + } + if out, err = c.processSMP2(mpis); err != nil { + out = c.generateSMPAbort() + return + } + c.smp.state = smpState4 + case tlvTypeSMP3: + if c.smp.state != smpState3 { + c.resetSMP() + out = c.generateSMPAbort() + return + } + if out, err = c.processSMP3(mpis); err != nil { + return + } + c.smp.state = smpState1 + c.smp.secret = nil + complete = true + case tlvTypeSMP4: + if c.smp.state != smpState4 { + c.resetSMP() + out = c.generateSMPAbort() + return + } + if err = c.processSMP4(mpis); err != nil { + out = c.generateSMPAbort() + return + } + c.smp.state = smpState1 + c.smp.secret = nil + complete = true + default: + panic("unknown SMP message") + } + + return +} + +func (c *Conversation) calcSMPSecret(mutualSecret []byte, weStarted bool) { + h := sha256.New() + h.Write([]byte{smpVersion}) + if weStarted { + h.Write(c.PrivateKey.PublicKey.Fingerprint()) + h.Write(c.TheirPublicKey.Fingerprint()) + } else { + h.Write(c.TheirPublicKey.Fingerprint()) + h.Write(c.PrivateKey.PublicKey.Fingerprint()) + } + h.Write(c.SSID[:]) + h.Write(mutualSecret) + c.smp.secret = new(big.Int).SetBytes(h.Sum(nil)) +} + +func (c *Conversation) generateSMP1(question string) tlv { + var randBuf [16]byte + c.smp.a2 = c.randMPI(randBuf[:]) + c.smp.a3 = c.randMPI(randBuf[:]) + g2a := new(big.Int).Exp(g, c.smp.a2, p) + g3a := new(big.Int).Exp(g, c.smp.a3, p) + h := sha256.New() + + r2 := c.randMPI(randBuf[:]) + r := new(big.Int).Exp(g, r2, p) + c2 := new(big.Int).SetBytes(hashMPIs(h, 1, r)) + d2 := new(big.Int).Mul(c.smp.a2, c2) + d2.Sub(r2, d2) + d2.Mod(d2, q) + if d2.Sign() < 0 { + d2.Add(d2, q) + } + + r3 := c.randMPI(randBuf[:]) + r.Exp(g, r3, p) + c3 := new(big.Int).SetBytes(hashMPIs(h, 2, r)) + d3 := new(big.Int).Mul(c.smp.a3, c3) + d3.Sub(r3, d3) + d3.Mod(d3, q) + if d3.Sign() < 0 { + d3.Add(d3, q) + } + + var ret tlv + if len(question) > 0 { + ret.typ = tlvTypeSMP1WithQuestion + ret.data = append(ret.data, question...) + ret.data = append(ret.data, 0) + } else { + ret.typ = tlvTypeSMP1 + } + ret.data = appendU32(ret.data, 6) + ret.data = appendMPIs(ret.data, g2a, c2, d2, g3a, c3, d3) + return ret +} + +func (c *Conversation) processSMP1(mpis []*big.Int) error { + if len(mpis) != 6 { + return errors.New("otr: incorrect number of arguments in SMP1 message") + } + g2a := mpis[0] + c2 := mpis[1] + d2 := mpis[2] + g3a := mpis[3] + c3 := mpis[4] + d3 := mpis[5] + h := sha256.New() + + r := new(big.Int).Exp(g, d2, p) + s := new(big.Int).Exp(g2a, c2, p) + r.Mul(r, s) + r.Mod(r, p) + t := new(big.Int).SetBytes(hashMPIs(h, 1, r)) + if c2.Cmp(t) != 0 { + return errors.New("otr: ZKP c2 incorrect in SMP1 message") + } + r.Exp(g, d3, p) + s.Exp(g3a, c3, p) + r.Mul(r, s) + r.Mod(r, p) + t.SetBytes(hashMPIs(h, 2, r)) + if c3.Cmp(t) != 0 { + return errors.New("otr: ZKP c3 incorrect in SMP1 message") + } + + c.smp.g2a = g2a + c.smp.g3a = g3a + return nil +} + +func (c *Conversation) generateSMP2() tlv { + var randBuf [16]byte + b2 := c.randMPI(randBuf[:]) + c.smp.b3 = c.randMPI(randBuf[:]) + r2 := c.randMPI(randBuf[:]) + r3 := c.randMPI(randBuf[:]) + r4 := c.randMPI(randBuf[:]) + r5 := c.randMPI(randBuf[:]) + r6 := c.randMPI(randBuf[:]) + + g2b := new(big.Int).Exp(g, b2, p) + g3b := new(big.Int).Exp(g, c.smp.b3, p) + + r := new(big.Int).Exp(g, r2, p) + h := sha256.New() + c2 := new(big.Int).SetBytes(hashMPIs(h, 3, r)) + d2 := new(big.Int).Mul(b2, c2) + d2.Sub(r2, d2) + d2.Mod(d2, q) + if d2.Sign() < 0 { + d2.Add(d2, q) + } + + r.Exp(g, r3, p) + c3 := new(big.Int).SetBytes(hashMPIs(h, 4, r)) + d3 := new(big.Int).Mul(c.smp.b3, c3) + d3.Sub(r3, d3) + d3.Mod(d3, q) + if d3.Sign() < 0 { + d3.Add(d3, q) + } + + c.smp.g2 = new(big.Int).Exp(c.smp.g2a, b2, p) + c.smp.g3 = new(big.Int).Exp(c.smp.g3a, c.smp.b3, p) + c.smp.pb = new(big.Int).Exp(c.smp.g3, r4, p) + c.smp.qb = new(big.Int).Exp(g, r4, p) + r.Exp(c.smp.g2, c.smp.secret, p) + c.smp.qb.Mul(c.smp.qb, r) + c.smp.qb.Mod(c.smp.qb, p) + + s := new(big.Int) + s.Exp(c.smp.g2, r6, p) + r.Exp(g, r5, p) + s.Mul(r, s) + s.Mod(s, p) + r.Exp(c.smp.g3, r5, p) + cp := new(big.Int).SetBytes(hashMPIs(h, 5, r, s)) + + // D5 = r5 - r4 cP mod q and D6 = r6 - y cP mod q + + s.Mul(r4, cp) + r.Sub(r5, s) + d5 := new(big.Int).Mod(r, q) + if d5.Sign() < 0 { + d5.Add(d5, q) + } + + s.Mul(c.smp.secret, cp) + r.Sub(r6, s) + d6 := new(big.Int).Mod(r, q) + if d6.Sign() < 0 { + d6.Add(d6, q) + } + + var ret tlv + ret.typ = tlvTypeSMP2 + ret.data = appendU32(ret.data, 11) + ret.data = appendMPIs(ret.data, g2b, c2, d2, g3b, c3, d3, c.smp.pb, c.smp.qb, cp, d5, d6) + return ret +} + +func (c *Conversation) processSMP2(mpis []*big.Int) (out tlv, err error) { + if len(mpis) != 11 { + err = errors.New("otr: incorrect number of arguments in SMP2 message") + return + } + g2b := mpis[0] + c2 := mpis[1] + d2 := mpis[2] + g3b := mpis[3] + c3 := mpis[4] + d3 := mpis[5] + pb := mpis[6] + qb := mpis[7] + cp := mpis[8] + d5 := mpis[9] + d6 := mpis[10] + h := sha256.New() + + r := new(big.Int).Exp(g, d2, p) + s := new(big.Int).Exp(g2b, c2, p) + r.Mul(r, s) + r.Mod(r, p) + s.SetBytes(hashMPIs(h, 3, r)) + if c2.Cmp(s) != 0 { + err = errors.New("otr: ZKP c2 failed in SMP2 message") + return + } + + r.Exp(g, d3, p) + s.Exp(g3b, c3, p) + r.Mul(r, s) + r.Mod(r, p) + s.SetBytes(hashMPIs(h, 4, r)) + if c3.Cmp(s) != 0 { + err = errors.New("otr: ZKP c3 failed in SMP2 message") + return + } + + c.smp.g2 = new(big.Int).Exp(g2b, c.smp.a2, p) + c.smp.g3 = new(big.Int).Exp(g3b, c.smp.a3, p) + + r.Exp(g, d5, p) + s.Exp(c.smp.g2, d6, p) + r.Mul(r, s) + s.Exp(qb, cp, p) + r.Mul(r, s) + r.Mod(r, p) + + s.Exp(c.smp.g3, d5, p) + t := new(big.Int).Exp(pb, cp, p) + s.Mul(s, t) + s.Mod(s, p) + t.SetBytes(hashMPIs(h, 5, s, r)) + if cp.Cmp(t) != 0 { + err = errors.New("otr: ZKP cP failed in SMP2 message") + return + } + + var randBuf [16]byte + r4 := c.randMPI(randBuf[:]) + r5 := c.randMPI(randBuf[:]) + r6 := c.randMPI(randBuf[:]) + r7 := c.randMPI(randBuf[:]) + + pa := new(big.Int).Exp(c.smp.g3, r4, p) + r.Exp(c.smp.g2, c.smp.secret, p) + qa := new(big.Int).Exp(g, r4, p) + qa.Mul(qa, r) + qa.Mod(qa, p) + + r.Exp(g, r5, p) + s.Exp(c.smp.g2, r6, p) + r.Mul(r, s) + r.Mod(r, p) + + s.Exp(c.smp.g3, r5, p) + cp.SetBytes(hashMPIs(h, 6, s, r)) + + r.Mul(r4, cp) + d5 = new(big.Int).Sub(r5, r) + d5.Mod(d5, q) + if d5.Sign() < 0 { + d5.Add(d5, q) + } + + r.Mul(c.smp.secret, cp) + d6 = new(big.Int).Sub(r6, r) + d6.Mod(d6, q) + if d6.Sign() < 0 { + d6.Add(d6, q) + } + + r.ModInverse(qb, p) + qaqb := new(big.Int).Mul(qa, r) + qaqb.Mod(qaqb, p) + + ra := new(big.Int).Exp(qaqb, c.smp.a3, p) + r.Exp(qaqb, r7, p) + s.Exp(g, r7, p) + cr := new(big.Int).SetBytes(hashMPIs(h, 7, s, r)) + + r.Mul(c.smp.a3, cr) + d7 := new(big.Int).Sub(r7, r) + d7.Mod(d7, q) + if d7.Sign() < 0 { + d7.Add(d7, q) + } + + c.smp.g3b = g3b + c.smp.qaqb = qaqb + + r.ModInverse(pb, p) + c.smp.papb = new(big.Int).Mul(pa, r) + c.smp.papb.Mod(c.smp.papb, p) + c.smp.ra = ra + + out.typ = tlvTypeSMP3 + out.data = appendU32(out.data, 8) + out.data = appendMPIs(out.data, pa, qa, cp, d5, d6, ra, cr, d7) + return +} + +func (c *Conversation) processSMP3(mpis []*big.Int) (out tlv, err error) { + if len(mpis) != 8 { + err = errors.New("otr: incorrect number of arguments in SMP3 message") + return + } + pa := mpis[0] + qa := mpis[1] + cp := mpis[2] + d5 := mpis[3] + d6 := mpis[4] + ra := mpis[5] + cr := mpis[6] + d7 := mpis[7] + h := sha256.New() + + r := new(big.Int).Exp(g, d5, p) + s := new(big.Int).Exp(c.smp.g2, d6, p) + r.Mul(r, s) + s.Exp(qa, cp, p) + r.Mul(r, s) + r.Mod(r, p) + + s.Exp(c.smp.g3, d5, p) + t := new(big.Int).Exp(pa, cp, p) + s.Mul(s, t) + s.Mod(s, p) + t.SetBytes(hashMPIs(h, 6, s, r)) + if t.Cmp(cp) != 0 { + err = errors.New("otr: ZKP cP failed in SMP3 message") + return + } + + r.ModInverse(c.smp.qb, p) + qaqb := new(big.Int).Mul(qa, r) + qaqb.Mod(qaqb, p) + + r.Exp(qaqb, d7, p) + s.Exp(ra, cr, p) + r.Mul(r, s) + r.Mod(r, p) + + s.Exp(g, d7, p) + t.Exp(c.smp.g3a, cr, p) + s.Mul(s, t) + s.Mod(s, p) + t.SetBytes(hashMPIs(h, 7, s, r)) + if t.Cmp(cr) != 0 { + err = errors.New("otr: ZKP cR failed in SMP3 message") + return + } + + var randBuf [16]byte + r7 := c.randMPI(randBuf[:]) + rb := new(big.Int).Exp(qaqb, c.smp.b3, p) + + r.Exp(qaqb, r7, p) + s.Exp(g, r7, p) + cr = new(big.Int).SetBytes(hashMPIs(h, 8, s, r)) + + r.Mul(c.smp.b3, cr) + d7 = new(big.Int).Sub(r7, r) + d7.Mod(d7, q) + if d7.Sign() < 0 { + d7.Add(d7, q) + } + + out.typ = tlvTypeSMP4 + out.data = appendU32(out.data, 3) + out.data = appendMPIs(out.data, rb, cr, d7) + + r.ModInverse(c.smp.pb, p) + r.Mul(pa, r) + r.Mod(r, p) + s.Exp(ra, c.smp.b3, p) + if r.Cmp(s) != 0 { + err = smpFailureError + } + + return +} + +func (c *Conversation) processSMP4(mpis []*big.Int) error { + if len(mpis) != 3 { + return errors.New("otr: incorrect number of arguments in SMP4 message") + } + rb := mpis[0] + cr := mpis[1] + d7 := mpis[2] + h := sha256.New() + + r := new(big.Int).Exp(c.smp.qaqb, d7, p) + s := new(big.Int).Exp(rb, cr, p) + r.Mul(r, s) + r.Mod(r, p) + + s.Exp(g, d7, p) + t := new(big.Int).Exp(c.smp.g3b, cr, p) + s.Mul(s, t) + s.Mod(s, p) + t.SetBytes(hashMPIs(h, 8, s, r)) + if t.Cmp(cr) != 0 { + return errors.New("otr: ZKP cR failed in SMP4 message") + } + + r.Exp(rb, c.smp.a3, p) + if r.Cmp(c.smp.papb) != 0 { + return smpFailureError + } + + return nil +} + +func (c *Conversation) generateSMPAbort() tlv { + return tlv{typ: tlvTypeSMPAbort} +} + +func hashMPIs(h hash.Hash, magic byte, mpis ...*big.Int) []byte { + if h != nil { + h.Reset() + } else { + h = sha256.New() + } + + h.Write([]byte{magic}) + for _, mpi := range mpis { + h.Write(appendMPI(nil, mpi)) + } + return h.Sum(nil) +} diff --git a/vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go b/vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go new file mode 100644 index 0000000000000000000000000000000000000000..593f6530084f246495fc42f2ce6d59a2bccb4c17 --- /dev/null +++ b/vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go @@ -0,0 +1,77 @@ +// 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 pbkdf2 implements the key derivation function PBKDF2 as defined in RFC +2898 / PKCS #5 v2.0. + +A key derivation function is useful when encrypting data based on a password +or any other not-fully-random data. It uses a pseudorandom function to derive +a secure encryption key based on the password. + +While v2.0 of the standard defines only one pseudorandom function to use, +HMAC-SHA1, the drafted v2.1 specification allows use of all five FIPS Approved +Hash Functions SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 for HMAC. To +choose, you can pass the `New` functions from the different SHA packages to +pbkdf2.Key. +*/ +package pbkdf2 // import "golang.org/x/crypto/pbkdf2" + +import ( + "crypto/hmac" + "hash" +) + +// Key derives a key from the password, salt and iteration count, returning a +// []byte of length keylen that can be used as cryptographic key. The key is +// derived based on the method described as PBKDF2 with the HMAC variant using +// the supplied hash function. +// +// For example, to use a HMAC-SHA-1 based PBKDF2 key derivation function, you +// can get a derived key for e.g. AES-256 (which needs a 32-byte key) by +// doing: +// +// dk := pbkdf2.Key([]byte("some password"), salt, 4096, 32, sha1.New) +// +// Remember to get a good random salt. At least 8 bytes is recommended by the +// RFC. +// +// Using a higher iteration count will increase the cost of an exhaustive +// search but will also make derivation proportionally slower. +func Key(password, salt []byte, iter, keyLen int, h func() hash.Hash) []byte { + prf := hmac.New(h, password) + hashLen := prf.Size() + numBlocks := (keyLen + hashLen - 1) / hashLen + + var buf [4]byte + dk := make([]byte, 0, numBlocks*hashLen) + U := make([]byte, hashLen) + for block := 1; block <= numBlocks; block++ { + // N.B.: || means concatenation, ^ means XOR + // for each block T_i = U_1 ^ U_2 ^ ... ^ U_iter + // U_1 = PRF(password, salt || uint(i)) + prf.Reset() + prf.Write(salt) + buf[0] = byte(block >> 24) + buf[1] = byte(block >> 16) + buf[2] = byte(block >> 8) + buf[3] = byte(block) + prf.Write(buf[:4]) + dk = prf.Sum(dk) + T := dk[len(dk)-hashLen:] + copy(U, T) + + // U_n = PRF(password, U_(n-1)) + for n := 2; n <= iter; n++ { + prf.Reset() + prf.Write(U) + U = U[:0] + U = prf.Sum(U) + for x := range U { + T[x] ^= U[x] + } + } + } + return dk[:keyLen] +} diff --git a/vendor/golang.org/x/crypto/pbkdf2/pbkdf2_test.go b/vendor/golang.org/x/crypto/pbkdf2/pbkdf2_test.go new file mode 100644 index 0000000000000000000000000000000000000000..f83cb69227371abdde10a6d7792636ab91715688 --- /dev/null +++ b/vendor/golang.org/x/crypto/pbkdf2/pbkdf2_test.go @@ -0,0 +1,176 @@ +// 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 pbkdf2 + +import ( + "bytes" + "crypto/sha1" + "crypto/sha256" + "hash" + "testing" +) + +type testVector struct { + password string + salt string + iter int + output []byte +} + +// Test vectors from RFC 6070, http://tools.ietf.org/html/rfc6070 +var sha1TestVectors = []testVector{ + { + "password", + "salt", + 1, + []byte{ + 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71, + 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06, + 0x2f, 0xe0, 0x37, 0xa6, + }, + }, + { + "password", + "salt", + 2, + []byte{ + 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c, + 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0, + 0xd8, 0xde, 0x89, 0x57, + }, + }, + { + "password", + "salt", + 4096, + []byte{ + 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a, + 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0, + 0x65, 0xa4, 0x29, 0xc1, + }, + }, + // // This one takes too long + // { + // "password", + // "salt", + // 16777216, + // []byte{ + // 0xee, 0xfe, 0x3d, 0x61, 0xcd, 0x4d, 0xa4, 0xe4, + // 0xe9, 0x94, 0x5b, 0x3d, 0x6b, 0xa2, 0x15, 0x8c, + // 0x26, 0x34, 0xe9, 0x84, + // }, + // }, + { + "passwordPASSWORDpassword", + "saltSALTsaltSALTsaltSALTsaltSALTsalt", + 4096, + []byte{ + 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b, + 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a, + 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70, + 0x38, + }, + }, + { + "pass\000word", + "sa\000lt", + 4096, + []byte{ + 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d, + 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3, + }, + }, +} + +// Test vectors from +// http://stackoverflow.com/questions/5130513/pbkdf2-hmac-sha2-test-vectors +var sha256TestVectors = []testVector{ + { + "password", + "salt", + 1, + []byte{ + 0x12, 0x0f, 0xb6, 0xcf, 0xfc, 0xf8, 0xb3, 0x2c, + 0x43, 0xe7, 0x22, 0x52, 0x56, 0xc4, 0xf8, 0x37, + 0xa8, 0x65, 0x48, 0xc9, + }, + }, + { + "password", + "salt", + 2, + []byte{ + 0xae, 0x4d, 0x0c, 0x95, 0xaf, 0x6b, 0x46, 0xd3, + 0x2d, 0x0a, 0xdf, 0xf9, 0x28, 0xf0, 0x6d, 0xd0, + 0x2a, 0x30, 0x3f, 0x8e, + }, + }, + { + "password", + "salt", + 4096, + []byte{ + 0xc5, 0xe4, 0x78, 0xd5, 0x92, 0x88, 0xc8, 0x41, + 0xaa, 0x53, 0x0d, 0xb6, 0x84, 0x5c, 0x4c, 0x8d, + 0x96, 0x28, 0x93, 0xa0, + }, + }, + { + "passwordPASSWORDpassword", + "saltSALTsaltSALTsaltSALTsaltSALTsalt", + 4096, + []byte{ + 0x34, 0x8c, 0x89, 0xdb, 0xcb, 0xd3, 0x2b, 0x2f, + 0x32, 0xd8, 0x14, 0xb8, 0x11, 0x6e, 0x84, 0xcf, + 0x2b, 0x17, 0x34, 0x7e, 0xbc, 0x18, 0x00, 0x18, + 0x1c, + }, + }, + { + "pass\000word", + "sa\000lt", + 4096, + []byte{ + 0x89, 0xb6, 0x9d, 0x05, 0x16, 0xf8, 0x29, 0x89, + 0x3c, 0x69, 0x62, 0x26, 0x65, 0x0a, 0x86, 0x87, + }, + }, +} + +func testHash(t *testing.T, h func() hash.Hash, hashName string, vectors []testVector) { + for i, v := range vectors { + o := Key([]byte(v.password), []byte(v.salt), v.iter, len(v.output), h) + if !bytes.Equal(o, v.output) { + t.Errorf("%s %d: expected %x, got %x", hashName, i, v.output, o) + } + } +} + +func TestWithHMACSHA1(t *testing.T) { + testHash(t, sha1.New, "SHA1", sha1TestVectors) +} + +func TestWithHMACSHA256(t *testing.T) { + testHash(t, sha256.New, "SHA256", sha256TestVectors) +} + +var sink uint8 + +func benchmark(b *testing.B, h func() hash.Hash) { + password := make([]byte, h().Size()) + salt := make([]byte, 8) + for i := 0; i < b.N; i++ { + password = Key(password, salt, 4096, len(password), h) + } + sink += password[0] +} + +func BenchmarkHMACSHA1(b *testing.B) { + benchmark(b, sha1.New) +} + +func BenchmarkHMACSHA256(b *testing.B) { + benchmark(b, sha256.New) +} diff --git a/vendor/golang.org/x/crypto/pkcs12/bmp-string.go b/vendor/golang.org/x/crypto/pkcs12/bmp-string.go new file mode 100644 index 0000000000000000000000000000000000000000..233b8b62cc2708ff95e4112ba7bf12b35c89ba71 --- /dev/null +++ b/vendor/golang.org/x/crypto/pkcs12/bmp-string.go @@ -0,0 +1,50 @@ +// Copyright 2015 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 pkcs12 + +import ( + "errors" + "unicode/utf16" +) + +// bmpString returns s encoded in UCS-2 with a zero terminator. +func bmpString(s string) ([]byte, error) { + // References: + // https://tools.ietf.org/html/rfc7292#appendix-B.1 + // https://en.wikipedia.org/wiki/Plane_(Unicode)#Basic_Multilingual_Plane + // - non-BMP characters are encoded in UTF 16 by using a surrogate pair of 16-bit codes + // EncodeRune returns 0xfffd if the rune does not need special encoding + // - the above RFC provides the info that BMPStrings are NULL terminated. + + ret := make([]byte, 0, 2*len(s)+2) + + for _, r := range s { + if t, _ := utf16.EncodeRune(r); t != 0xfffd { + return nil, errors.New("pkcs12: string contains characters that cannot be encoded in UCS-2") + } + ret = append(ret, byte(r/256), byte(r%256)) + } + + return append(ret, 0, 0), nil +} + +func decodeBMPString(bmpString []byte) (string, error) { + if len(bmpString)%2 != 0 { + return "", errors.New("pkcs12: odd-length BMP string") + } + + // strip terminator if present + if l := len(bmpString); l >= 2 && bmpString[l-1] == 0 && bmpString[l-2] == 0 { + bmpString = bmpString[:l-2] + } + + s := make([]uint16, 0, len(bmpString)/2) + for len(bmpString) > 0 { + s = append(s, uint16(bmpString[0])<<8+uint16(bmpString[1])) + bmpString = bmpString[2:] + } + + return string(utf16.Decode(s)), nil +} diff --git a/vendor/golang.org/x/crypto/pkcs12/bmp-string_test.go b/vendor/golang.org/x/crypto/pkcs12/bmp-string_test.go new file mode 100644 index 0000000000000000000000000000000000000000..7fca55f4e8b3a90a8346980fe9738fda799c90c7 --- /dev/null +++ b/vendor/golang.org/x/crypto/pkcs12/bmp-string_test.go @@ -0,0 +1,63 @@ +// Copyright 2015 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 pkcs12 + +import ( + "bytes" + "encoding/hex" + "testing" +) + +var bmpStringTests = []struct { + in string + expectedHex string + shouldFail bool +}{ + {"", "0000", false}, + // Example from https://tools.ietf.org/html/rfc7292#appendix-B. + {"Beavis", "0042006500610076006900730000", false}, + // Some characters from the "Letterlike Symbols Unicode block". + {"\u2115 - Double-struck N", "21150020002d00200044006f00750062006c0065002d00730074007200750063006b0020004e0000", false}, + // any character outside the BMP should trigger an error. + {"\U0001f000 East wind (Mahjong)", "", true}, +} + +func TestBMPString(t *testing.T) { + for i, test := range bmpStringTests { + expected, err := hex.DecodeString(test.expectedHex) + if err != nil { + t.Fatalf("#%d: failed to decode expectation", i) + } + + out, err := bmpString(test.in) + if err == nil && test.shouldFail { + t.Errorf("#%d: expected to fail, but produced %x", i, out) + continue + } + + if err != nil && !test.shouldFail { + t.Errorf("#%d: failed unexpectedly: %s", i, err) + continue + } + + if !test.shouldFail { + if !bytes.Equal(out, expected) { + t.Errorf("#%d: expected %s, got %x", i, test.expectedHex, out) + continue + } + + roundTrip, err := decodeBMPString(out) + if err != nil { + t.Errorf("#%d: decoding output gave an error: %s", i, err) + continue + } + + if roundTrip != test.in { + t.Errorf("#%d: decoding output resulted in %q, but it should have been %q", i, roundTrip, test.in) + continue + } + } + } +} diff --git a/vendor/golang.org/x/crypto/pkcs12/crypto.go b/vendor/golang.org/x/crypto/pkcs12/crypto.go new file mode 100644 index 0000000000000000000000000000000000000000..484ca51b715423854d8df00094c0af2203339520 --- /dev/null +++ b/vendor/golang.org/x/crypto/pkcs12/crypto.go @@ -0,0 +1,131 @@ +// Copyright 2015 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 pkcs12 + +import ( + "bytes" + "crypto/cipher" + "crypto/des" + "crypto/x509/pkix" + "encoding/asn1" + "errors" + + "golang.org/x/crypto/pkcs12/internal/rc2" +) + +var ( + oidPBEWithSHAAnd3KeyTripleDESCBC = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 1, 3}) + oidPBEWithSHAAnd40BitRC2CBC = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 1, 6}) +) + +// pbeCipher is an abstraction of a PKCS#12 cipher. +type pbeCipher interface { + // create returns a cipher.Block given a key. + create(key []byte) (cipher.Block, error) + // deriveKey returns a key derived from the given password and salt. + deriveKey(salt, password []byte, iterations int) []byte + // deriveKey returns an IV derived from the given password and salt. + deriveIV(salt, password []byte, iterations int) []byte +} + +type shaWithTripleDESCBC struct{} + +func (shaWithTripleDESCBC) create(key []byte) (cipher.Block, error) { + return des.NewTripleDESCipher(key) +} + +func (shaWithTripleDESCBC) deriveKey(salt, password []byte, iterations int) []byte { + return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 1, 24) +} + +func (shaWithTripleDESCBC) deriveIV(salt, password []byte, iterations int) []byte { + return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 2, 8) +} + +type shaWith40BitRC2CBC struct{} + +func (shaWith40BitRC2CBC) create(key []byte) (cipher.Block, error) { + return rc2.New(key, len(key)*8) +} + +func (shaWith40BitRC2CBC) deriveKey(salt, password []byte, iterations int) []byte { + return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 1, 5) +} + +func (shaWith40BitRC2CBC) deriveIV(salt, password []byte, iterations int) []byte { + return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 2, 8) +} + +type pbeParams struct { + Salt []byte + Iterations int +} + +func pbDecrypterFor(algorithm pkix.AlgorithmIdentifier, password []byte) (cipher.BlockMode, int, error) { + var cipherType pbeCipher + + switch { + case algorithm.Algorithm.Equal(oidPBEWithSHAAnd3KeyTripleDESCBC): + cipherType = shaWithTripleDESCBC{} + case algorithm.Algorithm.Equal(oidPBEWithSHAAnd40BitRC2CBC): + cipherType = shaWith40BitRC2CBC{} + default: + return nil, 0, NotImplementedError("algorithm " + algorithm.Algorithm.String() + " is not supported") + } + + var params pbeParams + if err := unmarshal(algorithm.Parameters.FullBytes, ¶ms); err != nil { + return nil, 0, err + } + + key := cipherType.deriveKey(params.Salt, password, params.Iterations) + iv := cipherType.deriveIV(params.Salt, password, params.Iterations) + + block, err := cipherType.create(key) + if err != nil { + return nil, 0, err + } + + return cipher.NewCBCDecrypter(block, iv), block.BlockSize(), nil +} + +func pbDecrypt(info decryptable, password []byte) (decrypted []byte, err error) { + cbc, blockSize, err := pbDecrypterFor(info.Algorithm(), password) + if err != nil { + return nil, err + } + + encrypted := info.Data() + if len(encrypted) == 0 { + return nil, errors.New("pkcs12: empty encrypted data") + } + if len(encrypted)%blockSize != 0 { + return nil, errors.New("pkcs12: input is not a multiple of the block size") + } + decrypted = make([]byte, len(encrypted)) + cbc.CryptBlocks(decrypted, encrypted) + + psLen := int(decrypted[len(decrypted)-1]) + if psLen == 0 || psLen > blockSize { + return nil, ErrDecryption + } + + if len(decrypted) < psLen { + return nil, ErrDecryption + } + ps := decrypted[len(decrypted)-psLen:] + decrypted = decrypted[:len(decrypted)-psLen] + if bytes.Compare(ps, bytes.Repeat([]byte{byte(psLen)}, psLen)) != 0 { + return nil, ErrDecryption + } + + return +} + +// decryptable abstracts an object that contains ciphertext. +type decryptable interface { + Algorithm() pkix.AlgorithmIdentifier + Data() []byte +} diff --git a/vendor/golang.org/x/crypto/pkcs12/crypto_test.go b/vendor/golang.org/x/crypto/pkcs12/crypto_test.go new file mode 100644 index 0000000000000000000000000000000000000000..eb4dae8fceba54529e568c4f745d097dceed4082 --- /dev/null +++ b/vendor/golang.org/x/crypto/pkcs12/crypto_test.go @@ -0,0 +1,125 @@ +// Copyright 2015 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 pkcs12 + +import ( + "bytes" + "crypto/x509/pkix" + "encoding/asn1" + "testing" +) + +var sha1WithTripleDES = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 1, 3}) + +func TestPbDecrypterFor(t *testing.T) { + params, _ := asn1.Marshal(pbeParams{ + Salt: []byte{1, 2, 3, 4, 5, 6, 7, 8}, + Iterations: 2048, + }) + alg := pkix.AlgorithmIdentifier{ + Algorithm: asn1.ObjectIdentifier([]int{1, 2, 3}), + Parameters: asn1.RawValue{ + FullBytes: params, + }, + } + + pass, _ := bmpString("Sesame open") + + _, _, err := pbDecrypterFor(alg, pass) + if _, ok := err.(NotImplementedError); !ok { + t.Errorf("expected not implemented error, got: %T %s", err, err) + } + + alg.Algorithm = sha1WithTripleDES + cbc, blockSize, err := pbDecrypterFor(alg, pass) + if err != nil { + t.Errorf("unexpected error from pbDecrypterFor %v", err) + } + if blockSize != 8 { + t.Errorf("unexpected block size %d, wanted 8", blockSize) + } + + plaintext := []byte{1, 2, 3, 4, 5, 6, 7, 8} + expectedCiphertext := []byte{185, 73, 135, 249, 137, 1, 122, 247} + ciphertext := make([]byte, len(plaintext)) + cbc.CryptBlocks(ciphertext, plaintext) + + if bytes.Compare(ciphertext, expectedCiphertext) != 0 { + t.Errorf("bad ciphertext, got %x but wanted %x", ciphertext, expectedCiphertext) + } +} + +var pbDecryptTests = []struct { + in []byte + expected []byte + expectedError error +}{ + { + []byte("\x33\x73\xf3\x9f\xda\x49\xae\xfc\xa0\x9a\xdf\x5a\x58\xa0\xea\x46"), // 7 padding bytes + []byte("A secret!"), + nil, + }, + { + []byte("\x33\x73\xf3\x9f\xda\x49\xae\xfc\x96\x24\x2f\x71\x7e\x32\x3f\xe7"), // 8 padding bytes + []byte("A secret"), + nil, + }, + { + []byte("\x35\x0c\xc0\x8d\xab\xa9\x5d\x30\x7f\x9a\xec\x6a\xd8\x9b\x9c\xd9"), // 9 padding bytes, incorrect + nil, + ErrDecryption, + }, + { + []byte("\xb2\xf9\x6e\x06\x60\xae\x20\xcf\x08\xa0\x7b\xd9\x6b\x20\xef\x41"), // incorrect padding bytes: [ ... 0x04 0x02 ] + nil, + ErrDecryption, + }, +} + +func TestPbDecrypt(t *testing.T) { + for i, test := range pbDecryptTests { + decryptable := testDecryptable{ + data: test.in, + algorithm: pkix.AlgorithmIdentifier{ + Algorithm: sha1WithTripleDES, + Parameters: pbeParams{ + Salt: []byte("\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8"), + Iterations: 4096, + }.RawASN1(), + }, + } + password, _ := bmpString("sesame") + + plaintext, err := pbDecrypt(decryptable, password) + if err != test.expectedError { + t.Errorf("#%d: got error %q, but wanted %q", i, err, test.expectedError) + continue + } + + if !bytes.Equal(plaintext, test.expected) { + t.Errorf("#%d: got %x, but wanted %x", i, plaintext, test.expected) + } + } +} + +type testDecryptable struct { + data []byte + algorithm pkix.AlgorithmIdentifier +} + +func (d testDecryptable) Algorithm() pkix.AlgorithmIdentifier { return d.algorithm } +func (d testDecryptable) Data() []byte { return d.data } + +func (params pbeParams) RawASN1() (raw asn1.RawValue) { + asn1Bytes, err := asn1.Marshal(params) + if err != nil { + panic(err) + } + _, err = asn1.Unmarshal(asn1Bytes, &raw) + if err != nil { + panic(err) + } + return +} diff --git a/vendor/golang.org/x/crypto/pkcs12/errors.go b/vendor/golang.org/x/crypto/pkcs12/errors.go new file mode 100644 index 0000000000000000000000000000000000000000..7377ce6fb2b814492e5427482cfd50800a7e3401 --- /dev/null +++ b/vendor/golang.org/x/crypto/pkcs12/errors.go @@ -0,0 +1,23 @@ +// Copyright 2015 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 pkcs12 + +import "errors" + +var ( + // ErrDecryption represents a failure to decrypt the input. + ErrDecryption = errors.New("pkcs12: decryption error, incorrect padding") + + // ErrIncorrectPassword is returned when an incorrect password is detected. + // Usually, P12/PFX data is signed to be able to verify the password. + ErrIncorrectPassword = errors.New("pkcs12: decryption password incorrect") +) + +// NotImplementedError indicates that the input is not currently supported. +type NotImplementedError string + +func (e NotImplementedError) Error() string { + return "pkcs12: " + string(e) +} diff --git a/vendor/golang.org/x/crypto/pkcs12/internal/rc2/bench_test.go b/vendor/golang.org/x/crypto/pkcs12/internal/rc2/bench_test.go new file mode 100644 index 0000000000000000000000000000000000000000..3347f338c186078151e6f6c2380ff0f55aa97a3c --- /dev/null +++ b/vendor/golang.org/x/crypto/pkcs12/internal/rc2/bench_test.go @@ -0,0 +1,27 @@ +// Copyright 2015 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 rc2 + +import ( + "testing" +) + +func BenchmarkEncrypt(b *testing.B) { + r, _ := New([]byte{0, 0, 0, 0, 0, 0, 0, 0}, 64) + b.ResetTimer() + var src [8]byte + for i := 0; i < b.N; i++ { + r.Encrypt(src[:], src[:]) + } +} + +func BenchmarkDecrypt(b *testing.B) { + r, _ := New([]byte{0, 0, 0, 0, 0, 0, 0, 0}, 64) + b.ResetTimer() + var src [8]byte + for i := 0; i < b.N; i++ { + r.Decrypt(src[:], src[:]) + } +} diff --git a/vendor/golang.org/x/crypto/pkcs12/internal/rc2/rc2.go b/vendor/golang.org/x/crypto/pkcs12/internal/rc2/rc2.go new file mode 100644 index 0000000000000000000000000000000000000000..7499e3fb69d2d3630d4c3813a6ba32da1264bc13 --- /dev/null +++ b/vendor/golang.org/x/crypto/pkcs12/internal/rc2/rc2.go @@ -0,0 +1,271 @@ +// Copyright 2015 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 rc2 implements the RC2 cipher +/* +https://www.ietf.org/rfc/rfc2268.txt +http://people.csail.mit.edu/rivest/pubs/KRRR98.pdf + +This code is licensed under the MIT license. +*/ +package rc2 + +import ( + "crypto/cipher" + "encoding/binary" +) + +// The rc2 block size in bytes +const BlockSize = 8 + +type rc2Cipher struct { + k [64]uint16 +} + +// New returns a new rc2 cipher with the given key and effective key length t1 +func New(key []byte, t1 int) (cipher.Block, error) { + // TODO(dgryski): error checking for key length + return &rc2Cipher{ + k: expandKey(key, t1), + }, nil +} + +func (*rc2Cipher) BlockSize() int { return BlockSize } + +var piTable = [256]byte{ + 0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed, 0x28, 0xe9, 0xfd, 0x79, 0x4a, 0xa0, 0xd8, 0x9d, + 0xc6, 0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e, 0x62, 0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2, + 0x17, 0x9a, 0x59, 0xf5, 0x87, 0xb3, 0x4f, 0x13, 0x61, 0x45, 0x6d, 0x8d, 0x09, 0x81, 0x7d, 0x32, + 0xbd, 0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0x0b, 0xf0, 0x95, 0x21, 0x22, 0x5c, 0x6b, 0x4e, 0x82, + 0x54, 0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c, 0x73, 0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc, + 0x12, 0x75, 0xca, 0x1f, 0x3b, 0xbe, 0xe4, 0xd1, 0x42, 0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26, + 0x6f, 0xbf, 0x0e, 0xda, 0x46, 0x69, 0x07, 0x57, 0x27, 0xf2, 0x1d, 0x9b, 0xbc, 0x94, 0x43, 0x03, + 0xf8, 0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7, 0x06, 0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7, + 0x08, 0xe8, 0xea, 0xde, 0x80, 0x52, 0xee, 0xf7, 0x84, 0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a, + 0x96, 0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74, 0x4b, 0x9f, 0xd0, 0x5e, 0x04, 0x18, 0xa4, 0xec, + 0xc2, 0xe0, 0x41, 0x6e, 0x0f, 0x51, 0xcb, 0xcc, 0x24, 0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39, + 0x99, 0x7c, 0x3a, 0x85, 0x23, 0xb8, 0xb4, 0x7a, 0xfc, 0x02, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31, + 0x2d, 0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae, 0x05, 0xdf, 0x29, 0x10, 0x67, 0x6c, 0xba, 0xc9, + 0xd3, 0x00, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c, 0x63, 0x16, 0x01, 0x3f, 0x58, 0xe2, 0x89, 0xa9, + 0x0d, 0x38, 0x34, 0x1b, 0xab, 0x33, 0xff, 0xb0, 0xbb, 0x48, 0x0c, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e, + 0xc5, 0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77, 0x0a, 0xa6, 0x20, 0x68, 0xfe, 0x7f, 0xc1, 0xad, +} + +func expandKey(key []byte, t1 int) [64]uint16 { + + l := make([]byte, 128) + copy(l, key) + + var t = len(key) + var t8 = (t1 + 7) / 8 + var tm = byte(255 % uint(1<<(8+uint(t1)-8*uint(t8)))) + + for i := len(key); i < 128; i++ { + l[i] = piTable[l[i-1]+l[uint8(i-t)]] + } + + l[128-t8] = piTable[l[128-t8]&tm] + + for i := 127 - t8; i >= 0; i-- { + l[i] = piTable[l[i+1]^l[i+t8]] + } + + var k [64]uint16 + + for i := range k { + k[i] = uint16(l[2*i]) + uint16(l[2*i+1])*256 + } + + return k +} + +func rotl16(x uint16, b uint) uint16 { + return (x >> (16 - b)) | (x << b) +} + +func (c *rc2Cipher) Encrypt(dst, src []byte) { + + r0 := binary.LittleEndian.Uint16(src[0:]) + r1 := binary.LittleEndian.Uint16(src[2:]) + r2 := binary.LittleEndian.Uint16(src[4:]) + r3 := binary.LittleEndian.Uint16(src[6:]) + + var j int + + for j <= 16 { + // mix r0 + r0 = r0 + c.k[j] + (r3 & r2) + ((^r3) & r1) + r0 = rotl16(r0, 1) + j++ + + // mix r1 + r1 = r1 + c.k[j] + (r0 & r3) + ((^r0) & r2) + r1 = rotl16(r1, 2) + j++ + + // mix r2 + r2 = r2 + c.k[j] + (r1 & r0) + ((^r1) & r3) + r2 = rotl16(r2, 3) + j++ + + // mix r3 + r3 = r3 + c.k[j] + (r2 & r1) + ((^r2) & r0) + r3 = rotl16(r3, 5) + j++ + + } + + r0 = r0 + c.k[r3&63] + r1 = r1 + c.k[r0&63] + r2 = r2 + c.k[r1&63] + r3 = r3 + c.k[r2&63] + + for j <= 40 { + // mix r0 + r0 = r0 + c.k[j] + (r3 & r2) + ((^r3) & r1) + r0 = rotl16(r0, 1) + j++ + + // mix r1 + r1 = r1 + c.k[j] + (r0 & r3) + ((^r0) & r2) + r1 = rotl16(r1, 2) + j++ + + // mix r2 + r2 = r2 + c.k[j] + (r1 & r0) + ((^r1) & r3) + r2 = rotl16(r2, 3) + j++ + + // mix r3 + r3 = r3 + c.k[j] + (r2 & r1) + ((^r2) & r0) + r3 = rotl16(r3, 5) + j++ + + } + + r0 = r0 + c.k[r3&63] + r1 = r1 + c.k[r0&63] + r2 = r2 + c.k[r1&63] + r3 = r3 + c.k[r2&63] + + for j <= 60 { + // mix r0 + r0 = r0 + c.k[j] + (r3 & r2) + ((^r3) & r1) + r0 = rotl16(r0, 1) + j++ + + // mix r1 + r1 = r1 + c.k[j] + (r0 & r3) + ((^r0) & r2) + r1 = rotl16(r1, 2) + j++ + + // mix r2 + r2 = r2 + c.k[j] + (r1 & r0) + ((^r1) & r3) + r2 = rotl16(r2, 3) + j++ + + // mix r3 + r3 = r3 + c.k[j] + (r2 & r1) + ((^r2) & r0) + r3 = rotl16(r3, 5) + j++ + } + + binary.LittleEndian.PutUint16(dst[0:], r0) + binary.LittleEndian.PutUint16(dst[2:], r1) + binary.LittleEndian.PutUint16(dst[4:], r2) + binary.LittleEndian.PutUint16(dst[6:], r3) +} + +func (c *rc2Cipher) Decrypt(dst, src []byte) { + + r0 := binary.LittleEndian.Uint16(src[0:]) + r1 := binary.LittleEndian.Uint16(src[2:]) + r2 := binary.LittleEndian.Uint16(src[4:]) + r3 := binary.LittleEndian.Uint16(src[6:]) + + j := 63 + + for j >= 44 { + // unmix r3 + r3 = rotl16(r3, 16-5) + r3 = r3 - c.k[j] - (r2 & r1) - ((^r2) & r0) + j-- + + // unmix r2 + r2 = rotl16(r2, 16-3) + r2 = r2 - c.k[j] - (r1 & r0) - ((^r1) & r3) + j-- + + // unmix r1 + r1 = rotl16(r1, 16-2) + r1 = r1 - c.k[j] - (r0 & r3) - ((^r0) & r2) + j-- + + // unmix r0 + r0 = rotl16(r0, 16-1) + r0 = r0 - c.k[j] - (r3 & r2) - ((^r3) & r1) + j-- + } + + r3 = r3 - c.k[r2&63] + r2 = r2 - c.k[r1&63] + r1 = r1 - c.k[r0&63] + r0 = r0 - c.k[r3&63] + + for j >= 20 { + // unmix r3 + r3 = rotl16(r3, 16-5) + r3 = r3 - c.k[j] - (r2 & r1) - ((^r2) & r0) + j-- + + // unmix r2 + r2 = rotl16(r2, 16-3) + r2 = r2 - c.k[j] - (r1 & r0) - ((^r1) & r3) + j-- + + // unmix r1 + r1 = rotl16(r1, 16-2) + r1 = r1 - c.k[j] - (r0 & r3) - ((^r0) & r2) + j-- + + // unmix r0 + r0 = rotl16(r0, 16-1) + r0 = r0 - c.k[j] - (r3 & r2) - ((^r3) & r1) + j-- + + } + + r3 = r3 - c.k[r2&63] + r2 = r2 - c.k[r1&63] + r1 = r1 - c.k[r0&63] + r0 = r0 - c.k[r3&63] + + for j >= 0 { + // unmix r3 + r3 = rotl16(r3, 16-5) + r3 = r3 - c.k[j] - (r2 & r1) - ((^r2) & r0) + j-- + + // unmix r2 + r2 = rotl16(r2, 16-3) + r2 = r2 - c.k[j] - (r1 & r0) - ((^r1) & r3) + j-- + + // unmix r1 + r1 = rotl16(r1, 16-2) + r1 = r1 - c.k[j] - (r0 & r3) - ((^r0) & r2) + j-- + + // unmix r0 + r0 = rotl16(r0, 16-1) + r0 = r0 - c.k[j] - (r3 & r2) - ((^r3) & r1) + j-- + + } + + binary.LittleEndian.PutUint16(dst[0:], r0) + binary.LittleEndian.PutUint16(dst[2:], r1) + binary.LittleEndian.PutUint16(dst[4:], r2) + binary.LittleEndian.PutUint16(dst[6:], r3) +} diff --git a/vendor/golang.org/x/crypto/pkcs12/internal/rc2/rc2_test.go b/vendor/golang.org/x/crypto/pkcs12/internal/rc2/rc2_test.go new file mode 100644 index 0000000000000000000000000000000000000000..51a7efe506289f126cace44ad27bf8f9b7bcd45b --- /dev/null +++ b/vendor/golang.org/x/crypto/pkcs12/internal/rc2/rc2_test.go @@ -0,0 +1,92 @@ +// Copyright 2015 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 rc2 + +import ( + "bytes" + "encoding/hex" + "testing" +) + +func TestEncryptDecrypt(t *testing.T) { + // TODO(dgryski): add the rest of the test vectors from the RFC + var tests = []struct { + key string + plain string + cipher string + t1 int + }{ + { + "0000000000000000", + "0000000000000000", + "ebb773f993278eff", + 63, + }, + { + "ffffffffffffffff", + "ffffffffffffffff", + "278b27e42e2f0d49", + 64, + }, + { + "3000000000000000", + "1000000000000001", + "30649edf9be7d2c2", + 64, + }, + { + "88", + "0000000000000000", + "61a8a244adacccf0", + 64, + }, + { + "88bca90e90875a", + "0000000000000000", + "6ccf4308974c267f", + 64, + }, + { + "88bca90e90875a7f0f79c384627bafb2", + "0000000000000000", + "1a807d272bbe5db1", + 64, + }, + { + "88bca90e90875a7f0f79c384627bafb2", + "0000000000000000", + "2269552ab0f85ca6", + 128, + }, + { + "88bca90e90875a7f0f79c384627bafb216f80a6f85920584c42fceb0be255daf1e", + "0000000000000000", + "5b78d3a43dfff1f1", + 129, + }, + } + + for _, tt := range tests { + k, _ := hex.DecodeString(tt.key) + p, _ := hex.DecodeString(tt.plain) + c, _ := hex.DecodeString(tt.cipher) + + b, _ := New(k, tt.t1) + + var dst [8]byte + + b.Encrypt(dst[:], p) + + if !bytes.Equal(dst[:], c) { + t.Errorf("encrypt failed: got % 2x wanted % 2x\n", dst, c) + } + + b.Decrypt(dst[:], c) + + if !bytes.Equal(dst[:], p) { + t.Errorf("decrypt failed: got % 2x wanted % 2x\n", dst, p) + } + } +} diff --git a/vendor/golang.org/x/crypto/pkcs12/mac.go b/vendor/golang.org/x/crypto/pkcs12/mac.go new file mode 100644 index 0000000000000000000000000000000000000000..5f38aa7de83ce0aabfe5d909eeb1128e94da6ab9 --- /dev/null +++ b/vendor/golang.org/x/crypto/pkcs12/mac.go @@ -0,0 +1,45 @@ +// Copyright 2015 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 pkcs12 + +import ( + "crypto/hmac" + "crypto/sha1" + "crypto/x509/pkix" + "encoding/asn1" +) + +type macData struct { + Mac digestInfo + MacSalt []byte + Iterations int `asn1:"optional,default:1"` +} + +// from PKCS#7: +type digestInfo struct { + Algorithm pkix.AlgorithmIdentifier + Digest []byte +} + +var ( + oidSHA1 = asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26}) +) + +func verifyMac(macData *macData, message, password []byte) error { + if !macData.Mac.Algorithm.Algorithm.Equal(oidSHA1) { + return NotImplementedError("unknown digest algorithm: " + macData.Mac.Algorithm.Algorithm.String()) + } + + key := pbkdf(sha1Sum, 20, 64, macData.MacSalt, password, macData.Iterations, 3, 20) + + mac := hmac.New(sha1.New, key) + mac.Write(message) + expectedMAC := mac.Sum(nil) + + if !hmac.Equal(macData.Mac.Digest, expectedMAC) { + return ErrIncorrectPassword + } + return nil +} diff --git a/vendor/golang.org/x/crypto/pkcs12/mac_test.go b/vendor/golang.org/x/crypto/pkcs12/mac_test.go new file mode 100644 index 0000000000000000000000000000000000000000..1ed4ff21e14b398e301530dcabd135873012095b --- /dev/null +++ b/vendor/golang.org/x/crypto/pkcs12/mac_test.go @@ -0,0 +1,42 @@ +// Copyright 2015 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 pkcs12 + +import ( + "encoding/asn1" + "testing" +) + +func TestVerifyMac(t *testing.T) { + td := macData{ + Mac: digestInfo{ + Digest: []byte{0x18, 0x20, 0x3d, 0xff, 0x1e, 0x16, 0xf4, 0x92, 0xf2, 0xaf, 0xc8, 0x91, 0xa9, 0xba, 0xd6, 0xca, 0x9d, 0xee, 0x51, 0x93}, + }, + MacSalt: []byte{1, 2, 3, 4, 5, 6, 7, 8}, + Iterations: 2048, + } + + message := []byte{11, 12, 13, 14, 15} + password, _ := bmpString("") + + td.Mac.Algorithm.Algorithm = asn1.ObjectIdentifier([]int{1, 2, 3}) + err := verifyMac(&td, message, password) + if _, ok := err.(NotImplementedError); !ok { + t.Errorf("err: %v", err) + } + + td.Mac.Algorithm.Algorithm = asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26}) + err = verifyMac(&td, message, password) + if err != ErrIncorrectPassword { + t.Errorf("Expected incorrect password, got err: %v", err) + } + + password, _ = bmpString("Sesame open") + err = verifyMac(&td, message, password) + if err != nil { + t.Errorf("err: %v", err) + } + +} diff --git a/vendor/golang.org/x/crypto/pkcs12/pbkdf.go b/vendor/golang.org/x/crypto/pkcs12/pbkdf.go new file mode 100644 index 0000000000000000000000000000000000000000..5c419d41e32c2a98ef245ca54a9ada763b1aa409 --- /dev/null +++ b/vendor/golang.org/x/crypto/pkcs12/pbkdf.go @@ -0,0 +1,170 @@ +// Copyright 2015 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 pkcs12 + +import ( + "bytes" + "crypto/sha1" + "math/big" +) + +var ( + one = big.NewInt(1) +) + +// sha1Sum returns the SHA-1 hash of in. +func sha1Sum(in []byte) []byte { + sum := sha1.Sum(in) + return sum[:] +} + +// fillWithRepeats returns v*ceiling(len(pattern) / v) bytes consisting of +// repeats of pattern. +func fillWithRepeats(pattern []byte, v int) []byte { + if len(pattern) == 0 { + return nil + } + outputLen := v * ((len(pattern) + v - 1) / v) + return bytes.Repeat(pattern, (outputLen+len(pattern)-1)/len(pattern))[:outputLen] +} + +func pbkdf(hash func([]byte) []byte, u, v int, salt, password []byte, r int, ID byte, size int) (key []byte) { + // implementation of https://tools.ietf.org/html/rfc7292#appendix-B.2 , RFC text verbatim in comments + + // Let H be a hash function built around a compression function f: + + // Z_2^u x Z_2^v -> Z_2^u + + // (that is, H has a chaining variable and output of length u bits, and + // the message input to the compression function of H is v bits). The + // values for u and v are as follows: + + // HASH FUNCTION VALUE u VALUE v + // MD2, MD5 128 512 + // SHA-1 160 512 + // SHA-224 224 512 + // SHA-256 256 512 + // SHA-384 384 1024 + // SHA-512 512 1024 + // SHA-512/224 224 1024 + // SHA-512/256 256 1024 + + // Furthermore, let r be the iteration count. + + // We assume here that u and v are both multiples of 8, as are the + // lengths of the password and salt strings (which we denote by p and s, + // respectively) and the number n of pseudorandom bits required. In + // addition, u and v are of course non-zero. + + // For information on security considerations for MD5 [19], see [25] and + // [1], and on those for MD2, see [18]. + + // The following procedure can be used to produce pseudorandom bits for + // a particular "purpose" that is identified by a byte called "ID". + // This standard specifies 3 different values for the ID byte: + + // 1. If ID=1, then the pseudorandom bits being produced are to be used + // as key material for performing encryption or decryption. + + // 2. If ID=2, then the pseudorandom bits being produced are to be used + // as an IV (Initial Value) for encryption or decryption. + + // 3. If ID=3, then the pseudorandom bits being produced are to be used + // as an integrity key for MACing. + + // 1. Construct a string, D (the "diversifier"), by concatenating v/8 + // copies of ID. + var D []byte + for i := 0; i < v; i++ { + D = append(D, ID) + } + + // 2. Concatenate copies of the salt together to create a string S of + // length v(ceiling(s/v)) bits (the final copy of the salt may be + // truncated to create S). Note that if the salt is the empty + // string, then so is S. + + S := fillWithRepeats(salt, v) + + // 3. Concatenate copies of the password together to create a string P + // of length v(ceiling(p/v)) bits (the final copy of the password + // may be truncated to create P). Note that if the password is the + // empty string, then so is P. + + P := fillWithRepeats(password, v) + + // 4. Set I=S||P to be the concatenation of S and P. + I := append(S, P...) + + // 5. Set c=ceiling(n/u). + c := (size + u - 1) / u + + // 6. For i=1, 2, ..., c, do the following: + A := make([]byte, c*20) + var IjBuf []byte + for i := 0; i < c; i++ { + // A. Set A2=H^r(D||I). (i.e., the r-th hash of D||1, + // H(H(H(... H(D||I)))) + Ai := hash(append(D, I...)) + for j := 1; j < r; j++ { + Ai = hash(Ai) + } + copy(A[i*20:], Ai[:]) + + if i < c-1 { // skip on last iteration + // B. Concatenate copies of Ai to create a string B of length v + // bits (the final copy of Ai may be truncated to create B). + var B []byte + for len(B) < v { + B = append(B, Ai[:]...) + } + B = B[:v] + + // C. Treating I as a concatenation I_0, I_1, ..., I_(k-1) of v-bit + // blocks, where k=ceiling(s/v)+ceiling(p/v), modify I by + // setting I_j=(I_j+B+1) mod 2^v for each j. + { + Bbi := new(big.Int).SetBytes(B) + Ij := new(big.Int) + + for j := 0; j < len(I)/v; j++ { + Ij.SetBytes(I[j*v : (j+1)*v]) + Ij.Add(Ij, Bbi) + Ij.Add(Ij, one) + Ijb := Ij.Bytes() + // We expect Ijb to be exactly v bytes, + // if it is longer or shorter we must + // adjust it accordingly. + if len(Ijb) > v { + Ijb = Ijb[len(Ijb)-v:] + } + if len(Ijb) < v { + if IjBuf == nil { + IjBuf = make([]byte, v) + } + bytesShort := v - len(Ijb) + for i := 0; i < bytesShort; i++ { + IjBuf[i] = 0 + } + copy(IjBuf[bytesShort:], Ijb) + Ijb = IjBuf + } + copy(I[j*v:(j+1)*v], Ijb) + } + } + } + } + // 7. Concatenate A_1, A_2, ..., A_c together to form a pseudorandom + // bit string, A. + + // 8. Use the first n bits of A as the output of this entire process. + return A[:size] + + // If the above process is being used to generate a DES key, the process + // should be used to create 64 random bits, and the key's parity bits + // should be set after the 64 bits have been produced. Similar concerns + // hold for 2-key and 3-key triple-DES keys, for CDMF keys, and for any + // similar keys with parity bits "built into them". +} diff --git a/vendor/golang.org/x/crypto/pkcs12/pbkdf_test.go b/vendor/golang.org/x/crypto/pkcs12/pbkdf_test.go new file mode 100644 index 0000000000000000000000000000000000000000..262037d7ebaac92611b90cd865cf960508131d5a --- /dev/null +++ b/vendor/golang.org/x/crypto/pkcs12/pbkdf_test.go @@ -0,0 +1,34 @@ +// Copyright 2015 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 pkcs12 + +import ( + "bytes" + "testing" +) + +func TestThatPBKDFWorksCorrectlyForLongKeys(t *testing.T) { + cipherInfo := shaWithTripleDESCBC{} + + salt := []byte("\xff\xff\xff\xff\xff\xff\xff\xff") + password, _ := bmpString("sesame") + key := cipherInfo.deriveKey(salt, password, 2048) + + if expected := []byte("\x7c\xd9\xfd\x3e\x2b\x3b\xe7\x69\x1a\x44\xe3\xbe\xf0\xf9\xea\x0f\xb9\xb8\x97\xd4\xe3\x25\xd9\xd1"); bytes.Compare(key, expected) != 0 { + t.Fatalf("expected key '%x', but found '%x'", expected, key) + } +} + +func TestThatPBKDFHandlesLeadingZeros(t *testing.T) { + // This test triggers a case where I_j (in step 6C) ends up with leading zero + // byte, meaning that len(Ijb) < v (leading zeros get stripped by big.Int). + // This was previously causing bug whereby certain inputs would break the + // derivation and produce the wrong output. + key := pbkdf(sha1Sum, 20, 64, []byte("\xf3\x7e\x05\xb5\x18\x32\x4b\x4b"), []byte("\x00\x00"), 2048, 1, 24) + expected := []byte("\x00\xf7\x59\xff\x47\xd1\x4d\xd0\x36\x65\xd5\x94\x3c\xb3\xc4\xa3\x9a\x25\x55\xc0\x2a\xed\x66\xe1") + if bytes.Compare(key, expected) != 0 { + t.Fatalf("expected key '%x', but found '%x'", expected, key) + } +} diff --git a/vendor/golang.org/x/crypto/pkcs12/pkcs12.go b/vendor/golang.org/x/crypto/pkcs12/pkcs12.go new file mode 100644 index 0000000000000000000000000000000000000000..eff9ad3a98f849c2068ea3f56f0d3704113c5629 --- /dev/null +++ b/vendor/golang.org/x/crypto/pkcs12/pkcs12.go @@ -0,0 +1,346 @@ +// Copyright 2015 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 pkcs12 implements some of PKCS#12. +// +// This implementation is distilled from https://tools.ietf.org/html/rfc7292 +// and referenced documents. It is intended for decoding P12/PFX-stored +// certificates and keys for use with the crypto/tls package. +package pkcs12 + +import ( + "crypto/ecdsa" + "crypto/rsa" + "crypto/x509" + "crypto/x509/pkix" + "encoding/asn1" + "encoding/hex" + "encoding/pem" + "errors" +) + +var ( + oidDataContentType = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 7, 1}) + oidEncryptedDataContentType = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 7, 6}) + + oidFriendlyName = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 9, 20}) + oidLocalKeyID = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 9, 21}) + oidMicrosoftCSPName = asn1.ObjectIdentifier([]int{1, 3, 6, 1, 4, 1, 311, 17, 1}) +) + +type pfxPdu struct { + Version int + AuthSafe contentInfo + MacData macData `asn1:"optional"` +} + +type contentInfo struct { + ContentType asn1.ObjectIdentifier + Content asn1.RawValue `asn1:"tag:0,explicit,optional"` +} + +type encryptedData struct { + Version int + EncryptedContentInfo encryptedContentInfo +} + +type encryptedContentInfo struct { + ContentType asn1.ObjectIdentifier + ContentEncryptionAlgorithm pkix.AlgorithmIdentifier + EncryptedContent []byte `asn1:"tag:0,optional"` +} + +func (i encryptedContentInfo) Algorithm() pkix.AlgorithmIdentifier { + return i.ContentEncryptionAlgorithm +} + +func (i encryptedContentInfo) Data() []byte { return i.EncryptedContent } + +type safeBag struct { + Id asn1.ObjectIdentifier + Value asn1.RawValue `asn1:"tag:0,explicit"` + Attributes []pkcs12Attribute `asn1:"set,optional"` +} + +type pkcs12Attribute struct { + Id asn1.ObjectIdentifier + Value asn1.RawValue `asn1:"set"` +} + +type encryptedPrivateKeyInfo struct { + AlgorithmIdentifier pkix.AlgorithmIdentifier + EncryptedData []byte +} + +func (i encryptedPrivateKeyInfo) Algorithm() pkix.AlgorithmIdentifier { + return i.AlgorithmIdentifier +} + +func (i encryptedPrivateKeyInfo) Data() []byte { + return i.EncryptedData +} + +// PEM block types +const ( + certificateType = "CERTIFICATE" + privateKeyType = "PRIVATE KEY" +) + +// unmarshal calls asn1.Unmarshal, but also returns an error if there is any +// trailing data after unmarshaling. +func unmarshal(in []byte, out interface{}) error { + trailing, err := asn1.Unmarshal(in, out) + if err != nil { + return err + } + if len(trailing) != 0 { + return errors.New("pkcs12: trailing data found") + } + return nil +} + +// ConvertToPEM converts all "safe bags" contained in pfxData to PEM blocks. +func ToPEM(pfxData []byte, password string) ([]*pem.Block, error) { + encodedPassword, err := bmpString(password) + if err != nil { + return nil, ErrIncorrectPassword + } + + bags, encodedPassword, err := getSafeContents(pfxData, encodedPassword) + + if err != nil { + return nil, err + } + + blocks := make([]*pem.Block, 0, len(bags)) + for _, bag := range bags { + block, err := convertBag(&bag, encodedPassword) + if err != nil { + return nil, err + } + blocks = append(blocks, block) + } + + return blocks, nil +} + +func convertBag(bag *safeBag, password []byte) (*pem.Block, error) { + block := &pem.Block{ + Headers: make(map[string]string), + } + + for _, attribute := range bag.Attributes { + k, v, err := convertAttribute(&attribute) + if err != nil { + return nil, err + } + block.Headers[k] = v + } + + switch { + case bag.Id.Equal(oidCertBag): + block.Type = certificateType + certsData, err := decodeCertBag(bag.Value.Bytes) + if err != nil { + return nil, err + } + block.Bytes = certsData + case bag.Id.Equal(oidPKCS8ShroundedKeyBag): + block.Type = privateKeyType + + key, err := decodePkcs8ShroudedKeyBag(bag.Value.Bytes, password) + if err != nil { + return nil, err + } + + switch key := key.(type) { + case *rsa.PrivateKey: + block.Bytes = x509.MarshalPKCS1PrivateKey(key) + case *ecdsa.PrivateKey: + block.Bytes, err = x509.MarshalECPrivateKey(key) + if err != nil { + return nil, err + } + default: + return nil, errors.New("found unknown private key type in PKCS#8 wrapping") + } + default: + return nil, errors.New("don't know how to convert a safe bag of type " + bag.Id.String()) + } + return block, nil +} + +func convertAttribute(attribute *pkcs12Attribute) (key, value string, err error) { + isString := false + + switch { + case attribute.Id.Equal(oidFriendlyName): + key = "friendlyName" + isString = true + case attribute.Id.Equal(oidLocalKeyID): + key = "localKeyId" + case attribute.Id.Equal(oidMicrosoftCSPName): + // This key is chosen to match OpenSSL. + key = "Microsoft CSP Name" + isString = true + default: + return "", "", errors.New("pkcs12: unknown attribute with OID " + attribute.Id.String()) + } + + if isString { + if err := unmarshal(attribute.Value.Bytes, &attribute.Value); err != nil { + return "", "", err + } + if value, err = decodeBMPString(attribute.Value.Bytes); err != nil { + return "", "", err + } + } else { + var id []byte + if err := unmarshal(attribute.Value.Bytes, &id); err != nil { + return "", "", err + } + value = hex.EncodeToString(id) + } + + return key, value, nil +} + +// Decode extracts a certificate and private key from pfxData. This function +// assumes that there is only one certificate and only one private key in the +// pfxData. +func Decode(pfxData []byte, password string) (privateKey interface{}, certificate *x509.Certificate, err error) { + encodedPassword, err := bmpString(password) + if err != nil { + return nil, nil, err + } + + bags, encodedPassword, err := getSafeContents(pfxData, encodedPassword) + if err != nil { + return nil, nil, err + } + + if len(bags) != 2 { + err = errors.New("pkcs12: expected exactly two safe bags in the PFX PDU") + return + } + + for _, bag := range bags { + switch { + case bag.Id.Equal(oidCertBag): + if certificate != nil { + err = errors.New("pkcs12: expected exactly one certificate bag") + } + + certsData, err := decodeCertBag(bag.Value.Bytes) + if err != nil { + return nil, nil, err + } + certs, err := x509.ParseCertificates(certsData) + if err != nil { + return nil, nil, err + } + if len(certs) != 1 { + err = errors.New("pkcs12: expected exactly one certificate in the certBag") + return nil, nil, err + } + certificate = certs[0] + + case bag.Id.Equal(oidPKCS8ShroundedKeyBag): + if privateKey != nil { + err = errors.New("pkcs12: expected exactly one key bag") + } + + if privateKey, err = decodePkcs8ShroudedKeyBag(bag.Value.Bytes, encodedPassword); err != nil { + return nil, nil, err + } + } + } + + if certificate == nil { + return nil, nil, errors.New("pkcs12: certificate missing") + } + if privateKey == nil { + return nil, nil, errors.New("pkcs12: private key missing") + } + + return +} + +func getSafeContents(p12Data, password []byte) (bags []safeBag, updatedPassword []byte, err error) { + pfx := new(pfxPdu) + if err := unmarshal(p12Data, pfx); err != nil { + return nil, nil, errors.New("pkcs12: error reading P12 data: " + err.Error()) + } + + if pfx.Version != 3 { + return nil, nil, NotImplementedError("can only decode v3 PFX PDU's") + } + + if !pfx.AuthSafe.ContentType.Equal(oidDataContentType) { + return nil, nil, NotImplementedError("only password-protected PFX is implemented") + } + + // unmarshal the explicit bytes in the content for type 'data' + if err := unmarshal(pfx.AuthSafe.Content.Bytes, &pfx.AuthSafe.Content); err != nil { + return nil, nil, err + } + + if len(pfx.MacData.Mac.Algorithm.Algorithm) == 0 { + return nil, nil, errors.New("pkcs12: no MAC in data") + } + + if err := verifyMac(&pfx.MacData, pfx.AuthSafe.Content.Bytes, password); err != nil { + if err == ErrIncorrectPassword && len(password) == 2 && password[0] == 0 && password[1] == 0 { + // some implementations use an empty byte array + // for the empty string password try one more + // time with empty-empty password + password = nil + err = verifyMac(&pfx.MacData, pfx.AuthSafe.Content.Bytes, password) + } + if err != nil { + return nil, nil, err + } + } + + var authenticatedSafe []contentInfo + if err := unmarshal(pfx.AuthSafe.Content.Bytes, &authenticatedSafe); err != nil { + return nil, nil, err + } + + if len(authenticatedSafe) != 2 { + return nil, nil, NotImplementedError("expected exactly two items in the authenticated safe") + } + + for _, ci := range authenticatedSafe { + var data []byte + + switch { + case ci.ContentType.Equal(oidDataContentType): + if err := unmarshal(ci.Content.Bytes, &data); err != nil { + return nil, nil, err + } + case ci.ContentType.Equal(oidEncryptedDataContentType): + var encryptedData encryptedData + if err := unmarshal(ci.Content.Bytes, &encryptedData); err != nil { + return nil, nil, err + } + if encryptedData.Version != 0 { + return nil, nil, NotImplementedError("only version 0 of EncryptedData is supported") + } + if data, err = pbDecrypt(encryptedData.EncryptedContentInfo, password); err != nil { + return nil, nil, err + } + default: + return nil, nil, NotImplementedError("only data and encryptedData content types are supported in authenticated safe") + } + + var safeContents []safeBag + if err := unmarshal(data, &safeContents); err != nil { + return nil, nil, err + } + bags = append(bags, safeContents...) + } + + return bags, password, nil +} diff --git a/vendor/golang.org/x/crypto/pkcs12/pkcs12_test.go b/vendor/golang.org/x/crypto/pkcs12/pkcs12_test.go new file mode 100644 index 0000000000000000000000000000000000000000..14dd2a6c5d664b36db5c862e3f1070549a4e41e2 --- /dev/null +++ b/vendor/golang.org/x/crypto/pkcs12/pkcs12_test.go @@ -0,0 +1,138 @@ +// Copyright 2015 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 pkcs12 + +import ( + "crypto/rsa" + "crypto/tls" + "encoding/base64" + "encoding/pem" + "testing" +) + +func TestPfx(t *testing.T) { + for commonName, base64P12 := range testdata { + p12, _ := base64.StdEncoding.DecodeString(base64P12) + + priv, cert, err := Decode(p12, "") + if err != nil { + t.Fatal(err) + } + + if err := priv.(*rsa.PrivateKey).Validate(); err != nil { + t.Errorf("error while validating private key: %v", err) + } + + if cert.Subject.CommonName != commonName { + t.Errorf("expected common name to be %q, but found %q", commonName, cert.Subject.CommonName) + } + } +} + +func TestPEM(t *testing.T) { + for commonName, base64P12 := range testdata { + p12, _ := base64.StdEncoding.DecodeString(base64P12) + + blocks, err := ToPEM(p12, "") + if err != nil { + t.Fatalf("error while converting to PEM: %s", err) + } + + var pemData []byte + for _, b := range blocks { + pemData = append(pemData, pem.EncodeToMemory(b)...) + } + + cert, err := tls.X509KeyPair(pemData, pemData) + if err != nil { + t.Errorf("err while converting to key pair: %v", err) + } + config := tls.Config{ + Certificates: []tls.Certificate{cert}, + } + config.BuildNameToCertificate() + + if _, exists := config.NameToCertificate[commonName]; !exists { + t.Errorf("did not find our cert in PEM?: %v", config.NameToCertificate) + } + } +} + +func ExampleToPEM() { + p12, _ := base64.StdEncoding.DecodeString(`MIIJzgIBAzCCCZQGCS ... CA+gwggPk==`) + + blocks, err := ToPEM(p12, "password") + if err != nil { + panic(err) + } + + var pemData []byte + for _, b := range blocks { + pemData = append(pemData, pem.EncodeToMemory(b)...) + } + + // then use PEM data for tls to construct tls certificate: + cert, err := tls.X509KeyPair(pemData, pemData) + if err != nil { + panic(err) + } + + config := &tls.Config{ + Certificates: []tls.Certificate{cert}, + } + + _ = config +} + +var testdata = map[string]string{ + // 'null' password test case + "Windows Azure Tools": `MIIKDAIBAzCCCcwGCSqGSIb3DQEHAaCCCb0Eggm5MIIJtTCCBe4GCSqGSIb3DQEHAaCCBd8EggXbMIIF1zCCBdMGCyqGSIb3DQEMCgECoIIE7jCCBOowHAYKKoZIhvcNAQwBAzAOBAhStUNnlTGV+gICB9AEggTIJ81JIossF6boFWpPtkiQRPtI6DW6e9QD4/WvHAVrM2bKdpMzSMsCML5NyuddANTKHBVq00Jc9keqGNAqJPKkjhSUebzQFyhe0E1oI9T4zY5UKr/I8JclOeccH4QQnsySzYUG2SnniXnQ+JrG3juetli7EKth9h6jLc6xbubPadY5HMB3wL/eG/kJymiXwU2KQ9Mgd4X6jbcV+NNCE/8jbZHvSTCPeYTJIjxfeX61Sj5kFKUCzERbsnpyevhY3X0eYtEDezZQarvGmXtMMdzf8HJHkWRdk9VLDLgjk8uiJif/+X4FohZ37ig0CpgC2+dP4DGugaZZ51hb8tN9GeCKIsrmWogMXDIVd0OACBp/EjJVmFB6y0kUCXxUE0TZt0XA1tjAGJcjDUpBvTntZjPsnH/4ZySy+s2d9OOhJ6pzRQBRm360TzkFdSwk9DLiLdGfv4pwMMu/vNGBlqjP/1sQtj+jprJiD1sDbCl4AdQZVoMBQHadF2uSD4/o17XG/Ci0r2h6Htc2yvZMAbEY4zMjjIn2a+vqIxD6onexaek1R3zbkS9j19D6EN9EWn8xgz80YRCyW65znZk8xaIhhvlU/mg7sTxeyuqroBZNcq6uDaQTehDpyH7bY2l4zWRpoj10a6JfH2q5shYz8Y6UZC/kOTfuGqbZDNZWro/9pYquvNNW0M847E5t9bsf9VkAAMHRGBbWoVoU9VpI0UnoXSfvpOo+aXa2DSq5sHHUTVY7A9eov3z5IqT+pligx11xcs+YhDWcU8di3BTJisohKvv5Y8WSkm/rloiZd4ig269k0jTRk1olP/vCksPli4wKG2wdsd5o42nX1yL7mFfXocOANZbB+5qMkiwdyoQSk+Vq+C8nAZx2bbKhUq2MbrORGMzOe0Hh0x2a0PeObycN1Bpyv7Mp3ZI9h5hBnONKCnqMhtyQHUj/nNvbJUnDVYNfoOEqDiEqqEwB7YqWzAKz8KW0OIqdlM8uiQ4JqZZlFllnWJUfaiDrdFM3lYSnFQBkzeVlts6GpDOOBjCYd7dcCNS6kq6pZC6p6HN60Twu0JnurZD6RT7rrPkIGE8vAenFt4iGe/yF52fahCSY8Ws4K0UTwN7bAS+4xRHVCWvE8sMRZsRCHizb5laYsVrPZJhE6+hux6OBb6w8kwPYXc+ud5v6UxawUWgt6uPwl8mlAtU9Z7Miw4Nn/wtBkiLL/ke1UI1gqJtcQXgHxx6mzsjh41+nAgTvdbsSEyU6vfOmxGj3Rwc1eOrIhJUqn5YjOWfzzsz/D5DzWKmwXIwdspt1p+u+kol1N3f2wT9fKPnd/RGCb4g/1hc3Aju4DQYgGY782l89CEEdalpQ/35bQczMFk6Fje12HykakWEXd/bGm9Unh82gH84USiRpeOfQvBDYoqEyrY3zkFZzBjhDqa+jEcAj41tcGx47oSfDq3iVYCdL7HSIjtnyEktVXd7mISZLoMt20JACFcMw+mrbjlug+eU7o2GR7T+LwtOp/p4LZqyLa7oQJDwde1BNZtm3TCK2P1mW94QDL0nDUps5KLtr1DaZXEkRbjSJub2ZE9WqDHyU3KA8G84Tq/rN1IoNu/if45jacyPje1Npj9IftUZSP22nV7HMwZtwQ4P4MYHRMBMGCSqGSIb3DQEJFTEGBAQBAAAAMFsGCSqGSIb3DQEJFDFOHkwAewBCADQAQQA0AEYARQBCADAALQBBADEAOABBAC0ANAA0AEIAQgAtAEIANQBGADIALQA0ADkAMQBFAEYAMQA1ADIAQgBBADEANgB9MF0GCSsGAQQBgjcRATFQHk4ATQBpAGMAcgBvAHMAbwBmAHQAIABTAG8AZgB0AHcAYQByAGUAIABLAGUAeQAgAFMAdABvAHIAYQBnAGUAIABQAHIAbwB2AGkAZABlAHIwggO/BgkqhkiG9w0BBwagggOwMIIDrAIBADCCA6UGCSqGSIb3DQEHATAcBgoqhkiG9w0BDAEGMA4ECEBk5ZAYpu0WAgIH0ICCA3hik4mQFGpw9Ha8TQPtk+j2jwWdxfF0+sTk6S8PTsEfIhB7wPltjiCK92Uv2tCBQnodBUmatIfkpnRDEySmgmdglmOCzj204lWAMRs94PoALGn3JVBXbO1vIDCbAPOZ7Z0Hd0/1t2hmk8v3//QJGUg+qr59/4y/MuVfIg4qfkPcC2QSvYWcK3oTf6SFi5rv9B1IOWFgN5D0+C+x/9Lb/myPYX+rbOHrwtJ4W1fWKoz9g7wwmGFA9IJ2DYGuH8ifVFbDFT1Vcgsvs8arSX7oBsJVW0qrP7XkuDRe3EqCmKW7rBEwYrFznhxZcRDEpMwbFoSvgSIZ4XhFY9VKYglT+JpNH5iDceYEBOQL4vBLpxNUk3l5jKaBNxVa14AIBxq18bVHJ+STInhLhad4u10v/Xbx7wIL3f9DX1yLAkPrpBYbNHS2/ew6H/ySDJnoIDxkw2zZ4qJ+qUJZ1S0lbZVG+VT0OP5uF6tyOSpbMlcGkdl3z254n6MlCrTifcwkzscysDsgKXaYQw06rzrPW6RDub+t+hXzGny799fS9jhQMLDmOggaQ7+LA4oEZsfT89HLMWxJYDqjo3gIfjciV2mV54R684qLDS+AO09U49e6yEbwGlq8lpmO/pbXCbpGbB1b3EomcQbxdWxW2WEkkEd/VBn81K4M3obmywwXJkw+tPXDXfBmzzaqqCR+onMQ5ME1nMkY8ybnfoCc1bDIupjVWsEL2Wvq752RgI6KqzVNr1ew1IdqV5AWN2fOfek+0vi3Jd9FHF3hx8JMwjJL9dZsETV5kHtYJtE7wJ23J68BnCt2eI0GEuwXcCf5EdSKN/xXCTlIokc4Qk/gzRdIZsvcEJ6B1lGovKG54X4IohikqTjiepjbsMWj38yxDmK3mtENZ9ci8FPfbbvIEcOCZIinuY3qFUlRSbx7VUerEoV1IP3clUwexVQo4lHFee2jd7ocWsdSqSapW7OWUupBtDzRkqVhE7tGria+i1W2d6YLlJ21QTjyapWJehAMO637OdbJCCzDs1cXbodRRE7bsP492ocJy8OX66rKdhYbg8srSFNKdb3pF3UDNbN9jhI/t8iagRhNBhlQtTr1me2E/c86Q18qcRXl4bcXTt6acgCeffK6Y26LcVlrgjlD33AEYRRUeyC+rpxbT0aMjdFderlndKRIyG23mSp0HaUwNzAfMAcGBSsOAwIaBBRlviCbIyRrhIysg2dc/KbLFTc2vQQUg4rfwHMM4IKYRD/fsd1x6dda+wQ=`, + // empty string password test case + "testing@example.com": `MIIJzgIBAzCCCZQGCSqGSIb3DQEHAaCCCYUEggmBMIIJfTCCA/cGCSqGSIb3DQEHBqCCA+gwggPk +AgEAMIID3QYJKoZIhvcNAQcBMBwGCiqGSIb3DQEMAQYwDgQIIszfRGqcmPcCAggAgIIDsOZ9Eg1L +s5Wx8JhYoV3HAL4aRnkAWvTYB5NISZOgSgIQTssmt/3A7134dibTmaT/93LikkL3cTKLnQzJ4wDf +YZ1bprpVJvUqz+HFT79m27bP9zYXFrvxWBJbxjYKTSjQMgz+h8LAEpXXGajCmxMJ1oCOtdXkhhzc +LdZN6SAYgtmtyFnCdMEDskSggGuLb3fw84QEJ/Sj6FAULXunW/CPaS7Ce0TMsKmNU/jfFWj3yXXw +ro0kwjKiVLpVFlnBlHo2OoVU7hmkm59YpGhLgS7nxLD3n7nBroQ0ID1+8R01NnV9XLGoGzxMm1te +6UyTCkr5mj+kEQ8EP1Ys7g/TC411uhVWySMt/rcpkx7Vz1r9kYEAzJpONAfr6cuEVkPKrxpq4Fh0 +2fzlKBky0i/hrfIEUmngh+ERHUb/Mtv/fkv1j5w9suESbhsMLLiCXAlsP1UWMX+3bNizi3WVMEts +FM2k9byn+p8IUD/A8ULlE4kEaWeoc+2idkCNQkLGuIdGUXUFVm58se0auUkVRoRJx8x4CkMesT8j +b1H831W66YRWoEwwDQp2kK1lA2vQXxdVHWlFevMNxJeromLzj3ayiaFrfByeUXhR2S+Hpm+c0yNR +4UVU9WED2kacsZcpRm9nlEa5sr28mri5JdBrNa/K02OOhvKCxr5ZGmbOVzUQKla2z4w+Ku9k8POm +dfDNU/fGx1b5hcFWtghXe3msWVsSJrQihnN6q1ughzNiYZlJUGcHdZDRtiWwCFI0bR8h/Dmg9uO9 +4rawQQrjIRT7B8yF3UbkZyAqs8Ppb1TsMeNPHh1rxEfGVQknh/48ouJYsmtbnzugTUt3mJCXXiL+ +XcPMV6bBVAUu4aaVKSmg9+yJtY4/VKv10iw88ktv29fViIdBe3t6l/oPuvQgbQ8dqf4T8w0l/uKZ +9lS1Na9jfT1vCoS7F5TRi+tmyj1vL5kr/amEIW6xKEP6oeAMvCMtbPAzVEj38zdJ1R22FfuIBxkh +f0Zl7pdVbmzRxl/SBx9iIBJSqAvcXItiT0FIj8HxQ+0iZKqMQMiBuNWJf5pYOLWGrIyntCWwHuaQ +wrx0sTGuEL9YXLEAsBDrsvzLkx/56E4INGZFrH8G7HBdW6iGqb22IMI4GHltYSyBRKbB0gadYTyv +abPEoqww8o7/85aPSzOTJ/53ozD438Q+d0u9SyDuOb60SzCD/zPuCEd78YgtXJwBYTuUNRT27FaM +3LGMX8Hz+6yPNRnmnA2XKPn7dx/IlaqAjIs8MIIFfgYJKoZIhvcNAQcBoIIFbwSCBWswggVnMIIF +YwYLKoZIhvcNAQwKAQKgggTuMIIE6jAcBgoqhkiG9w0BDAEDMA4ECJr0cClYqOlcAgIIAASCBMhe +OQSiP2s0/46ONXcNeVAkz2ksW3u/+qorhSiskGZ0b3dFa1hhgBU2Q7JVIkc4Hf7OXaT1eVQ8oqND +uhqsNz83/kqYo70+LS8Hocj49jFgWAKrf/yQkdyP1daHa2yzlEw4mkpqOfnIORQHvYCa8nEApspZ +wVu8y6WVuLHKU67mel7db2xwstQp7PRuSAYqGjTfAylElog8ASdaqqYbYIrCXucF8iF9oVgmb/Qo +xrXshJ9aSLO4MuXlTPELmWgj07AXKSb90FKNihE+y0bWb9LPVFY1Sly3AX9PfrtkSXIZwqW3phpv +MxGxQl/R6mr1z+hlTfY9Wdpb5vlKXPKA0L0Rt8d2pOesylFi6esJoS01QgP1kJILjbrV731kvDc0 +Jsd+Oxv4BMwA7ClG8w1EAOInc/GrV1MWFGw/HeEqj3CZ/l/0jv9bwkbVeVCiIhoL6P6lVx9pXq4t +KZ0uKg/tk5TVJmG2vLcMLvezD0Yk3G2ZOMrywtmskrwoF7oAUpO9e87szoH6fEvUZlkDkPVW1NV4 +cZk3DBSQiuA3VOOg8qbo/tx/EE3H59P0axZWno2GSB0wFPWd1aj+b//tJEJHaaNR6qPRj4IWj9ru +Qbc8eRAcVWleHg8uAehSvUXlFpyMQREyrnpvMGddpiTC8N4UMrrBRhV7+UbCOWhxPCbItnInBqgl +1JpSZIP7iUtsIMdu3fEC2cdbXMTRul+4rdzUR7F9OaezV3jjvcAbDvgbK1CpyC+MJ1Mxm/iTgk9V +iUArydhlR8OniN84GyGYoYCW9O/KUwb6ASmeFOu/msx8x6kAsSQHIkKqMKv0TUR3kZnkxUvdpBGP +KTl4YCTvNGX4dYALBqrAETRDhua2KVBD/kEttDHwBNVbN2xi81+Mc7ml461aADfk0c66R/m2sjHB +2tN9+wG12OIWFQjL6wF/UfJMYamxx2zOOExiId29Opt57uYiNVLOO4ourPewHPeH0u8Gz35aero7 +lkt7cZAe1Q0038JUuE/QGlnK4lESK9UkSIQAjSaAlTsrcfwtQxB2EjoOoLhwH5mvxUEmcNGNnXUc +9xj3M5BD3zBz3Ft7G3YMMDwB1+zC2l+0UG0MGVjMVaeoy32VVNvxgX7jk22OXG1iaOB+PY9kdk+O +X+52BGSf/rD6X0EnqY7XuRPkMGgjtpZeAYxRQnFtCZgDY4wYheuxqSSpdF49yNczSPLkgB3CeCfS ++9NTKN7aC6hBbmW/8yYh6OvSiCEwY0lFS/T+7iaVxr1loE4zI1y/FFp4Pe1qfLlLttVlkygga2UU +SCunTQ8UB/M5IXWKkhMOO11dP4niWwb39Y7pCWpau7mwbXOKfRPX96cgHnQJK5uG+BesDD1oYnX0 +6frN7FOnTSHKruRIwuI8KnOQ/I+owmyz71wiv5LMQt+yM47UrEjB/EZa5X8dpEwOZvkdqL7utcyo +l0XH5kWMXdW856LL/FYftAqJIDAmtX1TXF/rbP6mPyN/IlDC0gjP84Uzd/a2UyTIWr+wk49Ek3vQ +/uDamq6QrwAxVmNh5Tset5Vhpc1e1kb7mRMZIzxSP8JcTuYd45oFKi98I8YjvueHVZce1g7OudQP +SbFQoJvdT46iBg1TTatlltpOiH2mFaxWVS0xYjAjBgkqhkiG9w0BCRUxFgQUdA9eVqvETX4an/c8 +p8SsTugkit8wOwYJKoZIhvcNAQkUMS4eLABGAHIAaQBlAG4AZABsAHkAIABuAGEAbQBlACAAZgBv +AHIAIABjAGUAcgB0MDEwITAJBgUrDgMCGgUABBRFsNz3Zd1O1GI8GTuFwCWuDOjEEwQIuBEfIcAy +HQ8CAggA`, +} diff --git a/vendor/golang.org/x/crypto/pkcs12/safebags.go b/vendor/golang.org/x/crypto/pkcs12/safebags.go new file mode 100644 index 0000000000000000000000000000000000000000..def1f7b98d7de48b3ba062f332ced3a6e1049032 --- /dev/null +++ b/vendor/golang.org/x/crypto/pkcs12/safebags.go @@ -0,0 +1,57 @@ +// Copyright 2015 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 pkcs12 + +import ( + "crypto/x509" + "encoding/asn1" + "errors" +) + +var ( + // see https://tools.ietf.org/html/rfc7292#appendix-D + oidCertTypeX509Certificate = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 9, 22, 1}) + oidPKCS8ShroundedKeyBag = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 10, 1, 2}) + oidCertBag = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 10, 1, 3}) +) + +type certBag struct { + Id asn1.ObjectIdentifier + Data []byte `asn1:"tag:0,explicit"` +} + +func decodePkcs8ShroudedKeyBag(asn1Data, password []byte) (privateKey interface{}, err error) { + pkinfo := new(encryptedPrivateKeyInfo) + if err = unmarshal(asn1Data, pkinfo); err != nil { + return nil, errors.New("pkcs12: error decoding PKCS#8 shrouded key bag: " + err.Error()) + } + + pkData, err := pbDecrypt(pkinfo, password) + if err != nil { + return nil, errors.New("pkcs12: error decrypting PKCS#8 shrouded key bag: " + err.Error()) + } + + ret := new(asn1.RawValue) + if err = unmarshal(pkData, ret); err != nil { + return nil, errors.New("pkcs12: error unmarshaling decrypted private key: " + err.Error()) + } + + if privateKey, err = x509.ParsePKCS8PrivateKey(pkData); err != nil { + return nil, errors.New("pkcs12: error parsing PKCS#8 private key: " + err.Error()) + } + + return privateKey, nil +} + +func decodeCertBag(asn1Data []byte) (x509Certificates []byte, err error) { + bag := new(certBag) + if err := unmarshal(asn1Data, bag); err != nil { + return nil, errors.New("pkcs12: error decoding cert bag: " + err.Error()) + } + if !bag.Id.Equal(oidCertTypeX509Certificate) { + return nil, NotImplementedError("only X509 certificates are supported") + } + return bag.Data, nil +} diff --git a/vendor/golang.org/x/crypto/poly1305/poly1305.go b/vendor/golang.org/x/crypto/poly1305/poly1305.go new file mode 100644 index 0000000000000000000000000000000000000000..f562fa5712ba09a1bed13121c08a98b502ab328f --- /dev/null +++ b/vendor/golang.org/x/crypto/poly1305/poly1305.go @@ -0,0 +1,33 @@ +// 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 poly1305 implements Poly1305 one-time message authentication code as +specified in https://cr.yp.to/mac/poly1305-20050329.pdf. + +Poly1305 is a fast, one-time authentication function. It is infeasible for an +attacker to generate an authenticator for a message without the key. However, a +key must only be used for a single message. Authenticating two different +messages with the same key allows an attacker to forge authenticators for other +messages with the same key. + +Poly1305 was originally coupled with AES in order to make Poly1305-AES. AES was +used with a fixed key in order to generate one-time keys from an nonce. +However, in this package AES isn't used and the one-time key is specified +directly. +*/ +package poly1305 // import "golang.org/x/crypto/poly1305" + +import "crypto/subtle" + +// TagSize is the size, in bytes, of a poly1305 authenticator. +const TagSize = 16 + +// Verify returns true if mac is a valid authenticator for m with the given +// key. +func Verify(mac *[16]byte, m []byte, key *[32]byte) bool { + var tmp [16]byte + Sum(&tmp, m, key) + return subtle.ConstantTimeCompare(tmp[:], mac[:]) == 1 +} diff --git a/vendor/golang.org/x/crypto/poly1305/poly1305_test.go b/vendor/golang.org/x/crypto/poly1305/poly1305_test.go new file mode 100644 index 0000000000000000000000000000000000000000..017027fe6e5edbb2c4db9626fea3e7755e91962a --- /dev/null +++ b/vendor/golang.org/x/crypto/poly1305/poly1305_test.go @@ -0,0 +1,159 @@ +// 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 poly1305 + +import ( + "bytes" + "encoding/hex" + "flag" + "testing" + "unsafe" +) + +var stressFlag = flag.Bool("stress", false, "run slow stress tests") + +var testData = []struct { + in, k, correct []byte +}{ + { + []byte("Hello world!"), + []byte("this is 32-byte key for Poly1305"), + []byte{0xa6, 0xf7, 0x45, 0x00, 0x8f, 0x81, 0xc9, 0x16, 0xa2, 0x0d, 0xcc, 0x74, 0xee, 0xf2, 0xb2, 0xf0}, + }, + { + make([]byte, 32), + []byte("this is 32-byte key for Poly1305"), + []byte{0x49, 0xec, 0x78, 0x09, 0x0e, 0x48, 0x1e, 0xc6, 0xc2, 0x6b, 0x33, 0xb9, 0x1c, 0xcc, 0x03, 0x07}, + }, + { + make([]byte, 2007), + []byte("this is 32-byte key for Poly1305"), + []byte{0xda, 0x84, 0xbc, 0xab, 0x02, 0x67, 0x6c, 0x38, 0xcd, 0xb0, 0x15, 0x60, 0x42, 0x74, 0xc2, 0xaa}, + }, + { + make([]byte, 2007), + make([]byte, 32), + make([]byte, 16), + }, + { + // This test triggers an edge-case. See https://go-review.googlesource.com/#/c/30101/. + []byte{0x81, 0xd8, 0xb2, 0xe4, 0x6a, 0x25, 0x21, 0x3b, 0x58, 0xfe, 0xe4, 0x21, 0x3a, 0x2a, 0x28, 0xe9, 0x21, 0xc1, 0x2a, 0x96, 0x32, 0x51, 0x6d, 0x3b, 0x73, 0x27, 0x27, 0x27, 0xbe, 0xcf, 0x21, 0x29}, + []byte{0x3b, 0x3a, 0x29, 0xe9, 0x3b, 0x21, 0x3a, 0x5c, 0x5c, 0x3b, 0x3b, 0x05, 0x3a, 0x3a, 0x8c, 0x0d}, + []byte{0x6d, 0xc1, 0x8b, 0x8c, 0x34, 0x4c, 0xd7, 0x99, 0x27, 0x11, 0x8b, 0xbe, 0x84, 0xb7, 0xf3, 0x14}, + }, + { + // This test generates a result of (2^130-1) % (2^130-5). + []byte{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + []byte{1, 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}, + []byte{4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + }, + { + // This test generates a result of (2^130-6) % (2^130-5). + []byte{ + 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + []byte{1, 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}, + []byte{0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + }, + { + // This test generates a result of (2^130-5) % (2^130-5). + []byte{ + 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + []byte{1, 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}, + []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + }, +} + +func testSum(t *testing.T, unaligned bool) { + var out [16]byte + var key [32]byte + + for i, v := range testData { + in := v.in + if unaligned { + in = unalignBytes(in) + } + copy(key[:], v.k) + Sum(&out, in, &key) + if !bytes.Equal(out[:], v.correct) { + t.Errorf("%d: expected %x, got %x", i, v.correct, out[:]) + } + } +} + +func TestBurnin(t *testing.T) { + // This test can be used to sanity-check significant changes. It can + // take about many minutes to run, even on fast machines. It's disabled + // by default. + if !*stressFlag { + t.Skip("skipping without -stress") + } + + var key [32]byte + var input [25]byte + var output [16]byte + + for i := range key { + key[i] = 1 + } + for i := range input { + input[i] = 2 + } + + for i := uint64(0); i < 1e10; i++ { + Sum(&output, input[:], &key) + copy(key[0:], output[:]) + copy(key[16:], output[:]) + copy(input[:], output[:]) + copy(input[16:], output[:]) + } + + const expected = "5e3b866aea0b636d240c83c428f84bfa" + if got := hex.EncodeToString(output[:]); got != expected { + t.Errorf("expected %s, got %s", expected, got) + } +} + +func TestSum(t *testing.T) { testSum(t, false) } +func TestSumUnaligned(t *testing.T) { testSum(t, true) } + +func benchmark(b *testing.B, size int, unaligned bool) { + var out [16]byte + var key [32]byte + in := make([]byte, size) + if unaligned { + in = unalignBytes(in) + } + b.SetBytes(int64(len(in))) + b.ResetTimer() + for i := 0; i < b.N; i++ { + Sum(&out, in, &key) + } +} + +func Benchmark64(b *testing.B) { benchmark(b, 64, false) } +func Benchmark1K(b *testing.B) { benchmark(b, 1024, false) } +func Benchmark64Unaligned(b *testing.B) { benchmark(b, 64, true) } +func Benchmark1KUnaligned(b *testing.B) { benchmark(b, 1024, true) } + +func unalignBytes(in []byte) []byte { + out := make([]byte, len(in)+1) + if uintptr(unsafe.Pointer(&out[0]))&(unsafe.Alignof(uint32(0))-1) == 0 { + out = out[1:] + } else { + out = out[:len(in)] + } + copy(out, in) + return out +} diff --git a/vendor/golang.org/x/crypto/poly1305/sum_amd64.go b/vendor/golang.org/x/crypto/poly1305/sum_amd64.go new file mode 100644 index 0000000000000000000000000000000000000000..4dd72fe799b2d3524b9af7457df67fbad4444170 --- /dev/null +++ b/vendor/golang.org/x/crypto/poly1305/sum_amd64.go @@ -0,0 +1,22 @@ +// 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,!appengine + +package poly1305 + +// This function is implemented in sum_amd64.s +//go:noescape +func poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]byte) + +// Sum generates an authenticator for m using a one-time key and puts the +// 16-byte result into out. Authenticating two different messages with the same +// key allows an attacker to forge messages at will. +func Sum(out *[16]byte, m []byte, key *[32]byte) { + var mPtr *byte + if len(m) > 0 { + mPtr = &m[0] + } + poly1305(out, mPtr, uint64(len(m)), key) +} diff --git a/vendor/golang.org/x/crypto/poly1305/sum_amd64.s b/vendor/golang.org/x/crypto/poly1305/sum_amd64.s new file mode 100644 index 0000000000000000000000000000000000000000..2edae63828a5f0d3efa73585d3882a31c3f4343c --- /dev/null +++ b/vendor/golang.org/x/crypto/poly1305/sum_amd64.s @@ -0,0 +1,125 @@ +// 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,!appengine + +#include "textflag.h" + +#define POLY1305_ADD(msg, h0, h1, h2) \ + ADDQ 0(msg), h0; \ + ADCQ 8(msg), h1; \ + ADCQ $1, h2; \ + LEAQ 16(msg), msg + +#define POLY1305_MUL(h0, h1, h2, r0, r1, t0, t1, t2, t3) \ + MOVQ r0, AX; \ + MULQ h0; \ + MOVQ AX, t0; \ + MOVQ DX, t1; \ + MOVQ r0, AX; \ + MULQ h1; \ + ADDQ AX, t1; \ + ADCQ $0, DX; \ + MOVQ r0, t2; \ + IMULQ h2, t2; \ + ADDQ DX, t2; \ + \ + MOVQ r1, AX; \ + MULQ h0; \ + ADDQ AX, t1; \ + ADCQ $0, DX; \ + MOVQ DX, h0; \ + MOVQ r1, t3; \ + IMULQ h2, t3; \ + MOVQ r1, AX; \ + MULQ h1; \ + ADDQ AX, t2; \ + ADCQ DX, t3; \ + ADDQ h0, t2; \ + ADCQ $0, t3; \ + \ + MOVQ t0, h0; \ + MOVQ t1, h1; \ + MOVQ t2, h2; \ + ANDQ $3, h2; \ + MOVQ t2, t0; \ + ANDQ $0xFFFFFFFFFFFFFFFC, t0; \ + ADDQ t0, h0; \ + ADCQ t3, h1; \ + ADCQ $0, h2; \ + SHRQ $2, t3, t2; \ + SHRQ $2, t3; \ + ADDQ t2, h0; \ + ADCQ t3, h1; \ + ADCQ $0, h2 + +DATA ·poly1305Mask<>+0x00(SB)/8, $0x0FFFFFFC0FFFFFFF +DATA ·poly1305Mask<>+0x08(SB)/8, $0x0FFFFFFC0FFFFFFC +GLOBL ·poly1305Mask<>(SB), RODATA, $16 + +// func poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]key) +TEXT ·poly1305(SB), $0-32 + MOVQ out+0(FP), DI + MOVQ m+8(FP), SI + MOVQ mlen+16(FP), R15 + MOVQ key+24(FP), AX + + MOVQ 0(AX), R11 + MOVQ 8(AX), R12 + ANDQ ·poly1305Mask<>(SB), R11 // r0 + ANDQ ·poly1305Mask<>+8(SB), R12 // r1 + XORQ R8, R8 // h0 + XORQ R9, R9 // h1 + XORQ R10, R10 // h2 + + CMPQ R15, $16 + JB bytes_between_0_and_15 + +loop: + POLY1305_ADD(SI, R8, R9, R10) + +multiply: + POLY1305_MUL(R8, R9, R10, R11, R12, BX, CX, R13, R14) + SUBQ $16, R15 + CMPQ R15, $16 + JAE loop + +bytes_between_0_and_15: + TESTQ R15, R15 + JZ done + MOVQ $1, BX + XORQ CX, CX + XORQ R13, R13 + ADDQ R15, SI + +flush_buffer: + SHLQ $8, BX, CX + SHLQ $8, BX + MOVB -1(SI), R13 + XORQ R13, BX + DECQ SI + DECQ R15 + JNZ flush_buffer + + ADDQ BX, R8 + ADCQ CX, R9 + ADCQ $0, R10 + MOVQ $16, R15 + JMP multiply + +done: + MOVQ R8, AX + MOVQ R9, BX + SUBQ $0xFFFFFFFFFFFFFFFB, AX + SBBQ $0xFFFFFFFFFFFFFFFF, BX + SBBQ $3, R10 + CMOVQCS R8, AX + CMOVQCS R9, BX + MOVQ key+24(FP), R8 + ADDQ 16(R8), AX + ADCQ 24(R8), BX + + MOVQ AX, 0(DI) + MOVQ BX, 8(DI) + RET diff --git a/vendor/golang.org/x/crypto/poly1305/sum_arm.go b/vendor/golang.org/x/crypto/poly1305/sum_arm.go new file mode 100644 index 0000000000000000000000000000000000000000..5dc321c2f39e67863917e0cbe6b7b76aa5361669 --- /dev/null +++ b/vendor/golang.org/x/crypto/poly1305/sum_arm.go @@ -0,0 +1,22 @@ +// Copyright 2015 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 arm,!gccgo,!appengine,!nacl + +package poly1305 + +// This function is implemented in sum_arm.s +//go:noescape +func poly1305_auth_armv6(out *[16]byte, m *byte, mlen uint32, key *[32]byte) + +// Sum generates an authenticator for m using a one-time key and puts the +// 16-byte result into out. Authenticating two different messages with the same +// key allows an attacker to forge messages at will. +func Sum(out *[16]byte, m []byte, key *[32]byte) { + var mPtr *byte + if len(m) > 0 { + mPtr = &m[0] + } + poly1305_auth_armv6(out, mPtr, uint32(len(m)), key) +} diff --git a/vendor/golang.org/x/crypto/poly1305/sum_arm.s b/vendor/golang.org/x/crypto/poly1305/sum_arm.s new file mode 100644 index 0000000000000000000000000000000000000000..f70b4ac484518ba4a6e16009a769b0472e902bc1 --- /dev/null +++ b/vendor/golang.org/x/crypto/poly1305/sum_arm.s @@ -0,0 +1,427 @@ +// Copyright 2015 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 arm,!gccgo,!appengine,!nacl + +#include "textflag.h" + +// This code was translated into a form compatible with 5a from the public +// domain source by Andrew Moon: github.com/floodyberry/poly1305-opt/blob/master/app/extensions/poly1305. + +DATA ·poly1305_init_constants_armv6<>+0x00(SB)/4, $0x3ffffff +DATA ·poly1305_init_constants_armv6<>+0x04(SB)/4, $0x3ffff03 +DATA ·poly1305_init_constants_armv6<>+0x08(SB)/4, $0x3ffc0ff +DATA ·poly1305_init_constants_armv6<>+0x0c(SB)/4, $0x3f03fff +DATA ·poly1305_init_constants_armv6<>+0x10(SB)/4, $0x00fffff +GLOBL ·poly1305_init_constants_armv6<>(SB), 8, $20 + +// Warning: the linker may use R11 to synthesize certain instructions. Please +// take care and verify that no synthetic instructions use it. + +TEXT poly1305_init_ext_armv6<>(SB), NOSPLIT, $0 + // Needs 16 bytes of stack and 64 bytes of space pointed to by R0. (It + // might look like it's only 60 bytes of space but the final four bytes + // will be written by another function.) We need to skip over four + // bytes of stack because that's saving the value of 'g'. + ADD $4, R13, R8 + MOVM.IB [R4-R7], (R8) + MOVM.IA.W (R1), [R2-R5] + MOVW $·poly1305_init_constants_armv6<>(SB), R7 + MOVW R2, R8 + MOVW R2>>26, R9 + MOVW R3>>20, g + MOVW R4>>14, R11 + MOVW R5>>8, R12 + ORR R3<<6, R9, R9 + ORR R4<<12, g, g + ORR R5<<18, R11, R11 + MOVM.IA (R7), [R2-R6] + AND R8, R2, R2 + AND R9, R3, R3 + AND g, R4, R4 + AND R11, R5, R5 + AND R12, R6, R6 + MOVM.IA.W [R2-R6], (R0) + EOR R2, R2, R2 + EOR R3, R3, R3 + EOR R4, R4, R4 + EOR R5, R5, R5 + EOR R6, R6, R6 + MOVM.IA.W [R2-R6], (R0) + MOVM.IA.W (R1), [R2-R5] + MOVM.IA [R2-R6], (R0) + ADD $20, R13, R0 + MOVM.DA (R0), [R4-R7] + RET + +#define MOVW_UNALIGNED(Rsrc, Rdst, Rtmp, offset) \ + MOVBU (offset+0)(Rsrc), Rtmp; \ + MOVBU Rtmp, (offset+0)(Rdst); \ + MOVBU (offset+1)(Rsrc), Rtmp; \ + MOVBU Rtmp, (offset+1)(Rdst); \ + MOVBU (offset+2)(Rsrc), Rtmp; \ + MOVBU Rtmp, (offset+2)(Rdst); \ + MOVBU (offset+3)(Rsrc), Rtmp; \ + MOVBU Rtmp, (offset+3)(Rdst) + +TEXT poly1305_blocks_armv6<>(SB), NOSPLIT, $0 + // Needs 24 bytes of stack for saved registers and then 88 bytes of + // scratch space after that. We assume that 24 bytes at (R13) have + // already been used: four bytes for the link register saved in the + // prelude of poly1305_auth_armv6, four bytes for saving the value of g + // in that function and 16 bytes of scratch space used around + // poly1305_finish_ext_armv6_skip1. + ADD $24, R13, R12 + MOVM.IB [R4-R8, R14], (R12) + MOVW R0, 88(R13) + MOVW R1, 92(R13) + MOVW R2, 96(R13) + MOVW R1, R14 + MOVW R2, R12 + MOVW 56(R0), R8 + WORD $0xe1180008 // TST R8, R8 not working see issue 5921 + EOR R6, R6, R6 + MOVW.EQ $(1<<24), R6 + MOVW R6, 84(R13) + ADD $116, R13, g + MOVM.IA (R0), [R0-R9] + MOVM.IA [R0-R4], (g) + CMP $16, R12 + BLO poly1305_blocks_armv6_done + +poly1305_blocks_armv6_mainloop: + WORD $0xe31e0003 // TST R14, #3 not working see issue 5921 + BEQ poly1305_blocks_armv6_mainloop_aligned + ADD $100, R13, g + MOVW_UNALIGNED(R14, g, R0, 0) + MOVW_UNALIGNED(R14, g, R0, 4) + MOVW_UNALIGNED(R14, g, R0, 8) + MOVW_UNALIGNED(R14, g, R0, 12) + MOVM.IA (g), [R0-R3] + ADD $16, R14 + B poly1305_blocks_armv6_mainloop_loaded + +poly1305_blocks_armv6_mainloop_aligned: + MOVM.IA.W (R14), [R0-R3] + +poly1305_blocks_armv6_mainloop_loaded: + MOVW R0>>26, g + MOVW R1>>20, R11 + MOVW R2>>14, R12 + MOVW R14, 92(R13) + MOVW R3>>8, R4 + ORR R1<<6, g, g + ORR R2<<12, R11, R11 + ORR R3<<18, R12, R12 + BIC $0xfc000000, R0, R0 + BIC $0xfc000000, g, g + MOVW 84(R13), R3 + BIC $0xfc000000, R11, R11 + BIC $0xfc000000, R12, R12 + ADD R0, R5, R5 + ADD g, R6, R6 + ORR R3, R4, R4 + ADD R11, R7, R7 + ADD $116, R13, R14 + ADD R12, R8, R8 + ADD R4, R9, R9 + MOVM.IA (R14), [R0-R4] + MULLU R4, R5, (R11, g) + MULLU R3, R5, (R14, R12) + MULALU R3, R6, (R11, g) + MULALU R2, R6, (R14, R12) + MULALU R2, R7, (R11, g) + MULALU R1, R7, (R14, R12) + ADD R4<<2, R4, R4 + ADD R3<<2, R3, R3 + MULALU R1, R8, (R11, g) + MULALU R0, R8, (R14, R12) + MULALU R0, R9, (R11, g) + MULALU R4, R9, (R14, R12) + MOVW g, 76(R13) + MOVW R11, 80(R13) + MOVW R12, 68(R13) + MOVW R14, 72(R13) + MULLU R2, R5, (R11, g) + MULLU R1, R5, (R14, R12) + MULALU R1, R6, (R11, g) + MULALU R0, R6, (R14, R12) + MULALU R0, R7, (R11, g) + MULALU R4, R7, (R14, R12) + ADD R2<<2, R2, R2 + ADD R1<<2, R1, R1 + MULALU R4, R8, (R11, g) + MULALU R3, R8, (R14, R12) + MULALU R3, R9, (R11, g) + MULALU R2, R9, (R14, R12) + MOVW g, 60(R13) + MOVW R11, 64(R13) + MOVW R12, 52(R13) + MOVW R14, 56(R13) + MULLU R0, R5, (R11, g) + MULALU R4, R6, (R11, g) + MULALU R3, R7, (R11, g) + MULALU R2, R8, (R11, g) + MULALU R1, R9, (R11, g) + ADD $52, R13, R0 + MOVM.IA (R0), [R0-R7] + MOVW g>>26, R12 + MOVW R4>>26, R14 + ORR R11<<6, R12, R12 + ORR R5<<6, R14, R14 + BIC $0xfc000000, g, g + BIC $0xfc000000, R4, R4 + ADD.S R12, R0, R0 + ADC $0, R1, R1 + ADD.S R14, R6, R6 + ADC $0, R7, R7 + MOVW R0>>26, R12 + MOVW R6>>26, R14 + ORR R1<<6, R12, R12 + ORR R7<<6, R14, R14 + BIC $0xfc000000, R0, R0 + BIC $0xfc000000, R6, R6 + ADD R14<<2, R14, R14 + ADD.S R12, R2, R2 + ADC $0, R3, R3 + ADD R14, g, g + MOVW R2>>26, R12 + MOVW g>>26, R14 + ORR R3<<6, R12, R12 + BIC $0xfc000000, g, R5 + BIC $0xfc000000, R2, R7 + ADD R12, R4, R4 + ADD R14, R0, R0 + MOVW R4>>26, R12 + BIC $0xfc000000, R4, R8 + ADD R12, R6, R9 + MOVW 96(R13), R12 + MOVW 92(R13), R14 + MOVW R0, R6 + CMP $32, R12 + SUB $16, R12, R12 + MOVW R12, 96(R13) + BHS poly1305_blocks_armv6_mainloop + +poly1305_blocks_armv6_done: + MOVW 88(R13), R12 + MOVW R5, 20(R12) + MOVW R6, 24(R12) + MOVW R7, 28(R12) + MOVW R8, 32(R12) + MOVW R9, 36(R12) + ADD $48, R13, R0 + MOVM.DA (R0), [R4-R8, R14] + RET + +#define MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp) \ + MOVBU.P 1(Rsrc), Rtmp; \ + MOVBU.P Rtmp, 1(Rdst); \ + MOVBU.P 1(Rsrc), Rtmp; \ + MOVBU.P Rtmp, 1(Rdst) + +#define MOVWP_UNALIGNED(Rsrc, Rdst, Rtmp) \ + MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp); \ + MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp) + +// func poly1305_auth_armv6(out *[16]byte, m *byte, mlen uint32, key *[32]key) +TEXT ·poly1305_auth_armv6(SB), $196-16 + // The value 196, just above, is the sum of 64 (the size of the context + // structure) and 132 (the amount of stack needed). + // + // At this point, the stack pointer (R13) has been moved down. It + // points to the saved link register and there's 196 bytes of free + // space above it. + // + // The stack for this function looks like: + // + // +--------------------- + // | + // | 64 bytes of context structure + // | + // +--------------------- + // | + // | 112 bytes for poly1305_blocks_armv6 + // | + // +--------------------- + // | 16 bytes of final block, constructed at + // | poly1305_finish_ext_armv6_skip8 + // +--------------------- + // | four bytes of saved 'g' + // +--------------------- + // | lr, saved by prelude <- R13 points here + // +--------------------- + MOVW g, 4(R13) + + MOVW out+0(FP), R4 + MOVW m+4(FP), R5 + MOVW mlen+8(FP), R6 + MOVW key+12(FP), R7 + + ADD $136, R13, R0 // 136 = 4 + 4 + 16 + 112 + MOVW R7, R1 + + // poly1305_init_ext_armv6 will write to the stack from R13+4, but + // that's ok because none of the other values have been written yet. + BL poly1305_init_ext_armv6<>(SB) + BIC.S $15, R6, R2 + BEQ poly1305_auth_armv6_noblocks + ADD $136, R13, R0 + MOVW R5, R1 + ADD R2, R5, R5 + SUB R2, R6, R6 + BL poly1305_blocks_armv6<>(SB) + +poly1305_auth_armv6_noblocks: + ADD $136, R13, R0 + MOVW R5, R1 + MOVW R6, R2 + MOVW R4, R3 + + MOVW R0, R5 + MOVW R1, R6 + MOVW R2, R7 + MOVW R3, R8 + AND.S R2, R2, R2 + BEQ poly1305_finish_ext_armv6_noremaining + EOR R0, R0 + ADD $8, R13, R9 // 8 = offset to 16 byte scratch space + MOVW R0, (R9) + MOVW R0, 4(R9) + MOVW R0, 8(R9) + MOVW R0, 12(R9) + WORD $0xe3110003 // TST R1, #3 not working see issue 5921 + BEQ poly1305_finish_ext_armv6_aligned + WORD $0xe3120008 // TST R2, #8 not working see issue 5921 + BEQ poly1305_finish_ext_armv6_skip8 + MOVWP_UNALIGNED(R1, R9, g) + MOVWP_UNALIGNED(R1, R9, g) + +poly1305_finish_ext_armv6_skip8: + WORD $0xe3120004 // TST $4, R2 not working see issue 5921 + BEQ poly1305_finish_ext_armv6_skip4 + MOVWP_UNALIGNED(R1, R9, g) + +poly1305_finish_ext_armv6_skip4: + WORD $0xe3120002 // TST $2, R2 not working see issue 5921 + BEQ poly1305_finish_ext_armv6_skip2 + MOVHUP_UNALIGNED(R1, R9, g) + B poly1305_finish_ext_armv6_skip2 + +poly1305_finish_ext_armv6_aligned: + WORD $0xe3120008 // TST R2, #8 not working see issue 5921 + BEQ poly1305_finish_ext_armv6_skip8_aligned + MOVM.IA.W (R1), [g-R11] + MOVM.IA.W [g-R11], (R9) + +poly1305_finish_ext_armv6_skip8_aligned: + WORD $0xe3120004 // TST $4, R2 not working see issue 5921 + BEQ poly1305_finish_ext_armv6_skip4_aligned + MOVW.P 4(R1), g + MOVW.P g, 4(R9) + +poly1305_finish_ext_armv6_skip4_aligned: + WORD $0xe3120002 // TST $2, R2 not working see issue 5921 + BEQ poly1305_finish_ext_armv6_skip2 + MOVHU.P 2(R1), g + MOVH.P g, 2(R9) + +poly1305_finish_ext_armv6_skip2: + WORD $0xe3120001 // TST $1, R2 not working see issue 5921 + BEQ poly1305_finish_ext_armv6_skip1 + MOVBU.P 1(R1), g + MOVBU.P g, 1(R9) + +poly1305_finish_ext_armv6_skip1: + MOVW $1, R11 + MOVBU R11, 0(R9) + MOVW R11, 56(R5) + MOVW R5, R0 + ADD $8, R13, R1 + MOVW $16, R2 + BL poly1305_blocks_armv6<>(SB) + +poly1305_finish_ext_armv6_noremaining: + MOVW 20(R5), R0 + MOVW 24(R5), R1 + MOVW 28(R5), R2 + MOVW 32(R5), R3 + MOVW 36(R5), R4 + MOVW R4>>26, R12 + BIC $0xfc000000, R4, R4 + ADD R12<<2, R12, R12 + ADD R12, R0, R0 + MOVW R0>>26, R12 + BIC $0xfc000000, R0, R0 + ADD R12, R1, R1 + MOVW R1>>26, R12 + BIC $0xfc000000, R1, R1 + ADD R12, R2, R2 + MOVW R2>>26, R12 + BIC $0xfc000000, R2, R2 + ADD R12, R3, R3 + MOVW R3>>26, R12 + BIC $0xfc000000, R3, R3 + ADD R12, R4, R4 + ADD $5, R0, R6 + MOVW R6>>26, R12 + BIC $0xfc000000, R6, R6 + ADD R12, R1, R7 + MOVW R7>>26, R12 + BIC $0xfc000000, R7, R7 + ADD R12, R2, g + MOVW g>>26, R12 + BIC $0xfc000000, g, g + ADD R12, R3, R11 + MOVW $-(1<<26), R12 + ADD R11>>26, R12, R12 + BIC $0xfc000000, R11, R11 + ADD R12, R4, R9 + MOVW R9>>31, R12 + SUB $1, R12 + AND R12, R6, R6 + AND R12, R7, R7 + AND R12, g, g + AND R12, R11, R11 + AND R12, R9, R9 + MVN R12, R12 + AND R12, R0, R0 + AND R12, R1, R1 + AND R12, R2, R2 + AND R12, R3, R3 + AND R12, R4, R4 + ORR R6, R0, R0 + ORR R7, R1, R1 + ORR g, R2, R2 + ORR R11, R3, R3 + ORR R9, R4, R4 + ORR R1<<26, R0, R0 + MOVW R1>>6, R1 + ORR R2<<20, R1, R1 + MOVW R2>>12, R2 + ORR R3<<14, R2, R2 + MOVW R3>>18, R3 + ORR R4<<8, R3, R3 + MOVW 40(R5), R6 + MOVW 44(R5), R7 + MOVW 48(R5), g + MOVW 52(R5), R11 + ADD.S R6, R0, R0 + ADC.S R7, R1, R1 + ADC.S g, R2, R2 + ADC.S R11, R3, R3 + MOVM.IA [R0-R3], (R8) + MOVW R5, R12 + EOR R0, R0, R0 + EOR R1, R1, R1 + EOR R2, R2, R2 + EOR R3, R3, R3 + EOR R4, R4, R4 + EOR R5, R5, R5 + EOR R6, R6, R6 + EOR R7, R7, R7 + MOVM.IA.W [R0-R7], (R12) + MOVM.IA [R0-R7], (R12) + MOVW 4(R13), g + RET diff --git a/vendor/golang.org/x/crypto/poly1305/sum_ref.go b/vendor/golang.org/x/crypto/poly1305/sum_ref.go new file mode 100644 index 0000000000000000000000000000000000000000..b2805a5ca173b29dabaa49aade4ea82322779551 --- /dev/null +++ b/vendor/golang.org/x/crypto/poly1305/sum_ref.go @@ -0,0 +1,141 @@ +// 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,!arm gccgo appengine nacl + +package poly1305 + +import "encoding/binary" + +// Sum generates an authenticator for msg using a one-time key and puts the +// 16-byte result into out. Authenticating two different messages with the same +// key allows an attacker to forge messages at will. +func Sum(out *[TagSize]byte, msg []byte, key *[32]byte) { + var ( + h0, h1, h2, h3, h4 uint32 // the hash accumulators + r0, r1, r2, r3, r4 uint64 // the r part of the key + ) + + r0 = uint64(binary.LittleEndian.Uint32(key[0:]) & 0x3ffffff) + r1 = uint64((binary.LittleEndian.Uint32(key[3:]) >> 2) & 0x3ffff03) + r2 = uint64((binary.LittleEndian.Uint32(key[6:]) >> 4) & 0x3ffc0ff) + r3 = uint64((binary.LittleEndian.Uint32(key[9:]) >> 6) & 0x3f03fff) + r4 = uint64((binary.LittleEndian.Uint32(key[12:]) >> 8) & 0x00fffff) + + R1, R2, R3, R4 := r1*5, r2*5, r3*5, r4*5 + + for len(msg) >= TagSize { + // h += msg + h0 += binary.LittleEndian.Uint32(msg[0:]) & 0x3ffffff + h1 += (binary.LittleEndian.Uint32(msg[3:]) >> 2) & 0x3ffffff + h2 += (binary.LittleEndian.Uint32(msg[6:]) >> 4) & 0x3ffffff + h3 += (binary.LittleEndian.Uint32(msg[9:]) >> 6) & 0x3ffffff + h4 += (binary.LittleEndian.Uint32(msg[12:]) >> 8) | (1 << 24) + + // h *= r + d0 := (uint64(h0) * r0) + (uint64(h1) * R4) + (uint64(h2) * R3) + (uint64(h3) * R2) + (uint64(h4) * R1) + d1 := (d0 >> 26) + (uint64(h0) * r1) + (uint64(h1) * r0) + (uint64(h2) * R4) + (uint64(h3) * R3) + (uint64(h4) * R2) + d2 := (d1 >> 26) + (uint64(h0) * r2) + (uint64(h1) * r1) + (uint64(h2) * r0) + (uint64(h3) * R4) + (uint64(h4) * R3) + d3 := (d2 >> 26) + (uint64(h0) * r3) + (uint64(h1) * r2) + (uint64(h2) * r1) + (uint64(h3) * r0) + (uint64(h4) * R4) + d4 := (d3 >> 26) + (uint64(h0) * r4) + (uint64(h1) * r3) + (uint64(h2) * r2) + (uint64(h3) * r1) + (uint64(h4) * r0) + + // h %= p + h0 = uint32(d0) & 0x3ffffff + h1 = uint32(d1) & 0x3ffffff + h2 = uint32(d2) & 0x3ffffff + h3 = uint32(d3) & 0x3ffffff + h4 = uint32(d4) & 0x3ffffff + + h0 += uint32(d4>>26) * 5 + h1 += h0 >> 26 + h0 = h0 & 0x3ffffff + + msg = msg[TagSize:] + } + + if len(msg) > 0 { + var block [TagSize]byte + off := copy(block[:], msg) + block[off] = 0x01 + + // h += msg + h0 += binary.LittleEndian.Uint32(block[0:]) & 0x3ffffff + h1 += (binary.LittleEndian.Uint32(block[3:]) >> 2) & 0x3ffffff + h2 += (binary.LittleEndian.Uint32(block[6:]) >> 4) & 0x3ffffff + h3 += (binary.LittleEndian.Uint32(block[9:]) >> 6) & 0x3ffffff + h4 += (binary.LittleEndian.Uint32(block[12:]) >> 8) + + // h *= r + d0 := (uint64(h0) * r0) + (uint64(h1) * R4) + (uint64(h2) * R3) + (uint64(h3) * R2) + (uint64(h4) * R1) + d1 := (d0 >> 26) + (uint64(h0) * r1) + (uint64(h1) * r0) + (uint64(h2) * R4) + (uint64(h3) * R3) + (uint64(h4) * R2) + d2 := (d1 >> 26) + (uint64(h0) * r2) + (uint64(h1) * r1) + (uint64(h2) * r0) + (uint64(h3) * R4) + (uint64(h4) * R3) + d3 := (d2 >> 26) + (uint64(h0) * r3) + (uint64(h1) * r2) + (uint64(h2) * r1) + (uint64(h3) * r0) + (uint64(h4) * R4) + d4 := (d3 >> 26) + (uint64(h0) * r4) + (uint64(h1) * r3) + (uint64(h2) * r2) + (uint64(h3) * r1) + (uint64(h4) * r0) + + // h %= p + h0 = uint32(d0) & 0x3ffffff + h1 = uint32(d1) & 0x3ffffff + h2 = uint32(d2) & 0x3ffffff + h3 = uint32(d3) & 0x3ffffff + h4 = uint32(d4) & 0x3ffffff + + h0 += uint32(d4>>26) * 5 + h1 += h0 >> 26 + h0 = h0 & 0x3ffffff + } + + // h %= p reduction + h2 += h1 >> 26 + h1 &= 0x3ffffff + h3 += h2 >> 26 + h2 &= 0x3ffffff + h4 += h3 >> 26 + h3 &= 0x3ffffff + h0 += 5 * (h4 >> 26) + h4 &= 0x3ffffff + h1 += h0 >> 26 + h0 &= 0x3ffffff + + // h - p + t0 := h0 + 5 + t1 := h1 + (t0 >> 26) + t2 := h2 + (t1 >> 26) + t3 := h3 + (t2 >> 26) + t4 := h4 + (t3 >> 26) - (1 << 26) + t0 &= 0x3ffffff + t1 &= 0x3ffffff + t2 &= 0x3ffffff + t3 &= 0x3ffffff + + // select h if h < p else h - p + t_mask := (t4 >> 31) - 1 + h_mask := ^t_mask + h0 = (h0 & h_mask) | (t0 & t_mask) + h1 = (h1 & h_mask) | (t1 & t_mask) + h2 = (h2 & h_mask) | (t2 & t_mask) + h3 = (h3 & h_mask) | (t3 & t_mask) + h4 = (h4 & h_mask) | (t4 & t_mask) + + // h %= 2^128 + h0 |= h1 << 26 + h1 = ((h1 >> 6) | (h2 << 20)) + h2 = ((h2 >> 12) | (h3 << 14)) + h3 = ((h3 >> 18) | (h4 << 8)) + + // s: the s part of the key + // tag = (h + s) % (2^128) + t := uint64(h0) + uint64(binary.LittleEndian.Uint32(key[16:])) + h0 = uint32(t) + t = uint64(h1) + uint64(binary.LittleEndian.Uint32(key[20:])) + (t >> 32) + h1 = uint32(t) + t = uint64(h2) + uint64(binary.LittleEndian.Uint32(key[24:])) + (t >> 32) + h2 = uint32(t) + t = uint64(h3) + uint64(binary.LittleEndian.Uint32(key[28:])) + (t >> 32) + h3 = uint32(t) + + binary.LittleEndian.PutUint32(out[0:], h0) + binary.LittleEndian.PutUint32(out[4:], h1) + binary.LittleEndian.PutUint32(out[8:], h2) + binary.LittleEndian.PutUint32(out[12:], h3) +} diff --git a/vendor/golang.org/x/crypto/ripemd160/ripemd160.go b/vendor/golang.org/x/crypto/ripemd160/ripemd160.go new file mode 100644 index 0000000000000000000000000000000000000000..6c6e84236ab76c84070c85889507d2d9fb2e2d5d --- /dev/null +++ b/vendor/golang.org/x/crypto/ripemd160/ripemd160.go @@ -0,0 +1,120 @@ +// 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 ripemd160 implements the RIPEMD-160 hash algorithm. +package ripemd160 // import "golang.org/x/crypto/ripemd160" + +// RIPEMD-160 is designed by by Hans Dobbertin, Antoon Bosselaers, and Bart +// Preneel with specifications available at: +// http://homes.esat.kuleuven.be/~cosicart/pdf/AB-9601/AB-9601.pdf. + +import ( + "crypto" + "hash" +) + +func init() { + crypto.RegisterHash(crypto.RIPEMD160, New) +} + +// The size of the checksum in bytes. +const Size = 20 + +// The block size of the hash algorithm in bytes. +const BlockSize = 64 + +const ( + _s0 = 0x67452301 + _s1 = 0xefcdab89 + _s2 = 0x98badcfe + _s3 = 0x10325476 + _s4 = 0xc3d2e1f0 +) + +// digest represents the partial evaluation of a checksum. +type digest struct { + s [5]uint32 // running context + x [BlockSize]byte // temporary buffer + nx int // index into x + tc uint64 // total count of bytes processed +} + +func (d *digest) Reset() { + d.s[0], d.s[1], d.s[2], d.s[3], d.s[4] = _s0, _s1, _s2, _s3, _s4 + d.nx = 0 + d.tc = 0 +} + +// New returns a new hash.Hash computing the checksum. +func New() hash.Hash { + result := new(digest) + result.Reset() + return result +} + +func (d *digest) Size() int { return Size } + +func (d *digest) BlockSize() int { return BlockSize } + +func (d *digest) Write(p []byte) (nn int, err error) { + nn = len(p) + d.tc += uint64(nn) + if d.nx > 0 { + n := len(p) + if n > BlockSize-d.nx { + n = BlockSize - d.nx + } + for i := 0; i < n; i++ { + d.x[d.nx+i] = p[i] + } + d.nx += n + if d.nx == BlockSize { + _Block(d, d.x[0:]) + d.nx = 0 + } + p = p[n:] + } + n := _Block(d, p) + p = p[n:] + if len(p) > 0 { + d.nx = copy(d.x[:], p) + } + return +} + +func (d0 *digest) Sum(in []byte) []byte { + // Make a copy of d0 so that caller can keep writing and summing. + d := *d0 + + // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. + tc := d.tc + var tmp [64]byte + tmp[0] = 0x80 + if tc%64 < 56 { + d.Write(tmp[0 : 56-tc%64]) + } else { + d.Write(tmp[0 : 64+56-tc%64]) + } + + // Length in bits. + tc <<= 3 + for i := uint(0); i < 8; i++ { + tmp[i] = byte(tc >> (8 * i)) + } + d.Write(tmp[0:8]) + + if d.nx != 0 { + panic("d.nx != 0") + } + + var digest [Size]byte + for i, s := range d.s { + digest[i*4] = byte(s) + digest[i*4+1] = byte(s >> 8) + digest[i*4+2] = byte(s >> 16) + digest[i*4+3] = byte(s >> 24) + } + + return append(in, digest[:]...) +} diff --git a/vendor/golang.org/x/crypto/ripemd160/ripemd160_test.go b/vendor/golang.org/x/crypto/ripemd160/ripemd160_test.go new file mode 100644 index 0000000000000000000000000000000000000000..5df1b2593d2c16aa5bef5a54cb8fd18d0d895fa7 --- /dev/null +++ b/vendor/golang.org/x/crypto/ripemd160/ripemd160_test.go @@ -0,0 +1,64 @@ +// 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 ripemd160 + +// Test vectors are from: +// http://homes.esat.kuleuven.be/~bosselae/ripemd160.html + +import ( + "fmt" + "io" + "testing" +) + +type mdTest struct { + out string + in string +} + +var vectors = [...]mdTest{ + {"9c1185a5c5e9fc54612808977ee8f548b2258d31", ""}, + {"0bdc9d2d256b3ee9daae347be6f4dc835a467ffe", "a"}, + {"8eb208f7e05d987a9b044a8e98c6b087f15a0bfc", "abc"}, + {"5d0689ef49d2fae572b881b123a85ffa21595f36", "message digest"}, + {"f71c27109c692c1b56bbdceb5b9d2865b3708dbc", "abcdefghijklmnopqrstuvwxyz"}, + {"12a053384a9c0c88e405a06c27dcf49ada62eb2b", "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"}, + {"b0e20b6e3116640286ed3a87a5713079b21f5189", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"}, + {"9b752e45573d4b39f4dbd3323cab82bf63326bfb", "12345678901234567890123456789012345678901234567890123456789012345678901234567890"}, +} + +func TestVectors(t *testing.T) { + for i := 0; i < len(vectors); i++ { + tv := vectors[i] + md := New() + for j := 0; j < 3; j++ { + if j < 2 { + io.WriteString(md, tv.in) + } else { + io.WriteString(md, tv.in[0:len(tv.in)/2]) + md.Sum(nil) + io.WriteString(md, tv.in[len(tv.in)/2:]) + } + s := fmt.Sprintf("%x", md.Sum(nil)) + if s != tv.out { + t.Fatalf("RIPEMD-160[%d](%s) = %s, expected %s", j, tv.in, s, tv.out) + } + md.Reset() + } + } +} + +func TestMillionA(t *testing.T) { + md := New() + for i := 0; i < 100000; i++ { + io.WriteString(md, "aaaaaaaaaa") + } + out := "52783243c1697bdbe16d37f97f68f08325dc1528" + s := fmt.Sprintf("%x", md.Sum(nil)) + if s != out { + t.Fatalf("RIPEMD-160 (1 million 'a') = %s, expected %s", s, out) + } + md.Reset() +} diff --git a/vendor/golang.org/x/crypto/ripemd160/ripemd160block.go b/vendor/golang.org/x/crypto/ripemd160/ripemd160block.go new file mode 100644 index 0000000000000000000000000000000000000000..7bc8e6c485e53c6b55dfd2f16c2d93b84b2b4bee --- /dev/null +++ b/vendor/golang.org/x/crypto/ripemd160/ripemd160block.go @@ -0,0 +1,161 @@ +// 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. + +// RIPEMD-160 block step. +// In its own file so that a faster assembly or C version +// can be substituted easily. + +package ripemd160 + +// work buffer indices and roll amounts for one line +var _n = [80]uint{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, + 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, + 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, + 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13, +} + +var _r = [80]uint{ + 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, + 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, + 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, + 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, + 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6, +} + +// same for the other parallel one +var n_ = [80]uint{ + 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, + 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, + 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, + 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, + 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11, +} + +var r_ = [80]uint{ + 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, + 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, + 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, + 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, + 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11, +} + +func _Block(md *digest, p []byte) int { + n := 0 + var x [16]uint32 + var alpha, beta uint32 + for len(p) >= BlockSize { + a, b, c, d, e := md.s[0], md.s[1], md.s[2], md.s[3], md.s[4] + aa, bb, cc, dd, ee := a, b, c, d, e + j := 0 + for i := 0; i < 16; i++ { + x[i] = uint32(p[j]) | uint32(p[j+1])<<8 | uint32(p[j+2])<<16 | uint32(p[j+3])<<24 + j += 4 + } + + // round 1 + i := 0 + for i < 16 { + alpha = a + (b ^ c ^ d) + x[_n[i]] + s := _r[i] + alpha = (alpha<>(32-s)) + e + beta = c<<10 | c>>22 + a, b, c, d, e = e, alpha, b, beta, d + + // parallel line + alpha = aa + (bb ^ (cc | ^dd)) + x[n_[i]] + 0x50a28be6 + s = r_[i] + alpha = (alpha<>(32-s)) + ee + beta = cc<<10 | cc>>22 + aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd + + i++ + } + + // round 2 + for i < 32 { + alpha = a + (b&c | ^b&d) + x[_n[i]] + 0x5a827999 + s := _r[i] + alpha = (alpha<>(32-s)) + e + beta = c<<10 | c>>22 + a, b, c, d, e = e, alpha, b, beta, d + + // parallel line + alpha = aa + (bb&dd | cc&^dd) + x[n_[i]] + 0x5c4dd124 + s = r_[i] + alpha = (alpha<>(32-s)) + ee + beta = cc<<10 | cc>>22 + aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd + + i++ + } + + // round 3 + for i < 48 { + alpha = a + (b | ^c ^ d) + x[_n[i]] + 0x6ed9eba1 + s := _r[i] + alpha = (alpha<>(32-s)) + e + beta = c<<10 | c>>22 + a, b, c, d, e = e, alpha, b, beta, d + + // parallel line + alpha = aa + (bb | ^cc ^ dd) + x[n_[i]] + 0x6d703ef3 + s = r_[i] + alpha = (alpha<>(32-s)) + ee + beta = cc<<10 | cc>>22 + aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd + + i++ + } + + // round 4 + for i < 64 { + alpha = a + (b&d | c&^d) + x[_n[i]] + 0x8f1bbcdc + s := _r[i] + alpha = (alpha<>(32-s)) + e + beta = c<<10 | c>>22 + a, b, c, d, e = e, alpha, b, beta, d + + // parallel line + alpha = aa + (bb&cc | ^bb&dd) + x[n_[i]] + 0x7a6d76e9 + s = r_[i] + alpha = (alpha<>(32-s)) + ee + beta = cc<<10 | cc>>22 + aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd + + i++ + } + + // round 5 + for i < 80 { + alpha = a + (b ^ (c | ^d)) + x[_n[i]] + 0xa953fd4e + s := _r[i] + alpha = (alpha<>(32-s)) + e + beta = c<<10 | c>>22 + a, b, c, d, e = e, alpha, b, beta, d + + // parallel line + alpha = aa + (bb ^ cc ^ dd) + x[n_[i]] + s = r_[i] + alpha = (alpha<>(32-s)) + ee + beta = cc<<10 | cc>>22 + aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd + + i++ + } + + // combine results + dd += c + md.s[1] + md.s[1] = md.s[2] + d + ee + md.s[2] = md.s[3] + e + aa + md.s[3] = md.s[4] + a + bb + md.s[4] = md.s[0] + b + cc + md.s[0] = dd + + p = p[BlockSize:] + n += BlockSize + } + return n +} diff --git a/vendor/golang.org/x/crypto/salsa20/salsa/hsalsa20.go b/vendor/golang.org/x/crypto/salsa20/salsa/hsalsa20.go new file mode 100644 index 0000000000000000000000000000000000000000..4c96147c86b6dd292bf90318ce171c3c8d67e8a6 --- /dev/null +++ b/vendor/golang.org/x/crypto/salsa20/salsa/hsalsa20.go @@ -0,0 +1,144 @@ +// 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 salsa provides low-level access to functions in the Salsa family. +package salsa // import "golang.org/x/crypto/salsa20/salsa" + +// Sigma is the Salsa20 constant for 256-bit keys. +var Sigma = [16]byte{'e', 'x', 'p', 'a', 'n', 'd', ' ', '3', '2', '-', 'b', 'y', 't', 'e', ' ', 'k'} + +// HSalsa20 applies the HSalsa20 core function to a 16-byte input in, 32-byte +// key k, and 16-byte constant c, and puts the result into the 32-byte array +// out. +func HSalsa20(out *[32]byte, in *[16]byte, k *[32]byte, c *[16]byte) { + x0 := uint32(c[0]) | uint32(c[1])<<8 | uint32(c[2])<<16 | uint32(c[3])<<24 + x1 := uint32(k[0]) | uint32(k[1])<<8 | uint32(k[2])<<16 | uint32(k[3])<<24 + x2 := uint32(k[4]) | uint32(k[5])<<8 | uint32(k[6])<<16 | uint32(k[7])<<24 + x3 := uint32(k[8]) | uint32(k[9])<<8 | uint32(k[10])<<16 | uint32(k[11])<<24 + x4 := uint32(k[12]) | uint32(k[13])<<8 | uint32(k[14])<<16 | uint32(k[15])<<24 + x5 := uint32(c[4]) | uint32(c[5])<<8 | uint32(c[6])<<16 | uint32(c[7])<<24 + x6 := uint32(in[0]) | uint32(in[1])<<8 | uint32(in[2])<<16 | uint32(in[3])<<24 + x7 := uint32(in[4]) | uint32(in[5])<<8 | uint32(in[6])<<16 | uint32(in[7])<<24 + x8 := uint32(in[8]) | uint32(in[9])<<8 | uint32(in[10])<<16 | uint32(in[11])<<24 + x9 := uint32(in[12]) | uint32(in[13])<<8 | uint32(in[14])<<16 | uint32(in[15])<<24 + x10 := uint32(c[8]) | uint32(c[9])<<8 | uint32(c[10])<<16 | uint32(c[11])<<24 + x11 := uint32(k[16]) | uint32(k[17])<<8 | uint32(k[18])<<16 | uint32(k[19])<<24 + x12 := uint32(k[20]) | uint32(k[21])<<8 | uint32(k[22])<<16 | uint32(k[23])<<24 + x13 := uint32(k[24]) | uint32(k[25])<<8 | uint32(k[26])<<16 | uint32(k[27])<<24 + x14 := uint32(k[28]) | uint32(k[29])<<8 | uint32(k[30])<<16 | uint32(k[31])<<24 + x15 := uint32(c[12]) | uint32(c[13])<<8 | uint32(c[14])<<16 | uint32(c[15])<<24 + + for i := 0; i < 20; i += 2 { + u := x0 + x12 + x4 ^= u<<7 | u>>(32-7) + u = x4 + x0 + x8 ^= u<<9 | u>>(32-9) + u = x8 + x4 + x12 ^= u<<13 | u>>(32-13) + u = x12 + x8 + x0 ^= u<<18 | u>>(32-18) + + u = x5 + x1 + x9 ^= u<<7 | u>>(32-7) + u = x9 + x5 + x13 ^= u<<9 | u>>(32-9) + u = x13 + x9 + x1 ^= u<<13 | u>>(32-13) + u = x1 + x13 + x5 ^= u<<18 | u>>(32-18) + + u = x10 + x6 + x14 ^= u<<7 | u>>(32-7) + u = x14 + x10 + x2 ^= u<<9 | u>>(32-9) + u = x2 + x14 + x6 ^= u<<13 | u>>(32-13) + u = x6 + x2 + x10 ^= u<<18 | u>>(32-18) + + u = x15 + x11 + x3 ^= u<<7 | u>>(32-7) + u = x3 + x15 + x7 ^= u<<9 | u>>(32-9) + u = x7 + x3 + x11 ^= u<<13 | u>>(32-13) + u = x11 + x7 + x15 ^= u<<18 | u>>(32-18) + + u = x0 + x3 + x1 ^= u<<7 | u>>(32-7) + u = x1 + x0 + x2 ^= u<<9 | u>>(32-9) + u = x2 + x1 + x3 ^= u<<13 | u>>(32-13) + u = x3 + x2 + x0 ^= u<<18 | u>>(32-18) + + u = x5 + x4 + x6 ^= u<<7 | u>>(32-7) + u = x6 + x5 + x7 ^= u<<9 | u>>(32-9) + u = x7 + x6 + x4 ^= u<<13 | u>>(32-13) + u = x4 + x7 + x5 ^= u<<18 | u>>(32-18) + + u = x10 + x9 + x11 ^= u<<7 | u>>(32-7) + u = x11 + x10 + x8 ^= u<<9 | u>>(32-9) + u = x8 + x11 + x9 ^= u<<13 | u>>(32-13) + u = x9 + x8 + x10 ^= u<<18 | u>>(32-18) + + u = x15 + x14 + x12 ^= u<<7 | u>>(32-7) + u = x12 + x15 + x13 ^= u<<9 | u>>(32-9) + u = x13 + x12 + x14 ^= u<<13 | u>>(32-13) + u = x14 + x13 + x15 ^= u<<18 | u>>(32-18) + } + out[0] = byte(x0) + out[1] = byte(x0 >> 8) + out[2] = byte(x0 >> 16) + out[3] = byte(x0 >> 24) + + out[4] = byte(x5) + out[5] = byte(x5 >> 8) + out[6] = byte(x5 >> 16) + out[7] = byte(x5 >> 24) + + out[8] = byte(x10) + out[9] = byte(x10 >> 8) + out[10] = byte(x10 >> 16) + out[11] = byte(x10 >> 24) + + out[12] = byte(x15) + out[13] = byte(x15 >> 8) + out[14] = byte(x15 >> 16) + out[15] = byte(x15 >> 24) + + out[16] = byte(x6) + out[17] = byte(x6 >> 8) + out[18] = byte(x6 >> 16) + out[19] = byte(x6 >> 24) + + out[20] = byte(x7) + out[21] = byte(x7 >> 8) + out[22] = byte(x7 >> 16) + out[23] = byte(x7 >> 24) + + out[24] = byte(x8) + out[25] = byte(x8 >> 8) + out[26] = byte(x8 >> 16) + out[27] = byte(x8 >> 24) + + out[28] = byte(x9) + out[29] = byte(x9 >> 8) + out[30] = byte(x9 >> 16) + out[31] = byte(x9 >> 24) +} diff --git a/vendor/golang.org/x/crypto/salsa20/salsa/salsa2020_amd64.s b/vendor/golang.org/x/crypto/salsa20/salsa/salsa2020_amd64.s new file mode 100644 index 0000000000000000000000000000000000000000..22afbdcadcfa97e7a6333ba273d480d9f4537fb7 --- /dev/null +++ b/vendor/golang.org/x/crypto/salsa20/salsa/salsa2020_amd64.s @@ -0,0 +1,889 @@ +// 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,!appengine,!gccgo + +// This code was translated into a form compatible with 6a from the public +// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html + +// func salsa2020XORKeyStream(out, in *byte, n uint64, nonce, key *byte) +// This needs up to 64 bytes at 360(SP); hence the non-obvious frame size. +TEXT ·salsa2020XORKeyStream(SB),0,$456-40 // frame = 424 + 32 byte alignment + MOVQ out+0(FP),DI + MOVQ in+8(FP),SI + MOVQ n+16(FP),DX + MOVQ nonce+24(FP),CX + MOVQ key+32(FP),R8 + + MOVQ SP,R12 + MOVQ SP,R9 + ADDQ $31, R9 + ANDQ $~31, R9 + MOVQ R9, SP + + MOVQ DX,R9 + MOVQ CX,DX + MOVQ R8,R10 + CMPQ R9,$0 + JBE DONE + START: + MOVL 20(R10),CX + MOVL 0(R10),R8 + MOVL 0(DX),AX + MOVL 16(R10),R11 + MOVL CX,0(SP) + MOVL R8, 4 (SP) + MOVL AX, 8 (SP) + MOVL R11, 12 (SP) + MOVL 8(DX),CX + MOVL 24(R10),R8 + MOVL 4(R10),AX + MOVL 4(DX),R11 + MOVL CX,16(SP) + MOVL R8, 20 (SP) + MOVL AX, 24 (SP) + MOVL R11, 28 (SP) + MOVL 12(DX),CX + MOVL 12(R10),DX + MOVL 28(R10),R8 + MOVL 8(R10),AX + MOVL DX,32(SP) + MOVL CX, 36 (SP) + MOVL R8, 40 (SP) + MOVL AX, 44 (SP) + MOVQ $1634760805,DX + MOVQ $857760878,CX + MOVQ $2036477234,R8 + MOVQ $1797285236,AX + MOVL DX,48(SP) + MOVL CX, 52 (SP) + MOVL R8, 56 (SP) + MOVL AX, 60 (SP) + CMPQ R9,$256 + JB BYTESBETWEEN1AND255 + MOVOA 48(SP),X0 + PSHUFL $0X55,X0,X1 + PSHUFL $0XAA,X0,X2 + PSHUFL $0XFF,X0,X3 + PSHUFL $0X00,X0,X0 + MOVOA X1,64(SP) + MOVOA X2,80(SP) + MOVOA X3,96(SP) + MOVOA X0,112(SP) + MOVOA 0(SP),X0 + PSHUFL $0XAA,X0,X1 + PSHUFL $0XFF,X0,X2 + PSHUFL $0X00,X0,X3 + PSHUFL $0X55,X0,X0 + MOVOA X1,128(SP) + MOVOA X2,144(SP) + MOVOA X3,160(SP) + MOVOA X0,176(SP) + MOVOA 16(SP),X0 + PSHUFL $0XFF,X0,X1 + PSHUFL $0X55,X0,X2 + PSHUFL $0XAA,X0,X0 + MOVOA X1,192(SP) + MOVOA X2,208(SP) + MOVOA X0,224(SP) + MOVOA 32(SP),X0 + PSHUFL $0X00,X0,X1 + PSHUFL $0XAA,X0,X2 + PSHUFL $0XFF,X0,X0 + MOVOA X1,240(SP) + MOVOA X2,256(SP) + MOVOA X0,272(SP) + BYTESATLEAST256: + MOVL 16(SP),DX + MOVL 36 (SP),CX + MOVL DX,288(SP) + MOVL CX,304(SP) + ADDQ $1,DX + SHLQ $32,CX + ADDQ CX,DX + MOVQ DX,CX + SHRQ $32,CX + MOVL DX, 292 (SP) + MOVL CX, 308 (SP) + ADDQ $1,DX + SHLQ $32,CX + ADDQ CX,DX + MOVQ DX,CX + SHRQ $32,CX + MOVL DX, 296 (SP) + MOVL CX, 312 (SP) + ADDQ $1,DX + SHLQ $32,CX + ADDQ CX,DX + MOVQ DX,CX + SHRQ $32,CX + MOVL DX, 300 (SP) + MOVL CX, 316 (SP) + ADDQ $1,DX + SHLQ $32,CX + ADDQ CX,DX + MOVQ DX,CX + SHRQ $32,CX + MOVL DX,16(SP) + MOVL CX, 36 (SP) + MOVQ R9,352(SP) + MOVQ $20,DX + MOVOA 64(SP),X0 + MOVOA 80(SP),X1 + MOVOA 96(SP),X2 + MOVOA 256(SP),X3 + MOVOA 272(SP),X4 + MOVOA 128(SP),X5 + MOVOA 144(SP),X6 + MOVOA 176(SP),X7 + MOVOA 192(SP),X8 + MOVOA 208(SP),X9 + MOVOA 224(SP),X10 + MOVOA 304(SP),X11 + MOVOA 112(SP),X12 + MOVOA 160(SP),X13 + MOVOA 240(SP),X14 + MOVOA 288(SP),X15 + MAINLOOP1: + MOVOA X1,320(SP) + MOVOA X2,336(SP) + MOVOA X13,X1 + PADDL X12,X1 + MOVOA X1,X2 + PSLLL $7,X1 + PXOR X1,X14 + PSRLL $25,X2 + PXOR X2,X14 + MOVOA X7,X1 + PADDL X0,X1 + MOVOA X1,X2 + PSLLL $7,X1 + PXOR X1,X11 + PSRLL $25,X2 + PXOR X2,X11 + MOVOA X12,X1 + PADDL X14,X1 + MOVOA X1,X2 + PSLLL $9,X1 + PXOR X1,X15 + PSRLL $23,X2 + PXOR X2,X15 + MOVOA X0,X1 + PADDL X11,X1 + MOVOA X1,X2 + PSLLL $9,X1 + PXOR X1,X9 + PSRLL $23,X2 + PXOR X2,X9 + MOVOA X14,X1 + PADDL X15,X1 + MOVOA X1,X2 + PSLLL $13,X1 + PXOR X1,X13 + PSRLL $19,X2 + PXOR X2,X13 + MOVOA X11,X1 + PADDL X9,X1 + MOVOA X1,X2 + PSLLL $13,X1 + PXOR X1,X7 + PSRLL $19,X2 + PXOR X2,X7 + MOVOA X15,X1 + PADDL X13,X1 + MOVOA X1,X2 + PSLLL $18,X1 + PXOR X1,X12 + PSRLL $14,X2 + PXOR X2,X12 + MOVOA 320(SP),X1 + MOVOA X12,320(SP) + MOVOA X9,X2 + PADDL X7,X2 + MOVOA X2,X12 + PSLLL $18,X2 + PXOR X2,X0 + PSRLL $14,X12 + PXOR X12,X0 + MOVOA X5,X2 + PADDL X1,X2 + MOVOA X2,X12 + PSLLL $7,X2 + PXOR X2,X3 + PSRLL $25,X12 + PXOR X12,X3 + MOVOA 336(SP),X2 + MOVOA X0,336(SP) + MOVOA X6,X0 + PADDL X2,X0 + MOVOA X0,X12 + PSLLL $7,X0 + PXOR X0,X4 + PSRLL $25,X12 + PXOR X12,X4 + MOVOA X1,X0 + PADDL X3,X0 + MOVOA X0,X12 + PSLLL $9,X0 + PXOR X0,X10 + PSRLL $23,X12 + PXOR X12,X10 + MOVOA X2,X0 + PADDL X4,X0 + MOVOA X0,X12 + PSLLL $9,X0 + PXOR X0,X8 + PSRLL $23,X12 + PXOR X12,X8 + MOVOA X3,X0 + PADDL X10,X0 + MOVOA X0,X12 + PSLLL $13,X0 + PXOR X0,X5 + PSRLL $19,X12 + PXOR X12,X5 + MOVOA X4,X0 + PADDL X8,X0 + MOVOA X0,X12 + PSLLL $13,X0 + PXOR X0,X6 + PSRLL $19,X12 + PXOR X12,X6 + MOVOA X10,X0 + PADDL X5,X0 + MOVOA X0,X12 + PSLLL $18,X0 + PXOR X0,X1 + PSRLL $14,X12 + PXOR X12,X1 + MOVOA 320(SP),X0 + MOVOA X1,320(SP) + MOVOA X4,X1 + PADDL X0,X1 + MOVOA X1,X12 + PSLLL $7,X1 + PXOR X1,X7 + PSRLL $25,X12 + PXOR X12,X7 + MOVOA X8,X1 + PADDL X6,X1 + MOVOA X1,X12 + PSLLL $18,X1 + PXOR X1,X2 + PSRLL $14,X12 + PXOR X12,X2 + MOVOA 336(SP),X12 + MOVOA X2,336(SP) + MOVOA X14,X1 + PADDL X12,X1 + MOVOA X1,X2 + PSLLL $7,X1 + PXOR X1,X5 + PSRLL $25,X2 + PXOR X2,X5 + MOVOA X0,X1 + PADDL X7,X1 + MOVOA X1,X2 + PSLLL $9,X1 + PXOR X1,X10 + PSRLL $23,X2 + PXOR X2,X10 + MOVOA X12,X1 + PADDL X5,X1 + MOVOA X1,X2 + PSLLL $9,X1 + PXOR X1,X8 + PSRLL $23,X2 + PXOR X2,X8 + MOVOA X7,X1 + PADDL X10,X1 + MOVOA X1,X2 + PSLLL $13,X1 + PXOR X1,X4 + PSRLL $19,X2 + PXOR X2,X4 + MOVOA X5,X1 + PADDL X8,X1 + MOVOA X1,X2 + PSLLL $13,X1 + PXOR X1,X14 + PSRLL $19,X2 + PXOR X2,X14 + MOVOA X10,X1 + PADDL X4,X1 + MOVOA X1,X2 + PSLLL $18,X1 + PXOR X1,X0 + PSRLL $14,X2 + PXOR X2,X0 + MOVOA 320(SP),X1 + MOVOA X0,320(SP) + MOVOA X8,X0 + PADDL X14,X0 + MOVOA X0,X2 + PSLLL $18,X0 + PXOR X0,X12 + PSRLL $14,X2 + PXOR X2,X12 + MOVOA X11,X0 + PADDL X1,X0 + MOVOA X0,X2 + PSLLL $7,X0 + PXOR X0,X6 + PSRLL $25,X2 + PXOR X2,X6 + MOVOA 336(SP),X2 + MOVOA X12,336(SP) + MOVOA X3,X0 + PADDL X2,X0 + MOVOA X0,X12 + PSLLL $7,X0 + PXOR X0,X13 + PSRLL $25,X12 + PXOR X12,X13 + MOVOA X1,X0 + PADDL X6,X0 + MOVOA X0,X12 + PSLLL $9,X0 + PXOR X0,X15 + PSRLL $23,X12 + PXOR X12,X15 + MOVOA X2,X0 + PADDL X13,X0 + MOVOA X0,X12 + PSLLL $9,X0 + PXOR X0,X9 + PSRLL $23,X12 + PXOR X12,X9 + MOVOA X6,X0 + PADDL X15,X0 + MOVOA X0,X12 + PSLLL $13,X0 + PXOR X0,X11 + PSRLL $19,X12 + PXOR X12,X11 + MOVOA X13,X0 + PADDL X9,X0 + MOVOA X0,X12 + PSLLL $13,X0 + PXOR X0,X3 + PSRLL $19,X12 + PXOR X12,X3 + MOVOA X15,X0 + PADDL X11,X0 + MOVOA X0,X12 + PSLLL $18,X0 + PXOR X0,X1 + PSRLL $14,X12 + PXOR X12,X1 + MOVOA X9,X0 + PADDL X3,X0 + MOVOA X0,X12 + PSLLL $18,X0 + PXOR X0,X2 + PSRLL $14,X12 + PXOR X12,X2 + MOVOA 320(SP),X12 + MOVOA 336(SP),X0 + SUBQ $2,DX + JA MAINLOOP1 + PADDL 112(SP),X12 + PADDL 176(SP),X7 + PADDL 224(SP),X10 + PADDL 272(SP),X4 + MOVD X12,DX + MOVD X7,CX + MOVD X10,R8 + MOVD X4,R9 + PSHUFL $0X39,X12,X12 + PSHUFL $0X39,X7,X7 + PSHUFL $0X39,X10,X10 + PSHUFL $0X39,X4,X4 + XORL 0(SI),DX + XORL 4(SI),CX + XORL 8(SI),R8 + XORL 12(SI),R9 + MOVL DX,0(DI) + MOVL CX,4(DI) + MOVL R8,8(DI) + MOVL R9,12(DI) + MOVD X12,DX + MOVD X7,CX + MOVD X10,R8 + MOVD X4,R9 + PSHUFL $0X39,X12,X12 + PSHUFL $0X39,X7,X7 + PSHUFL $0X39,X10,X10 + PSHUFL $0X39,X4,X4 + XORL 64(SI),DX + XORL 68(SI),CX + XORL 72(SI),R8 + XORL 76(SI),R9 + MOVL DX,64(DI) + MOVL CX,68(DI) + MOVL R8,72(DI) + MOVL R9,76(DI) + MOVD X12,DX + MOVD X7,CX + MOVD X10,R8 + MOVD X4,R9 + PSHUFL $0X39,X12,X12 + PSHUFL $0X39,X7,X7 + PSHUFL $0X39,X10,X10 + PSHUFL $0X39,X4,X4 + XORL 128(SI),DX + XORL 132(SI),CX + XORL 136(SI),R8 + XORL 140(SI),R9 + MOVL DX,128(DI) + MOVL CX,132(DI) + MOVL R8,136(DI) + MOVL R9,140(DI) + MOVD X12,DX + MOVD X7,CX + MOVD X10,R8 + MOVD X4,R9 + XORL 192(SI),DX + XORL 196(SI),CX + XORL 200(SI),R8 + XORL 204(SI),R9 + MOVL DX,192(DI) + MOVL CX,196(DI) + MOVL R8,200(DI) + MOVL R9,204(DI) + PADDL 240(SP),X14 + PADDL 64(SP),X0 + PADDL 128(SP),X5 + PADDL 192(SP),X8 + MOVD X14,DX + MOVD X0,CX + MOVD X5,R8 + MOVD X8,R9 + PSHUFL $0X39,X14,X14 + PSHUFL $0X39,X0,X0 + PSHUFL $0X39,X5,X5 + PSHUFL $0X39,X8,X8 + XORL 16(SI),DX + XORL 20(SI),CX + XORL 24(SI),R8 + XORL 28(SI),R9 + MOVL DX,16(DI) + MOVL CX,20(DI) + MOVL R8,24(DI) + MOVL R9,28(DI) + MOVD X14,DX + MOVD X0,CX + MOVD X5,R8 + MOVD X8,R9 + PSHUFL $0X39,X14,X14 + PSHUFL $0X39,X0,X0 + PSHUFL $0X39,X5,X5 + PSHUFL $0X39,X8,X8 + XORL 80(SI),DX + XORL 84(SI),CX + XORL 88(SI),R8 + XORL 92(SI),R9 + MOVL DX,80(DI) + MOVL CX,84(DI) + MOVL R8,88(DI) + MOVL R9,92(DI) + MOVD X14,DX + MOVD X0,CX + MOVD X5,R8 + MOVD X8,R9 + PSHUFL $0X39,X14,X14 + PSHUFL $0X39,X0,X0 + PSHUFL $0X39,X5,X5 + PSHUFL $0X39,X8,X8 + XORL 144(SI),DX + XORL 148(SI),CX + XORL 152(SI),R8 + XORL 156(SI),R9 + MOVL DX,144(DI) + MOVL CX,148(DI) + MOVL R8,152(DI) + MOVL R9,156(DI) + MOVD X14,DX + MOVD X0,CX + MOVD X5,R8 + MOVD X8,R9 + XORL 208(SI),DX + XORL 212(SI),CX + XORL 216(SI),R8 + XORL 220(SI),R9 + MOVL DX,208(DI) + MOVL CX,212(DI) + MOVL R8,216(DI) + MOVL R9,220(DI) + PADDL 288(SP),X15 + PADDL 304(SP),X11 + PADDL 80(SP),X1 + PADDL 144(SP),X6 + MOVD X15,DX + MOVD X11,CX + MOVD X1,R8 + MOVD X6,R9 + PSHUFL $0X39,X15,X15 + PSHUFL $0X39,X11,X11 + PSHUFL $0X39,X1,X1 + PSHUFL $0X39,X6,X6 + XORL 32(SI),DX + XORL 36(SI),CX + XORL 40(SI),R8 + XORL 44(SI),R9 + MOVL DX,32(DI) + MOVL CX,36(DI) + MOVL R8,40(DI) + MOVL R9,44(DI) + MOVD X15,DX + MOVD X11,CX + MOVD X1,R8 + MOVD X6,R9 + PSHUFL $0X39,X15,X15 + PSHUFL $0X39,X11,X11 + PSHUFL $0X39,X1,X1 + PSHUFL $0X39,X6,X6 + XORL 96(SI),DX + XORL 100(SI),CX + XORL 104(SI),R8 + XORL 108(SI),R9 + MOVL DX,96(DI) + MOVL CX,100(DI) + MOVL R8,104(DI) + MOVL R9,108(DI) + MOVD X15,DX + MOVD X11,CX + MOVD X1,R8 + MOVD X6,R9 + PSHUFL $0X39,X15,X15 + PSHUFL $0X39,X11,X11 + PSHUFL $0X39,X1,X1 + PSHUFL $0X39,X6,X6 + XORL 160(SI),DX + XORL 164(SI),CX + XORL 168(SI),R8 + XORL 172(SI),R9 + MOVL DX,160(DI) + MOVL CX,164(DI) + MOVL R8,168(DI) + MOVL R9,172(DI) + MOVD X15,DX + MOVD X11,CX + MOVD X1,R8 + MOVD X6,R9 + XORL 224(SI),DX + XORL 228(SI),CX + XORL 232(SI),R8 + XORL 236(SI),R9 + MOVL DX,224(DI) + MOVL CX,228(DI) + MOVL R8,232(DI) + MOVL R9,236(DI) + PADDL 160(SP),X13 + PADDL 208(SP),X9 + PADDL 256(SP),X3 + PADDL 96(SP),X2 + MOVD X13,DX + MOVD X9,CX + MOVD X3,R8 + MOVD X2,R9 + PSHUFL $0X39,X13,X13 + PSHUFL $0X39,X9,X9 + PSHUFL $0X39,X3,X3 + PSHUFL $0X39,X2,X2 + XORL 48(SI),DX + XORL 52(SI),CX + XORL 56(SI),R8 + XORL 60(SI),R9 + MOVL DX,48(DI) + MOVL CX,52(DI) + MOVL R8,56(DI) + MOVL R9,60(DI) + MOVD X13,DX + MOVD X9,CX + MOVD X3,R8 + MOVD X2,R9 + PSHUFL $0X39,X13,X13 + PSHUFL $0X39,X9,X9 + PSHUFL $0X39,X3,X3 + PSHUFL $0X39,X2,X2 + XORL 112(SI),DX + XORL 116(SI),CX + XORL 120(SI),R8 + XORL 124(SI),R9 + MOVL DX,112(DI) + MOVL CX,116(DI) + MOVL R8,120(DI) + MOVL R9,124(DI) + MOVD X13,DX + MOVD X9,CX + MOVD X3,R8 + MOVD X2,R9 + PSHUFL $0X39,X13,X13 + PSHUFL $0X39,X9,X9 + PSHUFL $0X39,X3,X3 + PSHUFL $0X39,X2,X2 + XORL 176(SI),DX + XORL 180(SI),CX + XORL 184(SI),R8 + XORL 188(SI),R9 + MOVL DX,176(DI) + MOVL CX,180(DI) + MOVL R8,184(DI) + MOVL R9,188(DI) + MOVD X13,DX + MOVD X9,CX + MOVD X3,R8 + MOVD X2,R9 + XORL 240(SI),DX + XORL 244(SI),CX + XORL 248(SI),R8 + XORL 252(SI),R9 + MOVL DX,240(DI) + MOVL CX,244(DI) + MOVL R8,248(DI) + MOVL R9,252(DI) + MOVQ 352(SP),R9 + SUBQ $256,R9 + ADDQ $256,SI + ADDQ $256,DI + CMPQ R9,$256 + JAE BYTESATLEAST256 + CMPQ R9,$0 + JBE DONE + BYTESBETWEEN1AND255: + CMPQ R9,$64 + JAE NOCOPY + MOVQ DI,DX + LEAQ 360(SP),DI + MOVQ R9,CX + REP; MOVSB + LEAQ 360(SP),DI + LEAQ 360(SP),SI + NOCOPY: + MOVQ R9,352(SP) + MOVOA 48(SP),X0 + MOVOA 0(SP),X1 + MOVOA 16(SP),X2 + MOVOA 32(SP),X3 + MOVOA X1,X4 + MOVQ $20,CX + MAINLOOP2: + PADDL X0,X4 + MOVOA X0,X5 + MOVOA X4,X6 + PSLLL $7,X4 + PSRLL $25,X6 + PXOR X4,X3 + PXOR X6,X3 + PADDL X3,X5 + MOVOA X3,X4 + MOVOA X5,X6 + PSLLL $9,X5 + PSRLL $23,X6 + PXOR X5,X2 + PSHUFL $0X93,X3,X3 + PXOR X6,X2 + PADDL X2,X4 + MOVOA X2,X5 + MOVOA X4,X6 + PSLLL $13,X4 + PSRLL $19,X6 + PXOR X4,X1 + PSHUFL $0X4E,X2,X2 + PXOR X6,X1 + PADDL X1,X5 + MOVOA X3,X4 + MOVOA X5,X6 + PSLLL $18,X5 + PSRLL $14,X6 + PXOR X5,X0 + PSHUFL $0X39,X1,X1 + PXOR X6,X0 + PADDL X0,X4 + MOVOA X0,X5 + MOVOA X4,X6 + PSLLL $7,X4 + PSRLL $25,X6 + PXOR X4,X1 + PXOR X6,X1 + PADDL X1,X5 + MOVOA X1,X4 + MOVOA X5,X6 + PSLLL $9,X5 + PSRLL $23,X6 + PXOR X5,X2 + PSHUFL $0X93,X1,X1 + PXOR X6,X2 + PADDL X2,X4 + MOVOA X2,X5 + MOVOA X4,X6 + PSLLL $13,X4 + PSRLL $19,X6 + PXOR X4,X3 + PSHUFL $0X4E,X2,X2 + PXOR X6,X3 + PADDL X3,X5 + MOVOA X1,X4 + MOVOA X5,X6 + PSLLL $18,X5 + PSRLL $14,X6 + PXOR X5,X0 + PSHUFL $0X39,X3,X3 + PXOR X6,X0 + PADDL X0,X4 + MOVOA X0,X5 + MOVOA X4,X6 + PSLLL $7,X4 + PSRLL $25,X6 + PXOR X4,X3 + PXOR X6,X3 + PADDL X3,X5 + MOVOA X3,X4 + MOVOA X5,X6 + PSLLL $9,X5 + PSRLL $23,X6 + PXOR X5,X2 + PSHUFL $0X93,X3,X3 + PXOR X6,X2 + PADDL X2,X4 + MOVOA X2,X5 + MOVOA X4,X6 + PSLLL $13,X4 + PSRLL $19,X6 + PXOR X4,X1 + PSHUFL $0X4E,X2,X2 + PXOR X6,X1 + PADDL X1,X5 + MOVOA X3,X4 + MOVOA X5,X6 + PSLLL $18,X5 + PSRLL $14,X6 + PXOR X5,X0 + PSHUFL $0X39,X1,X1 + PXOR X6,X0 + PADDL X0,X4 + MOVOA X0,X5 + MOVOA X4,X6 + PSLLL $7,X4 + PSRLL $25,X6 + PXOR X4,X1 + PXOR X6,X1 + PADDL X1,X5 + MOVOA X1,X4 + MOVOA X5,X6 + PSLLL $9,X5 + PSRLL $23,X6 + PXOR X5,X2 + PSHUFL $0X93,X1,X1 + PXOR X6,X2 + PADDL X2,X4 + MOVOA X2,X5 + MOVOA X4,X6 + PSLLL $13,X4 + PSRLL $19,X6 + PXOR X4,X3 + PSHUFL $0X4E,X2,X2 + PXOR X6,X3 + SUBQ $4,CX + PADDL X3,X5 + MOVOA X1,X4 + MOVOA X5,X6 + PSLLL $18,X5 + PXOR X7,X7 + PSRLL $14,X6 + PXOR X5,X0 + PSHUFL $0X39,X3,X3 + PXOR X6,X0 + JA MAINLOOP2 + PADDL 48(SP),X0 + PADDL 0(SP),X1 + PADDL 16(SP),X2 + PADDL 32(SP),X3 + MOVD X0,CX + MOVD X1,R8 + MOVD X2,R9 + MOVD X3,AX + PSHUFL $0X39,X0,X0 + PSHUFL $0X39,X1,X1 + PSHUFL $0X39,X2,X2 + PSHUFL $0X39,X3,X3 + XORL 0(SI),CX + XORL 48(SI),R8 + XORL 32(SI),R9 + XORL 16(SI),AX + MOVL CX,0(DI) + MOVL R8,48(DI) + MOVL R9,32(DI) + MOVL AX,16(DI) + MOVD X0,CX + MOVD X1,R8 + MOVD X2,R9 + MOVD X3,AX + PSHUFL $0X39,X0,X0 + PSHUFL $0X39,X1,X1 + PSHUFL $0X39,X2,X2 + PSHUFL $0X39,X3,X3 + XORL 20(SI),CX + XORL 4(SI),R8 + XORL 52(SI),R9 + XORL 36(SI),AX + MOVL CX,20(DI) + MOVL R8,4(DI) + MOVL R9,52(DI) + MOVL AX,36(DI) + MOVD X0,CX + MOVD X1,R8 + MOVD X2,R9 + MOVD X3,AX + PSHUFL $0X39,X0,X0 + PSHUFL $0X39,X1,X1 + PSHUFL $0X39,X2,X2 + PSHUFL $0X39,X3,X3 + XORL 40(SI),CX + XORL 24(SI),R8 + XORL 8(SI),R9 + XORL 56(SI),AX + MOVL CX,40(DI) + MOVL R8,24(DI) + MOVL R9,8(DI) + MOVL AX,56(DI) + MOVD X0,CX + MOVD X1,R8 + MOVD X2,R9 + MOVD X3,AX + XORL 60(SI),CX + XORL 44(SI),R8 + XORL 28(SI),R9 + XORL 12(SI),AX + MOVL CX,60(DI) + MOVL R8,44(DI) + MOVL R9,28(DI) + MOVL AX,12(DI) + MOVQ 352(SP),R9 + MOVL 16(SP),CX + MOVL 36 (SP),R8 + ADDQ $1,CX + SHLQ $32,R8 + ADDQ R8,CX + MOVQ CX,R8 + SHRQ $32,R8 + MOVL CX,16(SP) + MOVL R8, 36 (SP) + CMPQ R9,$64 + JA BYTESATLEAST65 + JAE BYTESATLEAST64 + MOVQ DI,SI + MOVQ DX,DI + MOVQ R9,CX + REP; MOVSB + BYTESATLEAST64: + DONE: + MOVQ R12,SP + RET + BYTESATLEAST65: + SUBQ $64,R9 + ADDQ $64,DI + ADDQ $64,SI + JMP BYTESBETWEEN1AND255 diff --git a/vendor/golang.org/x/crypto/salsa20/salsa/salsa208.go b/vendor/golang.org/x/crypto/salsa20/salsa/salsa208.go new file mode 100644 index 0000000000000000000000000000000000000000..9bfc0927ce8c2586ac5460c7fcd4c55aa3581bda --- /dev/null +++ b/vendor/golang.org/x/crypto/salsa20/salsa/salsa208.go @@ -0,0 +1,199 @@ +// 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 salsa + +// Core208 applies the Salsa20/8 core function to the 64-byte array in and puts +// the result into the 64-byte array out. The input and output may be the same array. +func Core208(out *[64]byte, in *[64]byte) { + j0 := uint32(in[0]) | uint32(in[1])<<8 | uint32(in[2])<<16 | uint32(in[3])<<24 + j1 := uint32(in[4]) | uint32(in[5])<<8 | uint32(in[6])<<16 | uint32(in[7])<<24 + j2 := uint32(in[8]) | uint32(in[9])<<8 | uint32(in[10])<<16 | uint32(in[11])<<24 + j3 := uint32(in[12]) | uint32(in[13])<<8 | uint32(in[14])<<16 | uint32(in[15])<<24 + j4 := uint32(in[16]) | uint32(in[17])<<8 | uint32(in[18])<<16 | uint32(in[19])<<24 + j5 := uint32(in[20]) | uint32(in[21])<<8 | uint32(in[22])<<16 | uint32(in[23])<<24 + j6 := uint32(in[24]) | uint32(in[25])<<8 | uint32(in[26])<<16 | uint32(in[27])<<24 + j7 := uint32(in[28]) | uint32(in[29])<<8 | uint32(in[30])<<16 | uint32(in[31])<<24 + j8 := uint32(in[32]) | uint32(in[33])<<8 | uint32(in[34])<<16 | uint32(in[35])<<24 + j9 := uint32(in[36]) | uint32(in[37])<<8 | uint32(in[38])<<16 | uint32(in[39])<<24 + j10 := uint32(in[40]) | uint32(in[41])<<8 | uint32(in[42])<<16 | uint32(in[43])<<24 + j11 := uint32(in[44]) | uint32(in[45])<<8 | uint32(in[46])<<16 | uint32(in[47])<<24 + j12 := uint32(in[48]) | uint32(in[49])<<8 | uint32(in[50])<<16 | uint32(in[51])<<24 + j13 := uint32(in[52]) | uint32(in[53])<<8 | uint32(in[54])<<16 | uint32(in[55])<<24 + j14 := uint32(in[56]) | uint32(in[57])<<8 | uint32(in[58])<<16 | uint32(in[59])<<24 + j15 := uint32(in[60]) | uint32(in[61])<<8 | uint32(in[62])<<16 | uint32(in[63])<<24 + + x0, x1, x2, x3, x4, x5, x6, x7, x8 := j0, j1, j2, j3, j4, j5, j6, j7, j8 + x9, x10, x11, x12, x13, x14, x15 := j9, j10, j11, j12, j13, j14, j15 + + for i := 0; i < 8; i += 2 { + u := x0 + x12 + x4 ^= u<<7 | u>>(32-7) + u = x4 + x0 + x8 ^= u<<9 | u>>(32-9) + u = x8 + x4 + x12 ^= u<<13 | u>>(32-13) + u = x12 + x8 + x0 ^= u<<18 | u>>(32-18) + + u = x5 + x1 + x9 ^= u<<7 | u>>(32-7) + u = x9 + x5 + x13 ^= u<<9 | u>>(32-9) + u = x13 + x9 + x1 ^= u<<13 | u>>(32-13) + u = x1 + x13 + x5 ^= u<<18 | u>>(32-18) + + u = x10 + x6 + x14 ^= u<<7 | u>>(32-7) + u = x14 + x10 + x2 ^= u<<9 | u>>(32-9) + u = x2 + x14 + x6 ^= u<<13 | u>>(32-13) + u = x6 + x2 + x10 ^= u<<18 | u>>(32-18) + + u = x15 + x11 + x3 ^= u<<7 | u>>(32-7) + u = x3 + x15 + x7 ^= u<<9 | u>>(32-9) + u = x7 + x3 + x11 ^= u<<13 | u>>(32-13) + u = x11 + x7 + x15 ^= u<<18 | u>>(32-18) + + u = x0 + x3 + x1 ^= u<<7 | u>>(32-7) + u = x1 + x0 + x2 ^= u<<9 | u>>(32-9) + u = x2 + x1 + x3 ^= u<<13 | u>>(32-13) + u = x3 + x2 + x0 ^= u<<18 | u>>(32-18) + + u = x5 + x4 + x6 ^= u<<7 | u>>(32-7) + u = x6 + x5 + x7 ^= u<<9 | u>>(32-9) + u = x7 + x6 + x4 ^= u<<13 | u>>(32-13) + u = x4 + x7 + x5 ^= u<<18 | u>>(32-18) + + u = x10 + x9 + x11 ^= u<<7 | u>>(32-7) + u = x11 + x10 + x8 ^= u<<9 | u>>(32-9) + u = x8 + x11 + x9 ^= u<<13 | u>>(32-13) + u = x9 + x8 + x10 ^= u<<18 | u>>(32-18) + + u = x15 + x14 + x12 ^= u<<7 | u>>(32-7) + u = x12 + x15 + x13 ^= u<<9 | u>>(32-9) + u = x13 + x12 + x14 ^= u<<13 | u>>(32-13) + u = x14 + x13 + x15 ^= u<<18 | u>>(32-18) + } + x0 += j0 + x1 += j1 + x2 += j2 + x3 += j3 + x4 += j4 + x5 += j5 + x6 += j6 + x7 += j7 + x8 += j8 + x9 += j9 + x10 += j10 + x11 += j11 + x12 += j12 + x13 += j13 + x14 += j14 + x15 += j15 + + out[0] = byte(x0) + out[1] = byte(x0 >> 8) + out[2] = byte(x0 >> 16) + out[3] = byte(x0 >> 24) + + out[4] = byte(x1) + out[5] = byte(x1 >> 8) + out[6] = byte(x1 >> 16) + out[7] = byte(x1 >> 24) + + out[8] = byte(x2) + out[9] = byte(x2 >> 8) + out[10] = byte(x2 >> 16) + out[11] = byte(x2 >> 24) + + out[12] = byte(x3) + out[13] = byte(x3 >> 8) + out[14] = byte(x3 >> 16) + out[15] = byte(x3 >> 24) + + out[16] = byte(x4) + out[17] = byte(x4 >> 8) + out[18] = byte(x4 >> 16) + out[19] = byte(x4 >> 24) + + out[20] = byte(x5) + out[21] = byte(x5 >> 8) + out[22] = byte(x5 >> 16) + out[23] = byte(x5 >> 24) + + out[24] = byte(x6) + out[25] = byte(x6 >> 8) + out[26] = byte(x6 >> 16) + out[27] = byte(x6 >> 24) + + out[28] = byte(x7) + out[29] = byte(x7 >> 8) + out[30] = byte(x7 >> 16) + out[31] = byte(x7 >> 24) + + out[32] = byte(x8) + out[33] = byte(x8 >> 8) + out[34] = byte(x8 >> 16) + out[35] = byte(x8 >> 24) + + out[36] = byte(x9) + out[37] = byte(x9 >> 8) + out[38] = byte(x9 >> 16) + out[39] = byte(x9 >> 24) + + out[40] = byte(x10) + out[41] = byte(x10 >> 8) + out[42] = byte(x10 >> 16) + out[43] = byte(x10 >> 24) + + out[44] = byte(x11) + out[45] = byte(x11 >> 8) + out[46] = byte(x11 >> 16) + out[47] = byte(x11 >> 24) + + out[48] = byte(x12) + out[49] = byte(x12 >> 8) + out[50] = byte(x12 >> 16) + out[51] = byte(x12 >> 24) + + out[52] = byte(x13) + out[53] = byte(x13 >> 8) + out[54] = byte(x13 >> 16) + out[55] = byte(x13 >> 24) + + out[56] = byte(x14) + out[57] = byte(x14 >> 8) + out[58] = byte(x14 >> 16) + out[59] = byte(x14 >> 24) + + out[60] = byte(x15) + out[61] = byte(x15 >> 8) + out[62] = byte(x15 >> 16) + out[63] = byte(x15 >> 24) +} diff --git a/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go b/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go new file mode 100644 index 0000000000000000000000000000000000000000..f9269c38484db865dfa3f6937f4063064d34ebde --- /dev/null +++ b/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go @@ -0,0 +1,24 @@ +// 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,!appengine,!gccgo + +package salsa + +// This function is implemented in salsa2020_amd64.s. + +//go:noescape + +func salsa2020XORKeyStream(out, in *byte, n uint64, nonce, key *byte) + +// XORKeyStream crypts bytes from in to out using the given key and counters. +// In and out must overlap entirely or not at all. Counter +// contains the raw salsa20 counter bytes (both nonce and block counter). +func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) { + if len(in) == 0 { + return + } + _ = out[len(in)-1] + salsa2020XORKeyStream(&out[0], &in[0], uint64(len(in)), &counter[0], &key[0]) +} diff --git a/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go b/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go new file mode 100644 index 0000000000000000000000000000000000000000..22126d17c4e607fac09cb32ed28469c70fef1c10 --- /dev/null +++ b/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go @@ -0,0 +1,234 @@ +// 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 appengine gccgo + +package salsa + +const rounds = 20 + +// core applies the Salsa20 core function to 16-byte input in, 32-byte key k, +// and 16-byte constant c, and puts the result into 64-byte array out. +func core(out *[64]byte, in *[16]byte, k *[32]byte, c *[16]byte) { + j0 := uint32(c[0]) | uint32(c[1])<<8 | uint32(c[2])<<16 | uint32(c[3])<<24 + j1 := uint32(k[0]) | uint32(k[1])<<8 | uint32(k[2])<<16 | uint32(k[3])<<24 + j2 := uint32(k[4]) | uint32(k[5])<<8 | uint32(k[6])<<16 | uint32(k[7])<<24 + j3 := uint32(k[8]) | uint32(k[9])<<8 | uint32(k[10])<<16 | uint32(k[11])<<24 + j4 := uint32(k[12]) | uint32(k[13])<<8 | uint32(k[14])<<16 | uint32(k[15])<<24 + j5 := uint32(c[4]) | uint32(c[5])<<8 | uint32(c[6])<<16 | uint32(c[7])<<24 + j6 := uint32(in[0]) | uint32(in[1])<<8 | uint32(in[2])<<16 | uint32(in[3])<<24 + j7 := uint32(in[4]) | uint32(in[5])<<8 | uint32(in[6])<<16 | uint32(in[7])<<24 + j8 := uint32(in[8]) | uint32(in[9])<<8 | uint32(in[10])<<16 | uint32(in[11])<<24 + j9 := uint32(in[12]) | uint32(in[13])<<8 | uint32(in[14])<<16 | uint32(in[15])<<24 + j10 := uint32(c[8]) | uint32(c[9])<<8 | uint32(c[10])<<16 | uint32(c[11])<<24 + j11 := uint32(k[16]) | uint32(k[17])<<8 | uint32(k[18])<<16 | uint32(k[19])<<24 + j12 := uint32(k[20]) | uint32(k[21])<<8 | uint32(k[22])<<16 | uint32(k[23])<<24 + j13 := uint32(k[24]) | uint32(k[25])<<8 | uint32(k[26])<<16 | uint32(k[27])<<24 + j14 := uint32(k[28]) | uint32(k[29])<<8 | uint32(k[30])<<16 | uint32(k[31])<<24 + j15 := uint32(c[12]) | uint32(c[13])<<8 | uint32(c[14])<<16 | uint32(c[15])<<24 + + x0, x1, x2, x3, x4, x5, x6, x7, x8 := j0, j1, j2, j3, j4, j5, j6, j7, j8 + x9, x10, x11, x12, x13, x14, x15 := j9, j10, j11, j12, j13, j14, j15 + + for i := 0; i < rounds; i += 2 { + u := x0 + x12 + x4 ^= u<<7 | u>>(32-7) + u = x4 + x0 + x8 ^= u<<9 | u>>(32-9) + u = x8 + x4 + x12 ^= u<<13 | u>>(32-13) + u = x12 + x8 + x0 ^= u<<18 | u>>(32-18) + + u = x5 + x1 + x9 ^= u<<7 | u>>(32-7) + u = x9 + x5 + x13 ^= u<<9 | u>>(32-9) + u = x13 + x9 + x1 ^= u<<13 | u>>(32-13) + u = x1 + x13 + x5 ^= u<<18 | u>>(32-18) + + u = x10 + x6 + x14 ^= u<<7 | u>>(32-7) + u = x14 + x10 + x2 ^= u<<9 | u>>(32-9) + u = x2 + x14 + x6 ^= u<<13 | u>>(32-13) + u = x6 + x2 + x10 ^= u<<18 | u>>(32-18) + + u = x15 + x11 + x3 ^= u<<7 | u>>(32-7) + u = x3 + x15 + x7 ^= u<<9 | u>>(32-9) + u = x7 + x3 + x11 ^= u<<13 | u>>(32-13) + u = x11 + x7 + x15 ^= u<<18 | u>>(32-18) + + u = x0 + x3 + x1 ^= u<<7 | u>>(32-7) + u = x1 + x0 + x2 ^= u<<9 | u>>(32-9) + u = x2 + x1 + x3 ^= u<<13 | u>>(32-13) + u = x3 + x2 + x0 ^= u<<18 | u>>(32-18) + + u = x5 + x4 + x6 ^= u<<7 | u>>(32-7) + u = x6 + x5 + x7 ^= u<<9 | u>>(32-9) + u = x7 + x6 + x4 ^= u<<13 | u>>(32-13) + u = x4 + x7 + x5 ^= u<<18 | u>>(32-18) + + u = x10 + x9 + x11 ^= u<<7 | u>>(32-7) + u = x11 + x10 + x8 ^= u<<9 | u>>(32-9) + u = x8 + x11 + x9 ^= u<<13 | u>>(32-13) + u = x9 + x8 + x10 ^= u<<18 | u>>(32-18) + + u = x15 + x14 + x12 ^= u<<7 | u>>(32-7) + u = x12 + x15 + x13 ^= u<<9 | u>>(32-9) + u = x13 + x12 + x14 ^= u<<13 | u>>(32-13) + u = x14 + x13 + x15 ^= u<<18 | u>>(32-18) + } + x0 += j0 + x1 += j1 + x2 += j2 + x3 += j3 + x4 += j4 + x5 += j5 + x6 += j6 + x7 += j7 + x8 += j8 + x9 += j9 + x10 += j10 + x11 += j11 + x12 += j12 + x13 += j13 + x14 += j14 + x15 += j15 + + out[0] = byte(x0) + out[1] = byte(x0 >> 8) + out[2] = byte(x0 >> 16) + out[3] = byte(x0 >> 24) + + out[4] = byte(x1) + out[5] = byte(x1 >> 8) + out[6] = byte(x1 >> 16) + out[7] = byte(x1 >> 24) + + out[8] = byte(x2) + out[9] = byte(x2 >> 8) + out[10] = byte(x2 >> 16) + out[11] = byte(x2 >> 24) + + out[12] = byte(x3) + out[13] = byte(x3 >> 8) + out[14] = byte(x3 >> 16) + out[15] = byte(x3 >> 24) + + out[16] = byte(x4) + out[17] = byte(x4 >> 8) + out[18] = byte(x4 >> 16) + out[19] = byte(x4 >> 24) + + out[20] = byte(x5) + out[21] = byte(x5 >> 8) + out[22] = byte(x5 >> 16) + out[23] = byte(x5 >> 24) + + out[24] = byte(x6) + out[25] = byte(x6 >> 8) + out[26] = byte(x6 >> 16) + out[27] = byte(x6 >> 24) + + out[28] = byte(x7) + out[29] = byte(x7 >> 8) + out[30] = byte(x7 >> 16) + out[31] = byte(x7 >> 24) + + out[32] = byte(x8) + out[33] = byte(x8 >> 8) + out[34] = byte(x8 >> 16) + out[35] = byte(x8 >> 24) + + out[36] = byte(x9) + out[37] = byte(x9 >> 8) + out[38] = byte(x9 >> 16) + out[39] = byte(x9 >> 24) + + out[40] = byte(x10) + out[41] = byte(x10 >> 8) + out[42] = byte(x10 >> 16) + out[43] = byte(x10 >> 24) + + out[44] = byte(x11) + out[45] = byte(x11 >> 8) + out[46] = byte(x11 >> 16) + out[47] = byte(x11 >> 24) + + out[48] = byte(x12) + out[49] = byte(x12 >> 8) + out[50] = byte(x12 >> 16) + out[51] = byte(x12 >> 24) + + out[52] = byte(x13) + out[53] = byte(x13 >> 8) + out[54] = byte(x13 >> 16) + out[55] = byte(x13 >> 24) + + out[56] = byte(x14) + out[57] = byte(x14 >> 8) + out[58] = byte(x14 >> 16) + out[59] = byte(x14 >> 24) + + out[60] = byte(x15) + out[61] = byte(x15 >> 8) + out[62] = byte(x15 >> 16) + out[63] = byte(x15 >> 24) +} + +// XORKeyStream crypts bytes from in to out using the given key and counters. +// In and out must overlap entirely or not at all. Counter +// contains the raw salsa20 counter bytes (both nonce and block counter). +func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) { + var block [64]byte + var counterCopy [16]byte + copy(counterCopy[:], counter[:]) + + for len(in) >= 64 { + core(&block, &counterCopy, key, &Sigma) + for i, x := range block { + out[i] = in[i] ^ x + } + u := uint32(1) + for i := 8; i < 16; i++ { + u += uint32(counterCopy[i]) + counterCopy[i] = byte(u) + u >>= 8 + } + in = in[64:] + out = out[64:] + } + + if len(in) > 0 { + core(&block, &counterCopy, key, &Sigma) + for i, v := range in { + out[i] = v ^ block[i] + } + } +} diff --git a/vendor/golang.org/x/crypto/salsa20/salsa/salsa_test.go b/vendor/golang.org/x/crypto/salsa20/salsa/salsa_test.go new file mode 100644 index 0000000000000000000000000000000000000000..f67e94eba417939908526623828d843e124e5404 --- /dev/null +++ b/vendor/golang.org/x/crypto/salsa20/salsa/salsa_test.go @@ -0,0 +1,54 @@ +// 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 salsa + +import "testing" + +func TestCore208(t *testing.T) { + in := [64]byte{ + 0x7e, 0x87, 0x9a, 0x21, 0x4f, 0x3e, 0xc9, 0x86, + 0x7c, 0xa9, 0x40, 0xe6, 0x41, 0x71, 0x8f, 0x26, + 0xba, 0xee, 0x55, 0x5b, 0x8c, 0x61, 0xc1, 0xb5, + 0x0d, 0xf8, 0x46, 0x11, 0x6d, 0xcd, 0x3b, 0x1d, + 0xee, 0x24, 0xf3, 0x19, 0xdf, 0x9b, 0x3d, 0x85, + 0x14, 0x12, 0x1e, 0x4b, 0x5a, 0xc5, 0xaa, 0x32, + 0x76, 0x02, 0x1d, 0x29, 0x09, 0xc7, 0x48, 0x29, + 0xed, 0xeb, 0xc6, 0x8d, 0xb8, 0xb8, 0xc2, 0x5e} + + out := [64]byte{ + 0xa4, 0x1f, 0x85, 0x9c, 0x66, 0x08, 0xcc, 0x99, + 0x3b, 0x81, 0xca, 0xcb, 0x02, 0x0c, 0xef, 0x05, + 0x04, 0x4b, 0x21, 0x81, 0xa2, 0xfd, 0x33, 0x7d, + 0xfd, 0x7b, 0x1c, 0x63, 0x96, 0x68, 0x2f, 0x29, + 0xb4, 0x39, 0x31, 0x68, 0xe3, 0xc9, 0xe6, 0xbc, + 0xfe, 0x6b, 0xc5, 0xb7, 0xa0, 0x6d, 0x96, 0xba, + 0xe4, 0x24, 0xcc, 0x10, 0x2c, 0x91, 0x74, 0x5c, + 0x24, 0xad, 0x67, 0x3d, 0xc7, 0x61, 0x8f, 0x81, + } + + Core208(&in, &in) + if in != out { + t.Errorf("expected %x, got %x", out, in) + } +} + +func TestOutOfBoundsWrite(t *testing.T) { + // encrypted "0123456789" + cipherText := []byte{170, 166, 196, 104, 175, 121, 68, 44, 174, 51} + var counter [16]byte + var key [32]byte + want := "abcdefghij" + plainText := []byte(want) + defer func() { + err := recover() + if err == nil { + t.Error("XORKeyStream expected to panic on len(dst) < len(src), but didn't") + } + if plainText[3] == '3' { + t.Errorf("XORKeyStream did out of bounds write, want %v, got %v", want, string(plainText)) + } + }() + XORKeyStream(plainText[:3], cipherText, &counter, &key) +} diff --git a/vendor/golang.org/x/crypto/salsa20/salsa20.go b/vendor/golang.org/x/crypto/salsa20/salsa20.go new file mode 100644 index 0000000000000000000000000000000000000000..0ee62485a798e30ccbf6b7b71cf3de53a690eed2 --- /dev/null +++ b/vendor/golang.org/x/crypto/salsa20/salsa20.go @@ -0,0 +1,54 @@ +// 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 salsa20 implements the Salsa20 stream cipher as specified in https://cr.yp.to/snuffle/spec.pdf. + +Salsa20 differs from many other stream ciphers in that it is message orientated +rather than byte orientated. Keystream blocks are not preserved between calls, +therefore each side must encrypt/decrypt data with the same segmentation. + +Another aspect of this difference is that part of the counter is exposed as +a nonce in each call. Encrypting two different messages with the same (key, +nonce) pair leads to trivial plaintext recovery. This is analogous to +encrypting two different messages with the same key with a traditional stream +cipher. + +This package also implements XSalsa20: a version of Salsa20 with a 24-byte +nonce as specified in https://cr.yp.to/snuffle/xsalsa-20081128.pdf. Simply +passing a 24-byte slice as the nonce triggers XSalsa20. +*/ +package salsa20 // import "golang.org/x/crypto/salsa20" + +// TODO(agl): implement XORKeyStream12 and XORKeyStream8 - the reduced round variants of Salsa20. + +import ( + "golang.org/x/crypto/salsa20/salsa" +) + +// XORKeyStream crypts bytes from in to out using the given key and nonce. +// In and out must overlap entirely or not at all. Nonce must +// be either 8 or 24 bytes long. +func XORKeyStream(out, in []byte, nonce []byte, key *[32]byte) { + if len(out) < len(in) { + in = in[:len(out)] + } + + var subNonce [16]byte + + if len(nonce) == 24 { + var subKey [32]byte + var hNonce [16]byte + copy(hNonce[:], nonce[:16]) + salsa.HSalsa20(&subKey, &hNonce, key, &salsa.Sigma) + copy(subNonce[:], nonce[16:]) + key = &subKey + } else if len(nonce) == 8 { + copy(subNonce[:], nonce[:]) + } else { + panic("salsa20: nonce must be 8 or 24 bytes") + } + + salsa.XORKeyStream(out, in, &subNonce, key) +} diff --git a/vendor/golang.org/x/crypto/salsa20/salsa20_test.go b/vendor/golang.org/x/crypto/salsa20/salsa20_test.go new file mode 100644 index 0000000000000000000000000000000000000000..0ef3328eb0a8dc4b8f7bd988313506e98d2d6474 --- /dev/null +++ b/vendor/golang.org/x/crypto/salsa20/salsa20_test.go @@ -0,0 +1,139 @@ +// 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 salsa20 + +import ( + "bytes" + "encoding/hex" + "testing" +) + +func fromHex(s string) []byte { + ret, err := hex.DecodeString(s) + if err != nil { + panic(err) + } + return ret +} + +// testVectors was taken from set 6 of the ECRYPT test vectors: +// http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/salsa20/full/verified.test-vectors?logsort=rev&rev=210&view=markup +var testVectors = []struct { + key []byte + iv []byte + numBytes int + xor []byte +}{ + { + fromHex("0053A6F94C9FF24598EB3E91E4378ADD3083D6297CCF2275C81B6EC11467BA0D"), + fromHex("0D74DB42A91077DE"), + 131072, + fromHex("C349B6A51A3EC9B712EAED3F90D8BCEE69B7628645F251A996F55260C62EF31FD6C6B0AEA94E136C9D984AD2DF3578F78E457527B03A0450580DD874F63B1AB9"), + }, + { + fromHex("0558ABFE51A4F74A9DF04396E93C8FE23588DB2E81D4277ACD2073C6196CBF12"), + fromHex("167DE44BB21980E7"), + 131072, + fromHex("C3EAAF32836BACE32D04E1124231EF47E101367D6305413A0EEB07C60698A2876E4D031870A739D6FFDDD208597AFF0A47AC17EDB0167DD67EBA84F1883D4DFD"), + }, + { + fromHex("0A5DB00356A9FC4FA2F5489BEE4194E73A8DE03386D92C7FD22578CB1E71C417"), + fromHex("1F86ED54BB2289F0"), + 131072, + fromHex("3CD23C3DC90201ACC0CF49B440B6C417F0DC8D8410A716D5314C059E14B1A8D9A9FB8EA3D9C8DAE12B21402F674AA95C67B1FC514E994C9D3F3A6E41DFF5BBA6"), + }, + { + fromHex("0F62B5085BAE0154A7FA4DA0F34699EC3F92E5388BDE3184D72A7DD02376C91C"), + fromHex("288FF65DC42B92F9"), + 131072, + fromHex("E00EBCCD70D69152725F9987982178A2E2E139C7BCBE04CA8A0E99E318D9AB76F988C8549F75ADD790BA4F81C176DA653C1A043F11A958E169B6D2319F4EEC1A"), + }, +} + +func TestSalsa20(t *testing.T) { + var inBuf, outBuf []byte + var key [32]byte + + for i, test := range testVectors { + if test.numBytes%64 != 0 { + t.Errorf("#%d: numBytes is not a multiple of 64", i) + continue + } + + if test.numBytes > len(inBuf) { + inBuf = make([]byte, test.numBytes) + outBuf = make([]byte, test.numBytes) + } + in := inBuf[:test.numBytes] + out := outBuf[:test.numBytes] + copy(key[:], test.key) + XORKeyStream(out, in, test.iv, &key) + + var xor [64]byte + for len(out) > 0 { + for i := 0; i < 64; i++ { + xor[i] ^= out[i] + } + out = out[64:] + } + + if !bytes.Equal(xor[:], test.xor) { + t.Errorf("#%d: bad result", i) + } + } +} + +var xSalsa20TestData = []struct { + in, nonce, key, out []byte +}{ + { + []byte("Hello world!"), + []byte("24-byte nonce for xsalsa"), + []byte("this is 32-byte key for xsalsa20"), + []byte{0x00, 0x2d, 0x45, 0x13, 0x84, 0x3f, 0xc2, 0x40, 0xc4, 0x01, 0xe5, 0x41}, + }, + { + make([]byte, 64), + []byte("24-byte nonce for xsalsa"), + []byte("this is 32-byte key for xsalsa20"), + []byte{0x48, 0x48, 0x29, 0x7f, 0xeb, 0x1f, 0xb5, 0x2f, 0xb6, + 0x6d, 0x81, 0x60, 0x9b, 0xd5, 0x47, 0xfa, 0xbc, 0xbe, 0x70, + 0x26, 0xed, 0xc8, 0xb5, 0xe5, 0xe4, 0x49, 0xd0, 0x88, 0xbf, + 0xa6, 0x9c, 0x08, 0x8f, 0x5d, 0x8d, 0xa1, 0xd7, 0x91, 0x26, + 0x7c, 0x2c, 0x19, 0x5a, 0x7f, 0x8c, 0xae, 0x9c, 0x4b, 0x40, + 0x50, 0xd0, 0x8c, 0xe6, 0xd3, 0xa1, 0x51, 0xec, 0x26, 0x5f, + 0x3a, 0x58, 0xe4, 0x76, 0x48}, + }, +} + +func TestXSalsa20(t *testing.T) { + var key [32]byte + + for i, test := range xSalsa20TestData { + out := make([]byte, len(test.in)) + copy(key[:], test.key) + XORKeyStream(out, test.in, test.nonce, &key) + if !bytes.Equal(out, test.out) { + t.Errorf("%d: expected %x, got %x", i, test.out, out) + } + } +} + +var ( + keyArray [32]byte + key = &keyArray + nonce [8]byte + msg = make([]byte, 1<<10) +) + +func BenchmarkXOR1K(b *testing.B) { + b.StopTimer() + out := make([]byte, 1024) + b.StartTimer() + for i := 0; i < b.N; i++ { + XORKeyStream(out, msg[:1024], nonce[:], key) + } + b.SetBytes(1024) +} diff --git a/vendor/golang.org/x/crypto/scrypt/example_test.go b/vendor/golang.org/x/crypto/scrypt/example_test.go new file mode 100644 index 0000000000000000000000000000000000000000..6736479b1961531d89f62d02abe45fe0f9c47906 --- /dev/null +++ b/vendor/golang.org/x/crypto/scrypt/example_test.go @@ -0,0 +1,26 @@ +// Copyright 2017 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 scrypt_test + +import ( + "encoding/base64" + "fmt" + "log" + + "golang.org/x/crypto/scrypt" +) + +func Example() { + // DO NOT use this salt value; generate your own random salt. 8 bytes is + // a good length. + salt := []byte{0xc8, 0x28, 0xf2, 0x58, 0xa7, 0x6a, 0xad, 0x7b} + + dk, err := scrypt.Key([]byte("some password"), salt, 1<<15, 8, 1, 32) + if err != nil { + log.Fatal(err) + } + fmt.Println(base64.StdEncoding.EncodeToString(dk)) + // Output: lGnMz8io0AUkfzn6Pls1qX20Vs7PGN6sbYQ2TQgY12M= +} diff --git a/vendor/golang.org/x/crypto/scrypt/scrypt.go b/vendor/golang.org/x/crypto/scrypt/scrypt.go new file mode 100644 index 0000000000000000000000000000000000000000..ff28aaef6ff2f091efe8cdbae93da4c402908bd1 --- /dev/null +++ b/vendor/golang.org/x/crypto/scrypt/scrypt.go @@ -0,0 +1,244 @@ +// 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 scrypt implements the scrypt key derivation function as defined in +// Colin Percival's paper "Stronger Key Derivation via Sequential Memory-Hard +// Functions" (https://www.tarsnap.com/scrypt/scrypt.pdf). +package scrypt // import "golang.org/x/crypto/scrypt" + +import ( + "crypto/sha256" + "errors" + + "golang.org/x/crypto/pbkdf2" +) + +const maxInt = int(^uint(0) >> 1) + +// blockCopy copies n numbers from src into dst. +func blockCopy(dst, src []uint32, n int) { + copy(dst, src[:n]) +} + +// blockXOR XORs numbers from dst with n numbers from src. +func blockXOR(dst, src []uint32, n int) { + for i, v := range src[:n] { + dst[i] ^= v + } +} + +// salsaXOR applies Salsa20/8 to the XOR of 16 numbers from tmp and in, +// and puts the result into both both tmp and out. +func salsaXOR(tmp *[16]uint32, in, out []uint32) { + w0 := tmp[0] ^ in[0] + w1 := tmp[1] ^ in[1] + w2 := tmp[2] ^ in[2] + w3 := tmp[3] ^ in[3] + w4 := tmp[4] ^ in[4] + w5 := tmp[5] ^ in[5] + w6 := tmp[6] ^ in[6] + w7 := tmp[7] ^ in[7] + w8 := tmp[8] ^ in[8] + w9 := tmp[9] ^ in[9] + w10 := tmp[10] ^ in[10] + w11 := tmp[11] ^ in[11] + w12 := tmp[12] ^ in[12] + w13 := tmp[13] ^ in[13] + w14 := tmp[14] ^ in[14] + w15 := tmp[15] ^ in[15] + + x0, x1, x2, x3, x4, x5, x6, x7, x8 := w0, w1, w2, w3, w4, w5, w6, w7, w8 + x9, x10, x11, x12, x13, x14, x15 := w9, w10, w11, w12, w13, w14, w15 + + for i := 0; i < 8; i += 2 { + u := x0 + x12 + x4 ^= u<<7 | u>>(32-7) + u = x4 + x0 + x8 ^= u<<9 | u>>(32-9) + u = x8 + x4 + x12 ^= u<<13 | u>>(32-13) + u = x12 + x8 + x0 ^= u<<18 | u>>(32-18) + + u = x5 + x1 + x9 ^= u<<7 | u>>(32-7) + u = x9 + x5 + x13 ^= u<<9 | u>>(32-9) + u = x13 + x9 + x1 ^= u<<13 | u>>(32-13) + u = x1 + x13 + x5 ^= u<<18 | u>>(32-18) + + u = x10 + x6 + x14 ^= u<<7 | u>>(32-7) + u = x14 + x10 + x2 ^= u<<9 | u>>(32-9) + u = x2 + x14 + x6 ^= u<<13 | u>>(32-13) + u = x6 + x2 + x10 ^= u<<18 | u>>(32-18) + + u = x15 + x11 + x3 ^= u<<7 | u>>(32-7) + u = x3 + x15 + x7 ^= u<<9 | u>>(32-9) + u = x7 + x3 + x11 ^= u<<13 | u>>(32-13) + u = x11 + x7 + x15 ^= u<<18 | u>>(32-18) + + u = x0 + x3 + x1 ^= u<<7 | u>>(32-7) + u = x1 + x0 + x2 ^= u<<9 | u>>(32-9) + u = x2 + x1 + x3 ^= u<<13 | u>>(32-13) + u = x3 + x2 + x0 ^= u<<18 | u>>(32-18) + + u = x5 + x4 + x6 ^= u<<7 | u>>(32-7) + u = x6 + x5 + x7 ^= u<<9 | u>>(32-9) + u = x7 + x6 + x4 ^= u<<13 | u>>(32-13) + u = x4 + x7 + x5 ^= u<<18 | u>>(32-18) + + u = x10 + x9 + x11 ^= u<<7 | u>>(32-7) + u = x11 + x10 + x8 ^= u<<9 | u>>(32-9) + u = x8 + x11 + x9 ^= u<<13 | u>>(32-13) + u = x9 + x8 + x10 ^= u<<18 | u>>(32-18) + + u = x15 + x14 + x12 ^= u<<7 | u>>(32-7) + u = x12 + x15 + x13 ^= u<<9 | u>>(32-9) + u = x13 + x12 + x14 ^= u<<13 | u>>(32-13) + u = x14 + x13 + x15 ^= u<<18 | u>>(32-18) + } + x0 += w0 + x1 += w1 + x2 += w2 + x3 += w3 + x4 += w4 + x5 += w5 + x6 += w6 + x7 += w7 + x8 += w8 + x9 += w9 + x10 += w10 + x11 += w11 + x12 += w12 + x13 += w13 + x14 += w14 + x15 += w15 + + out[0], tmp[0] = x0, x0 + out[1], tmp[1] = x1, x1 + out[2], tmp[2] = x2, x2 + out[3], tmp[3] = x3, x3 + out[4], tmp[4] = x4, x4 + out[5], tmp[5] = x5, x5 + out[6], tmp[6] = x6, x6 + out[7], tmp[7] = x7, x7 + out[8], tmp[8] = x8, x8 + out[9], tmp[9] = x9, x9 + out[10], tmp[10] = x10, x10 + out[11], tmp[11] = x11, x11 + out[12], tmp[12] = x12, x12 + out[13], tmp[13] = x13, x13 + out[14], tmp[14] = x14, x14 + out[15], tmp[15] = x15, x15 +} + +func blockMix(tmp *[16]uint32, in, out []uint32, r int) { + blockCopy(tmp[:], in[(2*r-1)*16:], 16) + for i := 0; i < 2*r; i += 2 { + salsaXOR(tmp, in[i*16:], out[i*8:]) + salsaXOR(tmp, in[i*16+16:], out[i*8+r*16:]) + } +} + +func integer(b []uint32, r int) uint64 { + j := (2*r - 1) * 16 + return uint64(b[j]) | uint64(b[j+1])<<32 +} + +func smix(b []byte, r, N int, v, xy []uint32) { + var tmp [16]uint32 + x := xy + y := xy[32*r:] + + j := 0 + for i := 0; i < 32*r; i++ { + x[i] = uint32(b[j]) | uint32(b[j+1])<<8 | uint32(b[j+2])<<16 | uint32(b[j+3])<<24 + j += 4 + } + for i := 0; i < N; i += 2 { + blockCopy(v[i*(32*r):], x, 32*r) + blockMix(&tmp, x, y, r) + + blockCopy(v[(i+1)*(32*r):], y, 32*r) + blockMix(&tmp, y, x, r) + } + for i := 0; i < N; i += 2 { + j := int(integer(x, r) & uint64(N-1)) + blockXOR(x, v[j*(32*r):], 32*r) + blockMix(&tmp, x, y, r) + + j = int(integer(y, r) & uint64(N-1)) + blockXOR(y, v[j*(32*r):], 32*r) + blockMix(&tmp, y, x, r) + } + j = 0 + for _, v := range x[:32*r] { + b[j+0] = byte(v >> 0) + b[j+1] = byte(v >> 8) + b[j+2] = byte(v >> 16) + b[j+3] = byte(v >> 24) + j += 4 + } +} + +// Key derives a key from the password, salt, and cost parameters, returning +// a byte slice of length keyLen that can be used as cryptographic key. +// +// N is a CPU/memory cost parameter, which must be a power of two greater than 1. +// r and p must satisfy r * p < 2³â°. If the parameters do not satisfy the +// limits, the function returns a nil byte slice and an error. +// +// For example, you can get a derived key for e.g. AES-256 (which needs a +// 32-byte key) by doing: +// +// dk, err := scrypt.Key([]byte("some password"), salt, 16384, 8, 1, 32) +// +// The recommended parameters for interactive logins as of 2017 are N=32768, r=8 +// and p=1. The parameters N, r, and p should be increased as memory latency and +// CPU parallelism increases; consider setting N to the highest power of 2 you +// can derive within 100 milliseconds. Remember to get a good random salt. +func Key(password, salt []byte, N, r, p, keyLen int) ([]byte, error) { + if N <= 1 || N&(N-1) != 0 { + return nil, errors.New("scrypt: N must be > 1 and a power of 2") + } + if uint64(r)*uint64(p) >= 1<<30 || r > maxInt/128/p || r > maxInt/256 || N > maxInt/128/r { + return nil, errors.New("scrypt: parameters are too large") + } + + xy := make([]uint32, 64*r) + v := make([]uint32, 32*N*r) + b := pbkdf2.Key(password, salt, 1, p*128*r, sha256.New) + + for i := 0; i < p; i++ { + smix(b[i*128*r:], r, N, v, xy) + } + + return pbkdf2.Key(password, b, 1, keyLen, sha256.New), nil +} diff --git a/vendor/golang.org/x/crypto/scrypt/scrypt_test.go b/vendor/golang.org/x/crypto/scrypt/scrypt_test.go new file mode 100644 index 0000000000000000000000000000000000000000..766ed8d905025076c80cead4cf3e65f146979c76 --- /dev/null +++ b/vendor/golang.org/x/crypto/scrypt/scrypt_test.go @@ -0,0 +1,162 @@ +// 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 scrypt + +import ( + "bytes" + "testing" +) + +type testVector struct { + password string + salt string + N, r, p int + output []byte +} + +var good = []testVector{ + { + "password", + "salt", + 2, 10, 10, + []byte{ + 0x48, 0x2c, 0x85, 0x8e, 0x22, 0x90, 0x55, 0xe6, 0x2f, + 0x41, 0xe0, 0xec, 0x81, 0x9a, 0x5e, 0xe1, 0x8b, 0xdb, + 0x87, 0x25, 0x1a, 0x53, 0x4f, 0x75, 0xac, 0xd9, 0x5a, + 0xc5, 0xe5, 0xa, 0xa1, 0x5f, + }, + }, + { + "password", + "salt", + 16, 100, 100, + []byte{ + 0x88, 0xbd, 0x5e, 0xdb, 0x52, 0xd1, 0xdd, 0x0, 0x18, + 0x87, 0x72, 0xad, 0x36, 0x17, 0x12, 0x90, 0x22, 0x4e, + 0x74, 0x82, 0x95, 0x25, 0xb1, 0x8d, 0x73, 0x23, 0xa5, + 0x7f, 0x91, 0x96, 0x3c, 0x37, + }, + }, + { + "this is a long \000 password", + "and this is a long \000 salt", + 16384, 8, 1, + []byte{ + 0xc3, 0xf1, 0x82, 0xee, 0x2d, 0xec, 0x84, 0x6e, 0x70, + 0xa6, 0x94, 0x2f, 0xb5, 0x29, 0x98, 0x5a, 0x3a, 0x09, + 0x76, 0x5e, 0xf0, 0x4c, 0x61, 0x29, 0x23, 0xb1, 0x7f, + 0x18, 0x55, 0x5a, 0x37, 0x07, 0x6d, 0xeb, 0x2b, 0x98, + 0x30, 0xd6, 0x9d, 0xe5, 0x49, 0x26, 0x51, 0xe4, 0x50, + 0x6a, 0xe5, 0x77, 0x6d, 0x96, 0xd4, 0x0f, 0x67, 0xaa, + 0xee, 0x37, 0xe1, 0x77, 0x7b, 0x8a, 0xd5, 0xc3, 0x11, + 0x14, 0x32, 0xbb, 0x3b, 0x6f, 0x7e, 0x12, 0x64, 0x40, + 0x18, 0x79, 0xe6, 0x41, 0xae, + }, + }, + { + "p", + "s", + 2, 1, 1, + []byte{ + 0x48, 0xb0, 0xd2, 0xa8, 0xa3, 0x27, 0x26, 0x11, 0x98, + 0x4c, 0x50, 0xeb, 0xd6, 0x30, 0xaf, 0x52, + }, + }, + + { + "", + "", + 16, 1, 1, + []byte{ + 0x77, 0xd6, 0x57, 0x62, 0x38, 0x65, 0x7b, 0x20, 0x3b, + 0x19, 0xca, 0x42, 0xc1, 0x8a, 0x04, 0x97, 0xf1, 0x6b, + 0x48, 0x44, 0xe3, 0x07, 0x4a, 0xe8, 0xdf, 0xdf, 0xfa, + 0x3f, 0xed, 0xe2, 0x14, 0x42, 0xfc, 0xd0, 0x06, 0x9d, + 0xed, 0x09, 0x48, 0xf8, 0x32, 0x6a, 0x75, 0x3a, 0x0f, + 0xc8, 0x1f, 0x17, 0xe8, 0xd3, 0xe0, 0xfb, 0x2e, 0x0d, + 0x36, 0x28, 0xcf, 0x35, 0xe2, 0x0c, 0x38, 0xd1, 0x89, + 0x06, + }, + }, + { + "password", + "NaCl", + 1024, 8, 16, + []byte{ + 0xfd, 0xba, 0xbe, 0x1c, 0x9d, 0x34, 0x72, 0x00, 0x78, + 0x56, 0xe7, 0x19, 0x0d, 0x01, 0xe9, 0xfe, 0x7c, 0x6a, + 0xd7, 0xcb, 0xc8, 0x23, 0x78, 0x30, 0xe7, 0x73, 0x76, + 0x63, 0x4b, 0x37, 0x31, 0x62, 0x2e, 0xaf, 0x30, 0xd9, + 0x2e, 0x22, 0xa3, 0x88, 0x6f, 0xf1, 0x09, 0x27, 0x9d, + 0x98, 0x30, 0xda, 0xc7, 0x27, 0xaf, 0xb9, 0x4a, 0x83, + 0xee, 0x6d, 0x83, 0x60, 0xcb, 0xdf, 0xa2, 0xcc, 0x06, + 0x40, + }, + }, + { + "pleaseletmein", "SodiumChloride", + 16384, 8, 1, + []byte{ + 0x70, 0x23, 0xbd, 0xcb, 0x3a, 0xfd, 0x73, 0x48, 0x46, + 0x1c, 0x06, 0xcd, 0x81, 0xfd, 0x38, 0xeb, 0xfd, 0xa8, + 0xfb, 0xba, 0x90, 0x4f, 0x8e, 0x3e, 0xa9, 0xb5, 0x43, + 0xf6, 0x54, 0x5d, 0xa1, 0xf2, 0xd5, 0x43, 0x29, 0x55, + 0x61, 0x3f, 0x0f, 0xcf, 0x62, 0xd4, 0x97, 0x05, 0x24, + 0x2a, 0x9a, 0xf9, 0xe6, 0x1e, 0x85, 0xdc, 0x0d, 0x65, + 0x1e, 0x40, 0xdf, 0xcf, 0x01, 0x7b, 0x45, 0x57, 0x58, + 0x87, + }, + }, + /* + // Disabled: needs 1 GiB RAM and takes too long for a simple test. + { + "pleaseletmein", "SodiumChloride", + 1048576, 8, 1, + []byte{ + 0x21, 0x01, 0xcb, 0x9b, 0x6a, 0x51, 0x1a, 0xae, 0xad, + 0xdb, 0xbe, 0x09, 0xcf, 0x70, 0xf8, 0x81, 0xec, 0x56, + 0x8d, 0x57, 0x4a, 0x2f, 0xfd, 0x4d, 0xab, 0xe5, 0xee, + 0x98, 0x20, 0xad, 0xaa, 0x47, 0x8e, 0x56, 0xfd, 0x8f, + 0x4b, 0xa5, 0xd0, 0x9f, 0xfa, 0x1c, 0x6d, 0x92, 0x7c, + 0x40, 0xf4, 0xc3, 0x37, 0x30, 0x40, 0x49, 0xe8, 0xa9, + 0x52, 0xfb, 0xcb, 0xf4, 0x5c, 0x6f, 0xa7, 0x7a, 0x41, + 0xa4, + }, + }, + */ +} + +var bad = []testVector{ + {"p", "s", 0, 1, 1, nil}, // N == 0 + {"p", "s", 1, 1, 1, nil}, // N == 1 + {"p", "s", 7, 8, 1, nil}, // N is not power of 2 + {"p", "s", 16, maxInt / 2, maxInt / 2, nil}, // p * r too large +} + +func TestKey(t *testing.T) { + for i, v := range good { + k, err := Key([]byte(v.password), []byte(v.salt), v.N, v.r, v.p, len(v.output)) + if err != nil { + t.Errorf("%d: got unexpected error: %s", i, err) + } + if !bytes.Equal(k, v.output) { + t.Errorf("%d: expected %x, got %x", i, v.output, k) + } + } + for i, v := range bad { + _, err := Key([]byte(v.password), []byte(v.salt), v.N, v.r, v.p, 32) + if err == nil { + t.Errorf("%d: expected error, got nil", i) + } + } +} + +var sink []byte + +func BenchmarkKey(b *testing.B) { + for i := 0; i < b.N; i++ { + sink, _ = Key([]byte("password"), []byte("salt"), 1<<15, 8, 1, 64) + } +} diff --git a/vendor/golang.org/x/crypto/sha3/doc.go b/vendor/golang.org/x/crypto/sha3/doc.go new file mode 100644 index 0000000000000000000000000000000000000000..a0ee3ae725d032acefd5950481a1fe70d84f2d4b --- /dev/null +++ b/vendor/golang.org/x/crypto/sha3/doc.go @@ -0,0 +1,66 @@ +// 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 sha3 implements the SHA-3 fixed-output-length hash functions and +// the SHAKE variable-output-length hash functions defined by FIPS-202. +// +// Both types of hash function use the "sponge" construction and the Keccak +// permutation. For a detailed specification see http://keccak.noekeon.org/ +// +// +// Guidance +// +// If you aren't sure what function you need, use SHAKE256 with at least 64 +// bytes of output. The SHAKE instances are faster than the SHA3 instances; +// the latter have to allocate memory to conform to the hash.Hash interface. +// +// If you need a secret-key MAC (message authentication code), prepend the +// secret key to the input, hash with SHAKE256 and read at least 32 bytes of +// output. +// +// +// Security strengths +// +// The SHA3-x (x equals 224, 256, 384, or 512) functions have a security +// strength against preimage attacks of x bits. Since they only produce "x" +// bits of output, their collision-resistance is only "x/2" bits. +// +// The SHAKE-256 and -128 functions have a generic security strength of 256 and +// 128 bits against all attacks, provided that at least 2x bits of their output +// is used. Requesting more than 64 or 32 bytes of output, respectively, does +// not increase the collision-resistance of the SHAKE functions. +// +// +// The sponge construction +// +// A sponge builds a pseudo-random function from a public pseudo-random +// permutation, by applying the permutation to a state of "rate + capacity" +// bytes, but hiding "capacity" of the bytes. +// +// A sponge starts out with a zero state. To hash an input using a sponge, up +// to "rate" bytes of the input are XORed into the sponge's state. The sponge +// is then "full" and the permutation is applied to "empty" it. This process is +// repeated until all the input has been "absorbed". The input is then padded. +// The digest is "squeezed" from the sponge in the same way, except that output +// output is copied out instead of input being XORed in. +// +// A sponge is parameterized by its generic security strength, which is equal +// to half its capacity; capacity + rate is equal to the permutation's width. +// Since the KeccakF-1600 permutation is 1600 bits (200 bytes) wide, this means +// that the security strength of a sponge instance is equal to (1600 - bitrate) / 2. +// +// +// Recommendations +// +// The SHAKE functions are recommended for most new uses. They can produce +// output of arbitrary length. SHAKE256, with an output length of at least +// 64 bytes, provides 256-bit security against all attacks. The Keccak team +// recommends it for most applications upgrading from SHA2-512. (NIST chose a +// much stronger, but much slower, sponge instance for SHA3-512.) +// +// The SHA-3 functions are "drop-in" replacements for the SHA-2 functions. +// They produce output of the same length, with the same security strengths +// against all attacks. This means, in particular, that SHA3-256 only has +// 128-bit collision resistance, because its output length is 32 bytes. +package sha3 // import "golang.org/x/crypto/sha3" diff --git a/vendor/golang.org/x/crypto/sha3/hashes.go b/vendor/golang.org/x/crypto/sha3/hashes.go new file mode 100644 index 0000000000000000000000000000000000000000..2b51cf4e9b4047eb4d89cd96780b714bddd91677 --- /dev/null +++ b/vendor/golang.org/x/crypto/sha3/hashes.go @@ -0,0 +1,65 @@ +// 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 sha3 + +// This file provides functions for creating instances of the SHA-3 +// and SHAKE hash functions, as well as utility functions for hashing +// bytes. + +import ( + "hash" +) + +// New224 creates a new SHA3-224 hash. +// Its generic security strength is 224 bits against preimage attacks, +// and 112 bits against collision attacks. +func New224() hash.Hash { return &state{rate: 144, outputLen: 28, dsbyte: 0x06} } + +// New256 creates a new SHA3-256 hash. +// Its generic security strength is 256 bits against preimage attacks, +// and 128 bits against collision attacks. +func New256() hash.Hash { return &state{rate: 136, outputLen: 32, dsbyte: 0x06} } + +// New384 creates a new SHA3-384 hash. +// Its generic security strength is 384 bits against preimage attacks, +// and 192 bits against collision attacks. +func New384() hash.Hash { return &state{rate: 104, outputLen: 48, dsbyte: 0x06} } + +// New512 creates a new SHA3-512 hash. +// Its generic security strength is 512 bits against preimage attacks, +// and 256 bits against collision attacks. +func New512() hash.Hash { return &state{rate: 72, outputLen: 64, dsbyte: 0x06} } + +// Sum224 returns the SHA3-224 digest of the data. +func Sum224(data []byte) (digest [28]byte) { + h := New224() + h.Write(data) + h.Sum(digest[:0]) + return +} + +// Sum256 returns the SHA3-256 digest of the data. +func Sum256(data []byte) (digest [32]byte) { + h := New256() + h.Write(data) + h.Sum(digest[:0]) + return +} + +// Sum384 returns the SHA3-384 digest of the data. +func Sum384(data []byte) (digest [48]byte) { + h := New384() + h.Write(data) + h.Sum(digest[:0]) + return +} + +// Sum512 returns the SHA3-512 digest of the data. +func Sum512(data []byte) (digest [64]byte) { + h := New512() + h.Write(data) + h.Sum(digest[:0]) + return +} diff --git a/vendor/golang.org/x/crypto/sha3/keccakf.go b/vendor/golang.org/x/crypto/sha3/keccakf.go new file mode 100644 index 0000000000000000000000000000000000000000..46d03ed385dfe2da9d0168405f843cb913b914a6 --- /dev/null +++ b/vendor/golang.org/x/crypto/sha3/keccakf.go @@ -0,0 +1,412 @@ +// 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. + +// +build !amd64 appengine gccgo + +package sha3 + +// rc stores the round constants for use in the ι step. +var rc = [24]uint64{ + 0x0000000000000001, + 0x0000000000008082, + 0x800000000000808A, + 0x8000000080008000, + 0x000000000000808B, + 0x0000000080000001, + 0x8000000080008081, + 0x8000000000008009, + 0x000000000000008A, + 0x0000000000000088, + 0x0000000080008009, + 0x000000008000000A, + 0x000000008000808B, + 0x800000000000008B, + 0x8000000000008089, + 0x8000000000008003, + 0x8000000000008002, + 0x8000000000000080, + 0x000000000000800A, + 0x800000008000000A, + 0x8000000080008081, + 0x8000000000008080, + 0x0000000080000001, + 0x8000000080008008, +} + +// keccakF1600 applies the Keccak permutation to a 1600b-wide +// state represented as a slice of 25 uint64s. +func keccakF1600(a *[25]uint64) { + // Implementation translated from Keccak-inplace.c + // in the keccak reference code. + var t, bc0, bc1, bc2, bc3, bc4, d0, d1, d2, d3, d4 uint64 + + for i := 0; i < 24; i += 4 { + // Combines the 5 steps in each round into 2 steps. + // Unrolls 4 rounds per loop and spreads some steps across rounds. + + // Round 1 + bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] + bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] + bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] + bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] + bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] + d0 = bc4 ^ (bc1<<1 | bc1>>63) + d1 = bc0 ^ (bc2<<1 | bc2>>63) + d2 = bc1 ^ (bc3<<1 | bc3>>63) + d3 = bc2 ^ (bc4<<1 | bc4>>63) + d4 = bc3 ^ (bc0<<1 | bc0>>63) + + bc0 = a[0] ^ d0 + t = a[6] ^ d1 + bc1 = t<<44 | t>>(64-44) + t = a[12] ^ d2 + bc2 = t<<43 | t>>(64-43) + t = a[18] ^ d3 + bc3 = t<<21 | t>>(64-21) + t = a[24] ^ d4 + bc4 = t<<14 | t>>(64-14) + a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i] + a[6] = bc1 ^ (bc3 &^ bc2) + a[12] = bc2 ^ (bc4 &^ bc3) + a[18] = bc3 ^ (bc0 &^ bc4) + a[24] = bc4 ^ (bc1 &^ bc0) + + t = a[10] ^ d0 + bc2 = t<<3 | t>>(64-3) + t = a[16] ^ d1 + bc3 = t<<45 | t>>(64-45) + t = a[22] ^ d2 + bc4 = t<<61 | t>>(64-61) + t = a[3] ^ d3 + bc0 = t<<28 | t>>(64-28) + t = a[9] ^ d4 + bc1 = t<<20 | t>>(64-20) + a[10] = bc0 ^ (bc2 &^ bc1) + a[16] = bc1 ^ (bc3 &^ bc2) + a[22] = bc2 ^ (bc4 &^ bc3) + a[3] = bc3 ^ (bc0 &^ bc4) + a[9] = bc4 ^ (bc1 &^ bc0) + + t = a[20] ^ d0 + bc4 = t<<18 | t>>(64-18) + t = a[1] ^ d1 + bc0 = t<<1 | t>>(64-1) + t = a[7] ^ d2 + bc1 = t<<6 | t>>(64-6) + t = a[13] ^ d3 + bc2 = t<<25 | t>>(64-25) + t = a[19] ^ d4 + bc3 = t<<8 | t>>(64-8) + a[20] = bc0 ^ (bc2 &^ bc1) + a[1] = bc1 ^ (bc3 &^ bc2) + a[7] = bc2 ^ (bc4 &^ bc3) + a[13] = bc3 ^ (bc0 &^ bc4) + a[19] = bc4 ^ (bc1 &^ bc0) + + t = a[5] ^ d0 + bc1 = t<<36 | t>>(64-36) + t = a[11] ^ d1 + bc2 = t<<10 | t>>(64-10) + t = a[17] ^ d2 + bc3 = t<<15 | t>>(64-15) + t = a[23] ^ d3 + bc4 = t<<56 | t>>(64-56) + t = a[4] ^ d4 + bc0 = t<<27 | t>>(64-27) + a[5] = bc0 ^ (bc2 &^ bc1) + a[11] = bc1 ^ (bc3 &^ bc2) + a[17] = bc2 ^ (bc4 &^ bc3) + a[23] = bc3 ^ (bc0 &^ bc4) + a[4] = bc4 ^ (bc1 &^ bc0) + + t = a[15] ^ d0 + bc3 = t<<41 | t>>(64-41) + t = a[21] ^ d1 + bc4 = t<<2 | t>>(64-2) + t = a[2] ^ d2 + bc0 = t<<62 | t>>(64-62) + t = a[8] ^ d3 + bc1 = t<<55 | t>>(64-55) + t = a[14] ^ d4 + bc2 = t<<39 | t>>(64-39) + a[15] = bc0 ^ (bc2 &^ bc1) + a[21] = bc1 ^ (bc3 &^ bc2) + a[2] = bc2 ^ (bc4 &^ bc3) + a[8] = bc3 ^ (bc0 &^ bc4) + a[14] = bc4 ^ (bc1 &^ bc0) + + // Round 2 + bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] + bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] + bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] + bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] + bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] + d0 = bc4 ^ (bc1<<1 | bc1>>63) + d1 = bc0 ^ (bc2<<1 | bc2>>63) + d2 = bc1 ^ (bc3<<1 | bc3>>63) + d3 = bc2 ^ (bc4<<1 | bc4>>63) + d4 = bc3 ^ (bc0<<1 | bc0>>63) + + bc0 = a[0] ^ d0 + t = a[16] ^ d1 + bc1 = t<<44 | t>>(64-44) + t = a[7] ^ d2 + bc2 = t<<43 | t>>(64-43) + t = a[23] ^ d3 + bc3 = t<<21 | t>>(64-21) + t = a[14] ^ d4 + bc4 = t<<14 | t>>(64-14) + a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+1] + a[16] = bc1 ^ (bc3 &^ bc2) + a[7] = bc2 ^ (bc4 &^ bc3) + a[23] = bc3 ^ (bc0 &^ bc4) + a[14] = bc4 ^ (bc1 &^ bc0) + + t = a[20] ^ d0 + bc2 = t<<3 | t>>(64-3) + t = a[11] ^ d1 + bc3 = t<<45 | t>>(64-45) + t = a[2] ^ d2 + bc4 = t<<61 | t>>(64-61) + t = a[18] ^ d3 + bc0 = t<<28 | t>>(64-28) + t = a[9] ^ d4 + bc1 = t<<20 | t>>(64-20) + a[20] = bc0 ^ (bc2 &^ bc1) + a[11] = bc1 ^ (bc3 &^ bc2) + a[2] = bc2 ^ (bc4 &^ bc3) + a[18] = bc3 ^ (bc0 &^ bc4) + a[9] = bc4 ^ (bc1 &^ bc0) + + t = a[15] ^ d0 + bc4 = t<<18 | t>>(64-18) + t = a[6] ^ d1 + bc0 = t<<1 | t>>(64-1) + t = a[22] ^ d2 + bc1 = t<<6 | t>>(64-6) + t = a[13] ^ d3 + bc2 = t<<25 | t>>(64-25) + t = a[4] ^ d4 + bc3 = t<<8 | t>>(64-8) + a[15] = bc0 ^ (bc2 &^ bc1) + a[6] = bc1 ^ (bc3 &^ bc2) + a[22] = bc2 ^ (bc4 &^ bc3) + a[13] = bc3 ^ (bc0 &^ bc4) + a[4] = bc4 ^ (bc1 &^ bc0) + + t = a[10] ^ d0 + bc1 = t<<36 | t>>(64-36) + t = a[1] ^ d1 + bc2 = t<<10 | t>>(64-10) + t = a[17] ^ d2 + bc3 = t<<15 | t>>(64-15) + t = a[8] ^ d3 + bc4 = t<<56 | t>>(64-56) + t = a[24] ^ d4 + bc0 = t<<27 | t>>(64-27) + a[10] = bc0 ^ (bc2 &^ bc1) + a[1] = bc1 ^ (bc3 &^ bc2) + a[17] = bc2 ^ (bc4 &^ bc3) + a[8] = bc3 ^ (bc0 &^ bc4) + a[24] = bc4 ^ (bc1 &^ bc0) + + t = a[5] ^ d0 + bc3 = t<<41 | t>>(64-41) + t = a[21] ^ d1 + bc4 = t<<2 | t>>(64-2) + t = a[12] ^ d2 + bc0 = t<<62 | t>>(64-62) + t = a[3] ^ d3 + bc1 = t<<55 | t>>(64-55) + t = a[19] ^ d4 + bc2 = t<<39 | t>>(64-39) + a[5] = bc0 ^ (bc2 &^ bc1) + a[21] = bc1 ^ (bc3 &^ bc2) + a[12] = bc2 ^ (bc4 &^ bc3) + a[3] = bc3 ^ (bc0 &^ bc4) + a[19] = bc4 ^ (bc1 &^ bc0) + + // Round 3 + bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] + bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] + bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] + bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] + bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] + d0 = bc4 ^ (bc1<<1 | bc1>>63) + d1 = bc0 ^ (bc2<<1 | bc2>>63) + d2 = bc1 ^ (bc3<<1 | bc3>>63) + d3 = bc2 ^ (bc4<<1 | bc4>>63) + d4 = bc3 ^ (bc0<<1 | bc0>>63) + + bc0 = a[0] ^ d0 + t = a[11] ^ d1 + bc1 = t<<44 | t>>(64-44) + t = a[22] ^ d2 + bc2 = t<<43 | t>>(64-43) + t = a[8] ^ d3 + bc3 = t<<21 | t>>(64-21) + t = a[19] ^ d4 + bc4 = t<<14 | t>>(64-14) + a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+2] + a[11] = bc1 ^ (bc3 &^ bc2) + a[22] = bc2 ^ (bc4 &^ bc3) + a[8] = bc3 ^ (bc0 &^ bc4) + a[19] = bc4 ^ (bc1 &^ bc0) + + t = a[15] ^ d0 + bc2 = t<<3 | t>>(64-3) + t = a[1] ^ d1 + bc3 = t<<45 | t>>(64-45) + t = a[12] ^ d2 + bc4 = t<<61 | t>>(64-61) + t = a[23] ^ d3 + bc0 = t<<28 | t>>(64-28) + t = a[9] ^ d4 + bc1 = t<<20 | t>>(64-20) + a[15] = bc0 ^ (bc2 &^ bc1) + a[1] = bc1 ^ (bc3 &^ bc2) + a[12] = bc2 ^ (bc4 &^ bc3) + a[23] = bc3 ^ (bc0 &^ bc4) + a[9] = bc4 ^ (bc1 &^ bc0) + + t = a[5] ^ d0 + bc4 = t<<18 | t>>(64-18) + t = a[16] ^ d1 + bc0 = t<<1 | t>>(64-1) + t = a[2] ^ d2 + bc1 = t<<6 | t>>(64-6) + t = a[13] ^ d3 + bc2 = t<<25 | t>>(64-25) + t = a[24] ^ d4 + bc3 = t<<8 | t>>(64-8) + a[5] = bc0 ^ (bc2 &^ bc1) + a[16] = bc1 ^ (bc3 &^ bc2) + a[2] = bc2 ^ (bc4 &^ bc3) + a[13] = bc3 ^ (bc0 &^ bc4) + a[24] = bc4 ^ (bc1 &^ bc0) + + t = a[20] ^ d0 + bc1 = t<<36 | t>>(64-36) + t = a[6] ^ d1 + bc2 = t<<10 | t>>(64-10) + t = a[17] ^ d2 + bc3 = t<<15 | t>>(64-15) + t = a[3] ^ d3 + bc4 = t<<56 | t>>(64-56) + t = a[14] ^ d4 + bc0 = t<<27 | t>>(64-27) + a[20] = bc0 ^ (bc2 &^ bc1) + a[6] = bc1 ^ (bc3 &^ bc2) + a[17] = bc2 ^ (bc4 &^ bc3) + a[3] = bc3 ^ (bc0 &^ bc4) + a[14] = bc4 ^ (bc1 &^ bc0) + + t = a[10] ^ d0 + bc3 = t<<41 | t>>(64-41) + t = a[21] ^ d1 + bc4 = t<<2 | t>>(64-2) + t = a[7] ^ d2 + bc0 = t<<62 | t>>(64-62) + t = a[18] ^ d3 + bc1 = t<<55 | t>>(64-55) + t = a[4] ^ d4 + bc2 = t<<39 | t>>(64-39) + a[10] = bc0 ^ (bc2 &^ bc1) + a[21] = bc1 ^ (bc3 &^ bc2) + a[7] = bc2 ^ (bc4 &^ bc3) + a[18] = bc3 ^ (bc0 &^ bc4) + a[4] = bc4 ^ (bc1 &^ bc0) + + // Round 4 + bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] + bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] + bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] + bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] + bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] + d0 = bc4 ^ (bc1<<1 | bc1>>63) + d1 = bc0 ^ (bc2<<1 | bc2>>63) + d2 = bc1 ^ (bc3<<1 | bc3>>63) + d3 = bc2 ^ (bc4<<1 | bc4>>63) + d4 = bc3 ^ (bc0<<1 | bc0>>63) + + bc0 = a[0] ^ d0 + t = a[1] ^ d1 + bc1 = t<<44 | t>>(64-44) + t = a[2] ^ d2 + bc2 = t<<43 | t>>(64-43) + t = a[3] ^ d3 + bc3 = t<<21 | t>>(64-21) + t = a[4] ^ d4 + bc4 = t<<14 | t>>(64-14) + a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+3] + a[1] = bc1 ^ (bc3 &^ bc2) + a[2] = bc2 ^ (bc4 &^ bc3) + a[3] = bc3 ^ (bc0 &^ bc4) + a[4] = bc4 ^ (bc1 &^ bc0) + + t = a[5] ^ d0 + bc2 = t<<3 | t>>(64-3) + t = a[6] ^ d1 + bc3 = t<<45 | t>>(64-45) + t = a[7] ^ d2 + bc4 = t<<61 | t>>(64-61) + t = a[8] ^ d3 + bc0 = t<<28 | t>>(64-28) + t = a[9] ^ d4 + bc1 = t<<20 | t>>(64-20) + a[5] = bc0 ^ (bc2 &^ bc1) + a[6] = bc1 ^ (bc3 &^ bc2) + a[7] = bc2 ^ (bc4 &^ bc3) + a[8] = bc3 ^ (bc0 &^ bc4) + a[9] = bc4 ^ (bc1 &^ bc0) + + t = a[10] ^ d0 + bc4 = t<<18 | t>>(64-18) + t = a[11] ^ d1 + bc0 = t<<1 | t>>(64-1) + t = a[12] ^ d2 + bc1 = t<<6 | t>>(64-6) + t = a[13] ^ d3 + bc2 = t<<25 | t>>(64-25) + t = a[14] ^ d4 + bc3 = t<<8 | t>>(64-8) + a[10] = bc0 ^ (bc2 &^ bc1) + a[11] = bc1 ^ (bc3 &^ bc2) + a[12] = bc2 ^ (bc4 &^ bc3) + a[13] = bc3 ^ (bc0 &^ bc4) + a[14] = bc4 ^ (bc1 &^ bc0) + + t = a[15] ^ d0 + bc1 = t<<36 | t>>(64-36) + t = a[16] ^ d1 + bc2 = t<<10 | t>>(64-10) + t = a[17] ^ d2 + bc3 = t<<15 | t>>(64-15) + t = a[18] ^ d3 + bc4 = t<<56 | t>>(64-56) + t = a[19] ^ d4 + bc0 = t<<27 | t>>(64-27) + a[15] = bc0 ^ (bc2 &^ bc1) + a[16] = bc1 ^ (bc3 &^ bc2) + a[17] = bc2 ^ (bc4 &^ bc3) + a[18] = bc3 ^ (bc0 &^ bc4) + a[19] = bc4 ^ (bc1 &^ bc0) + + t = a[20] ^ d0 + bc3 = t<<41 | t>>(64-41) + t = a[21] ^ d1 + bc4 = t<<2 | t>>(64-2) + t = a[22] ^ d2 + bc0 = t<<62 | t>>(64-62) + t = a[23] ^ d3 + bc1 = t<<55 | t>>(64-55) + t = a[24] ^ d4 + bc2 = t<<39 | t>>(64-39) + a[20] = bc0 ^ (bc2 &^ bc1) + a[21] = bc1 ^ (bc3 &^ bc2) + a[22] = bc2 ^ (bc4 &^ bc3) + a[23] = bc3 ^ (bc0 &^ bc4) + a[24] = bc4 ^ (bc1 &^ bc0) + } +} diff --git a/vendor/golang.org/x/crypto/sha3/keccakf_amd64.go b/vendor/golang.org/x/crypto/sha3/keccakf_amd64.go new file mode 100644 index 0000000000000000000000000000000000000000..788679585027f8573cee4cc3d2afd5d8e2cdb8ad --- /dev/null +++ b/vendor/golang.org/x/crypto/sha3/keccakf_amd64.go @@ -0,0 +1,13 @@ +// Copyright 2015 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,!appengine,!gccgo + +package sha3 + +// This function is implemented in keccakf_amd64.s. + +//go:noescape + +func keccakF1600(a *[25]uint64) diff --git a/vendor/golang.org/x/crypto/sha3/keccakf_amd64.s b/vendor/golang.org/x/crypto/sha3/keccakf_amd64.s new file mode 100644 index 0000000000000000000000000000000000000000..f88533accd446f7176d2076e7b868ccd7718b7ba --- /dev/null +++ b/vendor/golang.org/x/crypto/sha3/keccakf_amd64.s @@ -0,0 +1,390 @@ +// Copyright 2015 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,!appengine,!gccgo + +// This code was translated into a form compatible with 6a from the public +// domain sources at https://github.com/gvanas/KeccakCodePackage + +// Offsets in state +#define _ba (0*8) +#define _be (1*8) +#define _bi (2*8) +#define _bo (3*8) +#define _bu (4*8) +#define _ga (5*8) +#define _ge (6*8) +#define _gi (7*8) +#define _go (8*8) +#define _gu (9*8) +#define _ka (10*8) +#define _ke (11*8) +#define _ki (12*8) +#define _ko (13*8) +#define _ku (14*8) +#define _ma (15*8) +#define _me (16*8) +#define _mi (17*8) +#define _mo (18*8) +#define _mu (19*8) +#define _sa (20*8) +#define _se (21*8) +#define _si (22*8) +#define _so (23*8) +#define _su (24*8) + +// Temporary registers +#define rT1 AX + +// Round vars +#define rpState DI +#define rpStack SP + +#define rDa BX +#define rDe CX +#define rDi DX +#define rDo R8 +#define rDu R9 + +#define rBa R10 +#define rBe R11 +#define rBi R12 +#define rBo R13 +#define rBu R14 + +#define rCa SI +#define rCe BP +#define rCi rBi +#define rCo rBo +#define rCu R15 + +#define MOVQ_RBI_RCE MOVQ rBi, rCe +#define XORQ_RT1_RCA XORQ rT1, rCa +#define XORQ_RT1_RCE XORQ rT1, rCe +#define XORQ_RBA_RCU XORQ rBa, rCu +#define XORQ_RBE_RCU XORQ rBe, rCu +#define XORQ_RDU_RCU XORQ rDu, rCu +#define XORQ_RDA_RCA XORQ rDa, rCa +#define XORQ_RDE_RCE XORQ rDe, rCe + +#define mKeccakRound(iState, oState, rc, B_RBI_RCE, G_RT1_RCA, G_RT1_RCE, G_RBA_RCU, K_RT1_RCA, K_RT1_RCE, K_RBA_RCU, M_RT1_RCA, M_RT1_RCE, M_RBE_RCU, S_RDU_RCU, S_RDA_RCA, S_RDE_RCE) \ + /* Prepare round */ \ + MOVQ rCe, rDa; \ + ROLQ $1, rDa; \ + \ + MOVQ _bi(iState), rCi; \ + XORQ _gi(iState), rDi; \ + XORQ rCu, rDa; \ + XORQ _ki(iState), rCi; \ + XORQ _mi(iState), rDi; \ + XORQ rDi, rCi; \ + \ + MOVQ rCi, rDe; \ + ROLQ $1, rDe; \ + \ + MOVQ _bo(iState), rCo; \ + XORQ _go(iState), rDo; \ + XORQ rCa, rDe; \ + XORQ _ko(iState), rCo; \ + XORQ _mo(iState), rDo; \ + XORQ rDo, rCo; \ + \ + MOVQ rCo, rDi; \ + ROLQ $1, rDi; \ + \ + MOVQ rCu, rDo; \ + XORQ rCe, rDi; \ + ROLQ $1, rDo; \ + \ + MOVQ rCa, rDu; \ + XORQ rCi, rDo; \ + ROLQ $1, rDu; \ + \ + /* Result b */ \ + MOVQ _ba(iState), rBa; \ + MOVQ _ge(iState), rBe; \ + XORQ rCo, rDu; \ + MOVQ _ki(iState), rBi; \ + MOVQ _mo(iState), rBo; \ + MOVQ _su(iState), rBu; \ + XORQ rDe, rBe; \ + ROLQ $44, rBe; \ + XORQ rDi, rBi; \ + XORQ rDa, rBa; \ + ROLQ $43, rBi; \ + \ + MOVQ rBe, rCa; \ + MOVQ rc, rT1; \ + ORQ rBi, rCa; \ + XORQ rBa, rT1; \ + XORQ rT1, rCa; \ + MOVQ rCa, _ba(oState); \ + \ + XORQ rDu, rBu; \ + ROLQ $14, rBu; \ + MOVQ rBa, rCu; \ + ANDQ rBe, rCu; \ + XORQ rBu, rCu; \ + MOVQ rCu, _bu(oState); \ + \ + XORQ rDo, rBo; \ + ROLQ $21, rBo; \ + MOVQ rBo, rT1; \ + ANDQ rBu, rT1; \ + XORQ rBi, rT1; \ + MOVQ rT1, _bi(oState); \ + \ + NOTQ rBi; \ + ORQ rBa, rBu; \ + ORQ rBo, rBi; \ + XORQ rBo, rBu; \ + XORQ rBe, rBi; \ + MOVQ rBu, _bo(oState); \ + MOVQ rBi, _be(oState); \ + B_RBI_RCE; \ + \ + /* Result g */ \ + MOVQ _gu(iState), rBe; \ + XORQ rDu, rBe; \ + MOVQ _ka(iState), rBi; \ + ROLQ $20, rBe; \ + XORQ rDa, rBi; \ + ROLQ $3, rBi; \ + MOVQ _bo(iState), rBa; \ + MOVQ rBe, rT1; \ + ORQ rBi, rT1; \ + XORQ rDo, rBa; \ + MOVQ _me(iState), rBo; \ + MOVQ _si(iState), rBu; \ + ROLQ $28, rBa; \ + XORQ rBa, rT1; \ + MOVQ rT1, _ga(oState); \ + G_RT1_RCA; \ + \ + XORQ rDe, rBo; \ + ROLQ $45, rBo; \ + MOVQ rBi, rT1; \ + ANDQ rBo, rT1; \ + XORQ rBe, rT1; \ + MOVQ rT1, _ge(oState); \ + G_RT1_RCE; \ + \ + XORQ rDi, rBu; \ + ROLQ $61, rBu; \ + MOVQ rBu, rT1; \ + ORQ rBa, rT1; \ + XORQ rBo, rT1; \ + MOVQ rT1, _go(oState); \ + \ + ANDQ rBe, rBa; \ + XORQ rBu, rBa; \ + MOVQ rBa, _gu(oState); \ + NOTQ rBu; \ + G_RBA_RCU; \ + \ + ORQ rBu, rBo; \ + XORQ rBi, rBo; \ + MOVQ rBo, _gi(oState); \ + \ + /* Result k */ \ + MOVQ _be(iState), rBa; \ + MOVQ _gi(iState), rBe; \ + MOVQ _ko(iState), rBi; \ + MOVQ _mu(iState), rBo; \ + MOVQ _sa(iState), rBu; \ + XORQ rDi, rBe; \ + ROLQ $6, rBe; \ + XORQ rDo, rBi; \ + ROLQ $25, rBi; \ + MOVQ rBe, rT1; \ + ORQ rBi, rT1; \ + XORQ rDe, rBa; \ + ROLQ $1, rBa; \ + XORQ rBa, rT1; \ + MOVQ rT1, _ka(oState); \ + K_RT1_RCA; \ + \ + XORQ rDu, rBo; \ + ROLQ $8, rBo; \ + MOVQ rBi, rT1; \ + ANDQ rBo, rT1; \ + XORQ rBe, rT1; \ + MOVQ rT1, _ke(oState); \ + K_RT1_RCE; \ + \ + XORQ rDa, rBu; \ + ROLQ $18, rBu; \ + NOTQ rBo; \ + MOVQ rBo, rT1; \ + ANDQ rBu, rT1; \ + XORQ rBi, rT1; \ + MOVQ rT1, _ki(oState); \ + \ + MOVQ rBu, rT1; \ + ORQ rBa, rT1; \ + XORQ rBo, rT1; \ + MOVQ rT1, _ko(oState); \ + \ + ANDQ rBe, rBa; \ + XORQ rBu, rBa; \ + MOVQ rBa, _ku(oState); \ + K_RBA_RCU; \ + \ + /* Result m */ \ + MOVQ _ga(iState), rBe; \ + XORQ rDa, rBe; \ + MOVQ _ke(iState), rBi; \ + ROLQ $36, rBe; \ + XORQ rDe, rBi; \ + MOVQ _bu(iState), rBa; \ + ROLQ $10, rBi; \ + MOVQ rBe, rT1; \ + MOVQ _mi(iState), rBo; \ + ANDQ rBi, rT1; \ + XORQ rDu, rBa; \ + MOVQ _so(iState), rBu; \ + ROLQ $27, rBa; \ + XORQ rBa, rT1; \ + MOVQ rT1, _ma(oState); \ + M_RT1_RCA; \ + \ + XORQ rDi, rBo; \ + ROLQ $15, rBo; \ + MOVQ rBi, rT1; \ + ORQ rBo, rT1; \ + XORQ rBe, rT1; \ + MOVQ rT1, _me(oState); \ + M_RT1_RCE; \ + \ + XORQ rDo, rBu; \ + ROLQ $56, rBu; \ + NOTQ rBo; \ + MOVQ rBo, rT1; \ + ORQ rBu, rT1; \ + XORQ rBi, rT1; \ + MOVQ rT1, _mi(oState); \ + \ + ORQ rBa, rBe; \ + XORQ rBu, rBe; \ + MOVQ rBe, _mu(oState); \ + \ + ANDQ rBa, rBu; \ + XORQ rBo, rBu; \ + MOVQ rBu, _mo(oState); \ + M_RBE_RCU; \ + \ + /* Result s */ \ + MOVQ _bi(iState), rBa; \ + MOVQ _go(iState), rBe; \ + MOVQ _ku(iState), rBi; \ + XORQ rDi, rBa; \ + MOVQ _ma(iState), rBo; \ + ROLQ $62, rBa; \ + XORQ rDo, rBe; \ + MOVQ _se(iState), rBu; \ + ROLQ $55, rBe; \ + \ + XORQ rDu, rBi; \ + MOVQ rBa, rDu; \ + XORQ rDe, rBu; \ + ROLQ $2, rBu; \ + ANDQ rBe, rDu; \ + XORQ rBu, rDu; \ + MOVQ rDu, _su(oState); \ + \ + ROLQ $39, rBi; \ + S_RDU_RCU; \ + NOTQ rBe; \ + XORQ rDa, rBo; \ + MOVQ rBe, rDa; \ + ANDQ rBi, rDa; \ + XORQ rBa, rDa; \ + MOVQ rDa, _sa(oState); \ + S_RDA_RCA; \ + \ + ROLQ $41, rBo; \ + MOVQ rBi, rDe; \ + ORQ rBo, rDe; \ + XORQ rBe, rDe; \ + MOVQ rDe, _se(oState); \ + S_RDE_RCE; \ + \ + MOVQ rBo, rDi; \ + MOVQ rBu, rDo; \ + ANDQ rBu, rDi; \ + ORQ rBa, rDo; \ + XORQ rBi, rDi; \ + XORQ rBo, rDo; \ + MOVQ rDi, _si(oState); \ + MOVQ rDo, _so(oState) \ + +// func keccakF1600(state *[25]uint64) +TEXT ·keccakF1600(SB), 0, $200-8 + MOVQ state+0(FP), rpState + + // Convert the user state into an internal state + NOTQ _be(rpState) + NOTQ _bi(rpState) + NOTQ _go(rpState) + NOTQ _ki(rpState) + NOTQ _mi(rpState) + NOTQ _sa(rpState) + + // Execute the KeccakF permutation + MOVQ _ba(rpState), rCa + MOVQ _be(rpState), rCe + MOVQ _bu(rpState), rCu + + XORQ _ga(rpState), rCa + XORQ _ge(rpState), rCe + XORQ _gu(rpState), rCu + + XORQ _ka(rpState), rCa + XORQ _ke(rpState), rCe + XORQ _ku(rpState), rCu + + XORQ _ma(rpState), rCa + XORQ _me(rpState), rCe + XORQ _mu(rpState), rCu + + XORQ _sa(rpState), rCa + XORQ _se(rpState), rCe + MOVQ _si(rpState), rDi + MOVQ _so(rpState), rDo + XORQ _su(rpState), rCu + + mKeccakRound(rpState, rpStack, $0x0000000000000001, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpStack, rpState, $0x0000000000008082, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpState, rpStack, $0x800000000000808a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpStack, rpState, $0x8000000080008000, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpState, rpStack, $0x000000000000808b, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpStack, rpState, $0x0000000080000001, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpState, rpStack, $0x8000000080008081, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpStack, rpState, $0x8000000000008009, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpState, rpStack, $0x000000000000008a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpStack, rpState, $0x0000000000000088, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpState, rpStack, $0x0000000080008009, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpStack, rpState, $0x000000008000000a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpState, rpStack, $0x000000008000808b, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpStack, rpState, $0x800000000000008b, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpState, rpStack, $0x8000000000008089, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpStack, rpState, $0x8000000000008003, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpState, rpStack, $0x8000000000008002, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpStack, rpState, $0x8000000000000080, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpState, rpStack, $0x000000000000800a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpStack, rpState, $0x800000008000000a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpState, rpStack, $0x8000000080008081, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpStack, rpState, $0x8000000000008080, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpState, rpStack, $0x0000000080000001, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpStack, rpState, $0x8000000080008008, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP) + + // Revert the internal state to the user state + NOTQ _be(rpState) + NOTQ _bi(rpState) + NOTQ _go(rpState) + NOTQ _ki(rpState) + NOTQ _mi(rpState) + NOTQ _sa(rpState) + + RET diff --git a/vendor/golang.org/x/crypto/sha3/register.go b/vendor/golang.org/x/crypto/sha3/register.go new file mode 100644 index 0000000000000000000000000000000000000000..3cf6a22e093ad380057828362461062268b35101 --- /dev/null +++ b/vendor/golang.org/x/crypto/sha3/register.go @@ -0,0 +1,18 @@ +// 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. + +// +build go1.4 + +package sha3 + +import ( + "crypto" +) + +func init() { + crypto.RegisterHash(crypto.SHA3_224, New224) + crypto.RegisterHash(crypto.SHA3_256, New256) + crypto.RegisterHash(crypto.SHA3_384, New384) + crypto.RegisterHash(crypto.SHA3_512, New512) +} diff --git a/vendor/golang.org/x/crypto/sha3/sha3.go b/vendor/golang.org/x/crypto/sha3/sha3.go new file mode 100644 index 0000000000000000000000000000000000000000..b12a35c87fc89befdb8a76272647b5600b4c80fe --- /dev/null +++ b/vendor/golang.org/x/crypto/sha3/sha3.go @@ -0,0 +1,192 @@ +// 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 sha3 + +// spongeDirection indicates the direction bytes are flowing through the sponge. +type spongeDirection int + +const ( + // spongeAbsorbing indicates that the sponge is absorbing input. + spongeAbsorbing spongeDirection = iota + // spongeSqueezing indicates that the sponge is being squeezed. + spongeSqueezing +) + +const ( + // maxRate is the maximum size of the internal buffer. SHAKE-256 + // currently needs the largest buffer. + maxRate = 168 +) + +type state struct { + // Generic sponge components. + a [25]uint64 // main state of the hash + buf []byte // points into storage + rate int // the number of bytes of state to use + + // dsbyte contains the "domain separation" bits and the first bit of + // the padding. Sections 6.1 and 6.2 of [1] separate the outputs of the + // SHA-3 and SHAKE functions by appending bitstrings to the message. + // Using a little-endian bit-ordering convention, these are "01" for SHA-3 + // and "1111" for SHAKE, or 00000010b and 00001111b, respectively. Then the + // padding rule from section 5.1 is applied to pad the message to a multiple + // of the rate, which involves adding a "1" bit, zero or more "0" bits, and + // a final "1" bit. We merge the first "1" bit from the padding into dsbyte, + // giving 00000110b (0x06) and 00011111b (0x1f). + // [1] http://csrc.nist.gov/publications/drafts/fips-202/fips_202_draft.pdf + // "Draft FIPS 202: SHA-3 Standard: Permutation-Based Hash and + // Extendable-Output Functions (May 2014)" + dsbyte byte + storage [maxRate]byte + + // Specific to SHA-3 and SHAKE. + outputLen int // the default output size in bytes + state spongeDirection // whether the sponge is absorbing or squeezing +} + +// BlockSize returns the rate of sponge underlying this hash function. +func (d *state) BlockSize() int { return d.rate } + +// Size returns the output size of the hash function in bytes. +func (d *state) Size() int { return d.outputLen } + +// Reset clears the internal state by zeroing the sponge state and +// the byte buffer, and setting Sponge.state to absorbing. +func (d *state) Reset() { + // Zero the permutation's state. + for i := range d.a { + d.a[i] = 0 + } + d.state = spongeAbsorbing + d.buf = d.storage[:0] +} + +func (d *state) clone() *state { + ret := *d + if ret.state == spongeAbsorbing { + ret.buf = ret.storage[:len(ret.buf)] + } else { + ret.buf = ret.storage[d.rate-cap(d.buf) : d.rate] + } + + return &ret +} + +// permute applies the KeccakF-1600 permutation. It handles +// any input-output buffering. +func (d *state) permute() { + switch d.state { + case spongeAbsorbing: + // If we're absorbing, we need to xor the input into the state + // before applying the permutation. + xorIn(d, d.buf) + d.buf = d.storage[:0] + keccakF1600(&d.a) + case spongeSqueezing: + // If we're squeezing, we need to apply the permutatin before + // copying more output. + keccakF1600(&d.a) + d.buf = d.storage[:d.rate] + copyOut(d, d.buf) + } +} + +// pads appends the domain separation bits in dsbyte, applies +// the multi-bitrate 10..1 padding rule, and permutes the state. +func (d *state) padAndPermute(dsbyte byte) { + if d.buf == nil { + d.buf = d.storage[:0] + } + // Pad with this instance's domain-separator bits. We know that there's + // at least one byte of space in d.buf because, if it were full, + // permute would have been called to empty it. dsbyte also contains the + // first one bit for the padding. See the comment in the state struct. + d.buf = append(d.buf, dsbyte) + zerosStart := len(d.buf) + d.buf = d.storage[:d.rate] + for i := zerosStart; i < d.rate; i++ { + d.buf[i] = 0 + } + // This adds the final one bit for the padding. Because of the way that + // bits are numbered from the LSB upwards, the final bit is the MSB of + // the last byte. + d.buf[d.rate-1] ^= 0x80 + // Apply the permutation + d.permute() + d.state = spongeSqueezing + d.buf = d.storage[:d.rate] + copyOut(d, d.buf) +} + +// Write absorbs more data into the hash's state. It produces an error +// if more data is written to the ShakeHash after writing +func (d *state) Write(p []byte) (written int, err error) { + if d.state != spongeAbsorbing { + panic("sha3: write to sponge after read") + } + if d.buf == nil { + d.buf = d.storage[:0] + } + written = len(p) + + for len(p) > 0 { + if len(d.buf) == 0 && len(p) >= d.rate { + // The fast path; absorb a full "rate" bytes of input and apply the permutation. + xorIn(d, p[:d.rate]) + p = p[d.rate:] + keccakF1600(&d.a) + } else { + // The slow path; buffer the input until we can fill the sponge, and then xor it in. + todo := d.rate - len(d.buf) + if todo > len(p) { + todo = len(p) + } + d.buf = append(d.buf, p[:todo]...) + p = p[todo:] + + // If the sponge is full, apply the permutation. + if len(d.buf) == d.rate { + d.permute() + } + } + } + + return +} + +// Read squeezes an arbitrary number of bytes from the sponge. +func (d *state) Read(out []byte) (n int, err error) { + // If we're still absorbing, pad and apply the permutation. + if d.state == spongeAbsorbing { + d.padAndPermute(d.dsbyte) + } + + n = len(out) + + // Now, do the squeezing. + for len(out) > 0 { + n := copy(out, d.buf) + d.buf = d.buf[n:] + out = out[n:] + + // Apply the permutation if we've squeezed the sponge dry. + if len(d.buf) == 0 { + d.permute() + } + } + + return +} + +// Sum applies padding to the hash state and then squeezes out the desired +// number of output bytes. +func (d *state) Sum(in []byte) []byte { + // Make a copy of the original hash so that caller can keep writing + // and summing. + dup := d.clone() + hash := make([]byte, dup.outputLen) + dup.Read(hash) + return append(in, hash...) +} diff --git a/vendor/golang.org/x/crypto/sha3/sha3_test.go b/vendor/golang.org/x/crypto/sha3/sha3_test.go new file mode 100644 index 0000000000000000000000000000000000000000..2c8719b443a34452a62cf60fe6d55bd6fbdd03a9 --- /dev/null +++ b/vendor/golang.org/x/crypto/sha3/sha3_test.go @@ -0,0 +1,311 @@ +// 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 sha3 + +// Tests include all the ShortMsgKATs provided by the Keccak team at +// https://github.com/gvanas/KeccakCodePackage +// +// They only include the zero-bit case of the bitwise testvectors +// published by NIST in the draft of FIPS-202. + +import ( + "bytes" + "compress/flate" + "encoding/hex" + "encoding/json" + "fmt" + "hash" + "os" + "strings" + "testing" +) + +const ( + testString = "brekeccakkeccak koax koax" + katFilename = "testdata/keccakKats.json.deflate" +) + +// Internal-use instances of SHAKE used to test against KATs. +func newHashShake128() hash.Hash { + return &state{rate: 168, dsbyte: 0x1f, outputLen: 512} +} +func newHashShake256() hash.Hash { + return &state{rate: 136, dsbyte: 0x1f, outputLen: 512} +} + +// testDigests contains functions returning hash.Hash instances +// with output-length equal to the KAT length for both SHA-3 and +// SHAKE instances. +var testDigests = map[string]func() hash.Hash{ + "SHA3-224": New224, + "SHA3-256": New256, + "SHA3-384": New384, + "SHA3-512": New512, + "SHAKE128": newHashShake128, + "SHAKE256": newHashShake256, +} + +// testShakes contains functions that return ShakeHash instances for +// testing the ShakeHash-specific interface. +var testShakes = map[string]func() ShakeHash{ + "SHAKE128": NewShake128, + "SHAKE256": NewShake256, +} + +// decodeHex converts a hex-encoded string into a raw byte string. +func decodeHex(s string) []byte { + b, err := hex.DecodeString(s) + if err != nil { + panic(err) + } + return b +} + +// structs used to marshal JSON test-cases. +type KeccakKats struct { + Kats map[string][]struct { + Digest string `json:"digest"` + Length int64 `json:"length"` + Message string `json:"message"` + } +} + +func testUnalignedAndGeneric(t *testing.T, testf func(impl string)) { + xorInOrig, copyOutOrig := xorIn, copyOut + xorIn, copyOut = xorInGeneric, copyOutGeneric + testf("generic") + if xorImplementationUnaligned != "generic" { + xorIn, copyOut = xorInUnaligned, copyOutUnaligned + testf("unaligned") + } + xorIn, copyOut = xorInOrig, copyOutOrig +} + +// TestKeccakKats tests the SHA-3 and Shake implementations against all the +// ShortMsgKATs from https://github.com/gvanas/KeccakCodePackage +// (The testvectors are stored in keccakKats.json.deflate due to their length.) +func TestKeccakKats(t *testing.T) { + testUnalignedAndGeneric(t, func(impl string) { + // Read the KATs. + deflated, err := os.Open(katFilename) + if err != nil { + t.Errorf("error opening %s: %s", katFilename, err) + } + file := flate.NewReader(deflated) + dec := json.NewDecoder(file) + var katSet KeccakKats + err = dec.Decode(&katSet) + if err != nil { + t.Errorf("error decoding KATs: %s", err) + } + + // Do the KATs. + for functionName, kats := range katSet.Kats { + d := testDigests[functionName]() + for _, kat := range kats { + d.Reset() + in, err := hex.DecodeString(kat.Message) + if err != nil { + t.Errorf("error decoding KAT: %s", err) + } + d.Write(in[:kat.Length/8]) + got := strings.ToUpper(hex.EncodeToString(d.Sum(nil))) + if got != kat.Digest { + t.Errorf("function=%s, implementation=%s, length=%d\nmessage:\n %s\ngot:\n %s\nwanted:\n %s", + functionName, impl, kat.Length, kat.Message, got, kat.Digest) + t.Logf("wanted %+v", kat) + t.FailNow() + } + continue + } + } + }) +} + +// TestUnalignedWrite tests that writing data in an arbitrary pattern with +// small input buffers. +func testUnalignedWrite(t *testing.T) { + testUnalignedAndGeneric(t, func(impl string) { + buf := sequentialBytes(0x10000) + for alg, df := range testDigests { + d := df() + d.Reset() + d.Write(buf) + want := d.Sum(nil) + d.Reset() + for i := 0; i < len(buf); { + // Cycle through offsets which make a 137 byte sequence. + // Because 137 is prime this sequence should exercise all corner cases. + offsets := [17]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1} + for _, j := range offsets { + if v := len(buf) - i; v < j { + j = v + } + d.Write(buf[i : i+j]) + i += j + } + } + got := d.Sum(nil) + if !bytes.Equal(got, want) { + t.Errorf("Unaligned writes, implementation=%s, alg=%s\ngot %q, want %q", impl, alg, got, want) + } + } + }) +} + +// TestAppend checks that appending works when reallocation is necessary. +func TestAppend(t *testing.T) { + testUnalignedAndGeneric(t, func(impl string) { + d := New224() + + for capacity := 2; capacity <= 66; capacity += 64 { + // The first time around the loop, Sum will have to reallocate. + // The second time, it will not. + buf := make([]byte, 2, capacity) + d.Reset() + d.Write([]byte{0xcc}) + buf = d.Sum(buf) + expected := "0000DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39" + if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected { + t.Errorf("got %s, want %s", got, expected) + } + } + }) +} + +// TestAppendNoRealloc tests that appending works when no reallocation is necessary. +func TestAppendNoRealloc(t *testing.T) { + testUnalignedAndGeneric(t, func(impl string) { + buf := make([]byte, 1, 200) + d := New224() + d.Write([]byte{0xcc}) + buf = d.Sum(buf) + expected := "00DF70ADC49B2E76EEE3A6931B93FA41841C3AF2CDF5B32A18B5478C39" + if got := strings.ToUpper(hex.EncodeToString(buf)); got != expected { + t.Errorf("%s: got %s, want %s", impl, got, expected) + } + }) +} + +// TestSqueezing checks that squeezing the full output a single time produces +// the same output as repeatedly squeezing the instance. +func TestSqueezing(t *testing.T) { + testUnalignedAndGeneric(t, func(impl string) { + for functionName, newShakeHash := range testShakes { + d0 := newShakeHash() + d0.Write([]byte(testString)) + ref := make([]byte, 32) + d0.Read(ref) + + d1 := newShakeHash() + d1.Write([]byte(testString)) + var multiple []byte + for range ref { + one := make([]byte, 1) + d1.Read(one) + multiple = append(multiple, one...) + } + if !bytes.Equal(ref, multiple) { + t.Errorf("%s (%s): squeezing %d bytes one at a time failed", functionName, impl, len(ref)) + } + } + }) +} + +// sequentialBytes produces a buffer of size consecutive bytes 0x00, 0x01, ..., used for testing. +func sequentialBytes(size int) []byte { + result := make([]byte, size) + for i := range result { + result[i] = byte(i) + } + return result +} + +// BenchmarkPermutationFunction measures the speed of the permutation function +// with no input data. +func BenchmarkPermutationFunction(b *testing.B) { + b.SetBytes(int64(200)) + var lanes [25]uint64 + for i := 0; i < b.N; i++ { + keccakF1600(&lanes) + } +} + +// benchmarkHash tests the speed to hash num buffers of buflen each. +func benchmarkHash(b *testing.B, h hash.Hash, size, num int) { + b.StopTimer() + h.Reset() + data := sequentialBytes(size) + b.SetBytes(int64(size * num)) + b.StartTimer() + + var state []byte + for i := 0; i < b.N; i++ { + for j := 0; j < num; j++ { + h.Write(data) + } + state = h.Sum(state[:0]) + } + b.StopTimer() + h.Reset() +} + +// benchmarkShake is specialized to the Shake instances, which don't +// require a copy on reading output. +func benchmarkShake(b *testing.B, h ShakeHash, size, num int) { + b.StopTimer() + h.Reset() + data := sequentialBytes(size) + d := make([]byte, 32) + + b.SetBytes(int64(size * num)) + b.StartTimer() + + for i := 0; i < b.N; i++ { + h.Reset() + for j := 0; j < num; j++ { + h.Write(data) + } + h.Read(d) + } +} + +func BenchmarkSha3_512_MTU(b *testing.B) { benchmarkHash(b, New512(), 1350, 1) } +func BenchmarkSha3_384_MTU(b *testing.B) { benchmarkHash(b, New384(), 1350, 1) } +func BenchmarkSha3_256_MTU(b *testing.B) { benchmarkHash(b, New256(), 1350, 1) } +func BenchmarkSha3_224_MTU(b *testing.B) { benchmarkHash(b, New224(), 1350, 1) } + +func BenchmarkShake128_MTU(b *testing.B) { benchmarkShake(b, NewShake128(), 1350, 1) } +func BenchmarkShake256_MTU(b *testing.B) { benchmarkShake(b, NewShake256(), 1350, 1) } +func BenchmarkShake256_16x(b *testing.B) { benchmarkShake(b, NewShake256(), 16, 1024) } +func BenchmarkShake256_1MiB(b *testing.B) { benchmarkShake(b, NewShake256(), 1024, 1024) } + +func BenchmarkSha3_512_1MiB(b *testing.B) { benchmarkHash(b, New512(), 1024, 1024) } + +func Example_sum() { + buf := []byte("some data to hash") + // A hash needs to be 64 bytes long to have 256-bit collision resistance. + h := make([]byte, 64) + // Compute a 64-byte hash of buf and put it in h. + ShakeSum256(h, buf) + fmt.Printf("%x\n", h) + // Output: 0f65fe41fc353e52c55667bb9e2b27bfcc8476f2c413e9437d272ee3194a4e3146d05ec04a25d16b8f577c19b82d16b1424c3e022e783d2b4da98de3658d363d +} + +func Example_mac() { + k := []byte("this is a secret key; you should generate a strong random key that's at least 32 bytes long") + buf := []byte("and this is some data to authenticate") + // A MAC with 32 bytes of output has 256-bit security strength -- if you use at least a 32-byte-long key. + h := make([]byte, 32) + d := NewShake256() + // Write the key into the hash. + d.Write(k) + // Now write the data. + d.Write(buf) + // Read 32 bytes of output from the hash into h. + d.Read(h) + fmt.Printf("%x\n", h) + // Output: 78de2974bd2711d5549ffd32b753ef0f5fa80a0db2556db60f0987eb8a9218ff +} diff --git a/vendor/golang.org/x/crypto/sha3/shake.go b/vendor/golang.org/x/crypto/sha3/shake.go new file mode 100644 index 0000000000000000000000000000000000000000..841f9860f031e92cc10d21be0bdabc1a40ab9f68 --- /dev/null +++ b/vendor/golang.org/x/crypto/sha3/shake.go @@ -0,0 +1,60 @@ +// 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 sha3 + +// This file defines the ShakeHash interface, and provides +// functions for creating SHAKE instances, as well as utility +// functions for hashing bytes to arbitrary-length output. + +import ( + "io" +) + +// ShakeHash defines the interface to hash functions that +// support arbitrary-length output. +type ShakeHash interface { + // Write absorbs more data into the hash's state. It panics if input is + // written to it after output has been read from it. + io.Writer + + // Read reads more output from the hash; reading affects the hash's + // state. (ShakeHash.Read is thus very different from Hash.Sum) + // It never returns an error. + io.Reader + + // Clone returns a copy of the ShakeHash in its current state. + Clone() ShakeHash + + // Reset resets the ShakeHash to its initial state. + Reset() +} + +func (d *state) Clone() ShakeHash { + return d.clone() +} + +// NewShake128 creates a new SHAKE128 variable-output-length ShakeHash. +// Its generic security strength is 128 bits against all attacks if at +// least 32 bytes of its output are used. +func NewShake128() ShakeHash { return &state{rate: 168, dsbyte: 0x1f} } + +// NewShake256 creates a new SHAKE128 variable-output-length ShakeHash. +// Its generic security strength is 256 bits against all attacks if +// at least 64 bytes of its output are used. +func NewShake256() ShakeHash { return &state{rate: 136, dsbyte: 0x1f} } + +// ShakeSum128 writes an arbitrary-length digest of data into hash. +func ShakeSum128(hash, data []byte) { + h := NewShake128() + h.Write(data) + h.Read(hash) +} + +// ShakeSum256 writes an arbitrary-length digest of data into hash. +func ShakeSum256(hash, data []byte) { + h := NewShake256() + h.Write(data) + h.Read(hash) +} diff --git a/vendor/golang.org/x/crypto/sha3/testdata/keccakKats.json.deflate b/vendor/golang.org/x/crypto/sha3/testdata/keccakKats.json.deflate new file mode 100644 index 0000000000000000000000000000000000000000..62e85ae24236b46c09e5cfa84c71c69f5cc33cf6 Binary files /dev/null and b/vendor/golang.org/x/crypto/sha3/testdata/keccakKats.json.deflate differ diff --git a/vendor/golang.org/x/crypto/sha3/xor.go b/vendor/golang.org/x/crypto/sha3/xor.go new file mode 100644 index 0000000000000000000000000000000000000000..46a0d63a6dfe506cf474467b462a6cf933c1cddf --- /dev/null +++ b/vendor/golang.org/x/crypto/sha3/xor.go @@ -0,0 +1,16 @@ +// Copyright 2015 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,!386,!ppc64le appengine + +package sha3 + +var ( + xorIn = xorInGeneric + copyOut = copyOutGeneric + xorInUnaligned = xorInGeneric + copyOutUnaligned = copyOutGeneric +) + +const xorImplementationUnaligned = "generic" diff --git a/vendor/golang.org/x/crypto/sha3/xor_generic.go b/vendor/golang.org/x/crypto/sha3/xor_generic.go new file mode 100644 index 0000000000000000000000000000000000000000..fd35f02ef6e0c98e2f7dbef539920814837455f9 --- /dev/null +++ b/vendor/golang.org/x/crypto/sha3/xor_generic.go @@ -0,0 +1,28 @@ +// Copyright 2015 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 sha3 + +import "encoding/binary" + +// xorInGeneric xors the bytes in buf into the state; it +// makes no non-portable assumptions about memory layout +// or alignment. +func xorInGeneric(d *state, buf []byte) { + n := len(buf) / 8 + + for i := 0; i < n; i++ { + a := binary.LittleEndian.Uint64(buf) + d.a[i] ^= a + buf = buf[8:] + } +} + +// copyOutGeneric copies ulint64s to a byte buffer. +func copyOutGeneric(d *state, b []byte) { + for i := 0; len(b) >= 8; i++ { + binary.LittleEndian.PutUint64(b, d.a[i]) + b = b[8:] + } +} diff --git a/vendor/golang.org/x/crypto/sha3/xor_unaligned.go b/vendor/golang.org/x/crypto/sha3/xor_unaligned.go new file mode 100644 index 0000000000000000000000000000000000000000..929a486a79d6d483d150d85094b23edc156fcc95 --- /dev/null +++ b/vendor/golang.org/x/crypto/sha3/xor_unaligned.go @@ -0,0 +1,58 @@ +// Copyright 2015 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 386 ppc64le +// +build !appengine + +package sha3 + +import "unsafe" + +func xorInUnaligned(d *state, buf []byte) { + bw := (*[maxRate / 8]uint64)(unsafe.Pointer(&buf[0])) + n := len(buf) + if n >= 72 { + d.a[0] ^= bw[0] + d.a[1] ^= bw[1] + d.a[2] ^= bw[2] + d.a[3] ^= bw[3] + d.a[4] ^= bw[4] + d.a[5] ^= bw[5] + d.a[6] ^= bw[6] + d.a[7] ^= bw[7] + d.a[8] ^= bw[8] + } + if n >= 104 { + d.a[9] ^= bw[9] + d.a[10] ^= bw[10] + d.a[11] ^= bw[11] + d.a[12] ^= bw[12] + } + if n >= 136 { + d.a[13] ^= bw[13] + d.a[14] ^= bw[14] + d.a[15] ^= bw[15] + d.a[16] ^= bw[16] + } + if n >= 144 { + d.a[17] ^= bw[17] + } + if n >= 168 { + d.a[18] ^= bw[18] + d.a[19] ^= bw[19] + d.a[20] ^= bw[20] + } +} + +func copyOutUnaligned(d *state, buf []byte) { + ab := (*[maxRate]uint8)(unsafe.Pointer(&d.a[0])) + copy(buf, ab[:]) +} + +var ( + xorIn = xorInUnaligned + copyOut = copyOutUnaligned +) + +const xorImplementationUnaligned = "unaligned" diff --git a/vendor/golang.org/x/crypto/ssh/agent/client.go b/vendor/golang.org/x/crypto/ssh/agent/client.go new file mode 100644 index 0000000000000000000000000000000000000000..acb5ad80e548e3d43f87e03606f7331d3e921495 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/agent/client.go @@ -0,0 +1,683 @@ +// 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 agent implements the ssh-agent protocol, and provides both +// a client and a server. The client can talk to a standard ssh-agent +// that uses UNIX sockets, and one could implement an alternative +// ssh-agent process using the sample server. +// +// References: +// [PROTOCOL.agent]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.agent?rev=HEAD +package agent // import "golang.org/x/crypto/ssh/agent" + +import ( + "bytes" + "crypto/dsa" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rsa" + "encoding/base64" + "encoding/binary" + "errors" + "fmt" + "io" + "math/big" + "sync" + + "golang.org/x/crypto/ed25519" + "golang.org/x/crypto/ssh" +) + +// Agent represents the capabilities of an ssh-agent. +type Agent interface { + // List returns the identities known to the agent. + List() ([]*Key, error) + + // Sign has the agent sign the data using a protocol 2 key as defined + // in [PROTOCOL.agent] section 2.6.2. + Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error) + + // Add adds a private key to the agent. + Add(key AddedKey) error + + // Remove removes all identities with the given public key. + Remove(key ssh.PublicKey) error + + // RemoveAll removes all identities. + RemoveAll() error + + // Lock locks the agent. Sign and Remove will fail, and List will empty an empty list. + Lock(passphrase []byte) error + + // Unlock undoes the effect of Lock + Unlock(passphrase []byte) error + + // Signers returns signers for all the known keys. + Signers() ([]ssh.Signer, error) +} + +// ConstraintExtension describes an optional constraint defined by users. +type ConstraintExtension struct { + // ExtensionName consist of a UTF-8 string suffixed by the + // implementation domain following the naming scheme defined + // in Section 4.2 of [RFC4251], e.g. "foo@example.com". + ExtensionName string + // ExtensionDetails contains the actual content of the extended + // constraint. + ExtensionDetails []byte +} + +// AddedKey describes an SSH key to be added to an Agent. +type AddedKey struct { + // PrivateKey must be a *rsa.PrivateKey, *dsa.PrivateKey or + // *ecdsa.PrivateKey, which will be inserted into the agent. + PrivateKey interface{} + // Certificate, if not nil, is communicated to the agent and will be + // stored with the key. + Certificate *ssh.Certificate + // Comment is an optional, free-form string. + Comment string + // LifetimeSecs, if not zero, is the number of seconds that the + // agent will store the key for. + LifetimeSecs uint32 + // ConfirmBeforeUse, if true, requests that the agent confirm with the + // user before each use of this key. + ConfirmBeforeUse bool + // ConstraintExtensions are the experimental or private-use constraints + // defined by users. + ConstraintExtensions []ConstraintExtension +} + +// See [PROTOCOL.agent], section 3. +const ( + agentRequestV1Identities = 1 + agentRemoveAllV1Identities = 9 + + // 3.2 Requests from client to agent for protocol 2 key operations + agentAddIdentity = 17 + agentRemoveIdentity = 18 + agentRemoveAllIdentities = 19 + agentAddIDConstrained = 25 + + // 3.3 Key-type independent requests from client to agent + agentAddSmartcardKey = 20 + agentRemoveSmartcardKey = 21 + agentLock = 22 + agentUnlock = 23 + agentAddSmartcardKeyConstrained = 26 + + // 3.7 Key constraint identifiers + agentConstrainLifetime = 1 + agentConstrainConfirm = 2 + agentConstrainExtension = 3 +) + +// maxAgentResponseBytes is the maximum agent reply size that is accepted. This +// is a sanity check, not a limit in the spec. +const maxAgentResponseBytes = 16 << 20 + +// Agent messages: +// These structures mirror the wire format of the corresponding ssh agent +// messages found in [PROTOCOL.agent]. + +// 3.4 Generic replies from agent to client +const agentFailure = 5 + +type failureAgentMsg struct{} + +const agentSuccess = 6 + +type successAgentMsg struct{} + +// See [PROTOCOL.agent], section 2.5.2. +const agentRequestIdentities = 11 + +type requestIdentitiesAgentMsg struct{} + +// See [PROTOCOL.agent], section 2.5.2. +const agentIdentitiesAnswer = 12 + +type identitiesAnswerAgentMsg struct { + NumKeys uint32 `sshtype:"12"` + Keys []byte `ssh:"rest"` +} + +// See [PROTOCOL.agent], section 2.6.2. +const agentSignRequest = 13 + +type signRequestAgentMsg struct { + KeyBlob []byte `sshtype:"13"` + Data []byte + Flags uint32 +} + +// See [PROTOCOL.agent], section 2.6.2. + +// 3.6 Replies from agent to client for protocol 2 key operations +const agentSignResponse = 14 + +type signResponseAgentMsg struct { + SigBlob []byte `sshtype:"14"` +} + +type publicKey struct { + Format string + Rest []byte `ssh:"rest"` +} + +// 3.7 Key constraint identifiers +type constrainLifetimeAgentMsg struct { + LifetimeSecs uint32 `sshtype:"1"` +} + +type constrainExtensionAgentMsg struct { + ExtensionName string `sshtype:"3"` + ExtensionDetails []byte + + // Rest is a field used for parsing, not part of message + Rest []byte `ssh:"rest"` +} + +// Key represents a protocol 2 public key as defined in +// [PROTOCOL.agent], section 2.5.2. +type Key struct { + Format string + Blob []byte + Comment string +} + +func clientErr(err error) error { + return fmt.Errorf("agent: client error: %v", err) +} + +// String returns the storage form of an agent key with the format, base64 +// encoded serialized key, and the comment if it is not empty. +func (k *Key) String() string { + s := string(k.Format) + " " + base64.StdEncoding.EncodeToString(k.Blob) + + if k.Comment != "" { + s += " " + k.Comment + } + + return s +} + +// Type returns the public key type. +func (k *Key) Type() string { + return k.Format +} + +// Marshal returns key blob to satisfy the ssh.PublicKey interface. +func (k *Key) Marshal() []byte { + return k.Blob +} + +// Verify satisfies the ssh.PublicKey interface. +func (k *Key) Verify(data []byte, sig *ssh.Signature) error { + pubKey, err := ssh.ParsePublicKey(k.Blob) + if err != nil { + return fmt.Errorf("agent: bad public key: %v", err) + } + return pubKey.Verify(data, sig) +} + +type wireKey struct { + Format string + Rest []byte `ssh:"rest"` +} + +func parseKey(in []byte) (out *Key, rest []byte, err error) { + var record struct { + Blob []byte + Comment string + Rest []byte `ssh:"rest"` + } + + if err := ssh.Unmarshal(in, &record); err != nil { + return nil, nil, err + } + + var wk wireKey + if err := ssh.Unmarshal(record.Blob, &wk); err != nil { + return nil, nil, err + } + + return &Key{ + Format: wk.Format, + Blob: record.Blob, + Comment: record.Comment, + }, record.Rest, nil +} + +// client is a client for an ssh-agent process. +type client struct { + // conn is typically a *net.UnixConn + conn io.ReadWriter + // mu is used to prevent concurrent access to the agent + mu sync.Mutex +} + +// NewClient returns an Agent that talks to an ssh-agent process over +// the given connection. +func NewClient(rw io.ReadWriter) Agent { + return &client{conn: rw} +} + +// call sends an RPC to the agent. On success, the reply is +// unmarshaled into reply and replyType is set to the first byte of +// the reply, which contains the type of the message. +func (c *client) call(req []byte) (reply interface{}, err error) { + c.mu.Lock() + defer c.mu.Unlock() + + msg := make([]byte, 4+len(req)) + binary.BigEndian.PutUint32(msg, uint32(len(req))) + copy(msg[4:], req) + if _, err = c.conn.Write(msg); err != nil { + return nil, clientErr(err) + } + + var respSizeBuf [4]byte + if _, err = io.ReadFull(c.conn, respSizeBuf[:]); err != nil { + return nil, clientErr(err) + } + respSize := binary.BigEndian.Uint32(respSizeBuf[:]) + if respSize > maxAgentResponseBytes { + return nil, clientErr(err) + } + + buf := make([]byte, respSize) + if _, err = io.ReadFull(c.conn, buf); err != nil { + return nil, clientErr(err) + } + reply, err = unmarshal(buf) + if err != nil { + return nil, clientErr(err) + } + return reply, err +} + +func (c *client) simpleCall(req []byte) error { + resp, err := c.call(req) + if err != nil { + return err + } + if _, ok := resp.(*successAgentMsg); ok { + return nil + } + return errors.New("agent: failure") +} + +func (c *client) RemoveAll() error { + return c.simpleCall([]byte{agentRemoveAllIdentities}) +} + +func (c *client) Remove(key ssh.PublicKey) error { + req := ssh.Marshal(&agentRemoveIdentityMsg{ + KeyBlob: key.Marshal(), + }) + return c.simpleCall(req) +} + +func (c *client) Lock(passphrase []byte) error { + req := ssh.Marshal(&agentLockMsg{ + Passphrase: passphrase, + }) + return c.simpleCall(req) +} + +func (c *client) Unlock(passphrase []byte) error { + req := ssh.Marshal(&agentUnlockMsg{ + Passphrase: passphrase, + }) + return c.simpleCall(req) +} + +// List returns the identities known to the agent. +func (c *client) List() ([]*Key, error) { + // see [PROTOCOL.agent] section 2.5.2. + req := []byte{agentRequestIdentities} + + msg, err := c.call(req) + if err != nil { + return nil, err + } + + switch msg := msg.(type) { + case *identitiesAnswerAgentMsg: + if msg.NumKeys > maxAgentResponseBytes/8 { + return nil, errors.New("agent: too many keys in agent reply") + } + keys := make([]*Key, msg.NumKeys) + data := msg.Keys + for i := uint32(0); i < msg.NumKeys; i++ { + var key *Key + var err error + if key, data, err = parseKey(data); err != nil { + return nil, err + } + keys[i] = key + } + return keys, nil + case *failureAgentMsg: + return nil, errors.New("agent: failed to list keys") + } + panic("unreachable") +} + +// Sign has the agent sign the data using a protocol 2 key as defined +// in [PROTOCOL.agent] section 2.6.2. +func (c *client) Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error) { + req := ssh.Marshal(signRequestAgentMsg{ + KeyBlob: key.Marshal(), + Data: data, + }) + + msg, err := c.call(req) + if err != nil { + return nil, err + } + + switch msg := msg.(type) { + case *signResponseAgentMsg: + var sig ssh.Signature + if err := ssh.Unmarshal(msg.SigBlob, &sig); err != nil { + return nil, err + } + + return &sig, nil + case *failureAgentMsg: + return nil, errors.New("agent: failed to sign challenge") + } + panic("unreachable") +} + +// unmarshal parses an agent message in packet, returning the parsed +// form and the message type of packet. +func unmarshal(packet []byte) (interface{}, error) { + if len(packet) < 1 { + return nil, errors.New("agent: empty packet") + } + var msg interface{} + switch packet[0] { + case agentFailure: + return new(failureAgentMsg), nil + case agentSuccess: + return new(successAgentMsg), nil + case agentIdentitiesAnswer: + msg = new(identitiesAnswerAgentMsg) + case agentSignResponse: + msg = new(signResponseAgentMsg) + case agentV1IdentitiesAnswer: + msg = new(agentV1IdentityMsg) + default: + return nil, fmt.Errorf("agent: unknown type tag %d", packet[0]) + } + if err := ssh.Unmarshal(packet, msg); err != nil { + return nil, err + } + return msg, nil +} + +type rsaKeyMsg struct { + Type string `sshtype:"17|25"` + N *big.Int + E *big.Int + D *big.Int + Iqmp *big.Int // IQMP = Inverse Q Mod P + P *big.Int + Q *big.Int + Comments string + Constraints []byte `ssh:"rest"` +} + +type dsaKeyMsg struct { + Type string `sshtype:"17|25"` + P *big.Int + Q *big.Int + G *big.Int + Y *big.Int + X *big.Int + Comments string + Constraints []byte `ssh:"rest"` +} + +type ecdsaKeyMsg struct { + Type string `sshtype:"17|25"` + Curve string + KeyBytes []byte + D *big.Int + Comments string + Constraints []byte `ssh:"rest"` +} + +type ed25519KeyMsg struct { + Type string `sshtype:"17|25"` + Pub []byte + Priv []byte + Comments string + Constraints []byte `ssh:"rest"` +} + +// Insert adds a private key to the agent. +func (c *client) insertKey(s interface{}, comment string, constraints []byte) error { + var req []byte + switch k := s.(type) { + case *rsa.PrivateKey: + if len(k.Primes) != 2 { + return fmt.Errorf("agent: unsupported RSA key with %d primes", len(k.Primes)) + } + k.Precompute() + req = ssh.Marshal(rsaKeyMsg{ + Type: ssh.KeyAlgoRSA, + N: k.N, + E: big.NewInt(int64(k.E)), + D: k.D, + Iqmp: k.Precomputed.Qinv, + P: k.Primes[0], + Q: k.Primes[1], + Comments: comment, + Constraints: constraints, + }) + case *dsa.PrivateKey: + req = ssh.Marshal(dsaKeyMsg{ + Type: ssh.KeyAlgoDSA, + P: k.P, + Q: k.Q, + G: k.G, + Y: k.Y, + X: k.X, + Comments: comment, + Constraints: constraints, + }) + case *ecdsa.PrivateKey: + nistID := fmt.Sprintf("nistp%d", k.Params().BitSize) + req = ssh.Marshal(ecdsaKeyMsg{ + Type: "ecdsa-sha2-" + nistID, + Curve: nistID, + KeyBytes: elliptic.Marshal(k.Curve, k.X, k.Y), + D: k.D, + Comments: comment, + Constraints: constraints, + }) + case *ed25519.PrivateKey: + req = ssh.Marshal(ed25519KeyMsg{ + Type: ssh.KeyAlgoED25519, + Pub: []byte(*k)[32:], + Priv: []byte(*k), + Comments: comment, + Constraints: constraints, + }) + default: + return fmt.Errorf("agent: unsupported key type %T", s) + } + + // if constraints are present then the message type needs to be changed. + if len(constraints) != 0 { + req[0] = agentAddIDConstrained + } + + resp, err := c.call(req) + if err != nil { + return err + } + if _, ok := resp.(*successAgentMsg); ok { + return nil + } + return errors.New("agent: failure") +} + +type rsaCertMsg struct { + Type string `sshtype:"17|25"` + CertBytes []byte + D *big.Int + Iqmp *big.Int // IQMP = Inverse Q Mod P + P *big.Int + Q *big.Int + Comments string + Constraints []byte `ssh:"rest"` +} + +type dsaCertMsg struct { + Type string `sshtype:"17|25"` + CertBytes []byte + X *big.Int + Comments string + Constraints []byte `ssh:"rest"` +} + +type ecdsaCertMsg struct { + Type string `sshtype:"17|25"` + CertBytes []byte + D *big.Int + Comments string + Constraints []byte `ssh:"rest"` +} + +type ed25519CertMsg struct { + Type string `sshtype:"17|25"` + CertBytes []byte + Pub []byte + Priv []byte + Comments string + Constraints []byte `ssh:"rest"` +} + +// Add adds a private key to the agent. If a certificate is given, +// that certificate is added instead as public key. +func (c *client) Add(key AddedKey) error { + var constraints []byte + + if secs := key.LifetimeSecs; secs != 0 { + constraints = append(constraints, ssh.Marshal(constrainLifetimeAgentMsg{secs})...) + } + + if key.ConfirmBeforeUse { + constraints = append(constraints, agentConstrainConfirm) + } + + cert := key.Certificate + if cert == nil { + return c.insertKey(key.PrivateKey, key.Comment, constraints) + } + return c.insertCert(key.PrivateKey, cert, key.Comment, constraints) +} + +func (c *client) insertCert(s interface{}, cert *ssh.Certificate, comment string, constraints []byte) error { + var req []byte + switch k := s.(type) { + case *rsa.PrivateKey: + if len(k.Primes) != 2 { + return fmt.Errorf("agent: unsupported RSA key with %d primes", len(k.Primes)) + } + k.Precompute() + req = ssh.Marshal(rsaCertMsg{ + Type: cert.Type(), + CertBytes: cert.Marshal(), + D: k.D, + Iqmp: k.Precomputed.Qinv, + P: k.Primes[0], + Q: k.Primes[1], + Comments: comment, + Constraints: constraints, + }) + case *dsa.PrivateKey: + req = ssh.Marshal(dsaCertMsg{ + Type: cert.Type(), + CertBytes: cert.Marshal(), + X: k.X, + Comments: comment, + Constraints: constraints, + }) + case *ecdsa.PrivateKey: + req = ssh.Marshal(ecdsaCertMsg{ + Type: cert.Type(), + CertBytes: cert.Marshal(), + D: k.D, + Comments: comment, + Constraints: constraints, + }) + case *ed25519.PrivateKey: + req = ssh.Marshal(ed25519CertMsg{ + Type: cert.Type(), + CertBytes: cert.Marshal(), + Pub: []byte(*k)[32:], + Priv: []byte(*k), + Comments: comment, + Constraints: constraints, + }) + default: + return fmt.Errorf("agent: unsupported key type %T", s) + } + + // if constraints are present then the message type needs to be changed. + if len(constraints) != 0 { + req[0] = agentAddIDConstrained + } + + signer, err := ssh.NewSignerFromKey(s) + if err != nil { + return err + } + if bytes.Compare(cert.Key.Marshal(), signer.PublicKey().Marshal()) != 0 { + return errors.New("agent: signer and cert have different public key") + } + + resp, err := c.call(req) + if err != nil { + return err + } + if _, ok := resp.(*successAgentMsg); ok { + return nil + } + return errors.New("agent: failure") +} + +// Signers provides a callback for client authentication. +func (c *client) Signers() ([]ssh.Signer, error) { + keys, err := c.List() + if err != nil { + return nil, err + } + + var result []ssh.Signer + for _, k := range keys { + result = append(result, &agentKeyringSigner{c, k}) + } + return result, nil +} + +type agentKeyringSigner struct { + agent *client + pub ssh.PublicKey +} + +func (s *agentKeyringSigner) PublicKey() ssh.PublicKey { + return s.pub +} + +func (s *agentKeyringSigner) Sign(rand io.Reader, data []byte) (*ssh.Signature, error) { + // The agent has its own entropy source, so the rand argument is ignored. + return s.agent.Sign(s.pub, data) +} diff --git a/vendor/golang.org/x/crypto/ssh/agent/client_test.go b/vendor/golang.org/x/crypto/ssh/agent/client_test.go new file mode 100644 index 0000000000000000000000000000000000000000..266fd6d40404c0a07585904b5af120a85494c34c --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/agent/client_test.go @@ -0,0 +1,379 @@ +// 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 agent + +import ( + "bytes" + "crypto/rand" + "errors" + "net" + "os" + "os/exec" + "path/filepath" + "strconv" + "testing" + "time" + + "golang.org/x/crypto/ssh" +) + +// startOpenSSHAgent executes ssh-agent, and returns an Agent interface to it. +func startOpenSSHAgent(t *testing.T) (client Agent, socket string, cleanup func()) { + if testing.Short() { + // ssh-agent is not always available, and the key + // types supported vary by platform. + t.Skip("skipping test due to -short") + } + + bin, err := exec.LookPath("ssh-agent") + if err != nil { + t.Skip("could not find ssh-agent") + } + + cmd := exec.Command(bin, "-s") + out, err := cmd.Output() + if err != nil { + t.Fatalf("cmd.Output: %v", err) + } + + /* Output looks like: + + SSH_AUTH_SOCK=/tmp/ssh-P65gpcqArqvH/agent.15541; export SSH_AUTH_SOCK; + SSH_AGENT_PID=15542; export SSH_AGENT_PID; + echo Agent pid 15542; + */ + fields := bytes.Split(out, []byte(";")) + line := bytes.SplitN(fields[0], []byte("="), 2) + line[0] = bytes.TrimLeft(line[0], "\n") + if string(line[0]) != "SSH_AUTH_SOCK" { + t.Fatalf("could not find key SSH_AUTH_SOCK in %q", fields[0]) + } + socket = string(line[1]) + + line = bytes.SplitN(fields[2], []byte("="), 2) + line[0] = bytes.TrimLeft(line[0], "\n") + if string(line[0]) != "SSH_AGENT_PID" { + t.Fatalf("could not find key SSH_AGENT_PID in %q", fields[2]) + } + pidStr := line[1] + pid, err := strconv.Atoi(string(pidStr)) + if err != nil { + t.Fatalf("Atoi(%q): %v", pidStr, err) + } + + conn, err := net.Dial("unix", string(socket)) + if err != nil { + t.Fatalf("net.Dial: %v", err) + } + + ac := NewClient(conn) + return ac, socket, func() { + proc, _ := os.FindProcess(pid) + if proc != nil { + proc.Kill() + } + conn.Close() + os.RemoveAll(filepath.Dir(socket)) + } +} + +// startKeyringAgent uses Keyring to simulate a ssh-agent Server and returns a client. +func startKeyringAgent(t *testing.T) (client Agent, cleanup func()) { + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + go ServeAgent(NewKeyring(), c2) + + return NewClient(c1), func() { + c1.Close() + c2.Close() + } +} + +func testOpenSSHAgent(t *testing.T, key interface{}, cert *ssh.Certificate, lifetimeSecs uint32) { + agent, _, cleanup := startOpenSSHAgent(t) + defer cleanup() + + testAgentInterface(t, agent, key, cert, lifetimeSecs) +} + +func testKeyringAgent(t *testing.T, key interface{}, cert *ssh.Certificate, lifetimeSecs uint32) { + agent, cleanup := startKeyringAgent(t) + defer cleanup() + + testAgentInterface(t, agent, key, cert, lifetimeSecs) +} + +func testAgentInterface(t *testing.T, agent Agent, key interface{}, cert *ssh.Certificate, lifetimeSecs uint32) { + signer, err := ssh.NewSignerFromKey(key) + if err != nil { + t.Fatalf("NewSignerFromKey(%T): %v", key, err) + } + // The agent should start up empty. + if keys, err := agent.List(); err != nil { + t.Fatalf("RequestIdentities: %v", err) + } else if len(keys) > 0 { + t.Fatalf("got %d keys, want 0: %v", len(keys), keys) + } + + // Attempt to insert the key, with certificate if specified. + var pubKey ssh.PublicKey + if cert != nil { + err = agent.Add(AddedKey{ + PrivateKey: key, + Certificate: cert, + Comment: "comment", + LifetimeSecs: lifetimeSecs, + }) + pubKey = cert + } else { + err = agent.Add(AddedKey{PrivateKey: key, Comment: "comment", LifetimeSecs: lifetimeSecs}) + pubKey = signer.PublicKey() + } + if err != nil { + t.Fatalf("insert(%T): %v", key, err) + } + + // Did the key get inserted successfully? + if keys, err := agent.List(); err != nil { + t.Fatalf("List: %v", err) + } else if len(keys) != 1 { + t.Fatalf("got %v, want 1 key", keys) + } else if keys[0].Comment != "comment" { + t.Fatalf("key comment: got %v, want %v", keys[0].Comment, "comment") + } else if !bytes.Equal(keys[0].Blob, pubKey.Marshal()) { + t.Fatalf("key mismatch") + } + + // Can the agent make a valid signature? + data := []byte("hello") + sig, err := agent.Sign(pubKey, data) + if err != nil { + t.Fatalf("Sign(%s): %v", pubKey.Type(), err) + } + + if err := pubKey.Verify(data, sig); err != nil { + t.Fatalf("Verify(%s): %v", pubKey.Type(), err) + } + + // If the key has a lifetime, is it removed when it should be? + if lifetimeSecs > 0 { + time.Sleep(time.Second*time.Duration(lifetimeSecs) + 100*time.Millisecond) + keys, err := agent.List() + if err != nil { + t.Fatalf("List: %v", err) + } + if len(keys) > 0 { + t.Fatalf("key not expired") + } + } + +} + +func TestAgent(t *testing.T) { + for _, keyType := range []string{"rsa", "dsa", "ecdsa", "ed25519"} { + testOpenSSHAgent(t, testPrivateKeys[keyType], nil, 0) + testKeyringAgent(t, testPrivateKeys[keyType], nil, 0) + } +} + +func TestCert(t *testing.T) { + cert := &ssh.Certificate{ + Key: testPublicKeys["rsa"], + ValidBefore: ssh.CertTimeInfinity, + CertType: ssh.UserCert, + } + cert.SignCert(rand.Reader, testSigners["ecdsa"]) + + testOpenSSHAgent(t, testPrivateKeys["rsa"], cert, 0) + testKeyringAgent(t, testPrivateKeys["rsa"], cert, 0) +} + +// netPipe is analogous to net.Pipe, but it uses a real net.Conn, and +// therefore is buffered (net.Pipe deadlocks if both sides start with +// a write.) +func netPipe() (net.Conn, net.Conn, error) { + listener, err := net.Listen("tcp", "127.0.0.1:0") + if err != nil { + listener, err = net.Listen("tcp", "[::1]:0") + if err != nil { + return nil, nil, err + } + } + defer listener.Close() + c1, err := net.Dial("tcp", listener.Addr().String()) + if err != nil { + return nil, nil, err + } + + c2, err := listener.Accept() + if err != nil { + c1.Close() + return nil, nil, err + } + + return c1, c2, nil +} + +func TestAuth(t *testing.T) { + agent, _, cleanup := startOpenSSHAgent(t) + defer cleanup() + + a, b, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + + defer a.Close() + defer b.Close() + + if err := agent.Add(AddedKey{PrivateKey: testPrivateKeys["rsa"], Comment: "comment"}); err != nil { + t.Errorf("Add: %v", err) + } + + serverConf := ssh.ServerConfig{} + serverConf.AddHostKey(testSigners["rsa"]) + serverConf.PublicKeyCallback = func(c ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) { + if bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) { + return nil, nil + } + + return nil, errors.New("pubkey rejected") + } + + go func() { + conn, _, _, err := ssh.NewServerConn(a, &serverConf) + if err != nil { + t.Fatalf("Server: %v", err) + } + conn.Close() + }() + + conf := ssh.ClientConfig{ + HostKeyCallback: ssh.InsecureIgnoreHostKey(), + } + conf.Auth = append(conf.Auth, ssh.PublicKeysCallback(agent.Signers)) + conn, _, _, err := ssh.NewClientConn(b, "", &conf) + if err != nil { + t.Fatalf("NewClientConn: %v", err) + } + conn.Close() +} + +func TestLockOpenSSHAgent(t *testing.T) { + agent, _, cleanup := startOpenSSHAgent(t) + defer cleanup() + testLockAgent(agent, t) +} + +func TestLockKeyringAgent(t *testing.T) { + agent, cleanup := startKeyringAgent(t) + defer cleanup() + testLockAgent(agent, t) +} + +func testLockAgent(agent Agent, t *testing.T) { + if err := agent.Add(AddedKey{PrivateKey: testPrivateKeys["rsa"], Comment: "comment 1"}); err != nil { + t.Errorf("Add: %v", err) + } + if err := agent.Add(AddedKey{PrivateKey: testPrivateKeys["dsa"], Comment: "comment dsa"}); err != nil { + t.Errorf("Add: %v", err) + } + if keys, err := agent.List(); err != nil { + t.Errorf("List: %v", err) + } else if len(keys) != 2 { + t.Errorf("Want 2 keys, got %v", keys) + } + + passphrase := []byte("secret") + if err := agent.Lock(passphrase); err != nil { + t.Errorf("Lock: %v", err) + } + + if keys, err := agent.List(); err != nil { + t.Errorf("List: %v", err) + } else if len(keys) != 0 { + t.Errorf("Want 0 keys, got %v", keys) + } + + signer, _ := ssh.NewSignerFromKey(testPrivateKeys["rsa"]) + if _, err := agent.Sign(signer.PublicKey(), []byte("hello")); err == nil { + t.Fatalf("Sign did not fail") + } + + if err := agent.Remove(signer.PublicKey()); err == nil { + t.Fatalf("Remove did not fail") + } + + if err := agent.RemoveAll(); err == nil { + t.Fatalf("RemoveAll did not fail") + } + + if err := agent.Unlock(nil); err == nil { + t.Errorf("Unlock with wrong passphrase succeeded") + } + if err := agent.Unlock(passphrase); err != nil { + t.Errorf("Unlock: %v", err) + } + + if err := agent.Remove(signer.PublicKey()); err != nil { + t.Fatalf("Remove: %v", err) + } + + if keys, err := agent.List(); err != nil { + t.Errorf("List: %v", err) + } else if len(keys) != 1 { + t.Errorf("Want 1 keys, got %v", keys) + } +} + +func testOpenSSHAgentLifetime(t *testing.T) { + agent, _, cleanup := startOpenSSHAgent(t) + defer cleanup() + testAgentLifetime(t, agent) +} + +func testKeyringAgentLifetime(t *testing.T) { + agent, cleanup := startKeyringAgent(t) + defer cleanup() + testAgentLifetime(t, agent) +} + +func testAgentLifetime(t *testing.T, agent Agent) { + for _, keyType := range []string{"rsa", "dsa", "ecdsa"} { + // Add private keys to the agent. + err := agent.Add(AddedKey{ + PrivateKey: testPrivateKeys[keyType], + Comment: "comment", + LifetimeSecs: 1, + }) + if err != nil { + t.Fatalf("add: %v", err) + } + // Add certs to the agent. + cert := &ssh.Certificate{ + Key: testPublicKeys[keyType], + ValidBefore: ssh.CertTimeInfinity, + CertType: ssh.UserCert, + } + cert.SignCert(rand.Reader, testSigners[keyType]) + err = agent.Add(AddedKey{ + PrivateKey: testPrivateKeys[keyType], + Certificate: cert, + Comment: "comment", + LifetimeSecs: 1, + }) + if err != nil { + t.Fatalf("add: %v", err) + } + } + time.Sleep(1100 * time.Millisecond) + if keys, err := agent.List(); err != nil { + t.Errorf("List: %v", err) + } else if len(keys) != 0 { + t.Errorf("Want 0 keys, got %v", len(keys)) + } +} diff --git a/vendor/golang.org/x/crypto/ssh/agent/example_test.go b/vendor/golang.org/x/crypto/ssh/agent/example_test.go new file mode 100644 index 0000000000000000000000000000000000000000..85562253eafad45434845e283b1aff2d85433c18 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/agent/example_test.go @@ -0,0 +1,41 @@ +// Copyright 2016 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 agent_test + +import ( + "log" + "net" + "os" + + "golang.org/x/crypto/ssh" + "golang.org/x/crypto/ssh/agent" +) + +func ExampleClientAgent() { + // ssh-agent has a UNIX socket under $SSH_AUTH_SOCK + socket := os.Getenv("SSH_AUTH_SOCK") + conn, err := net.Dial("unix", socket) + if err != nil { + log.Fatalf("net.Dial: %v", err) + } + agentClient := agent.NewClient(conn) + config := &ssh.ClientConfig{ + User: "username", + Auth: []ssh.AuthMethod{ + // Use a callback rather than PublicKeys + // so we only consult the agent once the remote server + // wants it. + ssh.PublicKeysCallback(agentClient.Signers), + }, + HostKeyCallback: ssh.InsecureIgnoreHostKey(), + } + + sshc, err := ssh.Dial("tcp", "localhost:22", config) + if err != nil { + log.Fatalf("Dial: %v", err) + } + // .. use sshc + sshc.Close() +} diff --git a/vendor/golang.org/x/crypto/ssh/agent/forward.go b/vendor/golang.org/x/crypto/ssh/agent/forward.go new file mode 100644 index 0000000000000000000000000000000000000000..fd24ba900d2541ff523678b62b424086d5ee853d --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/agent/forward.go @@ -0,0 +1,103 @@ +// 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 agent + +import ( + "errors" + "io" + "net" + "sync" + + "golang.org/x/crypto/ssh" +) + +// RequestAgentForwarding sets up agent forwarding for the session. +// ForwardToAgent or ForwardToRemote should be called to route +// the authentication requests. +func RequestAgentForwarding(session *ssh.Session) error { + ok, err := session.SendRequest("auth-agent-req@openssh.com", true, nil) + if err != nil { + return err + } + if !ok { + return errors.New("forwarding request denied") + } + return nil +} + +// ForwardToAgent routes authentication requests to the given keyring. +func ForwardToAgent(client *ssh.Client, keyring Agent) error { + channels := client.HandleChannelOpen(channelType) + if channels == nil { + return errors.New("agent: already have handler for " + channelType) + } + + go func() { + for ch := range channels { + channel, reqs, err := ch.Accept() + if err != nil { + continue + } + go ssh.DiscardRequests(reqs) + go func() { + ServeAgent(keyring, channel) + channel.Close() + }() + } + }() + return nil +} + +const channelType = "auth-agent@openssh.com" + +// ForwardToRemote routes authentication requests to the ssh-agent +// process serving on the given unix socket. +func ForwardToRemote(client *ssh.Client, addr string) error { + channels := client.HandleChannelOpen(channelType) + if channels == nil { + return errors.New("agent: already have handler for " + channelType) + } + conn, err := net.Dial("unix", addr) + if err != nil { + return err + } + conn.Close() + + go func() { + for ch := range channels { + channel, reqs, err := ch.Accept() + if err != nil { + continue + } + go ssh.DiscardRequests(reqs) + go forwardUnixSocket(channel, addr) + } + }() + return nil +} + +func forwardUnixSocket(channel ssh.Channel, addr string) { + conn, err := net.Dial("unix", addr) + if err != nil { + return + } + + var wg sync.WaitGroup + wg.Add(2) + go func() { + io.Copy(conn, channel) + conn.(*net.UnixConn).CloseWrite() + wg.Done() + }() + go func() { + io.Copy(channel, conn) + channel.CloseWrite() + wg.Done() + }() + + wg.Wait() + conn.Close() + channel.Close() +} diff --git a/vendor/golang.org/x/crypto/ssh/agent/keyring.go b/vendor/golang.org/x/crypto/ssh/agent/keyring.go new file mode 100644 index 0000000000000000000000000000000000000000..a6ba06ab3011916bee1737fe20fc8fc24e9b5382 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/agent/keyring.go @@ -0,0 +1,215 @@ +// 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 agent + +import ( + "bytes" + "crypto/rand" + "crypto/subtle" + "errors" + "fmt" + "sync" + "time" + + "golang.org/x/crypto/ssh" +) + +type privKey struct { + signer ssh.Signer + comment string + expire *time.Time +} + +type keyring struct { + mu sync.Mutex + keys []privKey + + locked bool + passphrase []byte +} + +var errLocked = errors.New("agent: locked") + +// NewKeyring returns an Agent that holds keys in memory. It is safe +// for concurrent use by multiple goroutines. +func NewKeyring() Agent { + return &keyring{} +} + +// RemoveAll removes all identities. +func (r *keyring) RemoveAll() error { + r.mu.Lock() + defer r.mu.Unlock() + if r.locked { + return errLocked + } + + r.keys = nil + return nil +} + +// removeLocked does the actual key removal. The caller must already be holding the +// keyring mutex. +func (r *keyring) removeLocked(want []byte) error { + found := false + for i := 0; i < len(r.keys); { + if bytes.Equal(r.keys[i].signer.PublicKey().Marshal(), want) { + found = true + r.keys[i] = r.keys[len(r.keys)-1] + r.keys = r.keys[:len(r.keys)-1] + continue + } else { + i++ + } + } + + if !found { + return errors.New("agent: key not found") + } + return nil +} + +// Remove removes all identities with the given public key. +func (r *keyring) Remove(key ssh.PublicKey) error { + r.mu.Lock() + defer r.mu.Unlock() + if r.locked { + return errLocked + } + + return r.removeLocked(key.Marshal()) +} + +// Lock locks the agent. Sign and Remove will fail, and List will return an empty list. +func (r *keyring) Lock(passphrase []byte) error { + r.mu.Lock() + defer r.mu.Unlock() + if r.locked { + return errLocked + } + + r.locked = true + r.passphrase = passphrase + return nil +} + +// Unlock undoes the effect of Lock +func (r *keyring) Unlock(passphrase []byte) error { + r.mu.Lock() + defer r.mu.Unlock() + if !r.locked { + return errors.New("agent: not locked") + } + if len(passphrase) != len(r.passphrase) || 1 != subtle.ConstantTimeCompare(passphrase, r.passphrase) { + return fmt.Errorf("agent: incorrect passphrase") + } + + r.locked = false + r.passphrase = nil + return nil +} + +// expireKeysLocked removes expired keys from the keyring. If a key was added +// with a lifetimesecs contraint and seconds >= lifetimesecs seconds have +// ellapsed, it is removed. The caller *must* be holding the keyring mutex. +func (r *keyring) expireKeysLocked() { + for _, k := range r.keys { + if k.expire != nil && time.Now().After(*k.expire) { + r.removeLocked(k.signer.PublicKey().Marshal()) + } + } +} + +// List returns the identities known to the agent. +func (r *keyring) List() ([]*Key, error) { + r.mu.Lock() + defer r.mu.Unlock() + if r.locked { + // section 2.7: locked agents return empty. + return nil, nil + } + + r.expireKeysLocked() + var ids []*Key + for _, k := range r.keys { + pub := k.signer.PublicKey() + ids = append(ids, &Key{ + Format: pub.Type(), + Blob: pub.Marshal(), + Comment: k.comment}) + } + return ids, nil +} + +// Insert adds a private key to the keyring. If a certificate +// is given, that certificate is added as public key. Note that +// any constraints given are ignored. +func (r *keyring) Add(key AddedKey) error { + r.mu.Lock() + defer r.mu.Unlock() + if r.locked { + return errLocked + } + signer, err := ssh.NewSignerFromKey(key.PrivateKey) + + if err != nil { + return err + } + + if cert := key.Certificate; cert != nil { + signer, err = ssh.NewCertSigner(cert, signer) + if err != nil { + return err + } + } + + p := privKey{ + signer: signer, + comment: key.Comment, + } + + if key.LifetimeSecs > 0 { + t := time.Now().Add(time.Duration(key.LifetimeSecs) * time.Second) + p.expire = &t + } + + r.keys = append(r.keys, p) + + return nil +} + +// Sign returns a signature for the data. +func (r *keyring) Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error) { + r.mu.Lock() + defer r.mu.Unlock() + if r.locked { + return nil, errLocked + } + + r.expireKeysLocked() + wanted := key.Marshal() + for _, k := range r.keys { + if bytes.Equal(k.signer.PublicKey().Marshal(), wanted) { + return k.signer.Sign(rand.Reader, data) + } + } + return nil, errors.New("not found") +} + +// Signers returns signers for all the known keys. +func (r *keyring) Signers() ([]ssh.Signer, error) { + r.mu.Lock() + defer r.mu.Unlock() + if r.locked { + return nil, errLocked + } + + r.expireKeysLocked() + s := make([]ssh.Signer, 0, len(r.keys)) + for _, k := range r.keys { + s = append(s, k.signer) + } + return s, nil +} diff --git a/vendor/golang.org/x/crypto/ssh/agent/keyring_test.go b/vendor/golang.org/x/crypto/ssh/agent/keyring_test.go new file mode 100644 index 0000000000000000000000000000000000000000..e5d50e7e0db559fa1f7646575036d0cefbd99b1c --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/agent/keyring_test.go @@ -0,0 +1,76 @@ +// Copyright 2015 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 agent + +import "testing" + +func addTestKey(t *testing.T, a Agent, keyName string) { + err := a.Add(AddedKey{ + PrivateKey: testPrivateKeys[keyName], + Comment: keyName, + }) + if err != nil { + t.Fatalf("failed to add key %q: %v", keyName, err) + } +} + +func removeTestKey(t *testing.T, a Agent, keyName string) { + err := a.Remove(testPublicKeys[keyName]) + if err != nil { + t.Fatalf("failed to remove key %q: %v", keyName, err) + } +} + +func validateListedKeys(t *testing.T, a Agent, expectedKeys []string) { + listedKeys, err := a.List() + if err != nil { + t.Fatalf("failed to list keys: %v", err) + return + } + actualKeys := make(map[string]bool) + for _, key := range listedKeys { + actualKeys[key.Comment] = true + } + + matchedKeys := make(map[string]bool) + for _, expectedKey := range expectedKeys { + if !actualKeys[expectedKey] { + t.Fatalf("expected key %q, but was not found", expectedKey) + } else { + matchedKeys[expectedKey] = true + } + } + + for actualKey := range actualKeys { + if !matchedKeys[actualKey] { + t.Fatalf("key %q was found, but was not expected", actualKey) + } + } +} + +func TestKeyringAddingAndRemoving(t *testing.T) { + keyNames := []string{"dsa", "ecdsa", "rsa", "user"} + + // add all test private keys + k := NewKeyring() + for _, keyName := range keyNames { + addTestKey(t, k, keyName) + } + validateListedKeys(t, k, keyNames) + + // remove a key in the middle + keyToRemove := keyNames[1] + keyNames = append(keyNames[:1], keyNames[2:]...) + + removeTestKey(t, k, keyToRemove) + validateListedKeys(t, k, keyNames) + + // remove all keys + err := k.RemoveAll() + if err != nil { + t.Fatalf("failed to remove all keys: %v", err) + } + validateListedKeys(t, k, []string{}) +} diff --git a/vendor/golang.org/x/crypto/ssh/agent/server.go b/vendor/golang.org/x/crypto/ssh/agent/server.go new file mode 100644 index 0000000000000000000000000000000000000000..2e4692cbd5a033e30474cc0f01ea209a88f132fc --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/agent/server.go @@ -0,0 +1,523 @@ +// 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 agent + +import ( + "crypto/dsa" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rsa" + "encoding/binary" + "errors" + "fmt" + "io" + "log" + "math/big" + + "golang.org/x/crypto/ed25519" + "golang.org/x/crypto/ssh" +) + +// Server wraps an Agent and uses it to implement the agent side of +// the SSH-agent, wire protocol. +type server struct { + agent Agent +} + +func (s *server) processRequestBytes(reqData []byte) []byte { + rep, err := s.processRequest(reqData) + if err != nil { + if err != errLocked { + // TODO(hanwen): provide better logging interface? + log.Printf("agent %d: %v", reqData[0], err) + } + return []byte{agentFailure} + } + + if err == nil && rep == nil { + return []byte{agentSuccess} + } + + return ssh.Marshal(rep) +} + +func marshalKey(k *Key) []byte { + var record struct { + Blob []byte + Comment string + } + record.Blob = k.Marshal() + record.Comment = k.Comment + + return ssh.Marshal(&record) +} + +// See [PROTOCOL.agent], section 2.5.1. +const agentV1IdentitiesAnswer = 2 + +type agentV1IdentityMsg struct { + Numkeys uint32 `sshtype:"2"` +} + +type agentRemoveIdentityMsg struct { + KeyBlob []byte `sshtype:"18"` +} + +type agentLockMsg struct { + Passphrase []byte `sshtype:"22"` +} + +type agentUnlockMsg struct { + Passphrase []byte `sshtype:"23"` +} + +func (s *server) processRequest(data []byte) (interface{}, error) { + switch data[0] { + case agentRequestV1Identities: + return &agentV1IdentityMsg{0}, nil + + case agentRemoveAllV1Identities: + return nil, nil + + case agentRemoveIdentity: + var req agentRemoveIdentityMsg + if err := ssh.Unmarshal(data, &req); err != nil { + return nil, err + } + + var wk wireKey + if err := ssh.Unmarshal(req.KeyBlob, &wk); err != nil { + return nil, err + } + + return nil, s.agent.Remove(&Key{Format: wk.Format, Blob: req.KeyBlob}) + + case agentRemoveAllIdentities: + return nil, s.agent.RemoveAll() + + case agentLock: + var req agentLockMsg + if err := ssh.Unmarshal(data, &req); err != nil { + return nil, err + } + + return nil, s.agent.Lock(req.Passphrase) + + case agentUnlock: + var req agentUnlockMsg + if err := ssh.Unmarshal(data, &req); err != nil { + return nil, err + } + return nil, s.agent.Unlock(req.Passphrase) + + case agentSignRequest: + var req signRequestAgentMsg + if err := ssh.Unmarshal(data, &req); err != nil { + return nil, err + } + + var wk wireKey + if err := ssh.Unmarshal(req.KeyBlob, &wk); err != nil { + return nil, err + } + + k := &Key{ + Format: wk.Format, + Blob: req.KeyBlob, + } + + sig, err := s.agent.Sign(k, req.Data) // TODO(hanwen): flags. + if err != nil { + return nil, err + } + return &signResponseAgentMsg{SigBlob: ssh.Marshal(sig)}, nil + + case agentRequestIdentities: + keys, err := s.agent.List() + if err != nil { + return nil, err + } + + rep := identitiesAnswerAgentMsg{ + NumKeys: uint32(len(keys)), + } + for _, k := range keys { + rep.Keys = append(rep.Keys, marshalKey(k)...) + } + return rep, nil + + case agentAddIDConstrained, agentAddIdentity: + return nil, s.insertIdentity(data) + } + + return nil, fmt.Errorf("unknown opcode %d", data[0]) +} + +func parseConstraints(constraints []byte) (lifetimeSecs uint32, confirmBeforeUse bool, extensions []ConstraintExtension, err error) { + for len(constraints) != 0 { + switch constraints[0] { + case agentConstrainLifetime: + lifetimeSecs = binary.BigEndian.Uint32(constraints[1:5]) + constraints = constraints[5:] + case agentConstrainConfirm: + confirmBeforeUse = true + constraints = constraints[1:] + case agentConstrainExtension: + var msg constrainExtensionAgentMsg + if err = ssh.Unmarshal(constraints, &msg); err != nil { + return 0, false, nil, err + } + extensions = append(extensions, ConstraintExtension{ + ExtensionName: msg.ExtensionName, + ExtensionDetails: msg.ExtensionDetails, + }) + constraints = msg.Rest + default: + return 0, false, nil, fmt.Errorf("unknown constraint type: %d", constraints[0]) + } + } + return +} + +func setConstraints(key *AddedKey, constraintBytes []byte) error { + lifetimeSecs, confirmBeforeUse, constraintExtensions, err := parseConstraints(constraintBytes) + if err != nil { + return err + } + + key.LifetimeSecs = lifetimeSecs + key.ConfirmBeforeUse = confirmBeforeUse + key.ConstraintExtensions = constraintExtensions + return nil +} + +func parseRSAKey(req []byte) (*AddedKey, error) { + var k rsaKeyMsg + if err := ssh.Unmarshal(req, &k); err != nil { + return nil, err + } + if k.E.BitLen() > 30 { + return nil, errors.New("agent: RSA public exponent too large") + } + priv := &rsa.PrivateKey{ + PublicKey: rsa.PublicKey{ + E: int(k.E.Int64()), + N: k.N, + }, + D: k.D, + Primes: []*big.Int{k.P, k.Q}, + } + priv.Precompute() + + addedKey := &AddedKey{PrivateKey: priv, Comment: k.Comments} + if err := setConstraints(addedKey, k.Constraints); err != nil { + return nil, err + } + return addedKey, nil +} + +func parseEd25519Key(req []byte) (*AddedKey, error) { + var k ed25519KeyMsg + if err := ssh.Unmarshal(req, &k); err != nil { + return nil, err + } + priv := ed25519.PrivateKey(k.Priv) + + addedKey := &AddedKey{PrivateKey: &priv, Comment: k.Comments} + if err := setConstraints(addedKey, k.Constraints); err != nil { + return nil, err + } + return addedKey, nil +} + +func parseDSAKey(req []byte) (*AddedKey, error) { + var k dsaKeyMsg + if err := ssh.Unmarshal(req, &k); err != nil { + return nil, err + } + priv := &dsa.PrivateKey{ + PublicKey: dsa.PublicKey{ + Parameters: dsa.Parameters{ + P: k.P, + Q: k.Q, + G: k.G, + }, + Y: k.Y, + }, + X: k.X, + } + + addedKey := &AddedKey{PrivateKey: priv, Comment: k.Comments} + if err := setConstraints(addedKey, k.Constraints); err != nil { + return nil, err + } + return addedKey, nil +} + +func unmarshalECDSA(curveName string, keyBytes []byte, privScalar *big.Int) (priv *ecdsa.PrivateKey, err error) { + priv = &ecdsa.PrivateKey{ + D: privScalar, + } + + switch curveName { + case "nistp256": + priv.Curve = elliptic.P256() + case "nistp384": + priv.Curve = elliptic.P384() + case "nistp521": + priv.Curve = elliptic.P521() + default: + return nil, fmt.Errorf("agent: unknown curve %q", curveName) + } + + priv.X, priv.Y = elliptic.Unmarshal(priv.Curve, keyBytes) + if priv.X == nil || priv.Y == nil { + return nil, errors.New("agent: point not on curve") + } + + return priv, nil +} + +func parseEd25519Cert(req []byte) (*AddedKey, error) { + var k ed25519CertMsg + if err := ssh.Unmarshal(req, &k); err != nil { + return nil, err + } + pubKey, err := ssh.ParsePublicKey(k.CertBytes) + if err != nil { + return nil, err + } + priv := ed25519.PrivateKey(k.Priv) + cert, ok := pubKey.(*ssh.Certificate) + if !ok { + return nil, errors.New("agent: bad ED25519 certificate") + } + + addedKey := &AddedKey{PrivateKey: &priv, Certificate: cert, Comment: k.Comments} + if err := setConstraints(addedKey, k.Constraints); err != nil { + return nil, err + } + return addedKey, nil +} + +func parseECDSAKey(req []byte) (*AddedKey, error) { + var k ecdsaKeyMsg + if err := ssh.Unmarshal(req, &k); err != nil { + return nil, err + } + + priv, err := unmarshalECDSA(k.Curve, k.KeyBytes, k.D) + if err != nil { + return nil, err + } + + addedKey := &AddedKey{PrivateKey: priv, Comment: k.Comments} + if err := setConstraints(addedKey, k.Constraints); err != nil { + return nil, err + } + return addedKey, nil +} + +func parseRSACert(req []byte) (*AddedKey, error) { + var k rsaCertMsg + if err := ssh.Unmarshal(req, &k); err != nil { + return nil, err + } + + pubKey, err := ssh.ParsePublicKey(k.CertBytes) + if err != nil { + return nil, err + } + + cert, ok := pubKey.(*ssh.Certificate) + if !ok { + return nil, errors.New("agent: bad RSA certificate") + } + + // An RSA publickey as marshaled by rsaPublicKey.Marshal() in keys.go + var rsaPub struct { + Name string + E *big.Int + N *big.Int + } + if err := ssh.Unmarshal(cert.Key.Marshal(), &rsaPub); err != nil { + return nil, fmt.Errorf("agent: Unmarshal failed to parse public key: %v", err) + } + + if rsaPub.E.BitLen() > 30 { + return nil, errors.New("agent: RSA public exponent too large") + } + + priv := rsa.PrivateKey{ + PublicKey: rsa.PublicKey{ + E: int(rsaPub.E.Int64()), + N: rsaPub.N, + }, + D: k.D, + Primes: []*big.Int{k.Q, k.P}, + } + priv.Precompute() + + addedKey := &AddedKey{PrivateKey: &priv, Certificate: cert, Comment: k.Comments} + if err := setConstraints(addedKey, k.Constraints); err != nil { + return nil, err + } + return addedKey, nil +} + +func parseDSACert(req []byte) (*AddedKey, error) { + var k dsaCertMsg + if err := ssh.Unmarshal(req, &k); err != nil { + return nil, err + } + pubKey, err := ssh.ParsePublicKey(k.CertBytes) + if err != nil { + return nil, err + } + cert, ok := pubKey.(*ssh.Certificate) + if !ok { + return nil, errors.New("agent: bad DSA certificate") + } + + // A DSA publickey as marshaled by dsaPublicKey.Marshal() in keys.go + var w struct { + Name string + P, Q, G, Y *big.Int + } + if err := ssh.Unmarshal(cert.Key.Marshal(), &w); err != nil { + return nil, fmt.Errorf("agent: Unmarshal failed to parse public key: %v", err) + } + + priv := &dsa.PrivateKey{ + PublicKey: dsa.PublicKey{ + Parameters: dsa.Parameters{ + P: w.P, + Q: w.Q, + G: w.G, + }, + Y: w.Y, + }, + X: k.X, + } + + addedKey := &AddedKey{PrivateKey: priv, Certificate: cert, Comment: k.Comments} + if err := setConstraints(addedKey, k.Constraints); err != nil { + return nil, err + } + return addedKey, nil +} + +func parseECDSACert(req []byte) (*AddedKey, error) { + var k ecdsaCertMsg + if err := ssh.Unmarshal(req, &k); err != nil { + return nil, err + } + + pubKey, err := ssh.ParsePublicKey(k.CertBytes) + if err != nil { + return nil, err + } + cert, ok := pubKey.(*ssh.Certificate) + if !ok { + return nil, errors.New("agent: bad ECDSA certificate") + } + + // An ECDSA publickey as marshaled by ecdsaPublicKey.Marshal() in keys.go + var ecdsaPub struct { + Name string + ID string + Key []byte + } + if err := ssh.Unmarshal(cert.Key.Marshal(), &ecdsaPub); err != nil { + return nil, err + } + + priv, err := unmarshalECDSA(ecdsaPub.ID, ecdsaPub.Key, k.D) + if err != nil { + return nil, err + } + + addedKey := &AddedKey{PrivateKey: priv, Certificate: cert, Comment: k.Comments} + if err := setConstraints(addedKey, k.Constraints); err != nil { + return nil, err + } + return addedKey, nil +} + +func (s *server) insertIdentity(req []byte) error { + var record struct { + Type string `sshtype:"17|25"` + Rest []byte `ssh:"rest"` + } + + if err := ssh.Unmarshal(req, &record); err != nil { + return err + } + + var addedKey *AddedKey + var err error + + switch record.Type { + case ssh.KeyAlgoRSA: + addedKey, err = parseRSAKey(req) + case ssh.KeyAlgoDSA: + addedKey, err = parseDSAKey(req) + case ssh.KeyAlgoECDSA256, ssh.KeyAlgoECDSA384, ssh.KeyAlgoECDSA521: + addedKey, err = parseECDSAKey(req) + case ssh.KeyAlgoED25519: + addedKey, err = parseEd25519Key(req) + case ssh.CertAlgoRSAv01: + addedKey, err = parseRSACert(req) + case ssh.CertAlgoDSAv01: + addedKey, err = parseDSACert(req) + case ssh.CertAlgoECDSA256v01, ssh.CertAlgoECDSA384v01, ssh.CertAlgoECDSA521v01: + addedKey, err = parseECDSACert(req) + case ssh.CertAlgoED25519v01: + addedKey, err = parseEd25519Cert(req) + default: + return fmt.Errorf("agent: not implemented: %q", record.Type) + } + + if err != nil { + return err + } + return s.agent.Add(*addedKey) +} + +// ServeAgent serves the agent protocol on the given connection. It +// returns when an I/O error occurs. +func ServeAgent(agent Agent, c io.ReadWriter) error { + s := &server{agent} + + var length [4]byte + for { + if _, err := io.ReadFull(c, length[:]); err != nil { + return err + } + l := binary.BigEndian.Uint32(length[:]) + if l > maxAgentResponseBytes { + // We also cap requests. + return fmt.Errorf("agent: request too large: %d", l) + } + + req := make([]byte, l) + if _, err := io.ReadFull(c, req); err != nil { + return err + } + + repData := s.processRequestBytes(req) + if len(repData) > maxAgentResponseBytes { + return fmt.Errorf("agent: reply too large: %d bytes", len(repData)) + } + + binary.BigEndian.PutUint32(length[:], uint32(len(repData))) + if _, err := c.Write(length[:]); err != nil { + return err + } + if _, err := c.Write(repData); err != nil { + return err + } + } +} diff --git a/vendor/golang.org/x/crypto/ssh/agent/server_test.go b/vendor/golang.org/x/crypto/ssh/agent/server_test.go new file mode 100644 index 0000000000000000000000000000000000000000..038018ebb18fb1d36cd44eb1cdbefc600528f6aa --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/agent/server_test.go @@ -0,0 +1,259 @@ +// 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 agent + +import ( + "crypto" + "crypto/rand" + "fmt" + pseudorand "math/rand" + "reflect" + "strings" + "testing" + + "golang.org/x/crypto/ssh" +) + +func TestServer(t *testing.T) { + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + client := NewClient(c1) + + go ServeAgent(NewKeyring(), c2) + + testAgentInterface(t, client, testPrivateKeys["rsa"], nil, 0) +} + +func TestLockServer(t *testing.T) { + testLockAgent(NewKeyring(), t) +} + +func TestSetupForwardAgent(t *testing.T) { + a, b, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + + defer a.Close() + defer b.Close() + + _, socket, cleanup := startOpenSSHAgent(t) + defer cleanup() + + serverConf := ssh.ServerConfig{ + NoClientAuth: true, + } + serverConf.AddHostKey(testSigners["rsa"]) + incoming := make(chan *ssh.ServerConn, 1) + go func() { + conn, _, _, err := ssh.NewServerConn(a, &serverConf) + if err != nil { + t.Fatalf("Server: %v", err) + } + incoming <- conn + }() + + conf := ssh.ClientConfig{ + HostKeyCallback: ssh.InsecureIgnoreHostKey(), + } + conn, chans, reqs, err := ssh.NewClientConn(b, "", &conf) + if err != nil { + t.Fatalf("NewClientConn: %v", err) + } + client := ssh.NewClient(conn, chans, reqs) + + if err := ForwardToRemote(client, socket); err != nil { + t.Fatalf("SetupForwardAgent: %v", err) + } + + server := <-incoming + ch, reqs, err := server.OpenChannel(channelType, nil) + if err != nil { + t.Fatalf("OpenChannel(%q): %v", channelType, err) + } + go ssh.DiscardRequests(reqs) + + agentClient := NewClient(ch) + testAgentInterface(t, agentClient, testPrivateKeys["rsa"], nil, 0) + conn.Close() +} + +func TestV1ProtocolMessages(t *testing.T) { + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + c := NewClient(c1) + + go ServeAgent(NewKeyring(), c2) + + testV1ProtocolMessages(t, c.(*client)) +} + +func testV1ProtocolMessages(t *testing.T, c *client) { + reply, err := c.call([]byte{agentRequestV1Identities}) + if err != nil { + t.Fatalf("v1 request all failed: %v", err) + } + if msg, ok := reply.(*agentV1IdentityMsg); !ok || msg.Numkeys != 0 { + t.Fatalf("invalid request all response: %#v", reply) + } + + reply, err = c.call([]byte{agentRemoveAllV1Identities}) + if err != nil { + t.Fatalf("v1 remove all failed: %v", err) + } + if _, ok := reply.(*successAgentMsg); !ok { + t.Fatalf("invalid remove all response: %#v", reply) + } +} + +func verifyKey(sshAgent Agent) error { + keys, err := sshAgent.List() + if err != nil { + return fmt.Errorf("listing keys: %v", err) + } + + if len(keys) != 1 { + return fmt.Errorf("bad number of keys found. expected 1, got %d", len(keys)) + } + + buf := make([]byte, 128) + if _, err := rand.Read(buf); err != nil { + return fmt.Errorf("rand: %v", err) + } + + sig, err := sshAgent.Sign(keys[0], buf) + if err != nil { + return fmt.Errorf("sign: %v", err) + } + + if err := keys[0].Verify(buf, sig); err != nil { + return fmt.Errorf("verify: %v", err) + } + return nil +} + +func addKeyToAgent(key crypto.PrivateKey) error { + sshAgent := NewKeyring() + if err := sshAgent.Add(AddedKey{PrivateKey: key}); err != nil { + return fmt.Errorf("add: %v", err) + } + return verifyKey(sshAgent) +} + +func TestKeyTypes(t *testing.T) { + for k, v := range testPrivateKeys { + if err := addKeyToAgent(v); err != nil { + t.Errorf("error adding key type %s, %v", k, err) + } + if err := addCertToAgentSock(v, nil); err != nil { + t.Errorf("error adding key type %s, %v", k, err) + } + } +} + +func addCertToAgentSock(key crypto.PrivateKey, cert *ssh.Certificate) error { + a, b, err := netPipe() + if err != nil { + return err + } + agentServer := NewKeyring() + go ServeAgent(agentServer, a) + + agentClient := NewClient(b) + if err := agentClient.Add(AddedKey{PrivateKey: key, Certificate: cert}); err != nil { + return fmt.Errorf("add: %v", err) + } + return verifyKey(agentClient) +} + +func addCertToAgent(key crypto.PrivateKey, cert *ssh.Certificate) error { + sshAgent := NewKeyring() + if err := sshAgent.Add(AddedKey{PrivateKey: key, Certificate: cert}); err != nil { + return fmt.Errorf("add: %v", err) + } + return verifyKey(sshAgent) +} + +func TestCertTypes(t *testing.T) { + for keyType, key := range testPublicKeys { + cert := &ssh.Certificate{ + ValidPrincipals: []string{"gopher1"}, + ValidAfter: 0, + ValidBefore: ssh.CertTimeInfinity, + Key: key, + Serial: 1, + CertType: ssh.UserCert, + SignatureKey: testPublicKeys["rsa"], + Permissions: ssh.Permissions{ + CriticalOptions: map[string]string{}, + Extensions: map[string]string{}, + }, + } + if err := cert.SignCert(rand.Reader, testSigners["rsa"]); err != nil { + t.Fatalf("signcert: %v", err) + } + if err := addCertToAgent(testPrivateKeys[keyType], cert); err != nil { + t.Fatalf("%v", err) + } + if err := addCertToAgentSock(testPrivateKeys[keyType], cert); err != nil { + t.Fatalf("%v", err) + } + } +} + +func TestParseConstraints(t *testing.T) { + // Test LifetimeSecs + var msg = constrainLifetimeAgentMsg{pseudorand.Uint32()} + lifetimeSecs, _, _, err := parseConstraints(ssh.Marshal(msg)) + if err != nil { + t.Fatalf("parseConstraints: %v", err) + } + if lifetimeSecs != msg.LifetimeSecs { + t.Errorf("got lifetime %v, want %v", lifetimeSecs, msg.LifetimeSecs) + } + + // Test ConfirmBeforeUse + _, confirmBeforeUse, _, err := parseConstraints([]byte{agentConstrainConfirm}) + if err != nil { + t.Fatalf("%v", err) + } + if !confirmBeforeUse { + t.Error("got comfirmBeforeUse == false") + } + + // Test ConstraintExtensions + var data []byte + var expect []ConstraintExtension + for i := 0; i < 10; i++ { + var ext = ConstraintExtension{ + ExtensionName: fmt.Sprintf("name%d", i), + ExtensionDetails: []byte(fmt.Sprintf("details: %d", i)), + } + expect = append(expect, ext) + data = append(data, agentConstrainExtension) + data = append(data, ssh.Marshal(ext)...) + } + _, _, extensions, err := parseConstraints(data) + if err != nil { + t.Fatalf("%v", err) + } + if !reflect.DeepEqual(expect, extensions) { + t.Errorf("got extension %v, want %v", extensions, expect) + } + + // Test Unknown Constraint + _, _, _, err = parseConstraints([]byte{128}) + if err == nil || !strings.Contains(err.Error(), "unknown constraint") { + t.Errorf("unexpected error: %v", err) + } +} diff --git a/vendor/golang.org/x/crypto/ssh/agent/testdata_test.go b/vendor/golang.org/x/crypto/ssh/agent/testdata_test.go new file mode 100644 index 0000000000000000000000000000000000000000..cc42a87cb967ea82b8f1f8b5a72171c42b5ae9dd --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/agent/testdata_test.go @@ -0,0 +1,64 @@ +// 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. + +// IMPLEMENTATION NOTE: To avoid a package loop, this file is in three places: +// ssh/, ssh/agent, and ssh/test/. It should be kept in sync across all three +// instances. + +package agent + +import ( + "crypto/rand" + "fmt" + + "golang.org/x/crypto/ssh" + "golang.org/x/crypto/ssh/testdata" +) + +var ( + testPrivateKeys map[string]interface{} + testSigners map[string]ssh.Signer + testPublicKeys map[string]ssh.PublicKey +) + +func init() { + var err error + + n := len(testdata.PEMBytes) + testPrivateKeys = make(map[string]interface{}, n) + testSigners = make(map[string]ssh.Signer, n) + testPublicKeys = make(map[string]ssh.PublicKey, n) + for t, k := range testdata.PEMBytes { + testPrivateKeys[t], err = ssh.ParseRawPrivateKey(k) + if err != nil { + panic(fmt.Sprintf("Unable to parse test key %s: %v", t, err)) + } + testSigners[t], err = ssh.NewSignerFromKey(testPrivateKeys[t]) + if err != nil { + panic(fmt.Sprintf("Unable to create signer for test key %s: %v", t, err)) + } + testPublicKeys[t] = testSigners[t].PublicKey() + } + + // Create a cert and sign it for use in tests. + testCert := &ssh.Certificate{ + Nonce: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil + ValidPrincipals: []string{"gopher1", "gopher2"}, // increases test coverage + ValidAfter: 0, // unix epoch + ValidBefore: ssh.CertTimeInfinity, // The end of currently representable time. + Reserved: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil + Key: testPublicKeys["ecdsa"], + SignatureKey: testPublicKeys["rsa"], + Permissions: ssh.Permissions{ + CriticalOptions: map[string]string{}, + Extensions: map[string]string{}, + }, + } + testCert.SignCert(rand.Reader, testSigners["rsa"]) + testPrivateKeys["cert"] = testPrivateKeys["ecdsa"] + testSigners["cert"], err = ssh.NewCertSigner(testCert, testSigners["ecdsa"]) + if err != nil { + panic(fmt.Sprintf("Unable to create certificate signer: %v", err)) + } +} diff --git a/vendor/golang.org/x/crypto/ssh/benchmark_test.go b/vendor/golang.org/x/crypto/ssh/benchmark_test.go new file mode 100644 index 0000000000000000000000000000000000000000..20c33077318b1245535287d79dbabdf33b621f65 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/benchmark_test.go @@ -0,0 +1,123 @@ +// 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. + +package ssh + +import ( + "errors" + "io" + "net" + "testing" +) + +type server struct { + *ServerConn + chans <-chan NewChannel +} + +func newServer(c net.Conn, conf *ServerConfig) (*server, error) { + sconn, chans, reqs, err := NewServerConn(c, conf) + if err != nil { + return nil, err + } + go DiscardRequests(reqs) + return &server{sconn, chans}, nil +} + +func (s *server) Accept() (NewChannel, error) { + n, ok := <-s.chans + if !ok { + return nil, io.EOF + } + return n, nil +} + +func sshPipe() (Conn, *server, error) { + c1, c2, err := netPipe() + if err != nil { + return nil, nil, err + } + + clientConf := ClientConfig{ + User: "user", + HostKeyCallback: InsecureIgnoreHostKey(), + } + serverConf := ServerConfig{ + NoClientAuth: true, + } + serverConf.AddHostKey(testSigners["ecdsa"]) + done := make(chan *server, 1) + go func() { + server, err := newServer(c2, &serverConf) + if err != nil { + done <- nil + } + done <- server + }() + + client, _, reqs, err := NewClientConn(c1, "", &clientConf) + if err != nil { + return nil, nil, err + } + + server := <-done + if server == nil { + return nil, nil, errors.New("server handshake failed.") + } + go DiscardRequests(reqs) + + return client, server, nil +} + +func BenchmarkEndToEnd(b *testing.B) { + b.StopTimer() + + client, server, err := sshPipe() + if err != nil { + b.Fatalf("sshPipe: %v", err) + } + + defer client.Close() + defer server.Close() + + size := (1 << 20) + input := make([]byte, size) + output := make([]byte, size) + b.SetBytes(int64(size)) + done := make(chan int, 1) + + go func() { + newCh, err := server.Accept() + if err != nil { + b.Fatalf("Client: %v", err) + } + ch, incoming, err := newCh.Accept() + go DiscardRequests(incoming) + for i := 0; i < b.N; i++ { + if _, err := io.ReadFull(ch, output); err != nil { + b.Fatalf("ReadFull: %v", err) + } + } + ch.Close() + done <- 1 + }() + + ch, in, err := client.OpenChannel("speed", nil) + if err != nil { + b.Fatalf("OpenChannel: %v", err) + } + go DiscardRequests(in) + + b.ResetTimer() + b.StartTimer() + for i := 0; i < b.N; i++ { + if _, err := ch.Write(input); err != nil { + b.Fatalf("WriteFull: %v", err) + } + } + ch.Close() + b.StopTimer() + + <-done +} diff --git a/vendor/golang.org/x/crypto/ssh/buffer.go b/vendor/golang.org/x/crypto/ssh/buffer.go new file mode 100644 index 0000000000000000000000000000000000000000..1ab07d078db1633be8977102b2defc0da0a6d4e8 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/buffer.go @@ -0,0 +1,97 @@ +// 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 ssh + +import ( + "io" + "sync" +) + +// buffer provides a linked list buffer for data exchange +// between producer and consumer. Theoretically the buffer is +// of unlimited capacity as it does no allocation of its own. +type buffer struct { + // protects concurrent access to head, tail and closed + *sync.Cond + + head *element // the buffer that will be read first + tail *element // the buffer that will be read last + + closed bool +} + +// An element represents a single link in a linked list. +type element struct { + buf []byte + next *element +} + +// newBuffer returns an empty buffer that is not closed. +func newBuffer() *buffer { + e := new(element) + b := &buffer{ + Cond: newCond(), + head: e, + tail: e, + } + return b +} + +// write makes buf available for Read to receive. +// buf must not be modified after the call to write. +func (b *buffer) write(buf []byte) { + b.Cond.L.Lock() + e := &element{buf: buf} + b.tail.next = e + b.tail = e + b.Cond.Signal() + b.Cond.L.Unlock() +} + +// eof closes the buffer. Reads from the buffer once all +// the data has been consumed will receive io.EOF. +func (b *buffer) eof() { + b.Cond.L.Lock() + b.closed = true + b.Cond.Signal() + b.Cond.L.Unlock() +} + +// Read reads data from the internal buffer in buf. Reads will block +// if no data is available, or until the buffer is closed. +func (b *buffer) Read(buf []byte) (n int, err error) { + b.Cond.L.Lock() + defer b.Cond.L.Unlock() + + for len(buf) > 0 { + // if there is data in b.head, copy it + if len(b.head.buf) > 0 { + r := copy(buf, b.head.buf) + buf, b.head.buf = buf[r:], b.head.buf[r:] + n += r + continue + } + // if there is a next buffer, make it the head + if len(b.head.buf) == 0 && b.head != b.tail { + b.head = b.head.next + continue + } + + // if at least one byte has been copied, return + if n > 0 { + break + } + + // if nothing was read, and there is nothing outstanding + // check to see if the buffer is closed. + if b.closed { + err = io.EOF + break + } + // out of buffers, wait for producer + b.Cond.Wait() + } + return +} diff --git a/vendor/golang.org/x/crypto/ssh/buffer_test.go b/vendor/golang.org/x/crypto/ssh/buffer_test.go new file mode 100644 index 0000000000000000000000000000000000000000..d5781cb3da997f1c0e1de74aead1e22004475f72 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/buffer_test.go @@ -0,0 +1,87 @@ +// 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 ssh + +import ( + "io" + "testing" +) + +var alphabet = []byte("abcdefghijklmnopqrstuvwxyz") + +func TestBufferReadwrite(t *testing.T) { + b := newBuffer() + b.write(alphabet[:10]) + r, _ := b.Read(make([]byte, 10)) + if r != 10 { + t.Fatalf("Expected written == read == 10, written: 10, read %d", r) + } + + b = newBuffer() + b.write(alphabet[:5]) + r, _ = b.Read(make([]byte, 10)) + if r != 5 { + t.Fatalf("Expected written == read == 5, written: 5, read %d", r) + } + + b = newBuffer() + b.write(alphabet[:10]) + r, _ = b.Read(make([]byte, 5)) + if r != 5 { + t.Fatalf("Expected written == 10, read == 5, written: 10, read %d", r) + } + + b = newBuffer() + b.write(alphabet[:5]) + b.write(alphabet[5:15]) + r, _ = b.Read(make([]byte, 10)) + r2, _ := b.Read(make([]byte, 10)) + if r != 10 || r2 != 5 || 15 != r+r2 { + t.Fatal("Expected written == read == 15") + } +} + +func TestBufferClose(t *testing.T) { + b := newBuffer() + b.write(alphabet[:10]) + b.eof() + _, err := b.Read(make([]byte, 5)) + if err != nil { + t.Fatal("expected read of 5 to not return EOF") + } + b = newBuffer() + b.write(alphabet[:10]) + b.eof() + r, err := b.Read(make([]byte, 5)) + r2, err2 := b.Read(make([]byte, 10)) + if r != 5 || r2 != 5 || err != nil || err2 != nil { + t.Fatal("expected reads of 5 and 5") + } + + b = newBuffer() + b.write(alphabet[:10]) + b.eof() + r, err = b.Read(make([]byte, 5)) + r2, err2 = b.Read(make([]byte, 10)) + r3, err3 := b.Read(make([]byte, 10)) + if r != 5 || r2 != 5 || r3 != 0 || err != nil || err2 != nil || err3 != io.EOF { + t.Fatal("expected reads of 5 and 5 and 0, with EOF") + } + + b = newBuffer() + b.write(make([]byte, 5)) + b.write(make([]byte, 10)) + b.eof() + r, err = b.Read(make([]byte, 9)) + r2, err2 = b.Read(make([]byte, 3)) + r3, err3 = b.Read(make([]byte, 3)) + r4, err4 := b.Read(make([]byte, 10)) + if err != nil || err2 != nil || err3 != nil || err4 != io.EOF { + t.Fatalf("Expected EOF on forth read only, err=%v, err2=%v, err3=%v, err4=%v", err, err2, err3, err4) + } + if r != 9 || r2 != 3 || r3 != 3 || r4 != 0 { + t.Fatal("Expected written == read == 15", r, r2, r3, r4) + } +} diff --git a/vendor/golang.org/x/crypto/ssh/certs.go b/vendor/golang.org/x/crypto/ssh/certs.go new file mode 100644 index 0000000000000000000000000000000000000000..cfc8ead1bcae29142a037e66214cec847e511198 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/certs.go @@ -0,0 +1,519 @@ +// 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 ssh + +import ( + "bytes" + "errors" + "fmt" + "io" + "net" + "sort" + "time" +) + +// These constants from [PROTOCOL.certkeys] represent the algorithm names +// for certificate types supported by this package. +const ( + CertAlgoRSAv01 = "ssh-rsa-cert-v01@openssh.com" + CertAlgoDSAv01 = "ssh-dss-cert-v01@openssh.com" + CertAlgoECDSA256v01 = "ecdsa-sha2-nistp256-cert-v01@openssh.com" + CertAlgoECDSA384v01 = "ecdsa-sha2-nistp384-cert-v01@openssh.com" + CertAlgoECDSA521v01 = "ecdsa-sha2-nistp521-cert-v01@openssh.com" + CertAlgoED25519v01 = "ssh-ed25519-cert-v01@openssh.com" +) + +// Certificate types distinguish between host and user +// certificates. The values can be set in the CertType field of +// Certificate. +const ( + UserCert = 1 + HostCert = 2 +) + +// Signature represents a cryptographic signature. +type Signature struct { + Format string + Blob []byte +} + +// CertTimeInfinity can be used for OpenSSHCertV01.ValidBefore to indicate that +// a certificate does not expire. +const CertTimeInfinity = 1<<64 - 1 + +// An Certificate represents an OpenSSH certificate as defined in +// [PROTOCOL.certkeys]?rev=1.8. +type Certificate struct { + Nonce []byte + Key PublicKey + Serial uint64 + CertType uint32 + KeyId string + ValidPrincipals []string + ValidAfter uint64 + ValidBefore uint64 + Permissions + Reserved []byte + SignatureKey PublicKey + Signature *Signature +} + +// genericCertData holds the key-independent part of the certificate data. +// Overall, certificates contain an nonce, public key fields and +// key-independent fields. +type genericCertData struct { + Serial uint64 + CertType uint32 + KeyId string + ValidPrincipals []byte + ValidAfter uint64 + ValidBefore uint64 + CriticalOptions []byte + Extensions []byte + Reserved []byte + SignatureKey []byte + Signature []byte +} + +func marshalStringList(namelist []string) []byte { + var to []byte + for _, name := range namelist { + s := struct{ N string }{name} + to = append(to, Marshal(&s)...) + } + return to +} + +type optionsTuple struct { + Key string + Value []byte +} + +type optionsTupleValue struct { + Value string +} + +// serialize a map of critical options or extensions +// issue #10569 - per [PROTOCOL.certkeys] and SSH implementation, +// we need two length prefixes for a non-empty string value +func marshalTuples(tups map[string]string) []byte { + keys := make([]string, 0, len(tups)) + for key := range tups { + keys = append(keys, key) + } + sort.Strings(keys) + + var ret []byte + for _, key := range keys { + s := optionsTuple{Key: key} + if value := tups[key]; len(value) > 0 { + s.Value = Marshal(&optionsTupleValue{value}) + } + ret = append(ret, Marshal(&s)...) + } + return ret +} + +// issue #10569 - per [PROTOCOL.certkeys] and SSH implementation, +// we need two length prefixes for a non-empty option value +func parseTuples(in []byte) (map[string]string, error) { + tups := map[string]string{} + var lastKey string + var haveLastKey bool + + for len(in) > 0 { + var key, val, extra []byte + var ok bool + + if key, in, ok = parseString(in); !ok { + return nil, errShortRead + } + keyStr := string(key) + // according to [PROTOCOL.certkeys], the names must be in + // lexical order. + if haveLastKey && keyStr <= lastKey { + return nil, fmt.Errorf("ssh: certificate options are not in lexical order") + } + lastKey, haveLastKey = keyStr, true + // the next field is a data field, which if non-empty has a string embedded + if val, in, ok = parseString(in); !ok { + return nil, errShortRead + } + if len(val) > 0 { + val, extra, ok = parseString(val) + if !ok { + return nil, errShortRead + } + if len(extra) > 0 { + return nil, fmt.Errorf("ssh: unexpected trailing data after certificate option value") + } + tups[keyStr] = string(val) + } else { + tups[keyStr] = "" + } + } + return tups, nil +} + +func parseCert(in []byte, privAlgo string) (*Certificate, error) { + nonce, rest, ok := parseString(in) + if !ok { + return nil, errShortRead + } + + key, rest, err := parsePubKey(rest, privAlgo) + if err != nil { + return nil, err + } + + var g genericCertData + if err := Unmarshal(rest, &g); err != nil { + return nil, err + } + + c := &Certificate{ + Nonce: nonce, + Key: key, + Serial: g.Serial, + CertType: g.CertType, + KeyId: g.KeyId, + ValidAfter: g.ValidAfter, + ValidBefore: g.ValidBefore, + } + + for principals := g.ValidPrincipals; len(principals) > 0; { + principal, rest, ok := parseString(principals) + if !ok { + return nil, errShortRead + } + c.ValidPrincipals = append(c.ValidPrincipals, string(principal)) + principals = rest + } + + c.CriticalOptions, err = parseTuples(g.CriticalOptions) + if err != nil { + return nil, err + } + c.Extensions, err = parseTuples(g.Extensions) + if err != nil { + return nil, err + } + c.Reserved = g.Reserved + k, err := ParsePublicKey(g.SignatureKey) + if err != nil { + return nil, err + } + + c.SignatureKey = k + c.Signature, rest, ok = parseSignatureBody(g.Signature) + if !ok || len(rest) > 0 { + return nil, errors.New("ssh: signature parse error") + } + + return c, nil +} + +type openSSHCertSigner struct { + pub *Certificate + signer Signer +} + +// NewCertSigner returns a Signer that signs with the given Certificate, whose +// private key is held by signer. It returns an error if the public key in cert +// doesn't match the key used by signer. +func NewCertSigner(cert *Certificate, signer Signer) (Signer, error) { + if bytes.Compare(cert.Key.Marshal(), signer.PublicKey().Marshal()) != 0 { + return nil, errors.New("ssh: signer and cert have different public key") + } + + return &openSSHCertSigner{cert, signer}, nil +} + +func (s *openSSHCertSigner) Sign(rand io.Reader, data []byte) (*Signature, error) { + return s.signer.Sign(rand, data) +} + +func (s *openSSHCertSigner) PublicKey() PublicKey { + return s.pub +} + +const sourceAddressCriticalOption = "source-address" + +// CertChecker does the work of verifying a certificate. Its methods +// can be plugged into ClientConfig.HostKeyCallback and +// ServerConfig.PublicKeyCallback. For the CertChecker to work, +// minimally, the IsAuthority callback should be set. +type CertChecker struct { + // SupportedCriticalOptions lists the CriticalOptions that the + // server application layer understands. These are only used + // for user certificates. + SupportedCriticalOptions []string + + // IsUserAuthority should return true if the key is recognized as an + // authority for the given user certificate. This allows for + // certificates to be signed by other certificates. This must be set + // if this CertChecker will be checking user certificates. + IsUserAuthority func(auth PublicKey) bool + + // IsHostAuthority should report whether the key is recognized as + // an authority for this host. This allows for certificates to be + // signed by other keys, and for those other keys to only be valid + // signers for particular hostnames. This must be set if this + // CertChecker will be checking host certificates. + IsHostAuthority func(auth PublicKey, address string) bool + + // Clock is used for verifying time stamps. If nil, time.Now + // is used. + Clock func() time.Time + + // UserKeyFallback is called when CertChecker.Authenticate encounters a + // public key that is not a certificate. It must implement validation + // of user keys or else, if nil, all such keys are rejected. + UserKeyFallback func(conn ConnMetadata, key PublicKey) (*Permissions, error) + + // HostKeyFallback is called when CertChecker.CheckHostKey encounters a + // public key that is not a certificate. It must implement host key + // validation or else, if nil, all such keys are rejected. + HostKeyFallback HostKeyCallback + + // IsRevoked is called for each certificate so that revocation checking + // can be implemented. It should return true if the given certificate + // is revoked and false otherwise. If nil, no certificates are + // considered to have been revoked. + IsRevoked func(cert *Certificate) bool +} + +// CheckHostKey checks a host key certificate. This method can be +// plugged into ClientConfig.HostKeyCallback. +func (c *CertChecker) CheckHostKey(addr string, remote net.Addr, key PublicKey) error { + cert, ok := key.(*Certificate) + if !ok { + if c.HostKeyFallback != nil { + return c.HostKeyFallback(addr, remote, key) + } + return errors.New("ssh: non-certificate host key") + } + if cert.CertType != HostCert { + return fmt.Errorf("ssh: certificate presented as a host key has type %d", cert.CertType) + } + if !c.IsHostAuthority(cert.SignatureKey, addr) { + return fmt.Errorf("ssh: no authorities for hostname: %v", addr) + } + + hostname, _, err := net.SplitHostPort(addr) + if err != nil { + return err + } + + // Pass hostname only as principal for host certificates (consistent with OpenSSH) + return c.CheckCert(hostname, cert) +} + +// Authenticate checks a user certificate. Authenticate can be used as +// a value for ServerConfig.PublicKeyCallback. +func (c *CertChecker) Authenticate(conn ConnMetadata, pubKey PublicKey) (*Permissions, error) { + cert, ok := pubKey.(*Certificate) + if !ok { + if c.UserKeyFallback != nil { + return c.UserKeyFallback(conn, pubKey) + } + return nil, errors.New("ssh: normal key pairs not accepted") + } + + if cert.CertType != UserCert { + return nil, fmt.Errorf("ssh: cert has type %d", cert.CertType) + } + if !c.IsUserAuthority(cert.SignatureKey) { + return nil, fmt.Errorf("ssh: certificate signed by unrecognized authority") + } + + if err := c.CheckCert(conn.User(), cert); err != nil { + return nil, err + } + + return &cert.Permissions, nil +} + +// CheckCert checks CriticalOptions, ValidPrincipals, revocation, timestamp and +// the signature of the certificate. +func (c *CertChecker) CheckCert(principal string, cert *Certificate) error { + if c.IsRevoked != nil && c.IsRevoked(cert) { + return fmt.Errorf("ssh: certificate serial %d revoked", cert.Serial) + } + + for opt := range cert.CriticalOptions { + // sourceAddressCriticalOption will be enforced by + // serverAuthenticate + if opt == sourceAddressCriticalOption { + continue + } + + found := false + for _, supp := range c.SupportedCriticalOptions { + if supp == opt { + found = true + break + } + } + if !found { + return fmt.Errorf("ssh: unsupported critical option %q in certificate", opt) + } + } + + if len(cert.ValidPrincipals) > 0 { + // By default, certs are valid for all users/hosts. + found := false + for _, p := range cert.ValidPrincipals { + if p == principal { + found = true + break + } + } + if !found { + return fmt.Errorf("ssh: principal %q not in the set of valid principals for given certificate: %q", principal, cert.ValidPrincipals) + } + } + + clock := c.Clock + if clock == nil { + clock = time.Now + } + + unixNow := clock().Unix() + if after := int64(cert.ValidAfter); after < 0 || unixNow < int64(cert.ValidAfter) { + return fmt.Errorf("ssh: cert is not yet valid") + } + if before := int64(cert.ValidBefore); cert.ValidBefore != uint64(CertTimeInfinity) && (unixNow >= before || before < 0) { + return fmt.Errorf("ssh: cert has expired") + } + if err := cert.SignatureKey.Verify(cert.bytesForSigning(), cert.Signature); err != nil { + return fmt.Errorf("ssh: certificate signature does not verify") + } + + return nil +} + +// SignCert sets c.SignatureKey to the authority's public key and stores a +// Signature, by authority, in the certificate. +func (c *Certificate) SignCert(rand io.Reader, authority Signer) error { + c.Nonce = make([]byte, 32) + if _, err := io.ReadFull(rand, c.Nonce); err != nil { + return err + } + c.SignatureKey = authority.PublicKey() + + sig, err := authority.Sign(rand, c.bytesForSigning()) + if err != nil { + return err + } + c.Signature = sig + return nil +} + +var certAlgoNames = map[string]string{ + KeyAlgoRSA: CertAlgoRSAv01, + KeyAlgoDSA: CertAlgoDSAv01, + KeyAlgoECDSA256: CertAlgoECDSA256v01, + KeyAlgoECDSA384: CertAlgoECDSA384v01, + KeyAlgoECDSA521: CertAlgoECDSA521v01, + KeyAlgoED25519: CertAlgoED25519v01, +} + +// certToPrivAlgo returns the underlying algorithm for a certificate algorithm. +// Panics if a non-certificate algorithm is passed. +func certToPrivAlgo(algo string) string { + for privAlgo, pubAlgo := range certAlgoNames { + if pubAlgo == algo { + return privAlgo + } + } + panic("unknown cert algorithm") +} + +func (cert *Certificate) bytesForSigning() []byte { + c2 := *cert + c2.Signature = nil + out := c2.Marshal() + // Drop trailing signature length. + return out[:len(out)-4] +} + +// Marshal serializes c into OpenSSH's wire format. It is part of the +// PublicKey interface. +func (c *Certificate) Marshal() []byte { + generic := genericCertData{ + Serial: c.Serial, + CertType: c.CertType, + KeyId: c.KeyId, + ValidPrincipals: marshalStringList(c.ValidPrincipals), + ValidAfter: uint64(c.ValidAfter), + ValidBefore: uint64(c.ValidBefore), + CriticalOptions: marshalTuples(c.CriticalOptions), + Extensions: marshalTuples(c.Extensions), + Reserved: c.Reserved, + SignatureKey: c.SignatureKey.Marshal(), + } + if c.Signature != nil { + generic.Signature = Marshal(c.Signature) + } + genericBytes := Marshal(&generic) + keyBytes := c.Key.Marshal() + _, keyBytes, _ = parseString(keyBytes) + prefix := Marshal(&struct { + Name string + Nonce []byte + Key []byte `ssh:"rest"` + }{c.Type(), c.Nonce, keyBytes}) + + result := make([]byte, 0, len(prefix)+len(genericBytes)) + result = append(result, prefix...) + result = append(result, genericBytes...) + return result +} + +// Type returns the key name. It is part of the PublicKey interface. +func (c *Certificate) Type() string { + algo, ok := certAlgoNames[c.Key.Type()] + if !ok { + panic("unknown cert key type " + c.Key.Type()) + } + return algo +} + +// Verify verifies a signature against the certificate's public +// key. It is part of the PublicKey interface. +func (c *Certificate) Verify(data []byte, sig *Signature) error { + return c.Key.Verify(data, sig) +} + +func parseSignatureBody(in []byte) (out *Signature, rest []byte, ok bool) { + format, in, ok := parseString(in) + if !ok { + return + } + + out = &Signature{ + Format: string(format), + } + + if out.Blob, in, ok = parseString(in); !ok { + return + } + + return out, in, ok +} + +func parseSignature(in []byte) (out *Signature, rest []byte, ok bool) { + sigBytes, rest, ok := parseString(in) + if !ok { + return + } + + out, trailing, ok := parseSignatureBody(sigBytes) + if !ok || len(trailing) > 0 { + return nil, nil, false + } + return +} diff --git a/vendor/golang.org/x/crypto/ssh/certs_test.go b/vendor/golang.org/x/crypto/ssh/certs_test.go new file mode 100644 index 0000000000000000000000000000000000000000..c8e7cf5851159beac3674c2752281c80034a65fc --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/certs_test.go @@ -0,0 +1,335 @@ +// 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. + +package ssh + +import ( + "bytes" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "net" + "reflect" + "testing" + "time" + + "golang.org/x/crypto/ssh/testdata" +) + +// Cert generated by ssh-keygen 6.0p1 Debian-4. +// % ssh-keygen -s ca-key -I test user-key +const exampleSSHCert = `ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgb1srW/W3ZDjYAO45xLYAwzHBDLsJ4Ux6ICFIkTjb1LEAAAADAQABAAAAYQCkoR51poH0wE8w72cqSB8Sszx+vAhzcMdCO0wqHTj7UNENHWEXGrU0E0UQekD7U+yhkhtoyjbPOVIP7hNa6aRk/ezdh/iUnCIt4Jt1v3Z1h1P+hA4QuYFMHNB+rmjPwAcAAAAAAAAAAAAAAAEAAAAEdGVzdAAAAAAAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAAHcAAAAHc3NoLXJzYQAAAAMBAAEAAABhANFS2kaktpSGc+CcmEKPyw9mJC4nZKxHKTgLVZeaGbFZOvJTNzBspQHdy7Q1uKSfktxpgjZnksiu/tFF9ngyY2KFoc+U88ya95IZUycBGCUbBQ8+bhDtw/icdDGQD5WnUwAAAG8AAAAHc3NoLXJzYQAAAGC8Y9Z2LQKhIhxf52773XaWrXdxP0t3GBVo4A10vUWiYoAGepr6rQIoGGXFxT4B9Gp+nEBJjOwKDXPrAevow0T9ca8gZN+0ykbhSrXLE5Ao48rqr3zP4O1/9P7e6gp0gw8=` + +func TestParseCert(t *testing.T) { + authKeyBytes := []byte(exampleSSHCert) + + key, _, _, rest, err := ParseAuthorizedKey(authKeyBytes) + if err != nil { + t.Fatalf("ParseAuthorizedKey: %v", err) + } + if len(rest) > 0 { + t.Errorf("rest: got %q, want empty", rest) + } + + if _, ok := key.(*Certificate); !ok { + t.Fatalf("got %v (%T), want *Certificate", key, key) + } + + marshaled := MarshalAuthorizedKey(key) + // Before comparison, remove the trailing newline that + // MarshalAuthorizedKey adds. + marshaled = marshaled[:len(marshaled)-1] + if !bytes.Equal(authKeyBytes, marshaled) { + t.Errorf("marshaled certificate does not match original: got %q, want %q", marshaled, authKeyBytes) + } +} + +// Cert generated by ssh-keygen OpenSSH_6.8p1 OS X 10.10.3 +// % ssh-keygen -s ca -I testcert -O source-address=192.168.1.0/24 -O force-command=/bin/sleep user.pub +// user.pub key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDACh1rt2DXfV3hk6fszSQcQ/rueMId0kVD9U7nl8cfEnFxqOCrNT92g4laQIGl2mn8lsGZfTLg8ksHq3gkvgO3oo/0wHy4v32JeBOHTsN5AL4gfHNEhWeWb50ev47hnTsRIt9P4dxogeUo/hTu7j9+s9lLpEQXCvq6xocXQt0j8MV9qZBBXFLXVT3cWIkSqOdwt/5ZBg+1GSrc7WfCXVWgTk4a20uPMuJPxU4RQwZW6X3+O8Pqo8C3cW0OzZRFP6gUYUKUsTI5WntlS+LAxgw1mZNsozFGdbiOPRnEryE3SRldh9vjDR3tin1fGpA5P7+CEB/bqaXtG3V+F2OkqaMN +// Critical Options: +// force-command /bin/sleep +// source-address 192.168.1.0/24 +// Extensions: +// permit-X11-forwarding +// permit-agent-forwarding +// permit-port-forwarding +// permit-pty +// permit-user-rc +const exampleSSHCertWithOptions = `ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgDyysCJY0XrO1n03EeRRoITnTPdjENFmWDs9X58PP3VUAAAADAQABAAABAQDACh1rt2DXfV3hk6fszSQcQ/rueMId0kVD9U7nl8cfEnFxqOCrNT92g4laQIGl2mn8lsGZfTLg8ksHq3gkvgO3oo/0wHy4v32JeBOHTsN5AL4gfHNEhWeWb50ev47hnTsRIt9P4dxogeUo/hTu7j9+s9lLpEQXCvq6xocXQt0j8MV9qZBBXFLXVT3cWIkSqOdwt/5ZBg+1GSrc7WfCXVWgTk4a20uPMuJPxU4RQwZW6X3+O8Pqo8C3cW0OzZRFP6gUYUKUsTI5WntlS+LAxgw1mZNsozFGdbiOPRnEryE3SRldh9vjDR3tin1fGpA5P7+CEB/bqaXtG3V+F2OkqaMNAAAAAAAAAAAAAAABAAAACHRlc3RjZXJ0AAAAAAAAAAAAAAAA//////////8AAABLAAAADWZvcmNlLWNvbW1hbmQAAAAOAAAACi9iaW4vc2xlZXAAAAAOc291cmNlLWFkZHJlc3MAAAASAAAADjE5Mi4xNjguMS4wLzI0AAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAABFwAAAAdzc2gtcnNhAAAAAwEAAQAAAQEAwU+c5ui5A8+J/CFpjW8wCa52bEODA808WWQDCSuTG/eMXNf59v9Y8Pk0F1E9dGCosSNyVcB/hacUrc6He+i97+HJCyKavBsE6GDxrjRyxYqAlfcOXi/IVmaUGiO8OQ39d4GHrjToInKvExSUeleQyH4Y4/e27T/pILAqPFL3fyrvMLT5qU9QyIt6zIpa7GBP5+urouNavMprV3zsfIqNBbWypinOQAw823a5wN+zwXnhZrgQiHZ/USG09Y6k98y1dTVz8YHlQVR4D3lpTAsKDKJ5hCH9WU4fdf+lU8OyNGaJ/vz0XNqxcToe1l4numLTnaoSuH89pHryjqurB7lJKwAAAQ8AAAAHc3NoLXJzYQAAAQCaHvUIoPL1zWUHIXLvu96/HU1s/i4CAW2IIEuGgxCUCiFj6vyTyYtgxQxcmbfZf6eaITlS6XJZa7Qq4iaFZh75C1DXTX8labXhRSD4E2t//AIP9MC1rtQC5xo6FmbQ+BoKcDskr+mNACcbRSxs3IL3bwCfWDnIw2WbVox9ZdcthJKk4UoCW4ix4QwdHw7zlddlz++fGEEVhmTbll1SUkycGApPFBsAYRTMupUJcYPIeReBI/m8XfkoMk99bV8ZJQTAd7OekHY2/48Ff53jLmyDjP7kNw1F8OaPtkFs6dGJXta4krmaekPy87j+35In5hFj7yoOqvSbmYUkeX70/GGQ` + +func TestParseCertWithOptions(t *testing.T) { + opts := map[string]string{ + "source-address": "192.168.1.0/24", + "force-command": "/bin/sleep", + } + exts := map[string]string{ + "permit-X11-forwarding": "", + "permit-agent-forwarding": "", + "permit-port-forwarding": "", + "permit-pty": "", + "permit-user-rc": "", + } + authKeyBytes := []byte(exampleSSHCertWithOptions) + + key, _, _, rest, err := ParseAuthorizedKey(authKeyBytes) + if err != nil { + t.Fatalf("ParseAuthorizedKey: %v", err) + } + if len(rest) > 0 { + t.Errorf("rest: got %q, want empty", rest) + } + cert, ok := key.(*Certificate) + if !ok { + t.Fatalf("got %v (%T), want *Certificate", key, key) + } + if !reflect.DeepEqual(cert.CriticalOptions, opts) { + t.Errorf("unexpected critical options - got %v, want %v", cert.CriticalOptions, opts) + } + if !reflect.DeepEqual(cert.Extensions, exts) { + t.Errorf("unexpected Extensions - got %v, want %v", cert.Extensions, exts) + } + marshaled := MarshalAuthorizedKey(key) + // Before comparison, remove the trailing newline that + // MarshalAuthorizedKey adds. + marshaled = marshaled[:len(marshaled)-1] + if !bytes.Equal(authKeyBytes, marshaled) { + t.Errorf("marshaled certificate does not match original: got %q, want %q", marshaled, authKeyBytes) + } +} + +func TestValidateCert(t *testing.T) { + key, _, _, _, err := ParseAuthorizedKey([]byte(exampleSSHCert)) + if err != nil { + t.Fatalf("ParseAuthorizedKey: %v", err) + } + validCert, ok := key.(*Certificate) + if !ok { + t.Fatalf("got %v (%T), want *Certificate", key, key) + } + checker := CertChecker{} + checker.IsUserAuthority = func(k PublicKey) bool { + return bytes.Equal(k.Marshal(), validCert.SignatureKey.Marshal()) + } + + if err := checker.CheckCert("user", validCert); err != nil { + t.Errorf("Unable to validate certificate: %v", err) + } + invalidCert := &Certificate{ + Key: testPublicKeys["rsa"], + SignatureKey: testPublicKeys["ecdsa"], + ValidBefore: CertTimeInfinity, + Signature: &Signature{}, + } + if err := checker.CheckCert("user", invalidCert); err == nil { + t.Error("Invalid cert signature passed validation") + } +} + +func TestValidateCertTime(t *testing.T) { + cert := Certificate{ + ValidPrincipals: []string{"user"}, + Key: testPublicKeys["rsa"], + ValidAfter: 50, + ValidBefore: 100, + } + + cert.SignCert(rand.Reader, testSigners["ecdsa"]) + + for ts, ok := range map[int64]bool{ + 25: false, + 50: true, + 99: true, + 100: false, + 125: false, + } { + checker := CertChecker{ + Clock: func() time.Time { return time.Unix(ts, 0) }, + } + checker.IsUserAuthority = func(k PublicKey) bool { + return bytes.Equal(k.Marshal(), + testPublicKeys["ecdsa"].Marshal()) + } + + if v := checker.CheckCert("user", &cert); (v == nil) != ok { + t.Errorf("Authenticate(%d): %v", ts, v) + } + } +} + +// TODO(hanwen): tests for +// +// host keys: +// * fallbacks + +func TestHostKeyCert(t *testing.T) { + cert := &Certificate{ + ValidPrincipals: []string{"hostname", "hostname.domain", "otherhost"}, + Key: testPublicKeys["rsa"], + ValidBefore: CertTimeInfinity, + CertType: HostCert, + } + cert.SignCert(rand.Reader, testSigners["ecdsa"]) + + checker := &CertChecker{ + IsHostAuthority: func(p PublicKey, addr string) bool { + return addr == "hostname:22" && bytes.Equal(testPublicKeys["ecdsa"].Marshal(), p.Marshal()) + }, + } + + certSigner, err := NewCertSigner(cert, testSigners["rsa"]) + if err != nil { + t.Errorf("NewCertSigner: %v", err) + } + + for _, test := range []struct { + addr string + succeed bool + }{ + {addr: "hostname:22", succeed: true}, + {addr: "otherhost:22", succeed: false}, // The certificate is valid for 'otherhost' as hostname, but we only recognize the authority of the signer for the address 'hostname:22' + {addr: "lasthost:22", succeed: false}, + } { + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + + errc := make(chan error) + + go func() { + conf := ServerConfig{ + NoClientAuth: true, + } + conf.AddHostKey(certSigner) + _, _, _, err := NewServerConn(c1, &conf) + errc <- err + }() + + config := &ClientConfig{ + User: "user", + HostKeyCallback: checker.CheckHostKey, + } + _, _, _, err = NewClientConn(c2, test.addr, config) + + if (err == nil) != test.succeed { + t.Fatalf("NewClientConn(%q): %v", test.addr, err) + } + + err = <-errc + if (err == nil) != test.succeed { + t.Fatalf("NewServerConn(%q): %v", test.addr, err) + } + } +} + +func TestCertTypes(t *testing.T) { + var testVars = []struct { + name string + keys func() Signer + }{ + { + name: CertAlgoECDSA256v01, + keys: func() Signer { + s, _ := ParsePrivateKey(testdata.PEMBytes["ecdsap256"]) + return s + }, + }, + { + name: CertAlgoECDSA384v01, + keys: func() Signer { + s, _ := ParsePrivateKey(testdata.PEMBytes["ecdsap384"]) + return s + }, + }, + { + name: CertAlgoECDSA521v01, + keys: func() Signer { + s, _ := ParsePrivateKey(testdata.PEMBytes["ecdsap521"]) + return s + }, + }, + { + name: CertAlgoED25519v01, + keys: func() Signer { + s, _ := ParsePrivateKey(testdata.PEMBytes["ed25519"]) + return s + }, + }, + { + name: CertAlgoRSAv01, + keys: func() Signer { + s, _ := ParsePrivateKey(testdata.PEMBytes["rsa"]) + return s + }, + }, + { + name: CertAlgoDSAv01, + keys: func() Signer { + s, _ := ParsePrivateKey(testdata.PEMBytes["dsa"]) + return s + }, + }, + } + + k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + t.Fatalf("error generating host key: %v", err) + } + + signer, err := NewSignerFromKey(k) + if err != nil { + t.Fatalf("error generating signer for ssh listener: %v", err) + } + + conf := &ServerConfig{ + PublicKeyCallback: func(c ConnMetadata, k PublicKey) (*Permissions, error) { + return new(Permissions), nil + }, + } + conf.AddHostKey(signer) + + for _, m := range testVars { + t.Run(m.name, func(t *testing.T) { + + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + + go NewServerConn(c1, conf) + + priv := m.keys() + if err != nil { + t.Fatalf("error generating ssh pubkey: %v", err) + } + + cert := &Certificate{ + CertType: UserCert, + Key: priv.PublicKey(), + } + cert.SignCert(rand.Reader, priv) + + certSigner, err := NewCertSigner(cert, priv) + if err != nil { + t.Fatalf("error generating cert signer: %v", err) + } + + config := &ClientConfig{ + User: "user", + HostKeyCallback: func(h string, r net.Addr, k PublicKey) error { return nil }, + Auth: []AuthMethod{PublicKeys(certSigner)}, + } + + _, _, _, err = NewClientConn(c2, "", config) + if err != nil { + t.Fatalf("error connecting: %v", err) + } + }) + } +} diff --git a/vendor/golang.org/x/crypto/ssh/channel.go b/vendor/golang.org/x/crypto/ssh/channel.go new file mode 100644 index 0000000000000000000000000000000000000000..c0834c00dfee9a4e9ac17ed8eb4527b8fe33cf67 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/channel.go @@ -0,0 +1,633 @@ +// 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 ssh + +import ( + "encoding/binary" + "errors" + "fmt" + "io" + "log" + "sync" +) + +const ( + minPacketLength = 9 + // channelMaxPacket contains the maximum number of bytes that will be + // sent in a single packet. As per RFC 4253, section 6.1, 32k is also + // the minimum. + channelMaxPacket = 1 << 15 + // We follow OpenSSH here. + channelWindowSize = 64 * channelMaxPacket +) + +// NewChannel represents an incoming request to a channel. It must either be +// accepted for use by calling Accept, or rejected by calling Reject. +type NewChannel interface { + // Accept accepts the channel creation request. It returns the Channel + // and a Go channel containing SSH requests. The Go channel must be + // serviced otherwise the Channel will hang. + Accept() (Channel, <-chan *Request, error) + + // Reject rejects the channel creation request. After calling + // this, no other methods on the Channel may be called. + Reject(reason RejectionReason, message string) error + + // ChannelType returns the type of the channel, as supplied by the + // client. + ChannelType() string + + // ExtraData returns the arbitrary payload for this channel, as supplied + // by the client. This data is specific to the channel type. + ExtraData() []byte +} + +// A Channel is an ordered, reliable, flow-controlled, duplex stream +// that is multiplexed over an SSH connection. +type Channel interface { + // Read reads up to len(data) bytes from the channel. + Read(data []byte) (int, error) + + // Write writes len(data) bytes to the channel. + Write(data []byte) (int, error) + + // Close signals end of channel use. No data may be sent after this + // call. + Close() error + + // CloseWrite signals the end of sending in-band + // data. Requests may still be sent, and the other side may + // still send data + CloseWrite() error + + // SendRequest sends a channel request. If wantReply is true, + // it will wait for a reply and return the result as a + // boolean, otherwise the return value will be false. Channel + // requests are out-of-band messages so they may be sent even + // if the data stream is closed or blocked by flow control. + // If the channel is closed before a reply is returned, io.EOF + // is returned. + SendRequest(name string, wantReply bool, payload []byte) (bool, error) + + // Stderr returns an io.ReadWriter that writes to this channel + // with the extended data type set to stderr. Stderr may + // safely be read and written from a different goroutine than + // Read and Write respectively. + Stderr() io.ReadWriter +} + +// Request is a request sent outside of the normal stream of +// data. Requests can either be specific to an SSH channel, or they +// can be global. +type Request struct { + Type string + WantReply bool + Payload []byte + + ch *channel + mux *mux +} + +// Reply sends a response to a request. It must be called for all requests +// where WantReply is true and is a no-op otherwise. The payload argument is +// ignored for replies to channel-specific requests. +func (r *Request) Reply(ok bool, payload []byte) error { + if !r.WantReply { + return nil + } + + if r.ch == nil { + return r.mux.ackRequest(ok, payload) + } + + return r.ch.ackRequest(ok) +} + +// RejectionReason is an enumeration used when rejecting channel creation +// requests. See RFC 4254, section 5.1. +type RejectionReason uint32 + +const ( + Prohibited RejectionReason = iota + 1 + ConnectionFailed + UnknownChannelType + ResourceShortage +) + +// String converts the rejection reason to human readable form. +func (r RejectionReason) String() string { + switch r { + case Prohibited: + return "administratively prohibited" + case ConnectionFailed: + return "connect failed" + case UnknownChannelType: + return "unknown channel type" + case ResourceShortage: + return "resource shortage" + } + return fmt.Sprintf("unknown reason %d", int(r)) +} + +func min(a uint32, b int) uint32 { + if a < uint32(b) { + return a + } + return uint32(b) +} + +type channelDirection uint8 + +const ( + channelInbound channelDirection = iota + channelOutbound +) + +// channel is an implementation of the Channel interface that works +// with the mux class. +type channel struct { + // R/O after creation + chanType string + extraData []byte + localId, remoteId uint32 + + // maxIncomingPayload and maxRemotePayload are the maximum + // payload sizes of normal and extended data packets for + // receiving and sending, respectively. The wire packet will + // be 9 or 13 bytes larger (excluding encryption overhead). + maxIncomingPayload uint32 + maxRemotePayload uint32 + + mux *mux + + // decided is set to true if an accept or reject message has been sent + // (for outbound channels) or received (for inbound channels). + decided bool + + // direction contains either channelOutbound, for channels created + // locally, or channelInbound, for channels created by the peer. + direction channelDirection + + // Pending internal channel messages. + msg chan interface{} + + // Since requests have no ID, there can be only one request + // with WantReply=true outstanding. This lock is held by a + // goroutine that has such an outgoing request pending. + sentRequestMu sync.Mutex + + incomingRequests chan *Request + + sentEOF bool + + // thread-safe data + remoteWin window + pending *buffer + extPending *buffer + + // windowMu protects myWindow, the flow-control window. + windowMu sync.Mutex + myWindow uint32 + + // writeMu serializes calls to mux.conn.writePacket() and + // protects sentClose and packetPool. This mutex must be + // different from windowMu, as writePacket can block if there + // is a key exchange pending. + writeMu sync.Mutex + sentClose bool + + // packetPool has a buffer for each extended channel ID to + // save allocations during writes. + packetPool map[uint32][]byte +} + +// writePacket sends a packet. If the packet is a channel close, it updates +// sentClose. This method takes the lock c.writeMu. +func (ch *channel) writePacket(packet []byte) error { + ch.writeMu.Lock() + if ch.sentClose { + ch.writeMu.Unlock() + return io.EOF + } + ch.sentClose = (packet[0] == msgChannelClose) + err := ch.mux.conn.writePacket(packet) + ch.writeMu.Unlock() + return err +} + +func (ch *channel) sendMessage(msg interface{}) error { + if debugMux { + log.Printf("send(%d): %#v", ch.mux.chanList.offset, msg) + } + + p := Marshal(msg) + binary.BigEndian.PutUint32(p[1:], ch.remoteId) + return ch.writePacket(p) +} + +// WriteExtended writes data to a specific extended stream. These streams are +// used, for example, for stderr. +func (ch *channel) WriteExtended(data []byte, extendedCode uint32) (n int, err error) { + if ch.sentEOF { + return 0, io.EOF + } + // 1 byte message type, 4 bytes remoteId, 4 bytes data length + opCode := byte(msgChannelData) + headerLength := uint32(9) + if extendedCode > 0 { + headerLength += 4 + opCode = msgChannelExtendedData + } + + ch.writeMu.Lock() + packet := ch.packetPool[extendedCode] + // We don't remove the buffer from packetPool, so + // WriteExtended calls from different goroutines will be + // flagged as errors by the race detector. + ch.writeMu.Unlock() + + for len(data) > 0 { + space := min(ch.maxRemotePayload, len(data)) + if space, err = ch.remoteWin.reserve(space); err != nil { + return n, err + } + if want := headerLength + space; uint32(cap(packet)) < want { + packet = make([]byte, want) + } else { + packet = packet[:want] + } + + todo := data[:space] + + packet[0] = opCode + binary.BigEndian.PutUint32(packet[1:], ch.remoteId) + if extendedCode > 0 { + binary.BigEndian.PutUint32(packet[5:], uint32(extendedCode)) + } + binary.BigEndian.PutUint32(packet[headerLength-4:], uint32(len(todo))) + copy(packet[headerLength:], todo) + if err = ch.writePacket(packet); err != nil { + return n, err + } + + n += len(todo) + data = data[len(todo):] + } + + ch.writeMu.Lock() + ch.packetPool[extendedCode] = packet + ch.writeMu.Unlock() + + return n, err +} + +func (ch *channel) handleData(packet []byte) error { + headerLen := 9 + isExtendedData := packet[0] == msgChannelExtendedData + if isExtendedData { + headerLen = 13 + } + if len(packet) < headerLen { + // malformed data packet + return parseError(packet[0]) + } + + var extended uint32 + if isExtendedData { + extended = binary.BigEndian.Uint32(packet[5:]) + } + + length := binary.BigEndian.Uint32(packet[headerLen-4 : headerLen]) + if length == 0 { + return nil + } + if length > ch.maxIncomingPayload { + // TODO(hanwen): should send Disconnect? + return errors.New("ssh: incoming packet exceeds maximum payload size") + } + + data := packet[headerLen:] + if length != uint32(len(data)) { + return errors.New("ssh: wrong packet length") + } + + ch.windowMu.Lock() + if ch.myWindow < length { + ch.windowMu.Unlock() + // TODO(hanwen): should send Disconnect with reason? + return errors.New("ssh: remote side wrote too much") + } + ch.myWindow -= length + ch.windowMu.Unlock() + + if extended == 1 { + ch.extPending.write(data) + } else if extended > 0 { + // discard other extended data. + } else { + ch.pending.write(data) + } + return nil +} + +func (c *channel) adjustWindow(n uint32) error { + c.windowMu.Lock() + // Since myWindow is managed on our side, and can never exceed + // the initial window setting, we don't worry about overflow. + c.myWindow += uint32(n) + c.windowMu.Unlock() + return c.sendMessage(windowAdjustMsg{ + AdditionalBytes: uint32(n), + }) +} + +func (c *channel) ReadExtended(data []byte, extended uint32) (n int, err error) { + switch extended { + case 1: + n, err = c.extPending.Read(data) + case 0: + n, err = c.pending.Read(data) + default: + return 0, fmt.Errorf("ssh: extended code %d unimplemented", extended) + } + + if n > 0 { + err = c.adjustWindow(uint32(n)) + // sendWindowAdjust can return io.EOF if the remote + // peer has closed the connection, however we want to + // defer forwarding io.EOF to the caller of Read until + // the buffer has been drained. + if n > 0 && err == io.EOF { + err = nil + } + } + + return n, err +} + +func (c *channel) close() { + c.pending.eof() + c.extPending.eof() + close(c.msg) + close(c.incomingRequests) + c.writeMu.Lock() + // This is not necessary for a normal channel teardown, but if + // there was another error, it is. + c.sentClose = true + c.writeMu.Unlock() + // Unblock writers. + c.remoteWin.close() +} + +// responseMessageReceived is called when a success or failure message is +// received on a channel to check that such a message is reasonable for the +// given channel. +func (ch *channel) responseMessageReceived() error { + if ch.direction == channelInbound { + return errors.New("ssh: channel response message received on inbound channel") + } + if ch.decided { + return errors.New("ssh: duplicate response received for channel") + } + ch.decided = true + return nil +} + +func (ch *channel) handlePacket(packet []byte) error { + switch packet[0] { + case msgChannelData, msgChannelExtendedData: + return ch.handleData(packet) + case msgChannelClose: + ch.sendMessage(channelCloseMsg{PeersID: ch.remoteId}) + ch.mux.chanList.remove(ch.localId) + ch.close() + return nil + case msgChannelEOF: + // RFC 4254 is mute on how EOF affects dataExt messages but + // it is logical to signal EOF at the same time. + ch.extPending.eof() + ch.pending.eof() + return nil + } + + decoded, err := decode(packet) + if err != nil { + return err + } + + switch msg := decoded.(type) { + case *channelOpenFailureMsg: + if err := ch.responseMessageReceived(); err != nil { + return err + } + ch.mux.chanList.remove(msg.PeersID) + ch.msg <- msg + case *channelOpenConfirmMsg: + if err := ch.responseMessageReceived(); err != nil { + return err + } + if msg.MaxPacketSize < minPacketLength || msg.MaxPacketSize > 1<<31 { + return fmt.Errorf("ssh: invalid MaxPacketSize %d from peer", msg.MaxPacketSize) + } + ch.remoteId = msg.MyID + ch.maxRemotePayload = msg.MaxPacketSize + ch.remoteWin.add(msg.MyWindow) + ch.msg <- msg + case *windowAdjustMsg: + if !ch.remoteWin.add(msg.AdditionalBytes) { + return fmt.Errorf("ssh: invalid window update for %d bytes", msg.AdditionalBytes) + } + case *channelRequestMsg: + req := Request{ + Type: msg.Request, + WantReply: msg.WantReply, + Payload: msg.RequestSpecificData, + ch: ch, + } + + ch.incomingRequests <- &req + default: + ch.msg <- msg + } + return nil +} + +func (m *mux) newChannel(chanType string, direction channelDirection, extraData []byte) *channel { + ch := &channel{ + remoteWin: window{Cond: newCond()}, + myWindow: channelWindowSize, + pending: newBuffer(), + extPending: newBuffer(), + direction: direction, + incomingRequests: make(chan *Request, chanSize), + msg: make(chan interface{}, chanSize), + chanType: chanType, + extraData: extraData, + mux: m, + packetPool: make(map[uint32][]byte), + } + ch.localId = m.chanList.add(ch) + return ch +} + +var errUndecided = errors.New("ssh: must Accept or Reject channel") +var errDecidedAlready = errors.New("ssh: can call Accept or Reject only once") + +type extChannel struct { + code uint32 + ch *channel +} + +func (e *extChannel) Write(data []byte) (n int, err error) { + return e.ch.WriteExtended(data, e.code) +} + +func (e *extChannel) Read(data []byte) (n int, err error) { + return e.ch.ReadExtended(data, e.code) +} + +func (ch *channel) Accept() (Channel, <-chan *Request, error) { + if ch.decided { + return nil, nil, errDecidedAlready + } + ch.maxIncomingPayload = channelMaxPacket + confirm := channelOpenConfirmMsg{ + PeersID: ch.remoteId, + MyID: ch.localId, + MyWindow: ch.myWindow, + MaxPacketSize: ch.maxIncomingPayload, + } + ch.decided = true + if err := ch.sendMessage(confirm); err != nil { + return nil, nil, err + } + + return ch, ch.incomingRequests, nil +} + +func (ch *channel) Reject(reason RejectionReason, message string) error { + if ch.decided { + return errDecidedAlready + } + reject := channelOpenFailureMsg{ + PeersID: ch.remoteId, + Reason: reason, + Message: message, + Language: "en", + } + ch.decided = true + return ch.sendMessage(reject) +} + +func (ch *channel) Read(data []byte) (int, error) { + if !ch.decided { + return 0, errUndecided + } + return ch.ReadExtended(data, 0) +} + +func (ch *channel) Write(data []byte) (int, error) { + if !ch.decided { + return 0, errUndecided + } + return ch.WriteExtended(data, 0) +} + +func (ch *channel) CloseWrite() error { + if !ch.decided { + return errUndecided + } + ch.sentEOF = true + return ch.sendMessage(channelEOFMsg{ + PeersID: ch.remoteId}) +} + +func (ch *channel) Close() error { + if !ch.decided { + return errUndecided + } + + return ch.sendMessage(channelCloseMsg{ + PeersID: ch.remoteId}) +} + +// Extended returns an io.ReadWriter that sends and receives data on the given, +// SSH extended stream. Such streams are used, for example, for stderr. +func (ch *channel) Extended(code uint32) io.ReadWriter { + if !ch.decided { + return nil + } + return &extChannel{code, ch} +} + +func (ch *channel) Stderr() io.ReadWriter { + return ch.Extended(1) +} + +func (ch *channel) SendRequest(name string, wantReply bool, payload []byte) (bool, error) { + if !ch.decided { + return false, errUndecided + } + + if wantReply { + ch.sentRequestMu.Lock() + defer ch.sentRequestMu.Unlock() + } + + msg := channelRequestMsg{ + PeersID: ch.remoteId, + Request: name, + WantReply: wantReply, + RequestSpecificData: payload, + } + + if err := ch.sendMessage(msg); err != nil { + return false, err + } + + if wantReply { + m, ok := (<-ch.msg) + if !ok { + return false, io.EOF + } + switch m.(type) { + case *channelRequestFailureMsg: + return false, nil + case *channelRequestSuccessMsg: + return true, nil + default: + return false, fmt.Errorf("ssh: unexpected response to channel request: %#v", m) + } + } + + return false, nil +} + +// ackRequest either sends an ack or nack to the channel request. +func (ch *channel) ackRequest(ok bool) error { + if !ch.decided { + return errUndecided + } + + var msg interface{} + if !ok { + msg = channelRequestFailureMsg{ + PeersID: ch.remoteId, + } + } else { + msg = channelRequestSuccessMsg{ + PeersID: ch.remoteId, + } + } + return ch.sendMessage(msg) +} + +func (ch *channel) ChannelType() string { + return ch.chanType +} + +func (ch *channel) ExtraData() []byte { + return ch.extraData +} diff --git a/vendor/golang.org/x/crypto/ssh/cipher.go b/vendor/golang.org/x/crypto/ssh/cipher.go new file mode 100644 index 0000000000000000000000000000000000000000..30a49fdf27ad7df8f03d337564ed489e61855075 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/cipher.go @@ -0,0 +1,771 @@ +// 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 ssh + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/des" + "crypto/rc4" + "crypto/subtle" + "encoding/binary" + "errors" + "fmt" + "hash" + "io" + "io/ioutil" + + "golang.org/x/crypto/internal/chacha20" + "golang.org/x/crypto/poly1305" +) + +const ( + packetSizeMultiple = 16 // TODO(huin) this should be determined by the cipher. + + // RFC 4253 section 6.1 defines a minimum packet size of 32768 that implementations + // MUST be able to process (plus a few more kilobytes for padding and mac). The RFC + // indicates implementations SHOULD be able to handle larger packet sizes, but then + // waffles on about reasonable limits. + // + // OpenSSH caps their maxPacket at 256kB so we choose to do + // the same. maxPacket is also used to ensure that uint32 + // length fields do not overflow, so it should remain well + // below 4G. + maxPacket = 256 * 1024 +) + +// noneCipher implements cipher.Stream and provides no encryption. It is used +// by the transport before the first key-exchange. +type noneCipher struct{} + +func (c noneCipher) XORKeyStream(dst, src []byte) { + copy(dst, src) +} + +func newAESCTR(key, iv []byte) (cipher.Stream, error) { + c, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + return cipher.NewCTR(c, iv), nil +} + +func newRC4(key, iv []byte) (cipher.Stream, error) { + return rc4.NewCipher(key) +} + +type cipherMode struct { + keySize int + ivSize int + create func(key, iv []byte, macKey []byte, algs directionAlgorithms) (packetCipher, error) +} + +func streamCipherMode(skip int, createFunc func(key, iv []byte) (cipher.Stream, error)) func(key, iv []byte, macKey []byte, algs directionAlgorithms) (packetCipher, error) { + return func(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) { + stream, err := createFunc(key, iv) + if err != nil { + return nil, err + } + + var streamDump []byte + if skip > 0 { + streamDump = make([]byte, 512) + } + + for remainingToDump := skip; remainingToDump > 0; { + dumpThisTime := remainingToDump + if dumpThisTime > len(streamDump) { + dumpThisTime = len(streamDump) + } + stream.XORKeyStream(streamDump[:dumpThisTime], streamDump[:dumpThisTime]) + remainingToDump -= dumpThisTime + } + + mac := macModes[algs.MAC].new(macKey) + return &streamPacketCipher{ + mac: mac, + etm: macModes[algs.MAC].etm, + macResult: make([]byte, mac.Size()), + cipher: stream, + }, nil + } +} + +// cipherModes documents properties of supported ciphers. Ciphers not included +// are not supported and will not be negotiated, even if explicitly requested in +// ClientConfig.Crypto.Ciphers. +var cipherModes = map[string]*cipherMode{ + // Ciphers from RFC4344, which introduced many CTR-based ciphers. Algorithms + // are defined in the order specified in the RFC. + "aes128-ctr": {16, aes.BlockSize, streamCipherMode(0, newAESCTR)}, + "aes192-ctr": {24, aes.BlockSize, streamCipherMode(0, newAESCTR)}, + "aes256-ctr": {32, aes.BlockSize, streamCipherMode(0, newAESCTR)}, + + // Ciphers from RFC4345, which introduces security-improved arcfour ciphers. + // They are defined in the order specified in the RFC. + "arcfour128": {16, 0, streamCipherMode(1536, newRC4)}, + "arcfour256": {32, 0, streamCipherMode(1536, newRC4)}, + + // Cipher defined in RFC 4253, which describes SSH Transport Layer Protocol. + // Note that this cipher is not safe, as stated in RFC 4253: "Arcfour (and + // RC4) has problems with weak keys, and should be used with caution." + // RFC4345 introduces improved versions of Arcfour. + "arcfour": {16, 0, streamCipherMode(0, newRC4)}, + + // AEAD ciphers + gcmCipherID: {16, 12, newGCMCipher}, + chacha20Poly1305ID: {64, 0, newChaCha20Cipher}, + + // CBC mode is insecure and so is not included in the default config. + // (See http://www.isg.rhul.ac.uk/~kp/SandPfinal.pdf). If absolutely + // needed, it's possible to specify a custom Config to enable it. + // You should expect that an active attacker can recover plaintext if + // you do. + aes128cbcID: {16, aes.BlockSize, newAESCBCCipher}, + + // 3des-cbc is insecure and is not included in the default + // config. + tripledescbcID: {24, des.BlockSize, newTripleDESCBCCipher}, +} + +// prefixLen is the length of the packet prefix that contains the packet length +// and number of padding bytes. +const prefixLen = 5 + +// streamPacketCipher is a packetCipher using a stream cipher. +type streamPacketCipher struct { + mac hash.Hash + cipher cipher.Stream + etm bool + + // The following members are to avoid per-packet allocations. + prefix [prefixLen]byte + seqNumBytes [4]byte + padding [2 * packetSizeMultiple]byte + packetData []byte + macResult []byte +} + +// readPacket reads and decrypt a single packet from the reader argument. +func (s *streamPacketCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) { + if _, err := io.ReadFull(r, s.prefix[:]); err != nil { + return nil, err + } + + var encryptedPaddingLength [1]byte + if s.mac != nil && s.etm { + copy(encryptedPaddingLength[:], s.prefix[4:5]) + s.cipher.XORKeyStream(s.prefix[4:5], s.prefix[4:5]) + } else { + s.cipher.XORKeyStream(s.prefix[:], s.prefix[:]) + } + + length := binary.BigEndian.Uint32(s.prefix[0:4]) + paddingLength := uint32(s.prefix[4]) + + var macSize uint32 + if s.mac != nil { + s.mac.Reset() + binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum) + s.mac.Write(s.seqNumBytes[:]) + if s.etm { + s.mac.Write(s.prefix[:4]) + s.mac.Write(encryptedPaddingLength[:]) + } else { + s.mac.Write(s.prefix[:]) + } + macSize = uint32(s.mac.Size()) + } + + if length <= paddingLength+1 { + return nil, errors.New("ssh: invalid packet length, packet too small") + } + + if length > maxPacket { + return nil, errors.New("ssh: invalid packet length, packet too large") + } + + // the maxPacket check above ensures that length-1+macSize + // does not overflow. + if uint32(cap(s.packetData)) < length-1+macSize { + s.packetData = make([]byte, length-1+macSize) + } else { + s.packetData = s.packetData[:length-1+macSize] + } + + if _, err := io.ReadFull(r, s.packetData); err != nil { + return nil, err + } + mac := s.packetData[length-1:] + data := s.packetData[:length-1] + + if s.mac != nil && s.etm { + s.mac.Write(data) + } + + s.cipher.XORKeyStream(data, data) + + if s.mac != nil { + if !s.etm { + s.mac.Write(data) + } + s.macResult = s.mac.Sum(s.macResult[:0]) + if subtle.ConstantTimeCompare(s.macResult, mac) != 1 { + return nil, errors.New("ssh: MAC failure") + } + } + + return s.packetData[:length-paddingLength-1], nil +} + +// writePacket encrypts and sends a packet of data to the writer argument +func (s *streamPacketCipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error { + if len(packet) > maxPacket { + return errors.New("ssh: packet too large") + } + + aadlen := 0 + if s.mac != nil && s.etm { + // packet length is not encrypted for EtM modes + aadlen = 4 + } + + paddingLength := packetSizeMultiple - (prefixLen+len(packet)-aadlen)%packetSizeMultiple + if paddingLength < 4 { + paddingLength += packetSizeMultiple + } + + length := len(packet) + 1 + paddingLength + binary.BigEndian.PutUint32(s.prefix[:], uint32(length)) + s.prefix[4] = byte(paddingLength) + padding := s.padding[:paddingLength] + if _, err := io.ReadFull(rand, padding); err != nil { + return err + } + + if s.mac != nil { + s.mac.Reset() + binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum) + s.mac.Write(s.seqNumBytes[:]) + + if s.etm { + // For EtM algorithms, the packet length must stay unencrypted, + // but the following data (padding length) must be encrypted + s.cipher.XORKeyStream(s.prefix[4:5], s.prefix[4:5]) + } + + s.mac.Write(s.prefix[:]) + + if !s.etm { + // For non-EtM algorithms, the algorithm is applied on unencrypted data + s.mac.Write(packet) + s.mac.Write(padding) + } + } + + if !(s.mac != nil && s.etm) { + // For EtM algorithms, the padding length has already been encrypted + // and the packet length must remain unencrypted + s.cipher.XORKeyStream(s.prefix[:], s.prefix[:]) + } + + s.cipher.XORKeyStream(packet, packet) + s.cipher.XORKeyStream(padding, padding) + + if s.mac != nil && s.etm { + // For EtM algorithms, packet and padding must be encrypted + s.mac.Write(packet) + s.mac.Write(padding) + } + + if _, err := w.Write(s.prefix[:]); err != nil { + return err + } + if _, err := w.Write(packet); err != nil { + return err + } + if _, err := w.Write(padding); err != nil { + return err + } + + if s.mac != nil { + s.macResult = s.mac.Sum(s.macResult[:0]) + if _, err := w.Write(s.macResult); err != nil { + return err + } + } + + return nil +} + +type gcmCipher struct { + aead cipher.AEAD + prefix [4]byte + iv []byte + buf []byte +} + +func newGCMCipher(key, iv, unusedMacKey []byte, unusedAlgs directionAlgorithms) (packetCipher, error) { + c, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + + aead, err := cipher.NewGCM(c) + if err != nil { + return nil, err + } + + return &gcmCipher{ + aead: aead, + iv: iv, + }, nil +} + +const gcmTagSize = 16 + +func (c *gcmCipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error { + // Pad out to multiple of 16 bytes. This is different from the + // stream cipher because that encrypts the length too. + padding := byte(packetSizeMultiple - (1+len(packet))%packetSizeMultiple) + if padding < 4 { + padding += packetSizeMultiple + } + + length := uint32(len(packet) + int(padding) + 1) + binary.BigEndian.PutUint32(c.prefix[:], length) + if _, err := w.Write(c.prefix[:]); err != nil { + return err + } + + if cap(c.buf) < int(length) { + c.buf = make([]byte, length) + } else { + c.buf = c.buf[:length] + } + + c.buf[0] = padding + copy(c.buf[1:], packet) + if _, err := io.ReadFull(rand, c.buf[1+len(packet):]); err != nil { + return err + } + c.buf = c.aead.Seal(c.buf[:0], c.iv, c.buf, c.prefix[:]) + if _, err := w.Write(c.buf); err != nil { + return err + } + c.incIV() + + return nil +} + +func (c *gcmCipher) incIV() { + for i := 4 + 7; i >= 4; i-- { + c.iv[i]++ + if c.iv[i] != 0 { + break + } + } +} + +func (c *gcmCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) { + if _, err := io.ReadFull(r, c.prefix[:]); err != nil { + return nil, err + } + length := binary.BigEndian.Uint32(c.prefix[:]) + if length > maxPacket { + return nil, errors.New("ssh: max packet length exceeded") + } + + if cap(c.buf) < int(length+gcmTagSize) { + c.buf = make([]byte, length+gcmTagSize) + } else { + c.buf = c.buf[:length+gcmTagSize] + } + + if _, err := io.ReadFull(r, c.buf); err != nil { + return nil, err + } + + plain, err := c.aead.Open(c.buf[:0], c.iv, c.buf, c.prefix[:]) + if err != nil { + return nil, err + } + c.incIV() + + padding := plain[0] + if padding < 4 { + // padding is a byte, so it automatically satisfies + // the maximum size, which is 255. + return nil, fmt.Errorf("ssh: illegal padding %d", padding) + } + + if int(padding+1) >= len(plain) { + return nil, fmt.Errorf("ssh: padding %d too large", padding) + } + plain = plain[1 : length-uint32(padding)] + return plain, nil +} + +// cbcCipher implements aes128-cbc cipher defined in RFC 4253 section 6.1 +type cbcCipher struct { + mac hash.Hash + macSize uint32 + decrypter cipher.BlockMode + encrypter cipher.BlockMode + + // The following members are to avoid per-packet allocations. + seqNumBytes [4]byte + packetData []byte + macResult []byte + + // Amount of data we should still read to hide which + // verification error triggered. + oracleCamouflage uint32 +} + +func newCBCCipher(c cipher.Block, key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) { + cbc := &cbcCipher{ + mac: macModes[algs.MAC].new(macKey), + decrypter: cipher.NewCBCDecrypter(c, iv), + encrypter: cipher.NewCBCEncrypter(c, iv), + packetData: make([]byte, 1024), + } + if cbc.mac != nil { + cbc.macSize = uint32(cbc.mac.Size()) + } + + return cbc, nil +} + +func newAESCBCCipher(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) { + c, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + + cbc, err := newCBCCipher(c, key, iv, macKey, algs) + if err != nil { + return nil, err + } + + return cbc, nil +} + +func newTripleDESCBCCipher(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) { + c, err := des.NewTripleDESCipher(key) + if err != nil { + return nil, err + } + + cbc, err := newCBCCipher(c, key, iv, macKey, algs) + if err != nil { + return nil, err + } + + return cbc, nil +} + +func maxUInt32(a, b int) uint32 { + if a > b { + return uint32(a) + } + return uint32(b) +} + +const ( + cbcMinPacketSizeMultiple = 8 + cbcMinPacketSize = 16 + cbcMinPaddingSize = 4 +) + +// cbcError represents a verification error that may leak information. +type cbcError string + +func (e cbcError) Error() string { return string(e) } + +func (c *cbcCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) { + p, err := c.readPacketLeaky(seqNum, r) + if err != nil { + if _, ok := err.(cbcError); ok { + // Verification error: read a fixed amount of + // data, to make distinguishing between + // failing MAC and failing length check more + // difficult. + io.CopyN(ioutil.Discard, r, int64(c.oracleCamouflage)) + } + } + return p, err +} + +func (c *cbcCipher) readPacketLeaky(seqNum uint32, r io.Reader) ([]byte, error) { + blockSize := c.decrypter.BlockSize() + + // Read the header, which will include some of the subsequent data in the + // case of block ciphers - this is copied back to the payload later. + // How many bytes of payload/padding will be read with this first read. + firstBlockLength := uint32((prefixLen + blockSize - 1) / blockSize * blockSize) + firstBlock := c.packetData[:firstBlockLength] + if _, err := io.ReadFull(r, firstBlock); err != nil { + return nil, err + } + + c.oracleCamouflage = maxPacket + 4 + c.macSize - firstBlockLength + + c.decrypter.CryptBlocks(firstBlock, firstBlock) + length := binary.BigEndian.Uint32(firstBlock[:4]) + if length > maxPacket { + return nil, cbcError("ssh: packet too large") + } + if length+4 < maxUInt32(cbcMinPacketSize, blockSize) { + // The minimum size of a packet is 16 (or the cipher block size, whichever + // is larger) bytes. + return nil, cbcError("ssh: packet too small") + } + // The length of the packet (including the length field but not the MAC) must + // be a multiple of the block size or 8, whichever is larger. + if (length+4)%maxUInt32(cbcMinPacketSizeMultiple, blockSize) != 0 { + return nil, cbcError("ssh: invalid packet length multiple") + } + + paddingLength := uint32(firstBlock[4]) + if paddingLength < cbcMinPaddingSize || length <= paddingLength+1 { + return nil, cbcError("ssh: invalid packet length") + } + + // Positions within the c.packetData buffer: + macStart := 4 + length + paddingStart := macStart - paddingLength + + // Entire packet size, starting before length, ending at end of mac. + entirePacketSize := macStart + c.macSize + + // Ensure c.packetData is large enough for the entire packet data. + if uint32(cap(c.packetData)) < entirePacketSize { + // Still need to upsize and copy, but this should be rare at runtime, only + // on upsizing the packetData buffer. + c.packetData = make([]byte, entirePacketSize) + copy(c.packetData, firstBlock) + } else { + c.packetData = c.packetData[:entirePacketSize] + } + + n, err := io.ReadFull(r, c.packetData[firstBlockLength:]) + if err != nil { + return nil, err + } + c.oracleCamouflage -= uint32(n) + + remainingCrypted := c.packetData[firstBlockLength:macStart] + c.decrypter.CryptBlocks(remainingCrypted, remainingCrypted) + + mac := c.packetData[macStart:] + if c.mac != nil { + c.mac.Reset() + binary.BigEndian.PutUint32(c.seqNumBytes[:], seqNum) + c.mac.Write(c.seqNumBytes[:]) + c.mac.Write(c.packetData[:macStart]) + c.macResult = c.mac.Sum(c.macResult[:0]) + if subtle.ConstantTimeCompare(c.macResult, mac) != 1 { + return nil, cbcError("ssh: MAC failure") + } + } + + return c.packetData[prefixLen:paddingStart], nil +} + +func (c *cbcCipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error { + effectiveBlockSize := maxUInt32(cbcMinPacketSizeMultiple, c.encrypter.BlockSize()) + + // Length of encrypted portion of the packet (header, payload, padding). + // Enforce minimum padding and packet size. + encLength := maxUInt32(prefixLen+len(packet)+cbcMinPaddingSize, cbcMinPaddingSize) + // Enforce block size. + encLength = (encLength + effectiveBlockSize - 1) / effectiveBlockSize * effectiveBlockSize + + length := encLength - 4 + paddingLength := int(length) - (1 + len(packet)) + + // Overall buffer contains: header, payload, padding, mac. + // Space for the MAC is reserved in the capacity but not the slice length. + bufferSize := encLength + c.macSize + if uint32(cap(c.packetData)) < bufferSize { + c.packetData = make([]byte, encLength, bufferSize) + } else { + c.packetData = c.packetData[:encLength] + } + + p := c.packetData + + // Packet header. + binary.BigEndian.PutUint32(p, length) + p = p[4:] + p[0] = byte(paddingLength) + + // Payload. + p = p[1:] + copy(p, packet) + + // Padding. + p = p[len(packet):] + if _, err := io.ReadFull(rand, p); err != nil { + return err + } + + if c.mac != nil { + c.mac.Reset() + binary.BigEndian.PutUint32(c.seqNumBytes[:], seqNum) + c.mac.Write(c.seqNumBytes[:]) + c.mac.Write(c.packetData) + // The MAC is now appended into the capacity reserved for it earlier. + c.packetData = c.mac.Sum(c.packetData) + } + + c.encrypter.CryptBlocks(c.packetData[:encLength], c.packetData[:encLength]) + + if _, err := w.Write(c.packetData); err != nil { + return err + } + + return nil +} + +const chacha20Poly1305ID = "chacha20-poly1305@openssh.com" + +// chacha20Poly1305Cipher implements the chacha20-poly1305@openssh.com +// AEAD, which is described here: +// +// https://tools.ietf.org/html/draft-josefsson-ssh-chacha20-poly1305-openssh-00 +// +// the methods here also implement padding, which RFC4253 Section 6 +// also requires of stream ciphers. +type chacha20Poly1305Cipher struct { + lengthKey [32]byte + contentKey [32]byte + buf []byte +} + +func newChaCha20Cipher(key, unusedIV, unusedMACKey []byte, unusedAlgs directionAlgorithms) (packetCipher, error) { + if len(key) != 64 { + panic(len(key)) + } + + c := &chacha20Poly1305Cipher{ + buf: make([]byte, 256), + } + + copy(c.contentKey[:], key[:32]) + copy(c.lengthKey[:], key[32:]) + return c, nil +} + +// The Poly1305 key is obtained by encrypting 32 0-bytes. +var chacha20PolyKeyInput [32]byte + +func (c *chacha20Poly1305Cipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) { + var counter [16]byte + binary.BigEndian.PutUint64(counter[8:], uint64(seqNum)) + + var polyKey [32]byte + chacha20.XORKeyStream(polyKey[:], chacha20PolyKeyInput[:], &counter, &c.contentKey) + + encryptedLength := c.buf[:4] + if _, err := io.ReadFull(r, encryptedLength); err != nil { + return nil, err + } + + var lenBytes [4]byte + chacha20.XORKeyStream(lenBytes[:], encryptedLength, &counter, &c.lengthKey) + + length := binary.BigEndian.Uint32(lenBytes[:]) + if length > maxPacket { + return nil, errors.New("ssh: invalid packet length, packet too large") + } + + contentEnd := 4 + length + packetEnd := contentEnd + poly1305.TagSize + if uint32(cap(c.buf)) < packetEnd { + c.buf = make([]byte, packetEnd) + copy(c.buf[:], encryptedLength) + } else { + c.buf = c.buf[:packetEnd] + } + + if _, err := io.ReadFull(r, c.buf[4:packetEnd]); err != nil { + return nil, err + } + + var mac [poly1305.TagSize]byte + copy(mac[:], c.buf[contentEnd:packetEnd]) + if !poly1305.Verify(&mac, c.buf[:contentEnd], &polyKey) { + return nil, errors.New("ssh: MAC failure") + } + + counter[0] = 1 + + plain := c.buf[4:contentEnd] + chacha20.XORKeyStream(plain, plain, &counter, &c.contentKey) + + padding := plain[0] + if padding < 4 { + // padding is a byte, so it automatically satisfies + // the maximum size, which is 255. + return nil, fmt.Errorf("ssh: illegal padding %d", padding) + } + + if int(padding)+1 >= len(plain) { + return nil, fmt.Errorf("ssh: padding %d too large", padding) + } + + plain = plain[1 : len(plain)-int(padding)] + + return plain, nil +} + +func (c *chacha20Poly1305Cipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, payload []byte) error { + var counter [16]byte + binary.BigEndian.PutUint64(counter[8:], uint64(seqNum)) + + var polyKey [32]byte + chacha20.XORKeyStream(polyKey[:], chacha20PolyKeyInput[:], &counter, &c.contentKey) + + // There is no blocksize, so fall back to multiple of 8 byte + // padding, as described in RFC 4253, Sec 6. + const packetSizeMultiple = 8 + + padding := packetSizeMultiple - (1+len(payload))%packetSizeMultiple + if padding < 4 { + padding += packetSizeMultiple + } + + // size (4 bytes), padding (1), payload, padding, tag. + totalLength := 4 + 1 + len(payload) + padding + poly1305.TagSize + if cap(c.buf) < totalLength { + c.buf = make([]byte, totalLength) + } else { + c.buf = c.buf[:totalLength] + } + + binary.BigEndian.PutUint32(c.buf, uint32(1+len(payload)+padding)) + chacha20.XORKeyStream(c.buf, c.buf[:4], &counter, &c.lengthKey) + c.buf[4] = byte(padding) + copy(c.buf[5:], payload) + packetEnd := 5 + len(payload) + padding + if _, err := io.ReadFull(rand, c.buf[5+len(payload):packetEnd]); err != nil { + return err + } + + counter[0] = 1 + chacha20.XORKeyStream(c.buf[4:], c.buf[4:packetEnd], &counter, &c.contentKey) + + var mac [poly1305.TagSize]byte + poly1305.Sum(&mac, c.buf[:packetEnd], &polyKey) + + copy(c.buf[packetEnd:], mac[:]) + + if _, err := w.Write(c.buf); err != nil { + return err + } + return nil +} diff --git a/vendor/golang.org/x/crypto/ssh/cipher_test.go b/vendor/golang.org/x/crypto/ssh/cipher_test.go new file mode 100644 index 0000000000000000000000000000000000000000..a52d6e486a9ef16e32f8dd63a4f7b5bf88cac6a7 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/cipher_test.go @@ -0,0 +1,131 @@ +// 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 ssh + +import ( + "bytes" + "crypto" + "crypto/rand" + "testing" +) + +func TestDefaultCiphersExist(t *testing.T) { + for _, cipherAlgo := range supportedCiphers { + if _, ok := cipherModes[cipherAlgo]; !ok { + t.Errorf("supported cipher %q is unknown", cipherAlgo) + } + } + for _, cipherAlgo := range preferredCiphers { + if _, ok := cipherModes[cipherAlgo]; !ok { + t.Errorf("preferred cipher %q is unknown", cipherAlgo) + } + } +} + +func TestPacketCiphers(t *testing.T) { + defaultMac := "hmac-sha2-256" + defaultCipher := "aes128-ctr" + for cipher := range cipherModes { + t.Run("cipher="+cipher, + func(t *testing.T) { testPacketCipher(t, cipher, defaultMac) }) + } + for mac := range macModes { + t.Run("mac="+mac, + func(t *testing.T) { testPacketCipher(t, defaultCipher, mac) }) + } +} + +func testPacketCipher(t *testing.T, cipher, mac string) { + kr := &kexResult{Hash: crypto.SHA1} + algs := directionAlgorithms{ + Cipher: cipher, + MAC: mac, + Compression: "none", + } + client, err := newPacketCipher(clientKeys, algs, kr) + if err != nil { + t.Fatalf("newPacketCipher(client, %q, %q): %v", cipher, mac, err) + } + server, err := newPacketCipher(clientKeys, algs, kr) + if err != nil { + t.Fatalf("newPacketCipher(client, %q, %q): %v", cipher, mac, err) + } + + want := "bla bla" + input := []byte(want) + buf := &bytes.Buffer{} + if err := client.writePacket(0, buf, rand.Reader, input); err != nil { + t.Fatalf("writePacket(%q, %q): %v", cipher, mac, err) + } + + packet, err := server.readPacket(0, buf) + if err != nil { + t.Fatalf("readPacket(%q, %q): %v", cipher, mac, err) + } + + if string(packet) != want { + t.Errorf("roundtrip(%q, %q): got %q, want %q", cipher, mac, packet, want) + } +} + +func TestCBCOracleCounterMeasure(t *testing.T) { + kr := &kexResult{Hash: crypto.SHA1} + algs := directionAlgorithms{ + Cipher: aes128cbcID, + MAC: "hmac-sha1", + Compression: "none", + } + client, err := newPacketCipher(clientKeys, algs, kr) + if err != nil { + t.Fatalf("newPacketCipher(client): %v", err) + } + + want := "bla bla" + input := []byte(want) + buf := &bytes.Buffer{} + if err := client.writePacket(0, buf, rand.Reader, input); err != nil { + t.Errorf("writePacket: %v", err) + } + + packetSize := buf.Len() + buf.Write(make([]byte, 2*maxPacket)) + + // We corrupt each byte, but this usually will only test the + // 'packet too large' or 'MAC failure' cases. + lastRead := -1 + for i := 0; i < packetSize; i++ { + server, err := newPacketCipher(clientKeys, algs, kr) + if err != nil { + t.Fatalf("newPacketCipher(client): %v", err) + } + + fresh := &bytes.Buffer{} + fresh.Write(buf.Bytes()) + fresh.Bytes()[i] ^= 0x01 + + before := fresh.Len() + _, err = server.readPacket(0, fresh) + if err == nil { + t.Errorf("corrupt byte %d: readPacket succeeded ", i) + continue + } + if _, ok := err.(cbcError); !ok { + t.Errorf("corrupt byte %d: got %v (%T), want cbcError", i, err, err) + continue + } + + after := fresh.Len() + bytesRead := before - after + if bytesRead < maxPacket { + t.Errorf("corrupt byte %d: read %d bytes, want more than %d", i, bytesRead, maxPacket) + continue + } + + if i > 0 && bytesRead != lastRead { + t.Errorf("corrupt byte %d: read %d bytes, want %d bytes read", i, bytesRead, lastRead) + } + lastRead = bytesRead + } +} diff --git a/vendor/golang.org/x/crypto/ssh/client.go b/vendor/golang.org/x/crypto/ssh/client.go new file mode 100644 index 0000000000000000000000000000000000000000..6fd1994553bc37d03ba6a5d9cbbc2f89815ba52d --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/client.go @@ -0,0 +1,278 @@ +// 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 ssh + +import ( + "bytes" + "errors" + "fmt" + "net" + "os" + "sync" + "time" +) + +// Client implements a traditional SSH client that supports shells, +// subprocesses, TCP port/streamlocal forwarding and tunneled dialing. +type Client struct { + Conn + + forwards forwardList // forwarded tcpip connections from the remote side + mu sync.Mutex + channelHandlers map[string]chan NewChannel +} + +// HandleChannelOpen returns a channel on which NewChannel requests +// for the given type are sent. If the type already is being handled, +// nil is returned. The channel is closed when the connection is closed. +func (c *Client) HandleChannelOpen(channelType string) <-chan NewChannel { + c.mu.Lock() + defer c.mu.Unlock() + if c.channelHandlers == nil { + // The SSH channel has been closed. + c := make(chan NewChannel) + close(c) + return c + } + + ch := c.channelHandlers[channelType] + if ch != nil { + return nil + } + + ch = make(chan NewChannel, chanSize) + c.channelHandlers[channelType] = ch + return ch +} + +// NewClient creates a Client on top of the given connection. +func NewClient(c Conn, chans <-chan NewChannel, reqs <-chan *Request) *Client { + conn := &Client{ + Conn: c, + channelHandlers: make(map[string]chan NewChannel, 1), + } + + go conn.handleGlobalRequests(reqs) + go conn.handleChannelOpens(chans) + go func() { + conn.Wait() + conn.forwards.closeAll() + }() + go conn.forwards.handleChannels(conn.HandleChannelOpen("forwarded-tcpip")) + go conn.forwards.handleChannels(conn.HandleChannelOpen("forwarded-streamlocal@openssh.com")) + return conn +} + +// NewClientConn establishes an authenticated SSH connection using c +// as the underlying transport. The Request and NewChannel channels +// must be serviced or the connection will hang. +func NewClientConn(c net.Conn, addr string, config *ClientConfig) (Conn, <-chan NewChannel, <-chan *Request, error) { + fullConf := *config + fullConf.SetDefaults() + if fullConf.HostKeyCallback == nil { + c.Close() + return nil, nil, nil, errors.New("ssh: must specify HostKeyCallback") + } + + conn := &connection{ + sshConn: sshConn{conn: c}, + } + + if err := conn.clientHandshake(addr, &fullConf); err != nil { + c.Close() + return nil, nil, nil, fmt.Errorf("ssh: handshake failed: %v", err) + } + conn.mux = newMux(conn.transport) + return conn, conn.mux.incomingChannels, conn.mux.incomingRequests, nil +} + +// clientHandshake performs the client side key exchange. See RFC 4253 Section +// 7. +func (c *connection) clientHandshake(dialAddress string, config *ClientConfig) error { + if config.ClientVersion != "" { + c.clientVersion = []byte(config.ClientVersion) + } else { + c.clientVersion = []byte(packageVersion) + } + var err error + c.serverVersion, err = exchangeVersions(c.sshConn.conn, c.clientVersion) + if err != nil { + return err + } + + c.transport = newClientTransport( + newTransport(c.sshConn.conn, config.Rand, true /* is client */), + c.clientVersion, c.serverVersion, config, dialAddress, c.sshConn.RemoteAddr()) + if err := c.transport.waitSession(); err != nil { + return err + } + + c.sessionID = c.transport.getSessionID() + return c.clientAuthenticate(config) +} + +// verifyHostKeySignature verifies the host key obtained in the key +// exchange. +func verifyHostKeySignature(hostKey PublicKey, result *kexResult) error { + sig, rest, ok := parseSignatureBody(result.Signature) + if len(rest) > 0 || !ok { + return errors.New("ssh: signature parse error") + } + + return hostKey.Verify(result.H, sig) +} + +// NewSession opens a new Session for this client. (A session is a remote +// execution of a program.) +func (c *Client) NewSession() (*Session, error) { + ch, in, err := c.OpenChannel("session", nil) + if err != nil { + return nil, err + } + return newSession(ch, in) +} + +func (c *Client) handleGlobalRequests(incoming <-chan *Request) { + for r := range incoming { + // This handles keepalive messages and matches + // the behaviour of OpenSSH. + r.Reply(false, nil) + } +} + +// handleChannelOpens channel open messages from the remote side. +func (c *Client) handleChannelOpens(in <-chan NewChannel) { + for ch := range in { + c.mu.Lock() + handler := c.channelHandlers[ch.ChannelType()] + c.mu.Unlock() + + if handler != nil { + handler <- ch + } else { + ch.Reject(UnknownChannelType, fmt.Sprintf("unknown channel type: %v", ch.ChannelType())) + } + } + + c.mu.Lock() + for _, ch := range c.channelHandlers { + close(ch) + } + c.channelHandlers = nil + c.mu.Unlock() +} + +// Dial starts a client connection to the given SSH server. It is a +// convenience function that connects to the given network address, +// initiates the SSH handshake, and then sets up a Client. For access +// to incoming channels and requests, use net.Dial with NewClientConn +// instead. +func Dial(network, addr string, config *ClientConfig) (*Client, error) { + conn, err := net.DialTimeout(network, addr, config.Timeout) + if err != nil { + return nil, err + } + c, chans, reqs, err := NewClientConn(conn, addr, config) + if err != nil { + return nil, err + } + return NewClient(c, chans, reqs), nil +} + +// HostKeyCallback is the function type used for verifying server +// keys. A HostKeyCallback must return nil if the host key is OK, or +// an error to reject it. It receives the hostname as passed to Dial +// or NewClientConn. The remote address is the RemoteAddr of the +// net.Conn underlying the the SSH connection. +type HostKeyCallback func(hostname string, remote net.Addr, key PublicKey) error + +// BannerCallback is the function type used for treat the banner sent by +// the server. A BannerCallback receives the message sent by the remote server. +type BannerCallback func(message string) error + +// A ClientConfig structure is used to configure a Client. It must not be +// modified after having been passed to an SSH function. +type ClientConfig struct { + // Config contains configuration that is shared between clients and + // servers. + Config + + // User contains the username to authenticate as. + User string + + // Auth contains possible authentication methods to use with the + // server. Only the first instance of a particular RFC 4252 method will + // be used during authentication. + Auth []AuthMethod + + // HostKeyCallback is called during the cryptographic + // handshake to validate the server's host key. The client + // configuration must supply this callback for the connection + // to succeed. The functions InsecureIgnoreHostKey or + // FixedHostKey can be used for simplistic host key checks. + HostKeyCallback HostKeyCallback + + // BannerCallback is called during the SSH dance to display a custom + // server's message. The client configuration can supply this callback to + // handle it as wished. The function BannerDisplayStderr can be used for + // simplistic display on Stderr. + BannerCallback BannerCallback + + // ClientVersion contains the version identification string that will + // be used for the connection. If empty, a reasonable default is used. + ClientVersion string + + // HostKeyAlgorithms lists the key types that the client will + // accept from the server as host key, in order of + // preference. If empty, a reasonable default is used. Any + // string returned from PublicKey.Type method may be used, or + // any of the CertAlgoXxxx and KeyAlgoXxxx constants. + HostKeyAlgorithms []string + + // Timeout is the maximum amount of time for the TCP connection to establish. + // + // A Timeout of zero means no timeout. + Timeout time.Duration +} + +// InsecureIgnoreHostKey returns a function that can be used for +// ClientConfig.HostKeyCallback to accept any host key. It should +// not be used for production code. +func InsecureIgnoreHostKey() HostKeyCallback { + return func(hostname string, remote net.Addr, key PublicKey) error { + return nil + } +} + +type fixedHostKey struct { + key PublicKey +} + +func (f *fixedHostKey) check(hostname string, remote net.Addr, key PublicKey) error { + if f.key == nil { + return fmt.Errorf("ssh: required host key was nil") + } + if !bytes.Equal(key.Marshal(), f.key.Marshal()) { + return fmt.Errorf("ssh: host key mismatch") + } + return nil +} + +// FixedHostKey returns a function for use in +// ClientConfig.HostKeyCallback to accept only a specific host key. +func FixedHostKey(key PublicKey) HostKeyCallback { + hk := &fixedHostKey{key} + return hk.check +} + +// BannerDisplayStderr returns a function that can be used for +// ClientConfig.BannerCallback to display banners on os.Stderr. +func BannerDisplayStderr() BannerCallback { + return func(banner string) error { + _, err := os.Stderr.WriteString(banner) + + return err + } +} diff --git a/vendor/golang.org/x/crypto/ssh/client_auth.go b/vendor/golang.org/x/crypto/ssh/client_auth.go new file mode 100644 index 0000000000000000000000000000000000000000..a1252cb9be12d986184168bd663ed1bc04c4273e --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/client_auth.go @@ -0,0 +1,510 @@ +// 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 ssh + +import ( + "bytes" + "errors" + "fmt" + "io" +) + +// clientAuthenticate authenticates with the remote server. See RFC 4252. +func (c *connection) clientAuthenticate(config *ClientConfig) error { + // initiate user auth session + if err := c.transport.writePacket(Marshal(&serviceRequestMsg{serviceUserAuth})); err != nil { + return err + } + packet, err := c.transport.readPacket() + if err != nil { + return err + } + var serviceAccept serviceAcceptMsg + if err := Unmarshal(packet, &serviceAccept); err != nil { + return err + } + + // during the authentication phase the client first attempts the "none" method + // then any untried methods suggested by the server. + tried := make(map[string]bool) + var lastMethods []string + + sessionID := c.transport.getSessionID() + for auth := AuthMethod(new(noneAuth)); auth != nil; { + ok, methods, err := auth.auth(sessionID, config.User, c.transport, config.Rand) + if err != nil { + return err + } + if ok { + // success + return nil + } + tried[auth.method()] = true + if methods == nil { + methods = lastMethods + } + lastMethods = methods + + auth = nil + + findNext: + for _, a := range config.Auth { + candidateMethod := a.method() + if tried[candidateMethod] { + continue + } + for _, meth := range methods { + if meth == candidateMethod { + auth = a + break findNext + } + } + } + } + return fmt.Errorf("ssh: unable to authenticate, attempted methods %v, no supported methods remain", keys(tried)) +} + +func keys(m map[string]bool) []string { + s := make([]string, 0, len(m)) + + for key := range m { + s = append(s, key) + } + return s +} + +// An AuthMethod represents an instance of an RFC 4252 authentication method. +type AuthMethod interface { + // auth authenticates user over transport t. + // Returns true if authentication is successful. + // If authentication is not successful, a []string of alternative + // method names is returned. If the slice is nil, it will be ignored + // and the previous set of possible methods will be reused. + auth(session []byte, user string, p packetConn, rand io.Reader) (bool, []string, error) + + // method returns the RFC 4252 method name. + method() string +} + +// "none" authentication, RFC 4252 section 5.2. +type noneAuth int + +func (n *noneAuth) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) { + if err := c.writePacket(Marshal(&userAuthRequestMsg{ + User: user, + Service: serviceSSH, + Method: "none", + })); err != nil { + return false, nil, err + } + + return handleAuthResponse(c) +} + +func (n *noneAuth) method() string { + return "none" +} + +// passwordCallback is an AuthMethod that fetches the password through +// a function call, e.g. by prompting the user. +type passwordCallback func() (password string, err error) + +func (cb passwordCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) { + type passwordAuthMsg struct { + User string `sshtype:"50"` + Service string + Method string + Reply bool + Password string + } + + pw, err := cb() + // REVIEW NOTE: is there a need to support skipping a password attempt? + // The program may only find out that the user doesn't have a password + // when prompting. + if err != nil { + return false, nil, err + } + + if err := c.writePacket(Marshal(&passwordAuthMsg{ + User: user, + Service: serviceSSH, + Method: cb.method(), + Reply: false, + Password: pw, + })); err != nil { + return false, nil, err + } + + return handleAuthResponse(c) +} + +func (cb passwordCallback) method() string { + return "password" +} + +// Password returns an AuthMethod using the given password. +func Password(secret string) AuthMethod { + return passwordCallback(func() (string, error) { return secret, nil }) +} + +// PasswordCallback returns an AuthMethod that uses a callback for +// fetching a password. +func PasswordCallback(prompt func() (secret string, err error)) AuthMethod { + return passwordCallback(prompt) +} + +type publickeyAuthMsg struct { + User string `sshtype:"50"` + Service string + Method string + // HasSig indicates to the receiver packet that the auth request is signed and + // should be used for authentication of the request. + HasSig bool + Algoname string + PubKey []byte + // Sig is tagged with "rest" so Marshal will exclude it during + // validateKey + Sig []byte `ssh:"rest"` +} + +// publicKeyCallback is an AuthMethod that uses a set of key +// pairs for authentication. +type publicKeyCallback func() ([]Signer, error) + +func (cb publicKeyCallback) method() string { + return "publickey" +} + +func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) { + // Authentication is performed by sending an enquiry to test if a key is + // acceptable to the remote. If the key is acceptable, the client will + // attempt to authenticate with the valid key. If not the client will repeat + // the process with the remaining keys. + + signers, err := cb() + if err != nil { + return false, nil, err + } + var methods []string + for _, signer := range signers { + ok, err := validateKey(signer.PublicKey(), user, c) + if err != nil { + return false, nil, err + } + if !ok { + continue + } + + pub := signer.PublicKey() + pubKey := pub.Marshal() + sign, err := signer.Sign(rand, buildDataSignedForAuth(session, userAuthRequestMsg{ + User: user, + Service: serviceSSH, + Method: cb.method(), + }, []byte(pub.Type()), pubKey)) + if err != nil { + return false, nil, err + } + + // manually wrap the serialized signature in a string + s := Marshal(sign) + sig := make([]byte, stringLength(len(s))) + marshalString(sig, s) + msg := publickeyAuthMsg{ + User: user, + Service: serviceSSH, + Method: cb.method(), + HasSig: true, + Algoname: pub.Type(), + PubKey: pubKey, + Sig: sig, + } + p := Marshal(&msg) + if err := c.writePacket(p); err != nil { + return false, nil, err + } + var success bool + success, methods, err = handleAuthResponse(c) + if err != nil { + return false, nil, err + } + + // If authentication succeeds or the list of available methods does not + // contain the "publickey" method, do not attempt to authenticate with any + // other keys. According to RFC 4252 Section 7, the latter can occur when + // additional authentication methods are required. + if success || !containsMethod(methods, cb.method()) { + return success, methods, err + } + } + + return false, methods, nil +} + +func containsMethod(methods []string, method string) bool { + for _, m := range methods { + if m == method { + return true + } + } + + return false +} + +// validateKey validates the key provided is acceptable to the server. +func validateKey(key PublicKey, user string, c packetConn) (bool, error) { + pubKey := key.Marshal() + msg := publickeyAuthMsg{ + User: user, + Service: serviceSSH, + Method: "publickey", + HasSig: false, + Algoname: key.Type(), + PubKey: pubKey, + } + if err := c.writePacket(Marshal(&msg)); err != nil { + return false, err + } + + return confirmKeyAck(key, c) +} + +func confirmKeyAck(key PublicKey, c packetConn) (bool, error) { + pubKey := key.Marshal() + algoname := key.Type() + + for { + packet, err := c.readPacket() + if err != nil { + return false, err + } + switch packet[0] { + case msgUserAuthBanner: + if err := handleBannerResponse(c, packet); err != nil { + return false, err + } + case msgUserAuthPubKeyOk: + var msg userAuthPubKeyOkMsg + if err := Unmarshal(packet, &msg); err != nil { + return false, err + } + if msg.Algo != algoname || !bytes.Equal(msg.PubKey, pubKey) { + return false, nil + } + return true, nil + case msgUserAuthFailure: + return false, nil + default: + return false, unexpectedMessageError(msgUserAuthSuccess, packet[0]) + } + } +} + +// PublicKeys returns an AuthMethod that uses the given key +// pairs. +func PublicKeys(signers ...Signer) AuthMethod { + return publicKeyCallback(func() ([]Signer, error) { return signers, nil }) +} + +// PublicKeysCallback returns an AuthMethod that runs the given +// function to obtain a list of key pairs. +func PublicKeysCallback(getSigners func() (signers []Signer, err error)) AuthMethod { + return publicKeyCallback(getSigners) +} + +// handleAuthResponse returns whether the preceding authentication request succeeded +// along with a list of remaining authentication methods to try next and +// an error if an unexpected response was received. +func handleAuthResponse(c packetConn) (bool, []string, error) { + for { + packet, err := c.readPacket() + if err != nil { + return false, nil, err + } + + switch packet[0] { + case msgUserAuthBanner: + if err := handleBannerResponse(c, packet); err != nil { + return false, nil, err + } + case msgUserAuthFailure: + var msg userAuthFailureMsg + if err := Unmarshal(packet, &msg); err != nil { + return false, nil, err + } + return false, msg.Methods, nil + case msgUserAuthSuccess: + return true, nil, nil + default: + return false, nil, unexpectedMessageError(msgUserAuthSuccess, packet[0]) + } + } +} + +func handleBannerResponse(c packetConn, packet []byte) error { + var msg userAuthBannerMsg + if err := Unmarshal(packet, &msg); err != nil { + return err + } + + transport, ok := c.(*handshakeTransport) + if !ok { + return nil + } + + if transport.bannerCallback != nil { + return transport.bannerCallback(msg.Message) + } + + return nil +} + +// KeyboardInteractiveChallenge should print questions, optionally +// disabling echoing (e.g. for passwords), and return all the answers. +// Challenge may be called multiple times in a single session. After +// successful authentication, the server may send a challenge with no +// questions, for which the user and instruction messages should be +// printed. RFC 4256 section 3.3 details how the UI should behave for +// both CLI and GUI environments. +type KeyboardInteractiveChallenge func(user, instruction string, questions []string, echos []bool) (answers []string, err error) + +// KeyboardInteractive returns an AuthMethod using a prompt/response +// sequence controlled by the server. +func KeyboardInteractive(challenge KeyboardInteractiveChallenge) AuthMethod { + return challenge +} + +func (cb KeyboardInteractiveChallenge) method() string { + return "keyboard-interactive" +} + +func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) { + type initiateMsg struct { + User string `sshtype:"50"` + Service string + Method string + Language string + Submethods string + } + + if err := c.writePacket(Marshal(&initiateMsg{ + User: user, + Service: serviceSSH, + Method: "keyboard-interactive", + })); err != nil { + return false, nil, err + } + + for { + packet, err := c.readPacket() + if err != nil { + return false, nil, err + } + + // like handleAuthResponse, but with less options. + switch packet[0] { + case msgUserAuthBanner: + if err := handleBannerResponse(c, packet); err != nil { + return false, nil, err + } + continue + case msgUserAuthInfoRequest: + // OK + case msgUserAuthFailure: + var msg userAuthFailureMsg + if err := Unmarshal(packet, &msg); err != nil { + return false, nil, err + } + return false, msg.Methods, nil + case msgUserAuthSuccess: + return true, nil, nil + default: + return false, nil, unexpectedMessageError(msgUserAuthInfoRequest, packet[0]) + } + + var msg userAuthInfoRequestMsg + if err := Unmarshal(packet, &msg); err != nil { + return false, nil, err + } + + // Manually unpack the prompt/echo pairs. + rest := msg.Prompts + var prompts []string + var echos []bool + for i := 0; i < int(msg.NumPrompts); i++ { + prompt, r, ok := parseString(rest) + if !ok || len(r) == 0 { + return false, nil, errors.New("ssh: prompt format error") + } + prompts = append(prompts, string(prompt)) + echos = append(echos, r[0] != 0) + rest = r[1:] + } + + if len(rest) != 0 { + return false, nil, errors.New("ssh: extra data following keyboard-interactive pairs") + } + + answers, err := cb(msg.User, msg.Instruction, prompts, echos) + if err != nil { + return false, nil, err + } + + if len(answers) != len(prompts) { + return false, nil, errors.New("ssh: not enough answers from keyboard-interactive callback") + } + responseLength := 1 + 4 + for _, a := range answers { + responseLength += stringLength(len(a)) + } + serialized := make([]byte, responseLength) + p := serialized + p[0] = msgUserAuthInfoResponse + p = p[1:] + p = marshalUint32(p, uint32(len(answers))) + for _, a := range answers { + p = marshalString(p, []byte(a)) + } + + if err := c.writePacket(serialized); err != nil { + return false, nil, err + } + } +} + +type retryableAuthMethod struct { + authMethod AuthMethod + maxTries int +} + +func (r *retryableAuthMethod) auth(session []byte, user string, c packetConn, rand io.Reader) (ok bool, methods []string, err error) { + for i := 0; r.maxTries <= 0 || i < r.maxTries; i++ { + ok, methods, err = r.authMethod.auth(session, user, c, rand) + if ok || err != nil { // either success or error terminate + return ok, methods, err + } + } + return ok, methods, err +} + +func (r *retryableAuthMethod) method() string { + return r.authMethod.method() +} + +// RetryableAuthMethod is a decorator for other auth methods enabling them to +// be retried up to maxTries before considering that AuthMethod itself failed. +// If maxTries is <= 0, will retry indefinitely +// +// This is useful for interactive clients using challenge/response type +// authentication (e.g. Keyboard-Interactive, Password, etc) where the user +// could mistype their response resulting in the server issuing a +// SSH_MSG_USERAUTH_FAILURE (rfc4252 #8 [password] and rfc4256 #3.4 +// [keyboard-interactive]); Without this decorator, the non-retryable +// AuthMethod would be removed from future consideration, and never tried again +// (and so the user would never be able to retry their entry). +func RetryableAuthMethod(auth AuthMethod, maxTries int) AuthMethod { + return &retryableAuthMethod{authMethod: auth, maxTries: maxTries} +} diff --git a/vendor/golang.org/x/crypto/ssh/client_auth_test.go b/vendor/golang.org/x/crypto/ssh/client_auth_test.go new file mode 100644 index 0000000000000000000000000000000000000000..145b57a2bb70e0e8487bd89becde9187e5890c09 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/client_auth_test.go @@ -0,0 +1,628 @@ +// 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 ssh + +import ( + "bytes" + "crypto/rand" + "errors" + "fmt" + "os" + "strings" + "testing" +) + +type keyboardInteractive map[string]string + +func (cr keyboardInteractive) Challenge(user string, instruction string, questions []string, echos []bool) ([]string, error) { + var answers []string + for _, q := range questions { + answers = append(answers, cr[q]) + } + return answers, nil +} + +// reused internally by tests +var clientPassword = "tiger" + +// tryAuth runs a handshake with a given config against an SSH server +// with config serverConfig +func tryAuth(t *testing.T, config *ClientConfig) error { + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + + certChecker := CertChecker{ + IsUserAuthority: func(k PublicKey) bool { + return bytes.Equal(k.Marshal(), testPublicKeys["ecdsa"].Marshal()) + }, + UserKeyFallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) { + if conn.User() == "testuser" && bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) { + return nil, nil + } + + return nil, fmt.Errorf("pubkey for %q not acceptable", conn.User()) + }, + IsRevoked: func(c *Certificate) bool { + return c.Serial == 666 + }, + } + + serverConfig := &ServerConfig{ + PasswordCallback: func(conn ConnMetadata, pass []byte) (*Permissions, error) { + if conn.User() == "testuser" && string(pass) == clientPassword { + return nil, nil + } + return nil, errors.New("password auth failed") + }, + PublicKeyCallback: certChecker.Authenticate, + KeyboardInteractiveCallback: func(conn ConnMetadata, challenge KeyboardInteractiveChallenge) (*Permissions, error) { + ans, err := challenge("user", + "instruction", + []string{"question1", "question2"}, + []bool{true, true}) + if err != nil { + return nil, err + } + ok := conn.User() == "testuser" && ans[0] == "answer1" && ans[1] == "answer2" + if ok { + challenge("user", "motd", nil, nil) + return nil, nil + } + return nil, errors.New("keyboard-interactive failed") + }, + } + serverConfig.AddHostKey(testSigners["rsa"]) + + go newServer(c1, serverConfig) + _, _, _, err = NewClientConn(c2, "", config) + return err +} + +func TestClientAuthPublicKey(t *testing.T) { + config := &ClientConfig{ + User: "testuser", + Auth: []AuthMethod{ + PublicKeys(testSigners["rsa"]), + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + if err := tryAuth(t, config); err != nil { + t.Fatalf("unable to dial remote side: %s", err) + } +} + +func TestAuthMethodPassword(t *testing.T) { + config := &ClientConfig{ + User: "testuser", + Auth: []AuthMethod{ + Password(clientPassword), + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + + if err := tryAuth(t, config); err != nil { + t.Fatalf("unable to dial remote side: %s", err) + } +} + +func TestAuthMethodFallback(t *testing.T) { + var passwordCalled bool + config := &ClientConfig{ + User: "testuser", + Auth: []AuthMethod{ + PublicKeys(testSigners["rsa"]), + PasswordCallback( + func() (string, error) { + passwordCalled = true + return "WRONG", nil + }), + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + + if err := tryAuth(t, config); err != nil { + t.Fatalf("unable to dial remote side: %s", err) + } + + if passwordCalled { + t.Errorf("password auth tried before public-key auth.") + } +} + +func TestAuthMethodWrongPassword(t *testing.T) { + config := &ClientConfig{ + User: "testuser", + Auth: []AuthMethod{ + Password("wrong"), + PublicKeys(testSigners["rsa"]), + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + + if err := tryAuth(t, config); err != nil { + t.Fatalf("unable to dial remote side: %s", err) + } +} + +func TestAuthMethodKeyboardInteractive(t *testing.T) { + answers := keyboardInteractive(map[string]string{ + "question1": "answer1", + "question2": "answer2", + }) + config := &ClientConfig{ + User: "testuser", + Auth: []AuthMethod{ + KeyboardInteractive(answers.Challenge), + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + + if err := tryAuth(t, config); err != nil { + t.Fatalf("unable to dial remote side: %s", err) + } +} + +func TestAuthMethodWrongKeyboardInteractive(t *testing.T) { + answers := keyboardInteractive(map[string]string{ + "question1": "answer1", + "question2": "WRONG", + }) + config := &ClientConfig{ + User: "testuser", + Auth: []AuthMethod{ + KeyboardInteractive(answers.Challenge), + }, + } + + if err := tryAuth(t, config); err == nil { + t.Fatalf("wrong answers should not have authenticated with KeyboardInteractive") + } +} + +// the mock server will only authenticate ssh-rsa keys +func TestAuthMethodInvalidPublicKey(t *testing.T) { + config := &ClientConfig{ + User: "testuser", + Auth: []AuthMethod{ + PublicKeys(testSigners["dsa"]), + }, + } + + if err := tryAuth(t, config); err == nil { + t.Fatalf("dsa private key should not have authenticated with rsa public key") + } +} + +// the client should authenticate with the second key +func TestAuthMethodRSAandDSA(t *testing.T) { + config := &ClientConfig{ + User: "testuser", + Auth: []AuthMethod{ + PublicKeys(testSigners["dsa"], testSigners["rsa"]), + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + if err := tryAuth(t, config); err != nil { + t.Fatalf("client could not authenticate with rsa key: %v", err) + } +} + +func TestClientHMAC(t *testing.T) { + for _, mac := range supportedMACs { + config := &ClientConfig{ + User: "testuser", + Auth: []AuthMethod{ + PublicKeys(testSigners["rsa"]), + }, + Config: Config{ + MACs: []string{mac}, + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + if err := tryAuth(t, config); err != nil { + t.Fatalf("client could not authenticate with mac algo %s: %v", mac, err) + } + } +} + +// issue 4285. +func TestClientUnsupportedCipher(t *testing.T) { + config := &ClientConfig{ + User: "testuser", + Auth: []AuthMethod{ + PublicKeys(), + }, + Config: Config{ + Ciphers: []string{"aes128-cbc"}, // not currently supported + }, + } + if err := tryAuth(t, config); err == nil { + t.Errorf("expected no ciphers in common") + } +} + +func TestClientUnsupportedKex(t *testing.T) { + if os.Getenv("GO_BUILDER_NAME") != "" { + t.Skip("skipping known-flaky test on the Go build dashboard; see golang.org/issue/15198") + } + config := &ClientConfig{ + User: "testuser", + Auth: []AuthMethod{ + PublicKeys(), + }, + Config: Config{ + KeyExchanges: []string{"diffie-hellman-group-exchange-sha256"}, // not currently supported + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + if err := tryAuth(t, config); err == nil || !strings.Contains(err.Error(), "common algorithm") { + t.Errorf("got %v, expected 'common algorithm'", err) + } +} + +func TestClientLoginCert(t *testing.T) { + cert := &Certificate{ + Key: testPublicKeys["rsa"], + ValidBefore: CertTimeInfinity, + CertType: UserCert, + } + cert.SignCert(rand.Reader, testSigners["ecdsa"]) + certSigner, err := NewCertSigner(cert, testSigners["rsa"]) + if err != nil { + t.Fatalf("NewCertSigner: %v", err) + } + + clientConfig := &ClientConfig{ + User: "user", + HostKeyCallback: InsecureIgnoreHostKey(), + } + clientConfig.Auth = append(clientConfig.Auth, PublicKeys(certSigner)) + + // should succeed + if err := tryAuth(t, clientConfig); err != nil { + t.Errorf("cert login failed: %v", err) + } + + // corrupted signature + cert.Signature.Blob[0]++ + if err := tryAuth(t, clientConfig); err == nil { + t.Errorf("cert login passed with corrupted sig") + } + + // revoked + cert.Serial = 666 + cert.SignCert(rand.Reader, testSigners["ecdsa"]) + if err := tryAuth(t, clientConfig); err == nil { + t.Errorf("revoked cert login succeeded") + } + cert.Serial = 1 + + // sign with wrong key + cert.SignCert(rand.Reader, testSigners["dsa"]) + if err := tryAuth(t, clientConfig); err == nil { + t.Errorf("cert login passed with non-authoritative key") + } + + // host cert + cert.CertType = HostCert + cert.SignCert(rand.Reader, testSigners["ecdsa"]) + if err := tryAuth(t, clientConfig); err == nil { + t.Errorf("cert login passed with wrong type") + } + cert.CertType = UserCert + + // principal specified + cert.ValidPrincipals = []string{"user"} + cert.SignCert(rand.Reader, testSigners["ecdsa"]) + if err := tryAuth(t, clientConfig); err != nil { + t.Errorf("cert login failed: %v", err) + } + + // wrong principal specified + cert.ValidPrincipals = []string{"fred"} + cert.SignCert(rand.Reader, testSigners["ecdsa"]) + if err := tryAuth(t, clientConfig); err == nil { + t.Errorf("cert login passed with wrong principal") + } + cert.ValidPrincipals = nil + + // added critical option + cert.CriticalOptions = map[string]string{"root-access": "yes"} + cert.SignCert(rand.Reader, testSigners["ecdsa"]) + if err := tryAuth(t, clientConfig); err == nil { + t.Errorf("cert login passed with unrecognized critical option") + } + + // allowed source address + cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42/24,::42/120"} + cert.SignCert(rand.Reader, testSigners["ecdsa"]) + if err := tryAuth(t, clientConfig); err != nil { + t.Errorf("cert login with source-address failed: %v", err) + } + + // disallowed source address + cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42,::42"} + cert.SignCert(rand.Reader, testSigners["ecdsa"]) + if err := tryAuth(t, clientConfig); err == nil { + t.Errorf("cert login with source-address succeeded") + } +} + +func testPermissionsPassing(withPermissions bool, t *testing.T) { + serverConfig := &ServerConfig{ + PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) { + if conn.User() == "nopermissions" { + return nil, nil + } + return &Permissions{}, nil + }, + } + serverConfig.AddHostKey(testSigners["rsa"]) + + clientConfig := &ClientConfig{ + Auth: []AuthMethod{ + PublicKeys(testSigners["rsa"]), + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + if withPermissions { + clientConfig.User = "permissions" + } else { + clientConfig.User = "nopermissions" + } + + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + + go NewClientConn(c2, "", clientConfig) + serverConn, err := newServer(c1, serverConfig) + if err != nil { + t.Fatal(err) + } + if p := serverConn.Permissions; (p != nil) != withPermissions { + t.Fatalf("withPermissions is %t, but Permissions object is %#v", withPermissions, p) + } +} + +func TestPermissionsPassing(t *testing.T) { + testPermissionsPassing(true, t) +} + +func TestNoPermissionsPassing(t *testing.T) { + testPermissionsPassing(false, t) +} + +func TestRetryableAuth(t *testing.T) { + n := 0 + passwords := []string{"WRONG1", "WRONG2"} + + config := &ClientConfig{ + User: "testuser", + Auth: []AuthMethod{ + RetryableAuthMethod(PasswordCallback(func() (string, error) { + p := passwords[n] + n++ + return p, nil + }), 2), + PublicKeys(testSigners["rsa"]), + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + + if err := tryAuth(t, config); err != nil { + t.Fatalf("unable to dial remote side: %s", err) + } + if n != 2 { + t.Fatalf("Did not try all passwords") + } +} + +func ExampleRetryableAuthMethod(t *testing.T) { + user := "testuser" + NumberOfPrompts := 3 + + // Normally this would be a callback that prompts the user to answer the + // provided questions + Cb := func(user, instruction string, questions []string, echos []bool) (answers []string, err error) { + return []string{"answer1", "answer2"}, nil + } + + config := &ClientConfig{ + HostKeyCallback: InsecureIgnoreHostKey(), + User: user, + Auth: []AuthMethod{ + RetryableAuthMethod(KeyboardInteractiveChallenge(Cb), NumberOfPrompts), + }, + } + + if err := tryAuth(t, config); err != nil { + t.Fatalf("unable to dial remote side: %s", err) + } +} + +// Test if username is received on server side when NoClientAuth is used +func TestClientAuthNone(t *testing.T) { + user := "testuser" + serverConfig := &ServerConfig{ + NoClientAuth: true, + } + serverConfig.AddHostKey(testSigners["rsa"]) + + clientConfig := &ClientConfig{ + User: user, + HostKeyCallback: InsecureIgnoreHostKey(), + } + + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + + go NewClientConn(c2, "", clientConfig) + serverConn, err := newServer(c1, serverConfig) + if err != nil { + t.Fatalf("newServer: %v", err) + } + if serverConn.User() != user { + t.Fatalf("server: got %q, want %q", serverConn.User(), user) + } +} + +// Test if authentication attempts are limited on server when MaxAuthTries is set +func TestClientAuthMaxAuthTries(t *testing.T) { + user := "testuser" + + serverConfig := &ServerConfig{ + MaxAuthTries: 2, + PasswordCallback: func(conn ConnMetadata, pass []byte) (*Permissions, error) { + if conn.User() == "testuser" && string(pass) == "right" { + return nil, nil + } + return nil, errors.New("password auth failed") + }, + } + serverConfig.AddHostKey(testSigners["rsa"]) + + expectedErr := fmt.Errorf("ssh: handshake failed: %v", &disconnectMsg{ + Reason: 2, + Message: "too many authentication failures", + }) + + for tries := 2; tries < 4; tries++ { + n := tries + clientConfig := &ClientConfig{ + User: user, + Auth: []AuthMethod{ + RetryableAuthMethod(PasswordCallback(func() (string, error) { + n-- + if n == 0 { + return "right", nil + } + return "wrong", nil + }), tries), + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + + go newServer(c1, serverConfig) + _, _, _, err = NewClientConn(c2, "", clientConfig) + if tries > 2 { + if err == nil { + t.Fatalf("client: got no error, want %s", expectedErr) + } else if err.Error() != expectedErr.Error() { + t.Fatalf("client: got %s, want %s", err, expectedErr) + } + } else { + if err != nil { + t.Fatalf("client: got %s, want no error", err) + } + } + } +} + +// Test if authentication attempts are correctly limited on server +// when more public keys are provided then MaxAuthTries +func TestClientAuthMaxAuthTriesPublicKey(t *testing.T) { + signers := []Signer{} + for i := 0; i < 6; i++ { + signers = append(signers, testSigners["dsa"]) + } + + validConfig := &ClientConfig{ + User: "testuser", + Auth: []AuthMethod{ + PublicKeys(append([]Signer{testSigners["rsa"]}, signers...)...), + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + if err := tryAuth(t, validConfig); err != nil { + t.Fatalf("unable to dial remote side: %s", err) + } + + expectedErr := fmt.Errorf("ssh: handshake failed: %v", &disconnectMsg{ + Reason: 2, + Message: "too many authentication failures", + }) + invalidConfig := &ClientConfig{ + User: "testuser", + Auth: []AuthMethod{ + PublicKeys(append(signers, testSigners["rsa"])...), + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + if err := tryAuth(t, invalidConfig); err == nil { + t.Fatalf("client: got no error, want %s", expectedErr) + } else if err.Error() != expectedErr.Error() { + t.Fatalf("client: got %s, want %s", err, expectedErr) + } +} + +// Test whether authentication errors are being properly logged if all +// authentication methods have been exhausted +func TestClientAuthErrorList(t *testing.T) { + publicKeyErr := errors.New("This is an error from PublicKeyCallback") + + clientConfig := &ClientConfig{ + Auth: []AuthMethod{ + PublicKeys(testSigners["rsa"]), + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + serverConfig := &ServerConfig{ + PublicKeyCallback: func(_ ConnMetadata, _ PublicKey) (*Permissions, error) { + return nil, publicKeyErr + }, + } + serverConfig.AddHostKey(testSigners["rsa"]) + + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + + go NewClientConn(c2, "", clientConfig) + _, err = newServer(c1, serverConfig) + if err == nil { + t.Fatal("newServer: got nil, expected errors") + } + + authErrs, ok := err.(*ServerAuthError) + if !ok { + t.Fatalf("errors: got %T, want *ssh.ServerAuthError", err) + } + for i, e := range authErrs.Errors { + switch i { + case 0: + if e.Error() != "no auth passed yet" { + t.Fatalf("errors: got %v, want no auth passed yet", e.Error()) + } + case 1: + if e != publicKeyErr { + t.Fatalf("errors: got %v, want %v", e, publicKeyErr) + } + default: + t.Fatalf("errors: got %v, expected 2 errors", authErrs.Errors) + } + } +} diff --git a/vendor/golang.org/x/crypto/ssh/client_test.go b/vendor/golang.org/x/crypto/ssh/client_test.go new file mode 100644 index 0000000000000000000000000000000000000000..81f9599e1d45ce0a225aabc85935505273111281 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/client_test.go @@ -0,0 +1,166 @@ +// 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 ssh + +import ( + "strings" + "testing" +) + +func TestClientVersion(t *testing.T) { + for _, tt := range []struct { + name string + version string + multiLine string + wantErr bool + }{ + { + name: "default version", + version: packageVersion, + }, + { + name: "custom version", + version: "SSH-2.0-CustomClientVersionString", + }, + { + name: "good multi line version", + version: packageVersion, + multiLine: strings.Repeat("ignored\r\n", 20), + }, + { + name: "bad multi line version", + version: packageVersion, + multiLine: "bad multi line version", + wantErr: true, + }, + { + name: "long multi line version", + version: packageVersion, + multiLine: strings.Repeat("long multi line version\r\n", 50)[:256], + wantErr: true, + }, + } { + t.Run(tt.name, func(t *testing.T) { + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + go func() { + if tt.multiLine != "" { + c1.Write([]byte(tt.multiLine)) + } + NewClientConn(c1, "", &ClientConfig{ + ClientVersion: tt.version, + HostKeyCallback: InsecureIgnoreHostKey(), + }) + c1.Close() + }() + conf := &ServerConfig{NoClientAuth: true} + conf.AddHostKey(testSigners["rsa"]) + conn, _, _, err := NewServerConn(c2, conf) + if err == nil == tt.wantErr { + t.Fatalf("got err %v; wantErr %t", err, tt.wantErr) + } + if tt.wantErr { + // Don't verify the version on an expected error. + return + } + if got := string(conn.ClientVersion()); got != tt.version { + t.Fatalf("got %q; want %q", got, tt.version) + } + }) + } +} + +func TestHostKeyCheck(t *testing.T) { + for _, tt := range []struct { + name string + wantError string + key PublicKey + }{ + {"no callback", "must specify HostKeyCallback", nil}, + {"correct key", "", testSigners["rsa"].PublicKey()}, + {"mismatch", "mismatch", testSigners["ecdsa"].PublicKey()}, + } { + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + serverConf := &ServerConfig{ + NoClientAuth: true, + } + serverConf.AddHostKey(testSigners["rsa"]) + + go NewServerConn(c1, serverConf) + clientConf := ClientConfig{ + User: "user", + } + if tt.key != nil { + clientConf.HostKeyCallback = FixedHostKey(tt.key) + } + + _, _, _, err = NewClientConn(c2, "", &clientConf) + if err != nil { + if tt.wantError == "" || !strings.Contains(err.Error(), tt.wantError) { + t.Errorf("%s: got error %q, missing %q", tt.name, err.Error(), tt.wantError) + } + } else if tt.wantError != "" { + t.Errorf("%s: succeeded, but want error string %q", tt.name, tt.wantError) + } + } +} + +func TestBannerCallback(t *testing.T) { + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + + serverConf := &ServerConfig{ + PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) { + return &Permissions{}, nil + }, + BannerCallback: func(conn ConnMetadata) string { + return "Hello World" + }, + } + serverConf.AddHostKey(testSigners["rsa"]) + go NewServerConn(c1, serverConf) + + var receivedBanner string + var bannerCount int + clientConf := ClientConfig{ + Auth: []AuthMethod{ + Password("123"), + }, + User: "user", + HostKeyCallback: InsecureIgnoreHostKey(), + BannerCallback: func(message string) error { + bannerCount++ + receivedBanner = message + return nil + }, + } + + _, _, _, err = NewClientConn(c2, "", &clientConf) + if err != nil { + t.Fatal(err) + } + + if bannerCount != 1 { + t.Errorf("got %d banners; want 1", bannerCount) + } + + expected := "Hello World" + if receivedBanner != expected { + t.Fatalf("got %s; want %s", receivedBanner, expected) + } +} diff --git a/vendor/golang.org/x/crypto/ssh/common.go b/vendor/golang.org/x/crypto/ssh/common.go new file mode 100644 index 0000000000000000000000000000000000000000..04f3620b3d5ebe9252b0c8cabe2c4a54181d1548 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/common.go @@ -0,0 +1,383 @@ +// 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 ssh + +import ( + "crypto" + "crypto/rand" + "fmt" + "io" + "math" + "sync" + + _ "crypto/sha1" + _ "crypto/sha256" + _ "crypto/sha512" +) + +// These are string constants in the SSH protocol. +const ( + compressionNone = "none" + serviceUserAuth = "ssh-userauth" + serviceSSH = "ssh-connection" +) + +// supportedCiphers lists ciphers we support but might not recommend. +var supportedCiphers = []string{ + "aes128-ctr", "aes192-ctr", "aes256-ctr", + "aes128-gcm@openssh.com", + chacha20Poly1305ID, + "arcfour256", "arcfour128", "arcfour", + aes128cbcID, + tripledescbcID, +} + +// preferredCiphers specifies the default preference for ciphers. +var preferredCiphers = []string{ + "aes128-gcm@openssh.com", + chacha20Poly1305ID, + "aes128-ctr", "aes192-ctr", "aes256-ctr", +} + +// supportedKexAlgos specifies the supported key-exchange algorithms in +// preference order. +var supportedKexAlgos = []string{ + kexAlgoCurve25519SHA256, + // P384 and P521 are not constant-time yet, but since we don't + // reuse ephemeral keys, using them for ECDH should be OK. + kexAlgoECDH256, kexAlgoECDH384, kexAlgoECDH521, + kexAlgoDH14SHA1, kexAlgoDH1SHA1, +} + +// supportedHostKeyAlgos specifies the supported host-key algorithms (i.e. methods +// of authenticating servers) in preference order. +var supportedHostKeyAlgos = []string{ + CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, + CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoED25519v01, + + KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, + KeyAlgoRSA, KeyAlgoDSA, + + KeyAlgoED25519, +} + +// supportedMACs specifies a default set of MAC algorithms in preference order. +// This is based on RFC 4253, section 6.4, but with hmac-md5 variants removed +// because they have reached the end of their useful life. +var supportedMACs = []string{ + "hmac-sha2-256-etm@openssh.com", "hmac-sha2-256", "hmac-sha1", "hmac-sha1-96", +} + +var supportedCompressions = []string{compressionNone} + +// hashFuncs keeps the mapping of supported algorithms to their respective +// hashes needed for signature verification. +var hashFuncs = map[string]crypto.Hash{ + KeyAlgoRSA: crypto.SHA1, + KeyAlgoDSA: crypto.SHA1, + KeyAlgoECDSA256: crypto.SHA256, + KeyAlgoECDSA384: crypto.SHA384, + KeyAlgoECDSA521: crypto.SHA512, + CertAlgoRSAv01: crypto.SHA1, + CertAlgoDSAv01: crypto.SHA1, + CertAlgoECDSA256v01: crypto.SHA256, + CertAlgoECDSA384v01: crypto.SHA384, + CertAlgoECDSA521v01: crypto.SHA512, +} + +// unexpectedMessageError results when the SSH message that we received didn't +// match what we wanted. +func unexpectedMessageError(expected, got uint8) error { + return fmt.Errorf("ssh: unexpected message type %d (expected %d)", got, expected) +} + +// parseError results from a malformed SSH message. +func parseError(tag uint8) error { + return fmt.Errorf("ssh: parse error in message type %d", tag) +} + +func findCommon(what string, client []string, server []string) (common string, err error) { + for _, c := range client { + for _, s := range server { + if c == s { + return c, nil + } + } + } + return "", fmt.Errorf("ssh: no common algorithm for %s; client offered: %v, server offered: %v", what, client, server) +} + +type directionAlgorithms struct { + Cipher string + MAC string + Compression string +} + +// rekeyBytes returns a rekeying intervals in bytes. +func (a *directionAlgorithms) rekeyBytes() int64 { + // According to RFC4344 block ciphers should rekey after + // 2^(BLOCKSIZE/4) blocks. For all AES flavors BLOCKSIZE is + // 128. + switch a.Cipher { + case "aes128-ctr", "aes192-ctr", "aes256-ctr", gcmCipherID, aes128cbcID: + return 16 * (1 << 32) + + } + + // For others, stick with RFC4253 recommendation to rekey after 1 Gb of data. + return 1 << 30 +} + +type algorithms struct { + kex string + hostKey string + w directionAlgorithms + r directionAlgorithms +} + +func findAgreedAlgorithms(clientKexInit, serverKexInit *kexInitMsg) (algs *algorithms, err error) { + result := &algorithms{} + + result.kex, err = findCommon("key exchange", clientKexInit.KexAlgos, serverKexInit.KexAlgos) + if err != nil { + return + } + + result.hostKey, err = findCommon("host key", clientKexInit.ServerHostKeyAlgos, serverKexInit.ServerHostKeyAlgos) + if err != nil { + return + } + + result.w.Cipher, err = findCommon("client to server cipher", clientKexInit.CiphersClientServer, serverKexInit.CiphersClientServer) + if err != nil { + return + } + + result.r.Cipher, err = findCommon("server to client cipher", clientKexInit.CiphersServerClient, serverKexInit.CiphersServerClient) + if err != nil { + return + } + + result.w.MAC, err = findCommon("client to server MAC", clientKexInit.MACsClientServer, serverKexInit.MACsClientServer) + if err != nil { + return + } + + result.r.MAC, err = findCommon("server to client MAC", clientKexInit.MACsServerClient, serverKexInit.MACsServerClient) + if err != nil { + return + } + + result.w.Compression, err = findCommon("client to server compression", clientKexInit.CompressionClientServer, serverKexInit.CompressionClientServer) + if err != nil { + return + } + + result.r.Compression, err = findCommon("server to client compression", clientKexInit.CompressionServerClient, serverKexInit.CompressionServerClient) + if err != nil { + return + } + + return result, nil +} + +// If rekeythreshold is too small, we can't make any progress sending +// stuff. +const minRekeyThreshold uint64 = 256 + +// Config contains configuration data common to both ServerConfig and +// ClientConfig. +type Config struct { + // Rand provides the source of entropy for cryptographic + // primitives. If Rand is nil, the cryptographic random reader + // in package crypto/rand will be used. + Rand io.Reader + + // The maximum number of bytes sent or received after which a + // new key is negotiated. It must be at least 256. If + // unspecified, a size suitable for the chosen cipher is used. + RekeyThreshold uint64 + + // The allowed key exchanges algorithms. If unspecified then a + // default set of algorithms is used. + KeyExchanges []string + + // The allowed cipher algorithms. If unspecified then a sensible + // default is used. + Ciphers []string + + // The allowed MAC algorithms. If unspecified then a sensible default + // is used. + MACs []string +} + +// SetDefaults sets sensible values for unset fields in config. This is +// exported for testing: Configs passed to SSH functions are copied and have +// default values set automatically. +func (c *Config) SetDefaults() { + if c.Rand == nil { + c.Rand = rand.Reader + } + if c.Ciphers == nil { + c.Ciphers = preferredCiphers + } + var ciphers []string + for _, c := range c.Ciphers { + if cipherModes[c] != nil { + // reject the cipher if we have no cipherModes definition + ciphers = append(ciphers, c) + } + } + c.Ciphers = ciphers + + if c.KeyExchanges == nil { + c.KeyExchanges = supportedKexAlgos + } + + if c.MACs == nil { + c.MACs = supportedMACs + } + + if c.RekeyThreshold == 0 { + // cipher specific default + } else if c.RekeyThreshold < minRekeyThreshold { + c.RekeyThreshold = minRekeyThreshold + } else if c.RekeyThreshold >= math.MaxInt64 { + // Avoid weirdness if somebody uses -1 as a threshold. + c.RekeyThreshold = math.MaxInt64 + } +} + +// buildDataSignedForAuth returns the data that is signed in order to prove +// possession of a private key. See RFC 4252, section 7. +func buildDataSignedForAuth(sessionID []byte, req userAuthRequestMsg, algo, pubKey []byte) []byte { + data := struct { + Session []byte + Type byte + User string + Service string + Method string + Sign bool + Algo []byte + PubKey []byte + }{ + sessionID, + msgUserAuthRequest, + req.User, + req.Service, + req.Method, + true, + algo, + pubKey, + } + return Marshal(data) +} + +func appendU16(buf []byte, n uint16) []byte { + return append(buf, byte(n>>8), byte(n)) +} + +func appendU32(buf []byte, n uint32) []byte { + return append(buf, byte(n>>24), byte(n>>16), byte(n>>8), byte(n)) +} + +func appendU64(buf []byte, n uint64) []byte { + return append(buf, + byte(n>>56), byte(n>>48), byte(n>>40), byte(n>>32), + byte(n>>24), byte(n>>16), byte(n>>8), byte(n)) +} + +func appendInt(buf []byte, n int) []byte { + return appendU32(buf, uint32(n)) +} + +func appendString(buf []byte, s string) []byte { + buf = appendU32(buf, uint32(len(s))) + buf = append(buf, s...) + return buf +} + +func appendBool(buf []byte, b bool) []byte { + if b { + return append(buf, 1) + } + return append(buf, 0) +} + +// newCond is a helper to hide the fact that there is no usable zero +// value for sync.Cond. +func newCond() *sync.Cond { return sync.NewCond(new(sync.Mutex)) } + +// window represents the buffer available to clients +// wishing to write to a channel. +type window struct { + *sync.Cond + win uint32 // RFC 4254 5.2 says the window size can grow to 2^32-1 + writeWaiters int + closed bool +} + +// add adds win to the amount of window available +// for consumers. +func (w *window) add(win uint32) bool { + // a zero sized window adjust is a noop. + if win == 0 { + return true + } + w.L.Lock() + if w.win+win < win { + w.L.Unlock() + return false + } + w.win += win + // It is unusual that multiple goroutines would be attempting to reserve + // window space, but not guaranteed. Use broadcast to notify all waiters + // that additional window is available. + w.Broadcast() + w.L.Unlock() + return true +} + +// close sets the window to closed, so all reservations fail +// immediately. +func (w *window) close() { + w.L.Lock() + w.closed = true + w.Broadcast() + w.L.Unlock() +} + +// reserve reserves win from the available window capacity. +// If no capacity remains, reserve will block. reserve may +// return less than requested. +func (w *window) reserve(win uint32) (uint32, error) { + var err error + w.L.Lock() + w.writeWaiters++ + w.Broadcast() + for w.win == 0 && !w.closed { + w.Wait() + } + w.writeWaiters-- + if w.win < win { + win = w.win + } + w.win -= win + if w.closed { + err = io.EOF + } + w.L.Unlock() + return win, err +} + +// waitWriterBlocked waits until some goroutine is blocked for further +// writes. It is used in tests only. +func (w *window) waitWriterBlocked() { + w.Cond.L.Lock() + for w.writeWaiters == 0 { + w.Cond.Wait() + } + w.Cond.L.Unlock() +} diff --git a/vendor/golang.org/x/crypto/ssh/connection.go b/vendor/golang.org/x/crypto/ssh/connection.go new file mode 100644 index 0000000000000000000000000000000000000000..fd6b0681b5121fd0a8b92c7be7edc7fd5f5998b4 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/connection.go @@ -0,0 +1,143 @@ +// 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. + +package ssh + +import ( + "fmt" + "net" +) + +// OpenChannelError is returned if the other side rejects an +// OpenChannel request. +type OpenChannelError struct { + Reason RejectionReason + Message string +} + +func (e *OpenChannelError) Error() string { + return fmt.Sprintf("ssh: rejected: %s (%s)", e.Reason, e.Message) +} + +// ConnMetadata holds metadata for the connection. +type ConnMetadata interface { + // User returns the user ID for this connection. + User() string + + // SessionID returns the session hash, also denoted by H. + SessionID() []byte + + // ClientVersion returns the client's version string as hashed + // into the session ID. + ClientVersion() []byte + + // ServerVersion returns the server's version string as hashed + // into the session ID. + ServerVersion() []byte + + // RemoteAddr returns the remote address for this connection. + RemoteAddr() net.Addr + + // LocalAddr returns the local address for this connection. + LocalAddr() net.Addr +} + +// Conn represents an SSH connection for both server and client roles. +// Conn is the basis for implementing an application layer, such +// as ClientConn, which implements the traditional shell access for +// clients. +type Conn interface { + ConnMetadata + + // SendRequest sends a global request, and returns the + // reply. If wantReply is true, it returns the response status + // and payload. See also RFC4254, section 4. + SendRequest(name string, wantReply bool, payload []byte) (bool, []byte, error) + + // OpenChannel tries to open an channel. If the request is + // rejected, it returns *OpenChannelError. On success it returns + // the SSH Channel and a Go channel for incoming, out-of-band + // requests. The Go channel must be serviced, or the + // connection will hang. + OpenChannel(name string, data []byte) (Channel, <-chan *Request, error) + + // Close closes the underlying network connection + Close() error + + // Wait blocks until the connection has shut down, and returns the + // error causing the shutdown. + Wait() error + + // TODO(hanwen): consider exposing: + // RequestKeyChange + // Disconnect +} + +// DiscardRequests consumes and rejects all requests from the +// passed-in channel. +func DiscardRequests(in <-chan *Request) { + for req := range in { + if req.WantReply { + req.Reply(false, nil) + } + } +} + +// A connection represents an incoming connection. +type connection struct { + transport *handshakeTransport + sshConn + + // The connection protocol. + *mux +} + +func (c *connection) Close() error { + return c.sshConn.conn.Close() +} + +// sshconn provides net.Conn metadata, but disallows direct reads and +// writes. +type sshConn struct { + conn net.Conn + + user string + sessionID []byte + clientVersion []byte + serverVersion []byte +} + +func dup(src []byte) []byte { + dst := make([]byte, len(src)) + copy(dst, src) + return dst +} + +func (c *sshConn) User() string { + return c.user +} + +func (c *sshConn) RemoteAddr() net.Addr { + return c.conn.RemoteAddr() +} + +func (c *sshConn) Close() error { + return c.conn.Close() +} + +func (c *sshConn) LocalAddr() net.Addr { + return c.conn.LocalAddr() +} + +func (c *sshConn) SessionID() []byte { + return dup(c.sessionID) +} + +func (c *sshConn) ClientVersion() []byte { + return dup(c.clientVersion) +} + +func (c *sshConn) ServerVersion() []byte { + return dup(c.serverVersion) +} diff --git a/vendor/golang.org/x/crypto/ssh/doc.go b/vendor/golang.org/x/crypto/ssh/doc.go new file mode 100644 index 0000000000000000000000000000000000000000..67b7322c058058f4f794aab619d49b68b7289bd6 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/doc.go @@ -0,0 +1,21 @@ +// 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 ssh implements an SSH client and server. + +SSH is a transport security protocol, an authentication protocol and a +family of application protocols. The most typical application level +protocol is a remote shell and this is specifically implemented. However, +the multiplexed nature of SSH is exposed to users that wish to support +others. + +References: + [PROTOCOL.certkeys]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?rev=HEAD + [SSH-PARAMETERS]: http://www.iana.org/assignments/ssh-parameters/ssh-parameters.xml#ssh-parameters-1 + +This package does not fall under the stability promise of the Go language itself, +so its API may be changed when pressing needs arise. +*/ +package ssh // import "golang.org/x/crypto/ssh" diff --git a/vendor/golang.org/x/crypto/ssh/example_test.go b/vendor/golang.org/x/crypto/ssh/example_test.go new file mode 100644 index 0000000000000000000000000000000000000000..b910c7bf60ba9219ba1a59289a09416700d11a58 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/example_test.go @@ -0,0 +1,320 @@ +// 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 ssh_test + +import ( + "bufio" + "bytes" + "fmt" + "io/ioutil" + "log" + "net" + "net/http" + "os" + "path/filepath" + "strings" + + "golang.org/x/crypto/ssh" + "golang.org/x/crypto/ssh/terminal" +) + +func ExampleNewServerConn() { + // Public key authentication is done by comparing + // the public key of a received connection + // with the entries in the authorized_keys file. + authorizedKeysBytes, err := ioutil.ReadFile("authorized_keys") + if err != nil { + log.Fatalf("Failed to load authorized_keys, err: %v", err) + } + + authorizedKeysMap := map[string]bool{} + for len(authorizedKeysBytes) > 0 { + pubKey, _, _, rest, err := ssh.ParseAuthorizedKey(authorizedKeysBytes) + if err != nil { + log.Fatal(err) + } + + authorizedKeysMap[string(pubKey.Marshal())] = true + authorizedKeysBytes = rest + } + + // An SSH server is represented by a ServerConfig, which holds + // certificate details and handles authentication of ServerConns. + config := &ssh.ServerConfig{ + // Remove to disable password auth. + PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) { + // Should use constant-time compare (or better, salt+hash) in + // a production setting. + if c.User() == "testuser" && string(pass) == "tiger" { + return nil, nil + } + return nil, fmt.Errorf("password rejected for %q", c.User()) + }, + + // Remove to disable public key auth. + PublicKeyCallback: func(c ssh.ConnMetadata, pubKey ssh.PublicKey) (*ssh.Permissions, error) { + if authorizedKeysMap[string(pubKey.Marshal())] { + return &ssh.Permissions{ + // Record the public key used for authentication. + Extensions: map[string]string{ + "pubkey-fp": ssh.FingerprintSHA256(pubKey), + }, + }, nil + } + return nil, fmt.Errorf("unknown public key for %q", c.User()) + }, + } + + privateBytes, err := ioutil.ReadFile("id_rsa") + if err != nil { + log.Fatal("Failed to load private key: ", err) + } + + private, err := ssh.ParsePrivateKey(privateBytes) + if err != nil { + log.Fatal("Failed to parse private key: ", err) + } + + config.AddHostKey(private) + + // Once a ServerConfig has been configured, connections can be + // accepted. + listener, err := net.Listen("tcp", "0.0.0.0:2022") + if err != nil { + log.Fatal("failed to listen for connection: ", err) + } + nConn, err := listener.Accept() + if err != nil { + log.Fatal("failed to accept incoming connection: ", err) + } + + // Before use, a handshake must be performed on the incoming + // net.Conn. + conn, chans, reqs, err := ssh.NewServerConn(nConn, config) + if err != nil { + log.Fatal("failed to handshake: ", err) + } + log.Printf("logged in with key %s", conn.Permissions.Extensions["pubkey-fp"]) + + // The incoming Request channel must be serviced. + go ssh.DiscardRequests(reqs) + + // Service the incoming Channel channel. + for newChannel := range chans { + // Channels have a type, depending on the application level + // protocol intended. In the case of a shell, the type is + // "session" and ServerShell may be used to present a simple + // terminal interface. + if newChannel.ChannelType() != "session" { + newChannel.Reject(ssh.UnknownChannelType, "unknown channel type") + continue + } + channel, requests, err := newChannel.Accept() + if err != nil { + log.Fatalf("Could not accept channel: %v", err) + } + + // Sessions have out-of-band requests such as "shell", + // "pty-req" and "env". Here we handle only the + // "shell" request. + go func(in <-chan *ssh.Request) { + for req := range in { + req.Reply(req.Type == "shell", nil) + } + }(requests) + + term := terminal.NewTerminal(channel, "> ") + + go func() { + defer channel.Close() + for { + line, err := term.ReadLine() + if err != nil { + break + } + fmt.Println(line) + } + }() + } +} + +func ExampleHostKeyCheck() { + // Every client must provide a host key check. Here is a + // simple-minded parse of OpenSSH's known_hosts file + host := "hostname" + file, err := os.Open(filepath.Join(os.Getenv("HOME"), ".ssh", "known_hosts")) + if err != nil { + log.Fatal(err) + } + defer file.Close() + + scanner := bufio.NewScanner(file) + var hostKey ssh.PublicKey + for scanner.Scan() { + fields := strings.Split(scanner.Text(), " ") + if len(fields) != 3 { + continue + } + if strings.Contains(fields[0], host) { + var err error + hostKey, _, _, _, err = ssh.ParseAuthorizedKey(scanner.Bytes()) + if err != nil { + log.Fatalf("error parsing %q: %v", fields[2], err) + } + break + } + } + + if hostKey == nil { + log.Fatalf("no hostkey for %s", host) + } + + config := ssh.ClientConfig{ + User: os.Getenv("USER"), + HostKeyCallback: ssh.FixedHostKey(hostKey), + } + + _, err = ssh.Dial("tcp", host+":22", &config) + log.Println(err) +} + +func ExampleDial() { + var hostKey ssh.PublicKey + // An SSH client is represented with a ClientConn. + // + // To authenticate with the remote server you must pass at least one + // implementation of AuthMethod via the Auth field in ClientConfig, + // and provide a HostKeyCallback. + config := &ssh.ClientConfig{ + User: "username", + Auth: []ssh.AuthMethod{ + ssh.Password("yourpassword"), + }, + HostKeyCallback: ssh.FixedHostKey(hostKey), + } + client, err := ssh.Dial("tcp", "yourserver.com:22", config) + if err != nil { + log.Fatal("Failed to dial: ", err) + } + + // Each ClientConn can support multiple interactive sessions, + // represented by a Session. + session, err := client.NewSession() + if err != nil { + log.Fatal("Failed to create session: ", err) + } + defer session.Close() + + // Once a Session is created, you can execute a single command on + // the remote side using the Run method. + var b bytes.Buffer + session.Stdout = &b + if err := session.Run("/usr/bin/whoami"); err != nil { + log.Fatal("Failed to run: " + err.Error()) + } + fmt.Println(b.String()) +} + +func ExamplePublicKeys() { + var hostKey ssh.PublicKey + // A public key may be used to authenticate against the remote + // server by using an unencrypted PEM-encoded private key file. + // + // If you have an encrypted private key, the crypto/x509 package + // can be used to decrypt it. + key, err := ioutil.ReadFile("/home/user/.ssh/id_rsa") + if err != nil { + log.Fatalf("unable to read private key: %v", err) + } + + // Create the Signer for this private key. + signer, err := ssh.ParsePrivateKey(key) + if err != nil { + log.Fatalf("unable to parse private key: %v", err) + } + + config := &ssh.ClientConfig{ + User: "user", + Auth: []ssh.AuthMethod{ + // Use the PublicKeys method for remote authentication. + ssh.PublicKeys(signer), + }, + HostKeyCallback: ssh.FixedHostKey(hostKey), + } + + // Connect to the remote server and perform the SSH handshake. + client, err := ssh.Dial("tcp", "host.com:22", config) + if err != nil { + log.Fatalf("unable to connect: %v", err) + } + defer client.Close() +} + +func ExampleClient_Listen() { + var hostKey ssh.PublicKey + config := &ssh.ClientConfig{ + User: "username", + Auth: []ssh.AuthMethod{ + ssh.Password("password"), + }, + HostKeyCallback: ssh.FixedHostKey(hostKey), + } + // Dial your ssh server. + conn, err := ssh.Dial("tcp", "localhost:22", config) + if err != nil { + log.Fatal("unable to connect: ", err) + } + defer conn.Close() + + // Request the remote side to open port 8080 on all interfaces. + l, err := conn.Listen("tcp", "0.0.0.0:8080") + if err != nil { + log.Fatal("unable to register tcp forward: ", err) + } + defer l.Close() + + // Serve HTTP with your SSH server acting as a reverse proxy. + http.Serve(l, http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { + fmt.Fprintf(resp, "Hello world!\n") + })) +} + +func ExampleSession_RequestPty() { + var hostKey ssh.PublicKey + // Create client config + config := &ssh.ClientConfig{ + User: "username", + Auth: []ssh.AuthMethod{ + ssh.Password("password"), + }, + HostKeyCallback: ssh.FixedHostKey(hostKey), + } + // Connect to ssh server + conn, err := ssh.Dial("tcp", "localhost:22", config) + if err != nil { + log.Fatal("unable to connect: ", err) + } + defer conn.Close() + // Create a session + session, err := conn.NewSession() + if err != nil { + log.Fatal("unable to create session: ", err) + } + defer session.Close() + // Set up terminal modes + modes := ssh.TerminalModes{ + ssh.ECHO: 0, // disable echoing + ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud + ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud + } + // Request pseudo terminal + if err := session.RequestPty("xterm", 40, 80, modes); err != nil { + log.Fatal("request for pseudo terminal failed: ", err) + } + // Start remote shell + if err := session.Shell(); err != nil { + log.Fatal("failed to start shell: ", err) + } +} diff --git a/vendor/golang.org/x/crypto/ssh/handshake.go b/vendor/golang.org/x/crypto/ssh/handshake.go new file mode 100644 index 0000000000000000000000000000000000000000..4f7912ecd6565bf1b5405b7c2a68d31493411697 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/handshake.go @@ -0,0 +1,646 @@ +// 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. + +package ssh + +import ( + "crypto/rand" + "errors" + "fmt" + "io" + "log" + "net" + "sync" +) + +// debugHandshake, if set, prints messages sent and received. Key +// exchange messages are printed as if DH were used, so the debug +// messages are wrong when using ECDH. +const debugHandshake = false + +// chanSize sets the amount of buffering SSH connections. This is +// primarily for testing: setting chanSize=0 uncovers deadlocks more +// quickly. +const chanSize = 16 + +// keyingTransport is a packet based transport that supports key +// changes. It need not be thread-safe. It should pass through +// msgNewKeys in both directions. +type keyingTransport interface { + packetConn + + // prepareKeyChange sets up a key change. The key change for a + // direction will be effected if a msgNewKeys message is sent + // or received. + prepareKeyChange(*algorithms, *kexResult) error +} + +// handshakeTransport implements rekeying on top of a keyingTransport +// and offers a thread-safe writePacket() interface. +type handshakeTransport struct { + conn keyingTransport + config *Config + + serverVersion []byte + clientVersion []byte + + // hostKeys is non-empty if we are the server. In that case, + // it contains all host keys that can be used to sign the + // connection. + hostKeys []Signer + + // hostKeyAlgorithms is non-empty if we are the client. In that case, + // we accept these key types from the server as host key. + hostKeyAlgorithms []string + + // On read error, incoming is closed, and readError is set. + incoming chan []byte + readError error + + mu sync.Mutex + writeError error + sentInitPacket []byte + sentInitMsg *kexInitMsg + pendingPackets [][]byte // Used when a key exchange is in progress. + + // If the read loop wants to schedule a kex, it pings this + // channel, and the write loop will send out a kex + // message. + requestKex chan struct{} + + // If the other side requests or confirms a kex, its kexInit + // packet is sent here for the write loop to find it. + startKex chan *pendingKex + + // data for host key checking + hostKeyCallback HostKeyCallback + dialAddress string + remoteAddr net.Addr + + // bannerCallback is non-empty if we are the client and it has been set in + // ClientConfig. In that case it is called during the user authentication + // dance to handle a custom server's message. + bannerCallback BannerCallback + + // Algorithms agreed in the last key exchange. + algorithms *algorithms + + readPacketsLeft uint32 + readBytesLeft int64 + + writePacketsLeft uint32 + writeBytesLeft int64 + + // The session ID or nil if first kex did not complete yet. + sessionID []byte +} + +type pendingKex struct { + otherInit []byte + done chan error +} + +func newHandshakeTransport(conn keyingTransport, config *Config, clientVersion, serverVersion []byte) *handshakeTransport { + t := &handshakeTransport{ + conn: conn, + serverVersion: serverVersion, + clientVersion: clientVersion, + incoming: make(chan []byte, chanSize), + requestKex: make(chan struct{}, 1), + startKex: make(chan *pendingKex, 1), + + config: config, + } + t.resetReadThresholds() + t.resetWriteThresholds() + + // We always start with a mandatory key exchange. + t.requestKex <- struct{}{} + return t +} + +func newClientTransport(conn keyingTransport, clientVersion, serverVersion []byte, config *ClientConfig, dialAddr string, addr net.Addr) *handshakeTransport { + t := newHandshakeTransport(conn, &config.Config, clientVersion, serverVersion) + t.dialAddress = dialAddr + t.remoteAddr = addr + t.hostKeyCallback = config.HostKeyCallback + t.bannerCallback = config.BannerCallback + if config.HostKeyAlgorithms != nil { + t.hostKeyAlgorithms = config.HostKeyAlgorithms + } else { + t.hostKeyAlgorithms = supportedHostKeyAlgos + } + go t.readLoop() + go t.kexLoop() + return t +} + +func newServerTransport(conn keyingTransport, clientVersion, serverVersion []byte, config *ServerConfig) *handshakeTransport { + t := newHandshakeTransport(conn, &config.Config, clientVersion, serverVersion) + t.hostKeys = config.hostKeys + go t.readLoop() + go t.kexLoop() + return t +} + +func (t *handshakeTransport) getSessionID() []byte { + return t.sessionID +} + +// waitSession waits for the session to be established. This should be +// the first thing to call after instantiating handshakeTransport. +func (t *handshakeTransport) waitSession() error { + p, err := t.readPacket() + if err != nil { + return err + } + if p[0] != msgNewKeys { + return fmt.Errorf("ssh: first packet should be msgNewKeys") + } + + return nil +} + +func (t *handshakeTransport) id() string { + if len(t.hostKeys) > 0 { + return "server" + } + return "client" +} + +func (t *handshakeTransport) printPacket(p []byte, write bool) { + action := "got" + if write { + action = "sent" + } + + if p[0] == msgChannelData || p[0] == msgChannelExtendedData { + log.Printf("%s %s data (packet %d bytes)", t.id(), action, len(p)) + } else { + msg, err := decode(p) + log.Printf("%s %s %T %v (%v)", t.id(), action, msg, msg, err) + } +} + +func (t *handshakeTransport) readPacket() ([]byte, error) { + p, ok := <-t.incoming + if !ok { + return nil, t.readError + } + return p, nil +} + +func (t *handshakeTransport) readLoop() { + first := true + for { + p, err := t.readOnePacket(first) + first = false + if err != nil { + t.readError = err + close(t.incoming) + break + } + if p[0] == msgIgnore || p[0] == msgDebug { + continue + } + t.incoming <- p + } + + // Stop writers too. + t.recordWriteError(t.readError) + + // Unblock the writer should it wait for this. + close(t.startKex) + + // Don't close t.requestKex; it's also written to from writePacket. +} + +func (t *handshakeTransport) pushPacket(p []byte) error { + if debugHandshake { + t.printPacket(p, true) + } + return t.conn.writePacket(p) +} + +func (t *handshakeTransport) getWriteError() error { + t.mu.Lock() + defer t.mu.Unlock() + return t.writeError +} + +func (t *handshakeTransport) recordWriteError(err error) { + t.mu.Lock() + defer t.mu.Unlock() + if t.writeError == nil && err != nil { + t.writeError = err + } +} + +func (t *handshakeTransport) requestKeyExchange() { + select { + case t.requestKex <- struct{}{}: + default: + // something already requested a kex, so do nothing. + } +} + +func (t *handshakeTransport) resetWriteThresholds() { + t.writePacketsLeft = packetRekeyThreshold + if t.config.RekeyThreshold > 0 { + t.writeBytesLeft = int64(t.config.RekeyThreshold) + } else if t.algorithms != nil { + t.writeBytesLeft = t.algorithms.w.rekeyBytes() + } else { + t.writeBytesLeft = 1 << 30 + } +} + +func (t *handshakeTransport) kexLoop() { + +write: + for t.getWriteError() == nil { + var request *pendingKex + var sent bool + + for request == nil || !sent { + var ok bool + select { + case request, ok = <-t.startKex: + if !ok { + break write + } + case <-t.requestKex: + break + } + + if !sent { + if err := t.sendKexInit(); err != nil { + t.recordWriteError(err) + break + } + sent = true + } + } + + if err := t.getWriteError(); err != nil { + if request != nil { + request.done <- err + } + break + } + + // We're not servicing t.requestKex, but that is OK: + // we never block on sending to t.requestKex. + + // We're not servicing t.startKex, but the remote end + // has just sent us a kexInitMsg, so it can't send + // another key change request, until we close the done + // channel on the pendingKex request. + + err := t.enterKeyExchange(request.otherInit) + + t.mu.Lock() + t.writeError = err + t.sentInitPacket = nil + t.sentInitMsg = nil + + t.resetWriteThresholds() + + // we have completed the key exchange. Since the + // reader is still blocked, it is safe to clear out + // the requestKex channel. This avoids the situation + // where: 1) we consumed our own request for the + // initial kex, and 2) the kex from the remote side + // caused another send on the requestKex channel, + clear: + for { + select { + case <-t.requestKex: + // + default: + break clear + } + } + + request.done <- t.writeError + + // kex finished. Push packets that we received while + // the kex was in progress. Don't look at t.startKex + // and don't increment writtenSinceKex: if we trigger + // another kex while we are still busy with the last + // one, things will become very confusing. + for _, p := range t.pendingPackets { + t.writeError = t.pushPacket(p) + if t.writeError != nil { + break + } + } + t.pendingPackets = t.pendingPackets[:0] + t.mu.Unlock() + } + + // drain startKex channel. We don't service t.requestKex + // because nobody does blocking sends there. + go func() { + for init := range t.startKex { + init.done <- t.writeError + } + }() + + // Unblock reader. + t.conn.Close() +} + +// The protocol uses uint32 for packet counters, so we can't let them +// reach 1<<32. We will actually read and write more packets than +// this, though: the other side may send more packets, and after we +// hit this limit on writing we will send a few more packets for the +// key exchange itself. +const packetRekeyThreshold = (1 << 31) + +func (t *handshakeTransport) resetReadThresholds() { + t.readPacketsLeft = packetRekeyThreshold + if t.config.RekeyThreshold > 0 { + t.readBytesLeft = int64(t.config.RekeyThreshold) + } else if t.algorithms != nil { + t.readBytesLeft = t.algorithms.r.rekeyBytes() + } else { + t.readBytesLeft = 1 << 30 + } +} + +func (t *handshakeTransport) readOnePacket(first bool) ([]byte, error) { + p, err := t.conn.readPacket() + if err != nil { + return nil, err + } + + if t.readPacketsLeft > 0 { + t.readPacketsLeft-- + } else { + t.requestKeyExchange() + } + + if t.readBytesLeft > 0 { + t.readBytesLeft -= int64(len(p)) + } else { + t.requestKeyExchange() + } + + if debugHandshake { + t.printPacket(p, false) + } + + if first && p[0] != msgKexInit { + return nil, fmt.Errorf("ssh: first packet should be msgKexInit") + } + + if p[0] != msgKexInit { + return p, nil + } + + firstKex := t.sessionID == nil + + kex := pendingKex{ + done: make(chan error, 1), + otherInit: p, + } + t.startKex <- &kex + err = <-kex.done + + if debugHandshake { + log.Printf("%s exited key exchange (first %v), err %v", t.id(), firstKex, err) + } + + if err != nil { + return nil, err + } + + t.resetReadThresholds() + + // By default, a key exchange is hidden from higher layers by + // translating it into msgIgnore. + successPacket := []byte{msgIgnore} + if firstKex { + // sendKexInit() for the first kex waits for + // msgNewKeys so the authentication process is + // guaranteed to happen over an encrypted transport. + successPacket = []byte{msgNewKeys} + } + + return successPacket, nil +} + +// sendKexInit sends a key change message. +func (t *handshakeTransport) sendKexInit() error { + t.mu.Lock() + defer t.mu.Unlock() + if t.sentInitMsg != nil { + // kexInits may be sent either in response to the other side, + // or because our side wants to initiate a key change, so we + // may have already sent a kexInit. In that case, don't send a + // second kexInit. + return nil + } + + msg := &kexInitMsg{ + KexAlgos: t.config.KeyExchanges, + CiphersClientServer: t.config.Ciphers, + CiphersServerClient: t.config.Ciphers, + MACsClientServer: t.config.MACs, + MACsServerClient: t.config.MACs, + CompressionClientServer: supportedCompressions, + CompressionServerClient: supportedCompressions, + } + io.ReadFull(rand.Reader, msg.Cookie[:]) + + if len(t.hostKeys) > 0 { + for _, k := range t.hostKeys { + msg.ServerHostKeyAlgos = append( + msg.ServerHostKeyAlgos, k.PublicKey().Type()) + } + } else { + msg.ServerHostKeyAlgos = t.hostKeyAlgorithms + } + packet := Marshal(msg) + + // writePacket destroys the contents, so save a copy. + packetCopy := make([]byte, len(packet)) + copy(packetCopy, packet) + + if err := t.pushPacket(packetCopy); err != nil { + return err + } + + t.sentInitMsg = msg + t.sentInitPacket = packet + + return nil +} + +func (t *handshakeTransport) writePacket(p []byte) error { + switch p[0] { + case msgKexInit: + return errors.New("ssh: only handshakeTransport can send kexInit") + case msgNewKeys: + return errors.New("ssh: only handshakeTransport can send newKeys") + } + + t.mu.Lock() + defer t.mu.Unlock() + if t.writeError != nil { + return t.writeError + } + + if t.sentInitMsg != nil { + // Copy the packet so the writer can reuse the buffer. + cp := make([]byte, len(p)) + copy(cp, p) + t.pendingPackets = append(t.pendingPackets, cp) + return nil + } + + if t.writeBytesLeft > 0 { + t.writeBytesLeft -= int64(len(p)) + } else { + t.requestKeyExchange() + } + + if t.writePacketsLeft > 0 { + t.writePacketsLeft-- + } else { + t.requestKeyExchange() + } + + if err := t.pushPacket(p); err != nil { + t.writeError = err + } + + return nil +} + +func (t *handshakeTransport) Close() error { + return t.conn.Close() +} + +func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error { + if debugHandshake { + log.Printf("%s entered key exchange", t.id()) + } + + otherInit := &kexInitMsg{} + if err := Unmarshal(otherInitPacket, otherInit); err != nil { + return err + } + + magics := handshakeMagics{ + clientVersion: t.clientVersion, + serverVersion: t.serverVersion, + clientKexInit: otherInitPacket, + serverKexInit: t.sentInitPacket, + } + + clientInit := otherInit + serverInit := t.sentInitMsg + if len(t.hostKeys) == 0 { + clientInit, serverInit = serverInit, clientInit + + magics.clientKexInit = t.sentInitPacket + magics.serverKexInit = otherInitPacket + } + + var err error + t.algorithms, err = findAgreedAlgorithms(clientInit, serverInit) + if err != nil { + return err + } + + // We don't send FirstKexFollows, but we handle receiving it. + // + // RFC 4253 section 7 defines the kex and the agreement method for + // first_kex_packet_follows. It states that the guessed packet + // should be ignored if the "kex algorithm and/or the host + // key algorithm is guessed wrong (server and client have + // different preferred algorithm), or if any of the other + // algorithms cannot be agreed upon". The other algorithms have + // already been checked above so the kex algorithm and host key + // algorithm are checked here. + if otherInit.FirstKexFollows && (clientInit.KexAlgos[0] != serverInit.KexAlgos[0] || clientInit.ServerHostKeyAlgos[0] != serverInit.ServerHostKeyAlgos[0]) { + // other side sent a kex message for the wrong algorithm, + // which we have to ignore. + if _, err := t.conn.readPacket(); err != nil { + return err + } + } + + kex, ok := kexAlgoMap[t.algorithms.kex] + if !ok { + return fmt.Errorf("ssh: unexpected key exchange algorithm %v", t.algorithms.kex) + } + + var result *kexResult + if len(t.hostKeys) > 0 { + result, err = t.server(kex, t.algorithms, &magics) + } else { + result, err = t.client(kex, t.algorithms, &magics) + } + + if err != nil { + return err + } + + if t.sessionID == nil { + t.sessionID = result.H + } + result.SessionID = t.sessionID + + if err := t.conn.prepareKeyChange(t.algorithms, result); err != nil { + return err + } + if err = t.conn.writePacket([]byte{msgNewKeys}); err != nil { + return err + } + if packet, err := t.conn.readPacket(); err != nil { + return err + } else if packet[0] != msgNewKeys { + return unexpectedMessageError(msgNewKeys, packet[0]) + } + + return nil +} + +func (t *handshakeTransport) server(kex kexAlgorithm, algs *algorithms, magics *handshakeMagics) (*kexResult, error) { + var hostKey Signer + for _, k := range t.hostKeys { + if algs.hostKey == k.PublicKey().Type() { + hostKey = k + } + } + + r, err := kex.Server(t.conn, t.config.Rand, magics, hostKey) + return r, err +} + +func (t *handshakeTransport) client(kex kexAlgorithm, algs *algorithms, magics *handshakeMagics) (*kexResult, error) { + result, err := kex.Client(t.conn, t.config.Rand, magics) + if err != nil { + return nil, err + } + + hostKey, err := ParsePublicKey(result.HostKey) + if err != nil { + return nil, err + } + + if err := verifyHostKeySignature(hostKey, result); err != nil { + return nil, err + } + + err = t.hostKeyCallback(t.dialAddress, t.remoteAddr, hostKey) + if err != nil { + return nil, err + } + + return result, nil +} diff --git a/vendor/golang.org/x/crypto/ssh/handshake_test.go b/vendor/golang.org/x/crypto/ssh/handshake_test.go new file mode 100644 index 0000000000000000000000000000000000000000..91d493568973f737733251301b56926245f9ce4b --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/handshake_test.go @@ -0,0 +1,559 @@ +// 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. + +package ssh + +import ( + "bytes" + "crypto/rand" + "errors" + "fmt" + "io" + "net" + "reflect" + "runtime" + "strings" + "sync" + "testing" +) + +type testChecker struct { + calls []string +} + +func (t *testChecker) Check(dialAddr string, addr net.Addr, key PublicKey) error { + if dialAddr == "bad" { + return fmt.Errorf("dialAddr is bad") + } + + if tcpAddr, ok := addr.(*net.TCPAddr); !ok || tcpAddr == nil { + return fmt.Errorf("testChecker: got %T want *net.TCPAddr", addr) + } + + t.calls = append(t.calls, fmt.Sprintf("%s %v %s %x", dialAddr, addr, key.Type(), key.Marshal())) + + return nil +} + +// netPipe is analogous to net.Pipe, but it uses a real net.Conn, and +// therefore is buffered (net.Pipe deadlocks if both sides start with +// a write.) +func netPipe() (net.Conn, net.Conn, error) { + listener, err := net.Listen("tcp", "127.0.0.1:0") + if err != nil { + listener, err = net.Listen("tcp", "[::1]:0") + if err != nil { + return nil, nil, err + } + } + defer listener.Close() + c1, err := net.Dial("tcp", listener.Addr().String()) + if err != nil { + return nil, nil, err + } + + c2, err := listener.Accept() + if err != nil { + c1.Close() + return nil, nil, err + } + + return c1, c2, nil +} + +// noiseTransport inserts ignore messages to check that the read loop +// and the key exchange filters out these messages. +type noiseTransport struct { + keyingTransport +} + +func (t *noiseTransport) writePacket(p []byte) error { + ignore := []byte{msgIgnore} + if err := t.keyingTransport.writePacket(ignore); err != nil { + return err + } + debug := []byte{msgDebug, 1, 2, 3} + if err := t.keyingTransport.writePacket(debug); err != nil { + return err + } + + return t.keyingTransport.writePacket(p) +} + +func addNoiseTransport(t keyingTransport) keyingTransport { + return &noiseTransport{t} +} + +// handshakePair creates two handshakeTransports connected with each +// other. If the noise argument is true, both transports will try to +// confuse the other side by sending ignore and debug messages. +func handshakePair(clientConf *ClientConfig, addr string, noise bool) (client *handshakeTransport, server *handshakeTransport, err error) { + a, b, err := netPipe() + if err != nil { + return nil, nil, err + } + + var trC, trS keyingTransport + + trC = newTransport(a, rand.Reader, true) + trS = newTransport(b, rand.Reader, false) + if noise { + trC = addNoiseTransport(trC) + trS = addNoiseTransport(trS) + } + clientConf.SetDefaults() + + v := []byte("version") + client = newClientTransport(trC, v, v, clientConf, addr, a.RemoteAddr()) + + serverConf := &ServerConfig{} + serverConf.AddHostKey(testSigners["ecdsa"]) + serverConf.AddHostKey(testSigners["rsa"]) + serverConf.SetDefaults() + server = newServerTransport(trS, v, v, serverConf) + + if err := server.waitSession(); err != nil { + return nil, nil, fmt.Errorf("server.waitSession: %v", err) + } + if err := client.waitSession(); err != nil { + return nil, nil, fmt.Errorf("client.waitSession: %v", err) + } + + return client, server, nil +} + +func TestHandshakeBasic(t *testing.T) { + if runtime.GOOS == "plan9" { + t.Skip("see golang.org/issue/7237") + } + + checker := &syncChecker{ + waitCall: make(chan int, 10), + called: make(chan int, 10), + } + + checker.waitCall <- 1 + trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr", false) + if err != nil { + t.Fatalf("handshakePair: %v", err) + } + + defer trC.Close() + defer trS.Close() + + // Let first kex complete normally. + <-checker.called + + clientDone := make(chan int, 0) + gotHalf := make(chan int, 0) + const N = 20 + + go func() { + defer close(clientDone) + // Client writes a bunch of stuff, and does a key + // change in the middle. This should not confuse the + // handshake in progress. We do this twice, so we test + // that the packet buffer is reset correctly. + for i := 0; i < N; i++ { + p := []byte{msgRequestSuccess, byte(i)} + if err := trC.writePacket(p); err != nil { + t.Fatalf("sendPacket: %v", err) + } + if (i % 10) == 5 { + <-gotHalf + // halfway through, we request a key change. + trC.requestKeyExchange() + + // Wait until we can be sure the key + // change has really started before we + // write more. + <-checker.called + } + if (i % 10) == 7 { + // write some packets until the kex + // completes, to test buffering of + // packets. + checker.waitCall <- 1 + } + } + }() + + // Server checks that client messages come in cleanly + i := 0 + err = nil + for ; i < N; i++ { + var p []byte + p, err = trS.readPacket() + if err != nil { + break + } + if (i % 10) == 5 { + gotHalf <- 1 + } + + want := []byte{msgRequestSuccess, byte(i)} + if bytes.Compare(p, want) != 0 { + t.Errorf("message %d: got %v, want %v", i, p, want) + } + } + <-clientDone + if err != nil && err != io.EOF { + t.Fatalf("server error: %v", err) + } + if i != N { + t.Errorf("received %d messages, want 10.", i) + } + + close(checker.called) + if _, ok := <-checker.called; ok { + // If all went well, we registered exactly 2 key changes: one + // that establishes the session, and one that we requested + // additionally. + t.Fatalf("got another host key checks after 2 handshakes") + } +} + +func TestForceFirstKex(t *testing.T) { + // like handshakePair, but must access the keyingTransport. + checker := &testChecker{} + clientConf := &ClientConfig{HostKeyCallback: checker.Check} + a, b, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + + var trC, trS keyingTransport + + trC = newTransport(a, rand.Reader, true) + + // This is the disallowed packet: + trC.writePacket(Marshal(&serviceRequestMsg{serviceUserAuth})) + + // Rest of the setup. + trS = newTransport(b, rand.Reader, false) + clientConf.SetDefaults() + + v := []byte("version") + client := newClientTransport(trC, v, v, clientConf, "addr", a.RemoteAddr()) + + serverConf := &ServerConfig{} + serverConf.AddHostKey(testSigners["ecdsa"]) + serverConf.AddHostKey(testSigners["rsa"]) + serverConf.SetDefaults() + server := newServerTransport(trS, v, v, serverConf) + + defer client.Close() + defer server.Close() + + // We setup the initial key exchange, but the remote side + // tries to send serviceRequestMsg in cleartext, which is + // disallowed. + + if err := server.waitSession(); err == nil { + t.Errorf("server first kex init should reject unexpected packet") + } +} + +func TestHandshakeAutoRekeyWrite(t *testing.T) { + checker := &syncChecker{ + called: make(chan int, 10), + waitCall: nil, + } + clientConf := &ClientConfig{HostKeyCallback: checker.Check} + clientConf.RekeyThreshold = 500 + trC, trS, err := handshakePair(clientConf, "addr", false) + if err != nil { + t.Fatalf("handshakePair: %v", err) + } + defer trC.Close() + defer trS.Close() + + input := make([]byte, 251) + input[0] = msgRequestSuccess + + done := make(chan int, 1) + const numPacket = 5 + go func() { + defer close(done) + j := 0 + for ; j < numPacket; j++ { + if p, err := trS.readPacket(); err != nil { + break + } else if !bytes.Equal(input, p) { + t.Errorf("got packet type %d, want %d", p[0], input[0]) + } + } + + if j != numPacket { + t.Errorf("got %d, want 5 messages", j) + } + }() + + <-checker.called + + for i := 0; i < numPacket; i++ { + p := make([]byte, len(input)) + copy(p, input) + if err := trC.writePacket(p); err != nil { + t.Errorf("writePacket: %v", err) + } + if i == 2 { + // Make sure the kex is in progress. + <-checker.called + } + + } + <-done +} + +type syncChecker struct { + waitCall chan int + called chan int +} + +func (c *syncChecker) Check(dialAddr string, addr net.Addr, key PublicKey) error { + c.called <- 1 + if c.waitCall != nil { + <-c.waitCall + } + return nil +} + +func TestHandshakeAutoRekeyRead(t *testing.T) { + sync := &syncChecker{ + called: make(chan int, 2), + waitCall: nil, + } + clientConf := &ClientConfig{ + HostKeyCallback: sync.Check, + } + clientConf.RekeyThreshold = 500 + + trC, trS, err := handshakePair(clientConf, "addr", false) + if err != nil { + t.Fatalf("handshakePair: %v", err) + } + defer trC.Close() + defer trS.Close() + + packet := make([]byte, 501) + packet[0] = msgRequestSuccess + if err := trS.writePacket(packet); err != nil { + t.Fatalf("writePacket: %v", err) + } + + // While we read out the packet, a key change will be + // initiated. + done := make(chan int, 1) + go func() { + defer close(done) + if _, err := trC.readPacket(); err != nil { + t.Fatalf("readPacket(client): %v", err) + } + + }() + + <-done + <-sync.called +} + +// errorKeyingTransport generates errors after a given number of +// read/write operations. +type errorKeyingTransport struct { + packetConn + readLeft, writeLeft int +} + +func (n *errorKeyingTransport) prepareKeyChange(*algorithms, *kexResult) error { + return nil +} + +func (n *errorKeyingTransport) getSessionID() []byte { + return nil +} + +func (n *errorKeyingTransport) writePacket(packet []byte) error { + if n.writeLeft == 0 { + n.Close() + return errors.New("barf") + } + + n.writeLeft-- + return n.packetConn.writePacket(packet) +} + +func (n *errorKeyingTransport) readPacket() ([]byte, error) { + if n.readLeft == 0 { + n.Close() + return nil, errors.New("barf") + } + + n.readLeft-- + return n.packetConn.readPacket() +} + +func TestHandshakeErrorHandlingRead(t *testing.T) { + for i := 0; i < 20; i++ { + testHandshakeErrorHandlingN(t, i, -1, false) + } +} + +func TestHandshakeErrorHandlingWrite(t *testing.T) { + for i := 0; i < 20; i++ { + testHandshakeErrorHandlingN(t, -1, i, false) + } +} + +func TestHandshakeErrorHandlingReadCoupled(t *testing.T) { + for i := 0; i < 20; i++ { + testHandshakeErrorHandlingN(t, i, -1, true) + } +} + +func TestHandshakeErrorHandlingWriteCoupled(t *testing.T) { + for i := 0; i < 20; i++ { + testHandshakeErrorHandlingN(t, -1, i, true) + } +} + +// testHandshakeErrorHandlingN runs handshakes, injecting errors. If +// handshakeTransport deadlocks, the go runtime will detect it and +// panic. +func testHandshakeErrorHandlingN(t *testing.T, readLimit, writeLimit int, coupled bool) { + msg := Marshal(&serviceRequestMsg{strings.Repeat("x", int(minRekeyThreshold)/4)}) + + a, b := memPipe() + defer a.Close() + defer b.Close() + + key := testSigners["ecdsa"] + serverConf := Config{RekeyThreshold: minRekeyThreshold} + serverConf.SetDefaults() + serverConn := newHandshakeTransport(&errorKeyingTransport{a, readLimit, writeLimit}, &serverConf, []byte{'a'}, []byte{'b'}) + serverConn.hostKeys = []Signer{key} + go serverConn.readLoop() + go serverConn.kexLoop() + + clientConf := Config{RekeyThreshold: 10 * minRekeyThreshold} + clientConf.SetDefaults() + clientConn := newHandshakeTransport(&errorKeyingTransport{b, -1, -1}, &clientConf, []byte{'a'}, []byte{'b'}) + clientConn.hostKeyAlgorithms = []string{key.PublicKey().Type()} + clientConn.hostKeyCallback = InsecureIgnoreHostKey() + go clientConn.readLoop() + go clientConn.kexLoop() + + var wg sync.WaitGroup + + for _, hs := range []packetConn{serverConn, clientConn} { + if !coupled { + wg.Add(2) + go func(c packetConn) { + for i := 0; ; i++ { + str := fmt.Sprintf("%08x", i) + strings.Repeat("x", int(minRekeyThreshold)/4-8) + err := c.writePacket(Marshal(&serviceRequestMsg{str})) + if err != nil { + break + } + } + wg.Done() + c.Close() + }(hs) + go func(c packetConn) { + for { + _, err := c.readPacket() + if err != nil { + break + } + } + wg.Done() + }(hs) + } else { + wg.Add(1) + go func(c packetConn) { + for { + _, err := c.readPacket() + if err != nil { + break + } + if err := c.writePacket(msg); err != nil { + break + } + + } + wg.Done() + }(hs) + } + } + wg.Wait() +} + +func TestDisconnect(t *testing.T) { + if runtime.GOOS == "plan9" { + t.Skip("see golang.org/issue/7237") + } + checker := &testChecker{} + trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr", false) + if err != nil { + t.Fatalf("handshakePair: %v", err) + } + + defer trC.Close() + defer trS.Close() + + trC.writePacket([]byte{msgRequestSuccess, 0, 0}) + errMsg := &disconnectMsg{ + Reason: 42, + Message: "such is life", + } + trC.writePacket(Marshal(errMsg)) + trC.writePacket([]byte{msgRequestSuccess, 0, 0}) + + packet, err := trS.readPacket() + if err != nil { + t.Fatalf("readPacket 1: %v", err) + } + if packet[0] != msgRequestSuccess { + t.Errorf("got packet %v, want packet type %d", packet, msgRequestSuccess) + } + + _, err = trS.readPacket() + if err == nil { + t.Errorf("readPacket 2 succeeded") + } else if !reflect.DeepEqual(err, errMsg) { + t.Errorf("got error %#v, want %#v", err, errMsg) + } + + _, err = trS.readPacket() + if err == nil { + t.Errorf("readPacket 3 succeeded") + } +} + +func TestHandshakeRekeyDefault(t *testing.T) { + clientConf := &ClientConfig{ + Config: Config{ + Ciphers: []string{"aes128-ctr"}, + }, + HostKeyCallback: InsecureIgnoreHostKey(), + } + trC, trS, err := handshakePair(clientConf, "addr", false) + if err != nil { + t.Fatalf("handshakePair: %v", err) + } + defer trC.Close() + defer trS.Close() + + trC.writePacket([]byte{msgRequestSuccess, 0, 0}) + trC.Close() + + rgb := (1024 + trC.readBytesLeft) >> 30 + wgb := (1024 + trC.writeBytesLeft) >> 30 + + if rgb != 64 { + t.Errorf("got rekey after %dG read, want 64G", rgb) + } + if wgb != 64 { + t.Errorf("got rekey after %dG write, want 64G", wgb) + } +} diff --git a/vendor/golang.org/x/crypto/ssh/kex.go b/vendor/golang.org/x/crypto/ssh/kex.go new file mode 100644 index 0000000000000000000000000000000000000000..f34bcc013325fb6d62fa6e84eec3ce9ed740c15d --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/kex.go @@ -0,0 +1,540 @@ +// 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. + +package ssh + +import ( + "crypto" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/subtle" + "errors" + "io" + "math/big" + + "golang.org/x/crypto/curve25519" +) + +const ( + kexAlgoDH1SHA1 = "diffie-hellman-group1-sha1" + kexAlgoDH14SHA1 = "diffie-hellman-group14-sha1" + kexAlgoECDH256 = "ecdh-sha2-nistp256" + kexAlgoECDH384 = "ecdh-sha2-nistp384" + kexAlgoECDH521 = "ecdh-sha2-nistp521" + kexAlgoCurve25519SHA256 = "curve25519-sha256@libssh.org" +) + +// kexResult captures the outcome of a key exchange. +type kexResult struct { + // Session hash. See also RFC 4253, section 8. + H []byte + + // Shared secret. See also RFC 4253, section 8. + K []byte + + // Host key as hashed into H. + HostKey []byte + + // Signature of H. + Signature []byte + + // A cryptographic hash function that matches the security + // level of the key exchange algorithm. It is used for + // calculating H, and for deriving keys from H and K. + Hash crypto.Hash + + // The session ID, which is the first H computed. This is used + // to derive key material inside the transport. + SessionID []byte +} + +// handshakeMagics contains data that is always included in the +// session hash. +type handshakeMagics struct { + clientVersion, serverVersion []byte + clientKexInit, serverKexInit []byte +} + +func (m *handshakeMagics) write(w io.Writer) { + writeString(w, m.clientVersion) + writeString(w, m.serverVersion) + writeString(w, m.clientKexInit) + writeString(w, m.serverKexInit) +} + +// kexAlgorithm abstracts different key exchange algorithms. +type kexAlgorithm interface { + // Server runs server-side key agreement, signing the result + // with a hostkey. + Server(p packetConn, rand io.Reader, magics *handshakeMagics, s Signer) (*kexResult, error) + + // Client runs the client-side key agreement. Caller is + // responsible for verifying the host key signature. + Client(p packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) +} + +// dhGroup is a multiplicative group suitable for implementing Diffie-Hellman key agreement. +type dhGroup struct { + g, p, pMinus1 *big.Int +} + +func (group *dhGroup) diffieHellman(theirPublic, myPrivate *big.Int) (*big.Int, error) { + if theirPublic.Cmp(bigOne) <= 0 || theirPublic.Cmp(group.pMinus1) >= 0 { + return nil, errors.New("ssh: DH parameter out of bounds") + } + return new(big.Int).Exp(theirPublic, myPrivate, group.p), nil +} + +func (group *dhGroup) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) { + hashFunc := crypto.SHA1 + + var x *big.Int + for { + var err error + if x, err = rand.Int(randSource, group.pMinus1); err != nil { + return nil, err + } + if x.Sign() > 0 { + break + } + } + + X := new(big.Int).Exp(group.g, x, group.p) + kexDHInit := kexDHInitMsg{ + X: X, + } + if err := c.writePacket(Marshal(&kexDHInit)); err != nil { + return nil, err + } + + packet, err := c.readPacket() + if err != nil { + return nil, err + } + + var kexDHReply kexDHReplyMsg + if err = Unmarshal(packet, &kexDHReply); err != nil { + return nil, err + } + + ki, err := group.diffieHellman(kexDHReply.Y, x) + if err != nil { + return nil, err + } + + h := hashFunc.New() + magics.write(h) + writeString(h, kexDHReply.HostKey) + writeInt(h, X) + writeInt(h, kexDHReply.Y) + K := make([]byte, intLength(ki)) + marshalInt(K, ki) + h.Write(K) + + return &kexResult{ + H: h.Sum(nil), + K: K, + HostKey: kexDHReply.HostKey, + Signature: kexDHReply.Signature, + Hash: crypto.SHA1, + }, nil +} + +func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) { + hashFunc := crypto.SHA1 + packet, err := c.readPacket() + if err != nil { + return + } + var kexDHInit kexDHInitMsg + if err = Unmarshal(packet, &kexDHInit); err != nil { + return + } + + var y *big.Int + for { + if y, err = rand.Int(randSource, group.pMinus1); err != nil { + return + } + if y.Sign() > 0 { + break + } + } + + Y := new(big.Int).Exp(group.g, y, group.p) + ki, err := group.diffieHellman(kexDHInit.X, y) + if err != nil { + return nil, err + } + + hostKeyBytes := priv.PublicKey().Marshal() + + h := hashFunc.New() + magics.write(h) + writeString(h, hostKeyBytes) + writeInt(h, kexDHInit.X) + writeInt(h, Y) + + K := make([]byte, intLength(ki)) + marshalInt(K, ki) + h.Write(K) + + H := h.Sum(nil) + + // H is already a hash, but the hostkey signing will apply its + // own key-specific hash algorithm. + sig, err := signAndMarshal(priv, randSource, H) + if err != nil { + return nil, err + } + + kexDHReply := kexDHReplyMsg{ + HostKey: hostKeyBytes, + Y: Y, + Signature: sig, + } + packet = Marshal(&kexDHReply) + + err = c.writePacket(packet) + return &kexResult{ + H: H, + K: K, + HostKey: hostKeyBytes, + Signature: sig, + Hash: crypto.SHA1, + }, nil +} + +// ecdh performs Elliptic Curve Diffie-Hellman key exchange as +// described in RFC 5656, section 4. +type ecdh struct { + curve elliptic.Curve +} + +func (kex *ecdh) Client(c packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) { + ephKey, err := ecdsa.GenerateKey(kex.curve, rand) + if err != nil { + return nil, err + } + + kexInit := kexECDHInitMsg{ + ClientPubKey: elliptic.Marshal(kex.curve, ephKey.PublicKey.X, ephKey.PublicKey.Y), + } + + serialized := Marshal(&kexInit) + if err := c.writePacket(serialized); err != nil { + return nil, err + } + + packet, err := c.readPacket() + if err != nil { + return nil, err + } + + var reply kexECDHReplyMsg + if err = Unmarshal(packet, &reply); err != nil { + return nil, err + } + + x, y, err := unmarshalECKey(kex.curve, reply.EphemeralPubKey) + if err != nil { + return nil, err + } + + // generate shared secret + secret, _ := kex.curve.ScalarMult(x, y, ephKey.D.Bytes()) + + h := ecHash(kex.curve).New() + magics.write(h) + writeString(h, reply.HostKey) + writeString(h, kexInit.ClientPubKey) + writeString(h, reply.EphemeralPubKey) + K := make([]byte, intLength(secret)) + marshalInt(K, secret) + h.Write(K) + + return &kexResult{ + H: h.Sum(nil), + K: K, + HostKey: reply.HostKey, + Signature: reply.Signature, + Hash: ecHash(kex.curve), + }, nil +} + +// unmarshalECKey parses and checks an EC key. +func unmarshalECKey(curve elliptic.Curve, pubkey []byte) (x, y *big.Int, err error) { + x, y = elliptic.Unmarshal(curve, pubkey) + if x == nil { + return nil, nil, errors.New("ssh: elliptic.Unmarshal failure") + } + if !validateECPublicKey(curve, x, y) { + return nil, nil, errors.New("ssh: public key not on curve") + } + return x, y, nil +} + +// validateECPublicKey checks that the point is a valid public key for +// the given curve. See [SEC1], 3.2.2 +func validateECPublicKey(curve elliptic.Curve, x, y *big.Int) bool { + if x.Sign() == 0 && y.Sign() == 0 { + return false + } + + if x.Cmp(curve.Params().P) >= 0 { + return false + } + + if y.Cmp(curve.Params().P) >= 0 { + return false + } + + if !curve.IsOnCurve(x, y) { + return false + } + + // We don't check if N * PubKey == 0, since + // + // - the NIST curves have cofactor = 1, so this is implicit. + // (We don't foresee an implementation that supports non NIST + // curves) + // + // - for ephemeral keys, we don't need to worry about small + // subgroup attacks. + return true +} + +func (kex *ecdh) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) { + packet, err := c.readPacket() + if err != nil { + return nil, err + } + + var kexECDHInit kexECDHInitMsg + if err = Unmarshal(packet, &kexECDHInit); err != nil { + return nil, err + } + + clientX, clientY, err := unmarshalECKey(kex.curve, kexECDHInit.ClientPubKey) + if err != nil { + return nil, err + } + + // We could cache this key across multiple users/multiple + // connection attempts, but the benefit is small. OpenSSH + // generates a new key for each incoming connection. + ephKey, err := ecdsa.GenerateKey(kex.curve, rand) + if err != nil { + return nil, err + } + + hostKeyBytes := priv.PublicKey().Marshal() + + serializedEphKey := elliptic.Marshal(kex.curve, ephKey.PublicKey.X, ephKey.PublicKey.Y) + + // generate shared secret + secret, _ := kex.curve.ScalarMult(clientX, clientY, ephKey.D.Bytes()) + + h := ecHash(kex.curve).New() + magics.write(h) + writeString(h, hostKeyBytes) + writeString(h, kexECDHInit.ClientPubKey) + writeString(h, serializedEphKey) + + K := make([]byte, intLength(secret)) + marshalInt(K, secret) + h.Write(K) + + H := h.Sum(nil) + + // H is already a hash, but the hostkey signing will apply its + // own key-specific hash algorithm. + sig, err := signAndMarshal(priv, rand, H) + if err != nil { + return nil, err + } + + reply := kexECDHReplyMsg{ + EphemeralPubKey: serializedEphKey, + HostKey: hostKeyBytes, + Signature: sig, + } + + serialized := Marshal(&reply) + if err := c.writePacket(serialized); err != nil { + return nil, err + } + + return &kexResult{ + H: H, + K: K, + HostKey: reply.HostKey, + Signature: sig, + Hash: ecHash(kex.curve), + }, nil +} + +var kexAlgoMap = map[string]kexAlgorithm{} + +func init() { + // This is the group called diffie-hellman-group1-sha1 in RFC + // 4253 and Oakley Group 2 in RFC 2409. + p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF", 16) + kexAlgoMap[kexAlgoDH1SHA1] = &dhGroup{ + g: new(big.Int).SetInt64(2), + p: p, + pMinus1: new(big.Int).Sub(p, bigOne), + } + + // This is the group called diffie-hellman-group14-sha1 in RFC + // 4253 and Oakley Group 14 in RFC 3526. + p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16) + + kexAlgoMap[kexAlgoDH14SHA1] = &dhGroup{ + g: new(big.Int).SetInt64(2), + p: p, + pMinus1: new(big.Int).Sub(p, bigOne), + } + + kexAlgoMap[kexAlgoECDH521] = &ecdh{elliptic.P521()} + kexAlgoMap[kexAlgoECDH384] = &ecdh{elliptic.P384()} + kexAlgoMap[kexAlgoECDH256] = &ecdh{elliptic.P256()} + kexAlgoMap[kexAlgoCurve25519SHA256] = &curve25519sha256{} +} + +// curve25519sha256 implements the curve25519-sha256@libssh.org key +// agreement protocol, as described in +// https://git.libssh.org/projects/libssh.git/tree/doc/curve25519-sha256@libssh.org.txt +type curve25519sha256 struct{} + +type curve25519KeyPair struct { + priv [32]byte + pub [32]byte +} + +func (kp *curve25519KeyPair) generate(rand io.Reader) error { + if _, err := io.ReadFull(rand, kp.priv[:]); err != nil { + return err + } + curve25519.ScalarBaseMult(&kp.pub, &kp.priv) + return nil +} + +// curve25519Zeros is just an array of 32 zero bytes so that we have something +// convenient to compare against in order to reject curve25519 points with the +// wrong order. +var curve25519Zeros [32]byte + +func (kex *curve25519sha256) Client(c packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) { + var kp curve25519KeyPair + if err := kp.generate(rand); err != nil { + return nil, err + } + if err := c.writePacket(Marshal(&kexECDHInitMsg{kp.pub[:]})); err != nil { + return nil, err + } + + packet, err := c.readPacket() + if err != nil { + return nil, err + } + + var reply kexECDHReplyMsg + if err = Unmarshal(packet, &reply); err != nil { + return nil, err + } + if len(reply.EphemeralPubKey) != 32 { + return nil, errors.New("ssh: peer's curve25519 public value has wrong length") + } + + var servPub, secret [32]byte + copy(servPub[:], reply.EphemeralPubKey) + curve25519.ScalarMult(&secret, &kp.priv, &servPub) + if subtle.ConstantTimeCompare(secret[:], curve25519Zeros[:]) == 1 { + return nil, errors.New("ssh: peer's curve25519 public value has wrong order") + } + + h := crypto.SHA256.New() + magics.write(h) + writeString(h, reply.HostKey) + writeString(h, kp.pub[:]) + writeString(h, reply.EphemeralPubKey) + + ki := new(big.Int).SetBytes(secret[:]) + K := make([]byte, intLength(ki)) + marshalInt(K, ki) + h.Write(K) + + return &kexResult{ + H: h.Sum(nil), + K: K, + HostKey: reply.HostKey, + Signature: reply.Signature, + Hash: crypto.SHA256, + }, nil +} + +func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) { + packet, err := c.readPacket() + if err != nil { + return + } + var kexInit kexECDHInitMsg + if err = Unmarshal(packet, &kexInit); err != nil { + return + } + + if len(kexInit.ClientPubKey) != 32 { + return nil, errors.New("ssh: peer's curve25519 public value has wrong length") + } + + var kp curve25519KeyPair + if err := kp.generate(rand); err != nil { + return nil, err + } + + var clientPub, secret [32]byte + copy(clientPub[:], kexInit.ClientPubKey) + curve25519.ScalarMult(&secret, &kp.priv, &clientPub) + if subtle.ConstantTimeCompare(secret[:], curve25519Zeros[:]) == 1 { + return nil, errors.New("ssh: peer's curve25519 public value has wrong order") + } + + hostKeyBytes := priv.PublicKey().Marshal() + + h := crypto.SHA256.New() + magics.write(h) + writeString(h, hostKeyBytes) + writeString(h, kexInit.ClientPubKey) + writeString(h, kp.pub[:]) + + ki := new(big.Int).SetBytes(secret[:]) + K := make([]byte, intLength(ki)) + marshalInt(K, ki) + h.Write(K) + + H := h.Sum(nil) + + sig, err := signAndMarshal(priv, rand, H) + if err != nil { + return nil, err + } + + reply := kexECDHReplyMsg{ + EphemeralPubKey: kp.pub[:], + HostKey: hostKeyBytes, + Signature: sig, + } + if err := c.writePacket(Marshal(&reply)); err != nil { + return nil, err + } + return &kexResult{ + H: H, + K: K, + HostKey: hostKeyBytes, + Signature: sig, + Hash: crypto.SHA256, + }, nil +} diff --git a/vendor/golang.org/x/crypto/ssh/kex_test.go b/vendor/golang.org/x/crypto/ssh/kex_test.go new file mode 100644 index 0000000000000000000000000000000000000000..12ca0acd31d0c37bcd572b98c80639965d00759d --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/kex_test.go @@ -0,0 +1,50 @@ +// 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. + +package ssh + +// Key exchange tests. + +import ( + "crypto/rand" + "reflect" + "testing" +) + +func TestKexes(t *testing.T) { + type kexResultErr struct { + result *kexResult + err error + } + + for name, kex := range kexAlgoMap { + a, b := memPipe() + + s := make(chan kexResultErr, 1) + c := make(chan kexResultErr, 1) + var magics handshakeMagics + go func() { + r, e := kex.Client(a, rand.Reader, &magics) + a.Close() + c <- kexResultErr{r, e} + }() + go func() { + r, e := kex.Server(b, rand.Reader, &magics, testSigners["ecdsa"]) + b.Close() + s <- kexResultErr{r, e} + }() + + clientRes := <-c + serverRes := <-s + if clientRes.err != nil { + t.Errorf("client: %v", clientRes.err) + } + if serverRes.err != nil { + t.Errorf("server: %v", serverRes.err) + } + if !reflect.DeepEqual(clientRes.result, serverRes.result) { + t.Errorf("kex %q: mismatch %#v, %#v", name, clientRes.result, serverRes.result) + } + } +} diff --git a/vendor/golang.org/x/crypto/ssh/keys.go b/vendor/golang.org/x/crypto/ssh/keys.go new file mode 100644 index 0000000000000000000000000000000000000000..dadf41ab74066c7eaa82ed670117a36915f5786a --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/keys.go @@ -0,0 +1,1031 @@ +// 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 ssh + +import ( + "bytes" + "crypto" + "crypto/dsa" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/md5" + "crypto/rsa" + "crypto/sha256" + "crypto/x509" + "encoding/asn1" + "encoding/base64" + "encoding/hex" + "encoding/pem" + "errors" + "fmt" + "io" + "math/big" + "strings" + + "golang.org/x/crypto/ed25519" +) + +// These constants represent the algorithm names for key types supported by this +// package. +const ( + KeyAlgoRSA = "ssh-rsa" + KeyAlgoDSA = "ssh-dss" + KeyAlgoECDSA256 = "ecdsa-sha2-nistp256" + KeyAlgoECDSA384 = "ecdsa-sha2-nistp384" + KeyAlgoECDSA521 = "ecdsa-sha2-nistp521" + KeyAlgoED25519 = "ssh-ed25519" +) + +// parsePubKey parses a public key of the given algorithm. +// Use ParsePublicKey for keys with prepended algorithm. +func parsePubKey(in []byte, algo string) (pubKey PublicKey, rest []byte, err error) { + switch algo { + case KeyAlgoRSA: + return parseRSA(in) + case KeyAlgoDSA: + return parseDSA(in) + case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521: + return parseECDSA(in) + case KeyAlgoED25519: + return parseED25519(in) + case CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoED25519v01: + cert, err := parseCert(in, certToPrivAlgo(algo)) + if err != nil { + return nil, nil, err + } + return cert, nil, nil + } + return nil, nil, fmt.Errorf("ssh: unknown key algorithm: %v", algo) +} + +// parseAuthorizedKey parses a public key in OpenSSH authorized_keys format +// (see sshd(8) manual page) once the options and key type fields have been +// removed. +func parseAuthorizedKey(in []byte) (out PublicKey, comment string, err error) { + in = bytes.TrimSpace(in) + + i := bytes.IndexAny(in, " \t") + if i == -1 { + i = len(in) + } + base64Key := in[:i] + + key := make([]byte, base64.StdEncoding.DecodedLen(len(base64Key))) + n, err := base64.StdEncoding.Decode(key, base64Key) + if err != nil { + return nil, "", err + } + key = key[:n] + out, err = ParsePublicKey(key) + if err != nil { + return nil, "", err + } + comment = string(bytes.TrimSpace(in[i:])) + return out, comment, nil +} + +// ParseKnownHosts parses an entry in the format of the known_hosts file. +// +// The known_hosts format is documented in the sshd(8) manual page. This +// function will parse a single entry from in. On successful return, marker +// will contain the optional marker value (i.e. "cert-authority" or "revoked") +// or else be empty, hosts will contain the hosts that this entry matches, +// pubKey will contain the public key and comment will contain any trailing +// comment at the end of the line. See the sshd(8) manual page for the various +// forms that a host string can take. +// +// The unparsed remainder of the input will be returned in rest. This function +// can be called repeatedly to parse multiple entries. +// +// If no entries were found in the input then err will be io.EOF. Otherwise a +// non-nil err value indicates a parse error. +func ParseKnownHosts(in []byte) (marker string, hosts []string, pubKey PublicKey, comment string, rest []byte, err error) { + for len(in) > 0 { + end := bytes.IndexByte(in, '\n') + if end != -1 { + rest = in[end+1:] + in = in[:end] + } else { + rest = nil + } + + end = bytes.IndexByte(in, '\r') + if end != -1 { + in = in[:end] + } + + in = bytes.TrimSpace(in) + if len(in) == 0 || in[0] == '#' { + in = rest + continue + } + + i := bytes.IndexAny(in, " \t") + if i == -1 { + in = rest + continue + } + + // Strip out the beginning of the known_host key. + // This is either an optional marker or a (set of) hostname(s). + keyFields := bytes.Fields(in) + if len(keyFields) < 3 || len(keyFields) > 5 { + return "", nil, nil, "", nil, errors.New("ssh: invalid entry in known_hosts data") + } + + // keyFields[0] is either "@cert-authority", "@revoked" or a comma separated + // list of hosts + marker := "" + if keyFields[0][0] == '@' { + marker = string(keyFields[0][1:]) + keyFields = keyFields[1:] + } + + hosts := string(keyFields[0]) + // keyFields[1] contains the key type (e.g. “ssh-rsaâ€). + // However, that information is duplicated inside the + // base64-encoded key and so is ignored here. + + key := bytes.Join(keyFields[2:], []byte(" ")) + if pubKey, comment, err = parseAuthorizedKey(key); err != nil { + return "", nil, nil, "", nil, err + } + + return marker, strings.Split(hosts, ","), pubKey, comment, rest, nil + } + + return "", nil, nil, "", nil, io.EOF +} + +// ParseAuthorizedKeys parses a public key from an authorized_keys +// file used in OpenSSH according to the sshd(8) manual page. +func ParseAuthorizedKey(in []byte) (out PublicKey, comment string, options []string, rest []byte, err error) { + for len(in) > 0 { + end := bytes.IndexByte(in, '\n') + if end != -1 { + rest = in[end+1:] + in = in[:end] + } else { + rest = nil + } + + end = bytes.IndexByte(in, '\r') + if end != -1 { + in = in[:end] + } + + in = bytes.TrimSpace(in) + if len(in) == 0 || in[0] == '#' { + in = rest + continue + } + + i := bytes.IndexAny(in, " \t") + if i == -1 { + in = rest + continue + } + + if out, comment, err = parseAuthorizedKey(in[i:]); err == nil { + return out, comment, options, rest, nil + } + + // No key type recognised. Maybe there's an options field at + // the beginning. + var b byte + inQuote := false + var candidateOptions []string + optionStart := 0 + for i, b = range in { + isEnd := !inQuote && (b == ' ' || b == '\t') + if (b == ',' && !inQuote) || isEnd { + if i-optionStart > 0 { + candidateOptions = append(candidateOptions, string(in[optionStart:i])) + } + optionStart = i + 1 + } + if isEnd { + break + } + if b == '"' && (i == 0 || (i > 0 && in[i-1] != '\\')) { + inQuote = !inQuote + } + } + for i < len(in) && (in[i] == ' ' || in[i] == '\t') { + i++ + } + if i == len(in) { + // Invalid line: unmatched quote + in = rest + continue + } + + in = in[i:] + i = bytes.IndexAny(in, " \t") + if i == -1 { + in = rest + continue + } + + if out, comment, err = parseAuthorizedKey(in[i:]); err == nil { + options = candidateOptions + return out, comment, options, rest, nil + } + + in = rest + continue + } + + return nil, "", nil, nil, errors.New("ssh: no key found") +} + +// ParsePublicKey parses an SSH public key formatted for use in +// the SSH wire protocol according to RFC 4253, section 6.6. +func ParsePublicKey(in []byte) (out PublicKey, err error) { + algo, in, ok := parseString(in) + if !ok { + return nil, errShortRead + } + var rest []byte + out, rest, err = parsePubKey(in, string(algo)) + if len(rest) > 0 { + return nil, errors.New("ssh: trailing junk in public key") + } + + return out, err +} + +// MarshalAuthorizedKey serializes key for inclusion in an OpenSSH +// authorized_keys file. The return value ends with newline. +func MarshalAuthorizedKey(key PublicKey) []byte { + b := &bytes.Buffer{} + b.WriteString(key.Type()) + b.WriteByte(' ') + e := base64.NewEncoder(base64.StdEncoding, b) + e.Write(key.Marshal()) + e.Close() + b.WriteByte('\n') + return b.Bytes() +} + +// PublicKey is an abstraction of different types of public keys. +type PublicKey interface { + // Type returns the key's type, e.g. "ssh-rsa". + Type() string + + // Marshal returns the serialized key data in SSH wire format, + // with the name prefix. + Marshal() []byte + + // Verify that sig is a signature on the given data using this + // key. This function will hash the data appropriately first. + Verify(data []byte, sig *Signature) error +} + +// CryptoPublicKey, if implemented by a PublicKey, +// returns the underlying crypto.PublicKey form of the key. +type CryptoPublicKey interface { + CryptoPublicKey() crypto.PublicKey +} + +// A Signer can create signatures that verify against a public key. +type Signer interface { + // PublicKey returns an associated PublicKey instance. + PublicKey() PublicKey + + // Sign returns raw signature for the given data. This method + // will apply the hash specified for the keytype to the data. + Sign(rand io.Reader, data []byte) (*Signature, error) +} + +type rsaPublicKey rsa.PublicKey + +func (r *rsaPublicKey) Type() string { + return "ssh-rsa" +} + +// parseRSA parses an RSA key according to RFC 4253, section 6.6. +func parseRSA(in []byte) (out PublicKey, rest []byte, err error) { + var w struct { + E *big.Int + N *big.Int + Rest []byte `ssh:"rest"` + } + if err := Unmarshal(in, &w); err != nil { + return nil, nil, err + } + + if w.E.BitLen() > 24 { + return nil, nil, errors.New("ssh: exponent too large") + } + e := w.E.Int64() + if e < 3 || e&1 == 0 { + return nil, nil, errors.New("ssh: incorrect exponent") + } + + var key rsa.PublicKey + key.E = int(e) + key.N = w.N + return (*rsaPublicKey)(&key), w.Rest, nil +} + +func (r *rsaPublicKey) Marshal() []byte { + e := new(big.Int).SetInt64(int64(r.E)) + // RSA publickey struct layout should match the struct used by + // parseRSACert in the x/crypto/ssh/agent package. + wirekey := struct { + Name string + E *big.Int + N *big.Int + }{ + KeyAlgoRSA, + e, + r.N, + } + return Marshal(&wirekey) +} + +func (r *rsaPublicKey) Verify(data []byte, sig *Signature) error { + if sig.Format != r.Type() { + return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, r.Type()) + } + h := crypto.SHA1.New() + h.Write(data) + digest := h.Sum(nil) + return rsa.VerifyPKCS1v15((*rsa.PublicKey)(r), crypto.SHA1, digest, sig.Blob) +} + +func (r *rsaPublicKey) CryptoPublicKey() crypto.PublicKey { + return (*rsa.PublicKey)(r) +} + +type dsaPublicKey dsa.PublicKey + +func (k *dsaPublicKey) Type() string { + return "ssh-dss" +} + +func checkDSAParams(param *dsa.Parameters) error { + // SSH specifies FIPS 186-2, which only provided a single size + // (1024 bits) DSA key. FIPS 186-3 allows for larger key + // sizes, which would confuse SSH. + if l := param.P.BitLen(); l != 1024 { + return fmt.Errorf("ssh: unsupported DSA key size %d", l) + } + + return nil +} + +// parseDSA parses an DSA key according to RFC 4253, section 6.6. +func parseDSA(in []byte) (out PublicKey, rest []byte, err error) { + var w struct { + P, Q, G, Y *big.Int + Rest []byte `ssh:"rest"` + } + if err := Unmarshal(in, &w); err != nil { + return nil, nil, err + } + + param := dsa.Parameters{ + P: w.P, + Q: w.Q, + G: w.G, + } + if err := checkDSAParams(¶m); err != nil { + return nil, nil, err + } + + key := &dsaPublicKey{ + Parameters: param, + Y: w.Y, + } + return key, w.Rest, nil +} + +func (k *dsaPublicKey) Marshal() []byte { + // DSA publickey struct layout should match the struct used by + // parseDSACert in the x/crypto/ssh/agent package. + w := struct { + Name string + P, Q, G, Y *big.Int + }{ + k.Type(), + k.P, + k.Q, + k.G, + k.Y, + } + + return Marshal(&w) +} + +func (k *dsaPublicKey) Verify(data []byte, sig *Signature) error { + if sig.Format != k.Type() { + return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type()) + } + h := crypto.SHA1.New() + h.Write(data) + digest := h.Sum(nil) + + // Per RFC 4253, section 6.6, + // The value for 'dss_signature_blob' is encoded as a string containing + // r, followed by s (which are 160-bit integers, without lengths or + // padding, unsigned, and in network byte order). + // For DSS purposes, sig.Blob should be exactly 40 bytes in length. + if len(sig.Blob) != 40 { + return errors.New("ssh: DSA signature parse error") + } + r := new(big.Int).SetBytes(sig.Blob[:20]) + s := new(big.Int).SetBytes(sig.Blob[20:]) + if dsa.Verify((*dsa.PublicKey)(k), digest, r, s) { + return nil + } + return errors.New("ssh: signature did not verify") +} + +func (k *dsaPublicKey) CryptoPublicKey() crypto.PublicKey { + return (*dsa.PublicKey)(k) +} + +type dsaPrivateKey struct { + *dsa.PrivateKey +} + +func (k *dsaPrivateKey) PublicKey() PublicKey { + return (*dsaPublicKey)(&k.PrivateKey.PublicKey) +} + +func (k *dsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) { + h := crypto.SHA1.New() + h.Write(data) + digest := h.Sum(nil) + r, s, err := dsa.Sign(rand, k.PrivateKey, digest) + if err != nil { + return nil, err + } + + sig := make([]byte, 40) + rb := r.Bytes() + sb := s.Bytes() + + copy(sig[20-len(rb):20], rb) + copy(sig[40-len(sb):], sb) + + return &Signature{ + Format: k.PublicKey().Type(), + Blob: sig, + }, nil +} + +type ecdsaPublicKey ecdsa.PublicKey + +func (k *ecdsaPublicKey) Type() string { + return "ecdsa-sha2-" + k.nistID() +} + +func (k *ecdsaPublicKey) nistID() string { + switch k.Params().BitSize { + case 256: + return "nistp256" + case 384: + return "nistp384" + case 521: + return "nistp521" + } + panic("ssh: unsupported ecdsa key size") +} + +type ed25519PublicKey ed25519.PublicKey + +func (k ed25519PublicKey) Type() string { + return KeyAlgoED25519 +} + +func parseED25519(in []byte) (out PublicKey, rest []byte, err error) { + var w struct { + KeyBytes []byte + Rest []byte `ssh:"rest"` + } + + if err := Unmarshal(in, &w); err != nil { + return nil, nil, err + } + + key := ed25519.PublicKey(w.KeyBytes) + + return (ed25519PublicKey)(key), w.Rest, nil +} + +func (k ed25519PublicKey) Marshal() []byte { + w := struct { + Name string + KeyBytes []byte + }{ + KeyAlgoED25519, + []byte(k), + } + return Marshal(&w) +} + +func (k ed25519PublicKey) Verify(b []byte, sig *Signature) error { + if sig.Format != k.Type() { + return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type()) + } + + edKey := (ed25519.PublicKey)(k) + if ok := ed25519.Verify(edKey, b, sig.Blob); !ok { + return errors.New("ssh: signature did not verify") + } + + return nil +} + +func (k ed25519PublicKey) CryptoPublicKey() crypto.PublicKey { + return ed25519.PublicKey(k) +} + +func supportedEllipticCurve(curve elliptic.Curve) bool { + return curve == elliptic.P256() || curve == elliptic.P384() || curve == elliptic.P521() +} + +// ecHash returns the hash to match the given elliptic curve, see RFC +// 5656, section 6.2.1 +func ecHash(curve elliptic.Curve) crypto.Hash { + bitSize := curve.Params().BitSize + switch { + case bitSize <= 256: + return crypto.SHA256 + case bitSize <= 384: + return crypto.SHA384 + } + return crypto.SHA512 +} + +// parseECDSA parses an ECDSA key according to RFC 5656, section 3.1. +func parseECDSA(in []byte) (out PublicKey, rest []byte, err error) { + var w struct { + Curve string + KeyBytes []byte + Rest []byte `ssh:"rest"` + } + + if err := Unmarshal(in, &w); err != nil { + return nil, nil, err + } + + key := new(ecdsa.PublicKey) + + switch w.Curve { + case "nistp256": + key.Curve = elliptic.P256() + case "nistp384": + key.Curve = elliptic.P384() + case "nistp521": + key.Curve = elliptic.P521() + default: + return nil, nil, errors.New("ssh: unsupported curve") + } + + key.X, key.Y = elliptic.Unmarshal(key.Curve, w.KeyBytes) + if key.X == nil || key.Y == nil { + return nil, nil, errors.New("ssh: invalid curve point") + } + return (*ecdsaPublicKey)(key), w.Rest, nil +} + +func (k *ecdsaPublicKey) Marshal() []byte { + // See RFC 5656, section 3.1. + keyBytes := elliptic.Marshal(k.Curve, k.X, k.Y) + // ECDSA publickey struct layout should match the struct used by + // parseECDSACert in the x/crypto/ssh/agent package. + w := struct { + Name string + ID string + Key []byte + }{ + k.Type(), + k.nistID(), + keyBytes, + } + + return Marshal(&w) +} + +func (k *ecdsaPublicKey) Verify(data []byte, sig *Signature) error { + if sig.Format != k.Type() { + return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type()) + } + + h := ecHash(k.Curve).New() + h.Write(data) + digest := h.Sum(nil) + + // Per RFC 5656, section 3.1.2, + // The ecdsa_signature_blob value has the following specific encoding: + // mpint r + // mpint s + var ecSig struct { + R *big.Int + S *big.Int + } + + if err := Unmarshal(sig.Blob, &ecSig); err != nil { + return err + } + + if ecdsa.Verify((*ecdsa.PublicKey)(k), digest, ecSig.R, ecSig.S) { + return nil + } + return errors.New("ssh: signature did not verify") +} + +func (k *ecdsaPublicKey) CryptoPublicKey() crypto.PublicKey { + return (*ecdsa.PublicKey)(k) +} + +// NewSignerFromKey takes an *rsa.PrivateKey, *dsa.PrivateKey, +// *ecdsa.PrivateKey or any other crypto.Signer and returns a +// corresponding Signer instance. ECDSA keys must use P-256, P-384 or +// P-521. DSA keys must use parameter size L1024N160. +func NewSignerFromKey(key interface{}) (Signer, error) { + switch key := key.(type) { + case crypto.Signer: + return NewSignerFromSigner(key) + case *dsa.PrivateKey: + return newDSAPrivateKey(key) + default: + return nil, fmt.Errorf("ssh: unsupported key type %T", key) + } +} + +func newDSAPrivateKey(key *dsa.PrivateKey) (Signer, error) { + if err := checkDSAParams(&key.PublicKey.Parameters); err != nil { + return nil, err + } + + return &dsaPrivateKey{key}, nil +} + +type wrappedSigner struct { + signer crypto.Signer + pubKey PublicKey +} + +// NewSignerFromSigner takes any crypto.Signer implementation and +// returns a corresponding Signer interface. This can be used, for +// example, with keys kept in hardware modules. +func NewSignerFromSigner(signer crypto.Signer) (Signer, error) { + pubKey, err := NewPublicKey(signer.Public()) + if err != nil { + return nil, err + } + + return &wrappedSigner{signer, pubKey}, nil +} + +func (s *wrappedSigner) PublicKey() PublicKey { + return s.pubKey +} + +func (s *wrappedSigner) Sign(rand io.Reader, data []byte) (*Signature, error) { + var hashFunc crypto.Hash + + switch key := s.pubKey.(type) { + case *rsaPublicKey, *dsaPublicKey: + hashFunc = crypto.SHA1 + case *ecdsaPublicKey: + hashFunc = ecHash(key.Curve) + case ed25519PublicKey: + default: + return nil, fmt.Errorf("ssh: unsupported key type %T", key) + } + + var digest []byte + if hashFunc != 0 { + h := hashFunc.New() + h.Write(data) + digest = h.Sum(nil) + } else { + digest = data + } + + signature, err := s.signer.Sign(rand, digest, hashFunc) + if err != nil { + return nil, err + } + + // crypto.Signer.Sign is expected to return an ASN.1-encoded signature + // for ECDSA and DSA, but that's not the encoding expected by SSH, so + // re-encode. + switch s.pubKey.(type) { + case *ecdsaPublicKey, *dsaPublicKey: + type asn1Signature struct { + R, S *big.Int + } + asn1Sig := new(asn1Signature) + _, err := asn1.Unmarshal(signature, asn1Sig) + if err != nil { + return nil, err + } + + switch s.pubKey.(type) { + case *ecdsaPublicKey: + signature = Marshal(asn1Sig) + + case *dsaPublicKey: + signature = make([]byte, 40) + r := asn1Sig.R.Bytes() + s := asn1Sig.S.Bytes() + copy(signature[20-len(r):20], r) + copy(signature[40-len(s):40], s) + } + } + + return &Signature{ + Format: s.pubKey.Type(), + Blob: signature, + }, nil +} + +// NewPublicKey takes an *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey, +// or ed25519.PublicKey returns a corresponding PublicKey instance. +// ECDSA keys must use P-256, P-384 or P-521. +func NewPublicKey(key interface{}) (PublicKey, error) { + switch key := key.(type) { + case *rsa.PublicKey: + return (*rsaPublicKey)(key), nil + case *ecdsa.PublicKey: + if !supportedEllipticCurve(key.Curve) { + return nil, errors.New("ssh: only P-256, P-384 and P-521 EC keys are supported") + } + return (*ecdsaPublicKey)(key), nil + case *dsa.PublicKey: + return (*dsaPublicKey)(key), nil + case ed25519.PublicKey: + return (ed25519PublicKey)(key), nil + default: + return nil, fmt.Errorf("ssh: unsupported key type %T", key) + } +} + +// ParsePrivateKey returns a Signer from a PEM encoded private key. It supports +// the same keys as ParseRawPrivateKey. +func ParsePrivateKey(pemBytes []byte) (Signer, error) { + key, err := ParseRawPrivateKey(pemBytes) + if err != nil { + return nil, err + } + + return NewSignerFromKey(key) +} + +// ParsePrivateKeyWithPassphrase returns a Signer from a PEM encoded private +// key and passphrase. It supports the same keys as +// ParseRawPrivateKeyWithPassphrase. +func ParsePrivateKeyWithPassphrase(pemBytes, passPhrase []byte) (Signer, error) { + key, err := ParseRawPrivateKeyWithPassphrase(pemBytes, passPhrase) + if err != nil { + return nil, err + } + + return NewSignerFromKey(key) +} + +// encryptedBlock tells whether a private key is +// encrypted by examining its Proc-Type header +// for a mention of ENCRYPTED +// according to RFC 1421 Section 4.6.1.1. +func encryptedBlock(block *pem.Block) bool { + return strings.Contains(block.Headers["Proc-Type"], "ENCRYPTED") +} + +// ParseRawPrivateKey returns a private key from a PEM encoded private key. It +// supports RSA (PKCS#1), DSA (OpenSSL), and ECDSA private keys. +func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) { + block, _ := pem.Decode(pemBytes) + if block == nil { + return nil, errors.New("ssh: no key found") + } + + if encryptedBlock(block) { + return nil, errors.New("ssh: cannot decode encrypted private keys") + } + + switch block.Type { + case "RSA PRIVATE KEY": + return x509.ParsePKCS1PrivateKey(block.Bytes) + case "EC PRIVATE KEY": + return x509.ParseECPrivateKey(block.Bytes) + case "DSA PRIVATE KEY": + return ParseDSAPrivateKey(block.Bytes) + case "OPENSSH PRIVATE KEY": + return parseOpenSSHPrivateKey(block.Bytes) + default: + return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type) + } +} + +// ParseRawPrivateKeyWithPassphrase returns a private key decrypted with +// passphrase from a PEM encoded private key. If wrong passphrase, return +// x509.IncorrectPasswordError. +func ParseRawPrivateKeyWithPassphrase(pemBytes, passPhrase []byte) (interface{}, error) { + block, _ := pem.Decode(pemBytes) + if block == nil { + return nil, errors.New("ssh: no key found") + } + buf := block.Bytes + + if encryptedBlock(block) { + if x509.IsEncryptedPEMBlock(block) { + var err error + buf, err = x509.DecryptPEMBlock(block, passPhrase) + if err != nil { + if err == x509.IncorrectPasswordError { + return nil, err + } + return nil, fmt.Errorf("ssh: cannot decode encrypted private keys: %v", err) + } + } + } + + switch block.Type { + case "RSA PRIVATE KEY": + return x509.ParsePKCS1PrivateKey(buf) + case "EC PRIVATE KEY": + return x509.ParseECPrivateKey(buf) + case "DSA PRIVATE KEY": + return ParseDSAPrivateKey(buf) + case "OPENSSH PRIVATE KEY": + return parseOpenSSHPrivateKey(buf) + default: + return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type) + } +} + +// ParseDSAPrivateKey returns a DSA private key from its ASN.1 DER encoding, as +// specified by the OpenSSL DSA man page. +func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) { + var k struct { + Version int + P *big.Int + Q *big.Int + G *big.Int + Pub *big.Int + Priv *big.Int + } + rest, err := asn1.Unmarshal(der, &k) + if err != nil { + return nil, errors.New("ssh: failed to parse DSA key: " + err.Error()) + } + if len(rest) > 0 { + return nil, errors.New("ssh: garbage after DSA key") + } + + return &dsa.PrivateKey{ + PublicKey: dsa.PublicKey{ + Parameters: dsa.Parameters{ + P: k.P, + Q: k.Q, + G: k.G, + }, + Y: k.Pub, + }, + X: k.Priv, + }, nil +} + +// Implemented based on the documentation at +// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key +func parseOpenSSHPrivateKey(key []byte) (crypto.PrivateKey, error) { + magic := append([]byte("openssh-key-v1"), 0) + if !bytes.Equal(magic, key[0:len(magic)]) { + return nil, errors.New("ssh: invalid openssh private key format") + } + remaining := key[len(magic):] + + var w struct { + CipherName string + KdfName string + KdfOpts string + NumKeys uint32 + PubKey []byte + PrivKeyBlock []byte + } + + if err := Unmarshal(remaining, &w); err != nil { + return nil, err + } + + if w.KdfName != "none" || w.CipherName != "none" { + return nil, errors.New("ssh: cannot decode encrypted private keys") + } + + pk1 := struct { + Check1 uint32 + Check2 uint32 + Keytype string + Rest []byte `ssh:"rest"` + }{} + + if err := Unmarshal(w.PrivKeyBlock, &pk1); err != nil { + return nil, err + } + + if pk1.Check1 != pk1.Check2 { + return nil, errors.New("ssh: checkint mismatch") + } + + // we only handle ed25519 and rsa keys currently + switch pk1.Keytype { + case KeyAlgoRSA: + // https://github.com/openssh/openssh-portable/blob/master/sshkey.c#L2760-L2773 + key := struct { + N *big.Int + E *big.Int + D *big.Int + Iqmp *big.Int + P *big.Int + Q *big.Int + Comment string + Pad []byte `ssh:"rest"` + }{} + + if err := Unmarshal(pk1.Rest, &key); err != nil { + return nil, err + } + + for i, b := range key.Pad { + if int(b) != i+1 { + return nil, errors.New("ssh: padding not as expected") + } + } + + pk := &rsa.PrivateKey{ + PublicKey: rsa.PublicKey{ + N: key.N, + E: int(key.E.Int64()), + }, + D: key.D, + Primes: []*big.Int{key.P, key.Q}, + } + + if err := pk.Validate(); err != nil { + return nil, err + } + + pk.Precompute() + + return pk, nil + case KeyAlgoED25519: + key := struct { + Pub []byte + Priv []byte + Comment string + Pad []byte `ssh:"rest"` + }{} + + if err := Unmarshal(pk1.Rest, &key); err != nil { + return nil, err + } + + if len(key.Priv) != ed25519.PrivateKeySize { + return nil, errors.New("ssh: private key unexpected length") + } + + for i, b := range key.Pad { + if int(b) != i+1 { + return nil, errors.New("ssh: padding not as expected") + } + } + + pk := ed25519.PrivateKey(make([]byte, ed25519.PrivateKeySize)) + copy(pk, key.Priv) + return &pk, nil + default: + return nil, errors.New("ssh: unhandled key type") + } +} + +// FingerprintLegacyMD5 returns the user presentation of the key's +// fingerprint as described by RFC 4716 section 4. +func FingerprintLegacyMD5(pubKey PublicKey) string { + md5sum := md5.Sum(pubKey.Marshal()) + hexarray := make([]string, len(md5sum)) + for i, c := range md5sum { + hexarray[i] = hex.EncodeToString([]byte{c}) + } + return strings.Join(hexarray, ":") +} + +// FingerprintSHA256 returns the user presentation of the key's +// fingerprint as unpadded base64 encoded sha256 hash. +// This format was introduced from OpenSSH 6.8. +// https://www.openssh.com/txt/release-6.8 +// https://tools.ietf.org/html/rfc4648#section-3.2 (unpadded base64 encoding) +func FingerprintSHA256(pubKey PublicKey) string { + sha256sum := sha256.Sum256(pubKey.Marshal()) + hash := base64.RawStdEncoding.EncodeToString(sha256sum[:]) + return "SHA256:" + hash +} diff --git a/vendor/golang.org/x/crypto/ssh/keys_test.go b/vendor/golang.org/x/crypto/ssh/keys_test.go new file mode 100644 index 0000000000000000000000000000000000000000..20ab954e2afa8f3a064d50a29e0460abaca497e3 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/keys_test.go @@ -0,0 +1,500 @@ +// 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 ssh + +import ( + "bytes" + "crypto/dsa" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "encoding/base64" + "fmt" + "reflect" + "strings" + "testing" + + "golang.org/x/crypto/ed25519" + "golang.org/x/crypto/ssh/testdata" +) + +func rawKey(pub PublicKey) interface{} { + switch k := pub.(type) { + case *rsaPublicKey: + return (*rsa.PublicKey)(k) + case *dsaPublicKey: + return (*dsa.PublicKey)(k) + case *ecdsaPublicKey: + return (*ecdsa.PublicKey)(k) + case ed25519PublicKey: + return (ed25519.PublicKey)(k) + case *Certificate: + return k + } + panic("unknown key type") +} + +func TestKeyMarshalParse(t *testing.T) { + for _, priv := range testSigners { + pub := priv.PublicKey() + roundtrip, err := ParsePublicKey(pub.Marshal()) + if err != nil { + t.Errorf("ParsePublicKey(%T): %v", pub, err) + } + + k1 := rawKey(pub) + k2 := rawKey(roundtrip) + + if !reflect.DeepEqual(k1, k2) { + t.Errorf("got %#v in roundtrip, want %#v", k2, k1) + } + } +} + +func TestUnsupportedCurves(t *testing.T) { + raw, err := ecdsa.GenerateKey(elliptic.P224(), rand.Reader) + if err != nil { + t.Fatalf("GenerateKey: %v", err) + } + + if _, err = NewSignerFromKey(raw); err == nil || !strings.Contains(err.Error(), "only P-256") { + t.Fatalf("NewPrivateKey should not succeed with P-224, got: %v", err) + } + + if _, err = NewPublicKey(&raw.PublicKey); err == nil || !strings.Contains(err.Error(), "only P-256") { + t.Fatalf("NewPublicKey should not succeed with P-224, got: %v", err) + } +} + +func TestNewPublicKey(t *testing.T) { + for _, k := range testSigners { + raw := rawKey(k.PublicKey()) + // Skip certificates, as NewPublicKey does not support them. + if _, ok := raw.(*Certificate); ok { + continue + } + pub, err := NewPublicKey(raw) + if err != nil { + t.Errorf("NewPublicKey(%#v): %v", raw, err) + } + if !reflect.DeepEqual(k.PublicKey(), pub) { + t.Errorf("NewPublicKey(%#v) = %#v, want %#v", raw, pub, k.PublicKey()) + } + } +} + +func TestKeySignVerify(t *testing.T) { + for _, priv := range testSigners { + pub := priv.PublicKey() + + data := []byte("sign me") + sig, err := priv.Sign(rand.Reader, data) + if err != nil { + t.Fatalf("Sign(%T): %v", priv, err) + } + + if err := pub.Verify(data, sig); err != nil { + t.Errorf("publicKey.Verify(%T): %v", priv, err) + } + sig.Blob[5]++ + if err := pub.Verify(data, sig); err == nil { + t.Errorf("publicKey.Verify on broken sig did not fail") + } + } +} + +func TestParseRSAPrivateKey(t *testing.T) { + key := testPrivateKeys["rsa"] + + rsa, ok := key.(*rsa.PrivateKey) + if !ok { + t.Fatalf("got %T, want *rsa.PrivateKey", rsa) + } + + if err := rsa.Validate(); err != nil { + t.Errorf("Validate: %v", err) + } +} + +func TestParseECPrivateKey(t *testing.T) { + key := testPrivateKeys["ecdsa"] + + ecKey, ok := key.(*ecdsa.PrivateKey) + if !ok { + t.Fatalf("got %T, want *ecdsa.PrivateKey", ecKey) + } + + if !validateECPublicKey(ecKey.Curve, ecKey.X, ecKey.Y) { + t.Fatalf("public key does not validate.") + } +} + +// See Issue https://github.com/golang/go/issues/6650. +func TestParseEncryptedPrivateKeysFails(t *testing.T) { + const wantSubstring = "encrypted" + for i, tt := range testdata.PEMEncryptedKeys { + _, err := ParsePrivateKey(tt.PEMBytes) + if err == nil { + t.Errorf("#%d key %s: ParsePrivateKey successfully parsed, expected an error", i, tt.Name) + continue + } + + if !strings.Contains(err.Error(), wantSubstring) { + t.Errorf("#%d key %s: got error %q, want substring %q", i, tt.Name, err, wantSubstring) + } + } +} + +// Parse encrypted private keys with passphrase +func TestParseEncryptedPrivateKeysWithPassphrase(t *testing.T) { + data := []byte("sign me") + for _, tt := range testdata.PEMEncryptedKeys { + s, err := ParsePrivateKeyWithPassphrase(tt.PEMBytes, []byte(tt.EncryptionKey)) + if err != nil { + t.Fatalf("ParsePrivateKeyWithPassphrase returned error: %s", err) + continue + } + sig, err := s.Sign(rand.Reader, data) + if err != nil { + t.Fatalf("dsa.Sign: %v", err) + } + if err := s.PublicKey().Verify(data, sig); err != nil { + t.Errorf("Verify failed: %v", err) + } + } + + tt := testdata.PEMEncryptedKeys[0] + _, err := ParsePrivateKeyWithPassphrase(tt.PEMBytes, []byte("incorrect")) + if err != x509.IncorrectPasswordError { + t.Fatalf("got %v want IncorrectPasswordError", err) + } +} + +func TestParseDSA(t *testing.T) { + // We actually exercise the ParsePrivateKey codepath here, as opposed to + // using the ParseRawPrivateKey+NewSignerFromKey path that testdata_test.go + // uses. + s, err := ParsePrivateKey(testdata.PEMBytes["dsa"]) + if err != nil { + t.Fatalf("ParsePrivateKey returned error: %s", err) + } + + data := []byte("sign me") + sig, err := s.Sign(rand.Reader, data) + if err != nil { + t.Fatalf("dsa.Sign: %v", err) + } + + if err := s.PublicKey().Verify(data, sig); err != nil { + t.Errorf("Verify failed: %v", err) + } +} + +// Tests for authorized_keys parsing. + +// getTestKey returns a public key, and its base64 encoding. +func getTestKey() (PublicKey, string) { + k := testPublicKeys["rsa"] + + b := &bytes.Buffer{} + e := base64.NewEncoder(base64.StdEncoding, b) + e.Write(k.Marshal()) + e.Close() + + return k, b.String() +} + +func TestMarshalParsePublicKey(t *testing.T) { + pub, pubSerialized := getTestKey() + line := fmt.Sprintf("%s %s user@host", pub.Type(), pubSerialized) + + authKeys := MarshalAuthorizedKey(pub) + actualFields := strings.Fields(string(authKeys)) + if len(actualFields) == 0 { + t.Fatalf("failed authKeys: %v", authKeys) + } + + // drop the comment + expectedFields := strings.Fields(line)[0:2] + + if !reflect.DeepEqual(actualFields, expectedFields) { + t.Errorf("got %v, expected %v", actualFields, expectedFields) + } + + actPub, _, _, _, err := ParseAuthorizedKey([]byte(line)) + if err != nil { + t.Fatalf("cannot parse %v: %v", line, err) + } + if !reflect.DeepEqual(actPub, pub) { + t.Errorf("got %v, expected %v", actPub, pub) + } +} + +type authResult struct { + pubKey PublicKey + options []string + comments string + rest string + ok bool +} + +func testAuthorizedKeys(t *testing.T, authKeys []byte, expected []authResult) { + rest := authKeys + var values []authResult + for len(rest) > 0 { + var r authResult + var err error + r.pubKey, r.comments, r.options, rest, err = ParseAuthorizedKey(rest) + r.ok = (err == nil) + t.Log(err) + r.rest = string(rest) + values = append(values, r) + } + + if !reflect.DeepEqual(values, expected) { + t.Errorf("got %#v, expected %#v", values, expected) + } +} + +func TestAuthorizedKeyBasic(t *testing.T) { + pub, pubSerialized := getTestKey() + line := "ssh-rsa " + pubSerialized + " user@host" + testAuthorizedKeys(t, []byte(line), + []authResult{ + {pub, nil, "user@host", "", true}, + }) +} + +func TestAuth(t *testing.T) { + pub, pubSerialized := getTestKey() + authWithOptions := []string{ + `# comments to ignore before any keys...`, + ``, + `env="HOME=/home/root",no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host`, + `# comments to ignore, along with a blank line`, + ``, + `env="HOME=/home/root2" ssh-rsa ` + pubSerialized + ` user2@host2`, + ``, + `# more comments, plus a invalid entry`, + `ssh-rsa data-that-will-not-parse user@host3`, + } + for _, eol := range []string{"\n", "\r\n"} { + authOptions := strings.Join(authWithOptions, eol) + rest2 := strings.Join(authWithOptions[3:], eol) + rest3 := strings.Join(authWithOptions[6:], eol) + testAuthorizedKeys(t, []byte(authOptions), []authResult{ + {pub, []string{`env="HOME=/home/root"`, "no-port-forwarding"}, "user@host", rest2, true}, + {pub, []string{`env="HOME=/home/root2"`}, "user2@host2", rest3, true}, + {nil, nil, "", "", false}, + }) + } +} + +func TestAuthWithQuotedSpaceInEnv(t *testing.T) { + pub, pubSerialized := getTestKey() + authWithQuotedSpaceInEnv := []byte(`env="HOME=/home/root dir",no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host`) + testAuthorizedKeys(t, []byte(authWithQuotedSpaceInEnv), []authResult{ + {pub, []string{`env="HOME=/home/root dir"`, "no-port-forwarding"}, "user@host", "", true}, + }) +} + +func TestAuthWithQuotedCommaInEnv(t *testing.T) { + pub, pubSerialized := getTestKey() + authWithQuotedCommaInEnv := []byte(`env="HOME=/home/root,dir",no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host`) + testAuthorizedKeys(t, []byte(authWithQuotedCommaInEnv), []authResult{ + {pub, []string{`env="HOME=/home/root,dir"`, "no-port-forwarding"}, "user@host", "", true}, + }) +} + +func TestAuthWithQuotedQuoteInEnv(t *testing.T) { + pub, pubSerialized := getTestKey() + authWithQuotedQuoteInEnv := []byte(`env="HOME=/home/\"root dir",no-port-forwarding` + "\t" + `ssh-rsa` + "\t" + pubSerialized + ` user@host`) + authWithDoubleQuotedQuote := []byte(`no-port-forwarding,env="HOME=/home/ \"root dir\"" ssh-rsa ` + pubSerialized + "\t" + `user@host`) + testAuthorizedKeys(t, []byte(authWithQuotedQuoteInEnv), []authResult{ + {pub, []string{`env="HOME=/home/\"root dir"`, "no-port-forwarding"}, "user@host", "", true}, + }) + + testAuthorizedKeys(t, []byte(authWithDoubleQuotedQuote), []authResult{ + {pub, []string{"no-port-forwarding", `env="HOME=/home/ \"root dir\""`}, "user@host", "", true}, + }) +} + +func TestAuthWithInvalidSpace(t *testing.T) { + _, pubSerialized := getTestKey() + authWithInvalidSpace := []byte(`env="HOME=/home/root dir", no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host +#more to follow but still no valid keys`) + testAuthorizedKeys(t, []byte(authWithInvalidSpace), []authResult{ + {nil, nil, "", "", false}, + }) +} + +func TestAuthWithMissingQuote(t *testing.T) { + pub, pubSerialized := getTestKey() + authWithMissingQuote := []byte(`env="HOME=/home/root,no-port-forwarding ssh-rsa ` + pubSerialized + ` user@host +env="HOME=/home/root",shared-control ssh-rsa ` + pubSerialized + ` user@host`) + + testAuthorizedKeys(t, []byte(authWithMissingQuote), []authResult{ + {pub, []string{`env="HOME=/home/root"`, `shared-control`}, "user@host", "", true}, + }) +} + +func TestInvalidEntry(t *testing.T) { + authInvalid := []byte(`ssh-rsa`) + _, _, _, _, err := ParseAuthorizedKey(authInvalid) + if err == nil { + t.Errorf("got valid entry for %q", authInvalid) + } +} + +var knownHostsParseTests = []struct { + input string + err string + + marker string + comment string + hosts []string + rest string +}{ + { + "", + "EOF", + + "", "", nil, "", + }, + { + "# Just a comment", + "EOF", + + "", "", nil, "", + }, + { + " \t ", + "EOF", + + "", "", nil, "", + }, + { + "localhost ssh-rsa {RSAPUB}", + "", + + "", "", []string{"localhost"}, "", + }, + { + "localhost\tssh-rsa {RSAPUB}", + "", + + "", "", []string{"localhost"}, "", + }, + { + "localhost\tssh-rsa {RSAPUB}\tcomment comment", + "", + + "", "comment comment", []string{"localhost"}, "", + }, + { + "localhost\tssh-rsa {RSAPUB}\tcomment comment\n", + "", + + "", "comment comment", []string{"localhost"}, "", + }, + { + "localhost\tssh-rsa {RSAPUB}\tcomment comment\r\n", + "", + + "", "comment comment", []string{"localhost"}, "", + }, + { + "localhost\tssh-rsa {RSAPUB}\tcomment comment\r\nnext line", + "", + + "", "comment comment", []string{"localhost"}, "next line", + }, + { + "localhost,[host2:123]\tssh-rsa {RSAPUB}\tcomment comment", + "", + + "", "comment comment", []string{"localhost", "[host2:123]"}, "", + }, + { + "@marker \tlocalhost,[host2:123]\tssh-rsa {RSAPUB}", + "", + + "marker", "", []string{"localhost", "[host2:123]"}, "", + }, + { + "@marker \tlocalhost,[host2:123]\tssh-rsa aabbccdd", + "short read", + + "", "", nil, "", + }, +} + +func TestKnownHostsParsing(t *testing.T) { + rsaPub, rsaPubSerialized := getTestKey() + + for i, test := range knownHostsParseTests { + var expectedKey PublicKey + const rsaKeyToken = "{RSAPUB}" + + input := test.input + if strings.Contains(input, rsaKeyToken) { + expectedKey = rsaPub + input = strings.Replace(test.input, rsaKeyToken, rsaPubSerialized, -1) + } + + marker, hosts, pubKey, comment, rest, err := ParseKnownHosts([]byte(input)) + if err != nil { + if len(test.err) == 0 { + t.Errorf("#%d: unexpectedly failed with %q", i, err) + } else if !strings.Contains(err.Error(), test.err) { + t.Errorf("#%d: expected error containing %q, but got %q", i, test.err, err) + } + continue + } else if len(test.err) != 0 { + t.Errorf("#%d: succeeded but expected error including %q", i, test.err) + continue + } + + if !reflect.DeepEqual(expectedKey, pubKey) { + t.Errorf("#%d: expected key %#v, but got %#v", i, expectedKey, pubKey) + } + + if marker != test.marker { + t.Errorf("#%d: expected marker %q, but got %q", i, test.marker, marker) + } + + if comment != test.comment { + t.Errorf("#%d: expected comment %q, but got %q", i, test.comment, comment) + } + + if !reflect.DeepEqual(test.hosts, hosts) { + t.Errorf("#%d: expected hosts %#v, but got %#v", i, test.hosts, hosts) + } + + if rest := string(rest); rest != test.rest { + t.Errorf("#%d: expected remaining input to be %q, but got %q", i, test.rest, rest) + } + } +} + +func TestFingerprintLegacyMD5(t *testing.T) { + pub, _ := getTestKey() + fingerprint := FingerprintLegacyMD5(pub) + want := "fb:61:6d:1a:e3:f0:95:45:3c:a0:79:be:4a:93:63:66" // ssh-keygen -lf -E md5 rsa + if fingerprint != want { + t.Errorf("got fingerprint %q want %q", fingerprint, want) + } +} + +func TestFingerprintSHA256(t *testing.T) { + pub, _ := getTestKey() + fingerprint := FingerprintSHA256(pub) + want := "SHA256:Anr3LjZK8YVpjrxu79myrW9Hrb/wpcMNpVvTq/RcBm8" // ssh-keygen -lf rsa + if fingerprint != want { + t.Errorf("got fingerprint %q want %q", fingerprint, want) + } +} diff --git a/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts.go b/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts.go new file mode 100644 index 0000000000000000000000000000000000000000..46dad14015f6700974d3943fda9501c886b1a3e5 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts.go @@ -0,0 +1,546 @@ +// Copyright 2017 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 knownhosts implements a parser for the OpenSSH +// known_hosts host key database. +package knownhosts + +import ( + "bufio" + "bytes" + "crypto/hmac" + "crypto/rand" + "crypto/sha1" + "encoding/base64" + "errors" + "fmt" + "io" + "net" + "os" + "strings" + + "golang.org/x/crypto/ssh" +) + +// See the sshd manpage +// (http://man.openbsd.org/sshd#SSH_KNOWN_HOSTS_FILE_FORMAT) for +// background. + +type addr struct{ host, port string } + +func (a *addr) String() string { + h := a.host + if strings.Contains(h, ":") { + h = "[" + h + "]" + } + return h + ":" + a.port +} + +type matcher interface { + match([]addr) bool +} + +type hostPattern struct { + negate bool + addr addr +} + +func (p *hostPattern) String() string { + n := "" + if p.negate { + n = "!" + } + + return n + p.addr.String() +} + +type hostPatterns []hostPattern + +func (ps hostPatterns) match(addrs []addr) bool { + matched := false + for _, p := range ps { + for _, a := range addrs { + m := p.match(a) + if !m { + continue + } + if p.negate { + return false + } + matched = true + } + } + return matched +} + +// See +// https://android.googlesource.com/platform/external/openssh/+/ab28f5495c85297e7a597c1ba62e996416da7c7e/addrmatch.c +// The matching of * has no regard for separators, unlike filesystem globs +func wildcardMatch(pat []byte, str []byte) bool { + for { + if len(pat) == 0 { + return len(str) == 0 + } + if len(str) == 0 { + return false + } + + if pat[0] == '*' { + if len(pat) == 1 { + return true + } + + for j := range str { + if wildcardMatch(pat[1:], str[j:]) { + return true + } + } + return false + } + + if pat[0] == '?' || pat[0] == str[0] { + pat = pat[1:] + str = str[1:] + } else { + return false + } + } +} + +func (p *hostPattern) match(a addr) bool { + return wildcardMatch([]byte(p.addr.host), []byte(a.host)) && p.addr.port == a.port +} + +type keyDBLine struct { + cert bool + matcher matcher + knownKey KnownKey +} + +func serialize(k ssh.PublicKey) string { + return k.Type() + " " + base64.StdEncoding.EncodeToString(k.Marshal()) +} + +func (l *keyDBLine) match(addrs []addr) bool { + return l.matcher.match(addrs) +} + +type hostKeyDB struct { + // Serialized version of revoked keys + revoked map[string]*KnownKey + lines []keyDBLine +} + +func newHostKeyDB() *hostKeyDB { + db := &hostKeyDB{ + revoked: make(map[string]*KnownKey), + } + + return db +} + +func keyEq(a, b ssh.PublicKey) bool { + return bytes.Equal(a.Marshal(), b.Marshal()) +} + +// IsAuthorityForHost can be used as a callback in ssh.CertChecker +func (db *hostKeyDB) IsHostAuthority(remote ssh.PublicKey, address string) bool { + h, p, err := net.SplitHostPort(address) + if err != nil { + return false + } + a := addr{host: h, port: p} + + for _, l := range db.lines { + if l.cert && keyEq(l.knownKey.Key, remote) && l.match([]addr{a}) { + return true + } + } + return false +} + +// IsRevoked can be used as a callback in ssh.CertChecker +func (db *hostKeyDB) IsRevoked(key *ssh.Certificate) bool { + _, ok := db.revoked[string(key.Marshal())] + return ok +} + +const markerCert = "@cert-authority" +const markerRevoked = "@revoked" + +func nextWord(line []byte) (string, []byte) { + i := bytes.IndexAny(line, "\t ") + if i == -1 { + return string(line), nil + } + + return string(line[:i]), bytes.TrimSpace(line[i:]) +} + +func parseLine(line []byte) (marker, host string, key ssh.PublicKey, err error) { + if w, next := nextWord(line); w == markerCert || w == markerRevoked { + marker = w + line = next + } + + host, line = nextWord(line) + if len(line) == 0 { + return "", "", nil, errors.New("knownhosts: missing host pattern") + } + + // ignore the keytype as it's in the key blob anyway. + _, line = nextWord(line) + if len(line) == 0 { + return "", "", nil, errors.New("knownhosts: missing key type pattern") + } + + keyBlob, _ := nextWord(line) + + keyBytes, err := base64.StdEncoding.DecodeString(keyBlob) + if err != nil { + return "", "", nil, err + } + key, err = ssh.ParsePublicKey(keyBytes) + if err != nil { + return "", "", nil, err + } + + return marker, host, key, nil +} + +func (db *hostKeyDB) parseLine(line []byte, filename string, linenum int) error { + marker, pattern, key, err := parseLine(line) + if err != nil { + return err + } + + if marker == markerRevoked { + db.revoked[string(key.Marshal())] = &KnownKey{ + Key: key, + Filename: filename, + Line: linenum, + } + + return nil + } + + entry := keyDBLine{ + cert: marker == markerCert, + knownKey: KnownKey{ + Filename: filename, + Line: linenum, + Key: key, + }, + } + + if pattern[0] == '|' { + entry.matcher, err = newHashedHost(pattern) + } else { + entry.matcher, err = newHostnameMatcher(pattern) + } + + if err != nil { + return err + } + + db.lines = append(db.lines, entry) + return nil +} + +func newHostnameMatcher(pattern string) (matcher, error) { + var hps hostPatterns + for _, p := range strings.Split(pattern, ",") { + if len(p) == 0 { + continue + } + + var a addr + var negate bool + if p[0] == '!' { + negate = true + p = p[1:] + } + + if len(p) == 0 { + return nil, errors.New("knownhosts: negation without following hostname") + } + + var err error + if p[0] == '[' { + a.host, a.port, err = net.SplitHostPort(p) + if err != nil { + return nil, err + } + } else { + a.host, a.port, err = net.SplitHostPort(p) + if err != nil { + a.host = p + a.port = "22" + } + } + hps = append(hps, hostPattern{ + negate: negate, + addr: a, + }) + } + return hps, nil +} + +// KnownKey represents a key declared in a known_hosts file. +type KnownKey struct { + Key ssh.PublicKey + Filename string + Line int +} + +func (k *KnownKey) String() string { + return fmt.Sprintf("%s:%d: %s", k.Filename, k.Line, serialize(k.Key)) +} + +// KeyError is returned if we did not find the key in the host key +// database, or there was a mismatch. Typically, in batch +// applications, this should be interpreted as failure. Interactive +// applications can offer an interactive prompt to the user. +type KeyError struct { + // Want holds the accepted host keys. For each key algorithm, + // there can be one hostkey. If Want is empty, the host is + // unknown. If Want is non-empty, there was a mismatch, which + // can signify a MITM attack. + Want []KnownKey +} + +func (u *KeyError) Error() string { + if len(u.Want) == 0 { + return "knownhosts: key is unknown" + } + return "knownhosts: key mismatch" +} + +// RevokedError is returned if we found a key that was revoked. +type RevokedError struct { + Revoked KnownKey +} + +func (r *RevokedError) Error() string { + return "knownhosts: key is revoked" +} + +// check checks a key against the host database. This should not be +// used for verifying certificates. +func (db *hostKeyDB) check(address string, remote net.Addr, remoteKey ssh.PublicKey) error { + if revoked := db.revoked[string(remoteKey.Marshal())]; revoked != nil { + return &RevokedError{Revoked: *revoked} + } + + host, port, err := net.SplitHostPort(remote.String()) + if err != nil { + return fmt.Errorf("knownhosts: SplitHostPort(%s): %v", remote, err) + } + + addrs := []addr{ + {host, port}, + } + + if address != "" { + host, port, err := net.SplitHostPort(address) + if err != nil { + return fmt.Errorf("knownhosts: SplitHostPort(%s): %v", address, err) + } + + addrs = append(addrs, addr{host, port}) + } + + return db.checkAddrs(addrs, remoteKey) +} + +// checkAddrs checks if we can find the given public key for any of +// the given addresses. If we only find an entry for the IP address, +// or only the hostname, then this still succeeds. +func (db *hostKeyDB) checkAddrs(addrs []addr, remoteKey ssh.PublicKey) error { + // TODO(hanwen): are these the right semantics? What if there + // is just a key for the IP address, but not for the + // hostname? + + // Algorithm => key. + knownKeys := map[string]KnownKey{} + for _, l := range db.lines { + if l.match(addrs) { + typ := l.knownKey.Key.Type() + if _, ok := knownKeys[typ]; !ok { + knownKeys[typ] = l.knownKey + } + } + } + + keyErr := &KeyError{} + for _, v := range knownKeys { + keyErr.Want = append(keyErr.Want, v) + } + + // Unknown remote host. + if len(knownKeys) == 0 { + return keyErr + } + + // If the remote host starts using a different, unknown key type, we + // also interpret that as a mismatch. + if known, ok := knownKeys[remoteKey.Type()]; !ok || !keyEq(known.Key, remoteKey) { + return keyErr + } + + return nil +} + +// The Read function parses file contents. +func (db *hostKeyDB) Read(r io.Reader, filename string) error { + scanner := bufio.NewScanner(r) + + lineNum := 0 + for scanner.Scan() { + lineNum++ + line := scanner.Bytes() + line = bytes.TrimSpace(line) + if len(line) == 0 || line[0] == '#' { + continue + } + + if err := db.parseLine(line, filename, lineNum); err != nil { + return fmt.Errorf("knownhosts: %s:%d: %v", filename, lineNum, err) + } + } + return scanner.Err() +} + +// New creates a host key callback from the given OpenSSH host key +// files. The returned callback is for use in +// ssh.ClientConfig.HostKeyCallback. +func New(files ...string) (ssh.HostKeyCallback, error) { + db := newHostKeyDB() + for _, fn := range files { + f, err := os.Open(fn) + if err != nil { + return nil, err + } + defer f.Close() + if err := db.Read(f, fn); err != nil { + return nil, err + } + } + + var certChecker ssh.CertChecker + certChecker.IsHostAuthority = db.IsHostAuthority + certChecker.IsRevoked = db.IsRevoked + certChecker.HostKeyFallback = db.check + + return certChecker.CheckHostKey, nil +} + +// Normalize normalizes an address into the form used in known_hosts +func Normalize(address string) string { + host, port, err := net.SplitHostPort(address) + if err != nil { + host = address + port = "22" + } + entry := host + if port != "22" { + entry = "[" + entry + "]:" + port + } else if strings.Contains(host, ":") && !strings.HasPrefix(host, "[") { + entry = "[" + entry + "]" + } + return entry +} + +// Line returns a line to add append to the known_hosts files. +func Line(addresses []string, key ssh.PublicKey) string { + var trimmed []string + for _, a := range addresses { + trimmed = append(trimmed, Normalize(a)) + } + + return strings.Join(trimmed, ",") + " " + serialize(key) +} + +// HashHostname hashes the given hostname. The hostname is not +// normalized before hashing. +func HashHostname(hostname string) string { + // TODO(hanwen): check if we can safely normalize this always. + salt := make([]byte, sha1.Size) + + _, err := rand.Read(salt) + if err != nil { + panic(fmt.Sprintf("crypto/rand failure %v", err)) + } + + hash := hashHost(hostname, salt) + return encodeHash(sha1HashType, salt, hash) +} + +func decodeHash(encoded string) (hashType string, salt, hash []byte, err error) { + if len(encoded) == 0 || encoded[0] != '|' { + err = errors.New("knownhosts: hashed host must start with '|'") + return + } + components := strings.Split(encoded, "|") + if len(components) != 4 { + err = fmt.Errorf("knownhosts: got %d components, want 3", len(components)) + return + } + + hashType = components[1] + if salt, err = base64.StdEncoding.DecodeString(components[2]); err != nil { + return + } + if hash, err = base64.StdEncoding.DecodeString(components[3]); err != nil { + return + } + return +} + +func encodeHash(typ string, salt []byte, hash []byte) string { + return strings.Join([]string{"", + typ, + base64.StdEncoding.EncodeToString(salt), + base64.StdEncoding.EncodeToString(hash), + }, "|") +} + +// See https://android.googlesource.com/platform/external/openssh/+/ab28f5495c85297e7a597c1ba62e996416da7c7e/hostfile.c#120 +func hashHost(hostname string, salt []byte) []byte { + mac := hmac.New(sha1.New, salt) + mac.Write([]byte(hostname)) + return mac.Sum(nil) +} + +type hashedHost struct { + salt []byte + hash []byte +} + +const sha1HashType = "1" + +func newHashedHost(encoded string) (*hashedHost, error) { + typ, salt, hash, err := decodeHash(encoded) + if err != nil { + return nil, err + } + + // The type field seems for future algorithm agility, but it's + // actually hardcoded in openssh currently, see + // https://android.googlesource.com/platform/external/openssh/+/ab28f5495c85297e7a597c1ba62e996416da7c7e/hostfile.c#120 + if typ != sha1HashType { + return nil, fmt.Errorf("knownhosts: got hash type %s, must be '1'", typ) + } + + return &hashedHost{salt: salt, hash: hash}, nil +} + +func (h *hashedHost) match(addrs []addr) bool { + for _, a := range addrs { + if bytes.Equal(hashHost(Normalize(a.String()), h.salt), h.hash) { + return true + } + } + return false +} diff --git a/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts_test.go b/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts_test.go new file mode 100644 index 0000000000000000000000000000000000000000..be7cc0e80140b9160cd3f1fef77e102f88353823 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts_test.go @@ -0,0 +1,329 @@ +// Copyright 2017 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 knownhosts + +import ( + "bytes" + "fmt" + "net" + "reflect" + "testing" + + "golang.org/x/crypto/ssh" +) + +const edKeyStr = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGBAarftlLeoyf+v+nVchEZII/vna2PCV8FaX4vsF5BX" +const alternateEdKeyStr = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIXffBYeYL+WVzVru8npl5JHt2cjlr4ornFTWzoij9sx" +const ecKeyStr = "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNLCu01+wpXe3xB5olXCN4SqU2rQu0qjSRKJO4Bg+JRCPU+ENcgdA5srTU8xYDz/GEa4dzK5ldPw4J/gZgSXCMs=" + +var ecKey, alternateEdKey, edKey ssh.PublicKey +var testAddr = &net.TCPAddr{ + IP: net.IP{198, 41, 30, 196}, + Port: 22, +} + +var testAddr6 = &net.TCPAddr{ + IP: net.IP{198, 41, 30, 196, + 1, 2, 3, 4, + 1, 2, 3, 4, + 1, 2, 3, 4, + }, + Port: 22, +} + +func init() { + var err error + ecKey, _, _, _, err = ssh.ParseAuthorizedKey([]byte(ecKeyStr)) + if err != nil { + panic(err) + } + edKey, _, _, _, err = ssh.ParseAuthorizedKey([]byte(edKeyStr)) + if err != nil { + panic(err) + } + alternateEdKey, _, _, _, err = ssh.ParseAuthorizedKey([]byte(alternateEdKeyStr)) + if err != nil { + panic(err) + } +} + +func testDB(t *testing.T, s string) *hostKeyDB { + db := newHostKeyDB() + if err := db.Read(bytes.NewBufferString(s), "testdb"); err != nil { + t.Fatalf("Read: %v", err) + } + + return db +} + +func TestRevoked(t *testing.T) { + db := testDB(t, "\n\n@revoked * "+edKeyStr+"\n") + want := &RevokedError{ + Revoked: KnownKey{ + Key: edKey, + Filename: "testdb", + Line: 3, + }, + } + if err := db.check("", &net.TCPAddr{ + Port: 42, + }, edKey); err == nil { + t.Fatal("no error for revoked key") + } else if !reflect.DeepEqual(want, err) { + t.Fatalf("got %#v, want %#v", want, err) + } +} + +func TestHostAuthority(t *testing.T) { + for _, m := range []struct { + authorityFor string + address string + + good bool + }{ + {authorityFor: "localhost", address: "localhost:22", good: true}, + {authorityFor: "localhost", address: "localhost", good: false}, + {authorityFor: "localhost", address: "localhost:1234", good: false}, + {authorityFor: "[localhost]:1234", address: "localhost:1234", good: true}, + {authorityFor: "[localhost]:1234", address: "localhost:22", good: false}, + {authorityFor: "[localhost]:1234", address: "localhost", good: false}, + } { + db := testDB(t, `@cert-authority `+m.authorityFor+` `+edKeyStr) + if ok := db.IsHostAuthority(db.lines[0].knownKey.Key, m.address); ok != m.good { + t.Errorf("IsHostAuthority: authority %s, address %s, wanted good = %v, got good = %v", + m.authorityFor, m.address, m.good, ok) + } + } +} + +func TestBracket(t *testing.T) { + db := testDB(t, `[git.eclipse.org]:29418,[198.41.30.196]:29418 `+edKeyStr) + + if err := db.check("git.eclipse.org:29418", &net.TCPAddr{ + IP: net.IP{198, 41, 30, 196}, + Port: 29418, + }, edKey); err != nil { + t.Errorf("got error %v, want none", err) + } + + if err := db.check("git.eclipse.org:29419", &net.TCPAddr{ + Port: 42, + }, edKey); err == nil { + t.Fatalf("no error for unknown address") + } else if ke, ok := err.(*KeyError); !ok { + t.Fatalf("got type %T, want *KeyError", err) + } else if len(ke.Want) > 0 { + t.Fatalf("got Want %v, want []", ke.Want) + } +} + +func TestNewKeyType(t *testing.T) { + str := fmt.Sprintf("%s %s", testAddr, edKeyStr) + db := testDB(t, str) + if err := db.check("", testAddr, ecKey); err == nil { + t.Fatalf("no error for unknown address") + } else if ke, ok := err.(*KeyError); !ok { + t.Fatalf("got type %T, want *KeyError", err) + } else if len(ke.Want) == 0 { + t.Fatalf("got empty KeyError.Want") + } +} + +func TestSameKeyType(t *testing.T) { + str := fmt.Sprintf("%s %s", testAddr, edKeyStr) + db := testDB(t, str) + if err := db.check("", testAddr, alternateEdKey); err == nil { + t.Fatalf("no error for unknown address") + } else if ke, ok := err.(*KeyError); !ok { + t.Fatalf("got type %T, want *KeyError", err) + } else if len(ke.Want) == 0 { + t.Fatalf("got empty KeyError.Want") + } else if got, want := ke.Want[0].Key.Marshal(), edKey.Marshal(); !bytes.Equal(got, want) { + t.Fatalf("got key %q, want %q", got, want) + } +} + +func TestIPAddress(t *testing.T) { + str := fmt.Sprintf("%s %s", testAddr, edKeyStr) + db := testDB(t, str) + if err := db.check("", testAddr, edKey); err != nil { + t.Errorf("got error %q, want none", err) + } +} + +func TestIPv6Address(t *testing.T) { + str := fmt.Sprintf("%s %s", testAddr6, edKeyStr) + db := testDB(t, str) + + if err := db.check("", testAddr6, edKey); err != nil { + t.Errorf("got error %q, want none", err) + } +} + +func TestBasic(t *testing.T) { + str := fmt.Sprintf("#comment\n\nserver.org,%s %s\notherhost %s", testAddr, edKeyStr, ecKeyStr) + db := testDB(t, str) + if err := db.check("server.org:22", testAddr, edKey); err != nil { + t.Errorf("got error %q, want none", err) + } + + want := KnownKey{ + Key: edKey, + Filename: "testdb", + Line: 3, + } + if err := db.check("server.org:22", testAddr, ecKey); err == nil { + t.Errorf("succeeded, want KeyError") + } else if ke, ok := err.(*KeyError); !ok { + t.Errorf("got %T, want *KeyError", err) + } else if len(ke.Want) != 1 { + t.Errorf("got %v, want 1 entry", ke) + } else if !reflect.DeepEqual(ke.Want[0], want) { + t.Errorf("got %v, want %v", ke.Want[0], want) + } +} + +func TestNegate(t *testing.T) { + str := fmt.Sprintf("%s,!server.org %s", testAddr, edKeyStr) + db := testDB(t, str) + if err := db.check("server.org:22", testAddr, ecKey); err == nil { + t.Errorf("succeeded") + } else if ke, ok := err.(*KeyError); !ok { + t.Errorf("got error type %T, want *KeyError", err) + } else if len(ke.Want) != 0 { + t.Errorf("got expected keys %d (first of type %s), want []", len(ke.Want), ke.Want[0].Key.Type()) + } +} + +func TestWildcard(t *testing.T) { + str := fmt.Sprintf("server*.domain %s", edKeyStr) + db := testDB(t, str) + + want := &KeyError{ + Want: []KnownKey{{ + Filename: "testdb", + Line: 1, + Key: edKey, + }}, + } + + got := db.check("server.domain:22", &net.TCPAddr{}, ecKey) + if !reflect.DeepEqual(got, want) { + t.Errorf("got %s, want %s", got, want) + } +} + +func TestLine(t *testing.T) { + for in, want := range map[string]string{ + "server.org": "server.org " + edKeyStr, + "server.org:22": "server.org " + edKeyStr, + "server.org:23": "[server.org]:23 " + edKeyStr, + "[c629:1ec4:102:304:102:304:102:304]:22": "[c629:1ec4:102:304:102:304:102:304] " + edKeyStr, + "[c629:1ec4:102:304:102:304:102:304]:23": "[c629:1ec4:102:304:102:304:102:304]:23 " + edKeyStr, + } { + if got := Line([]string{in}, edKey); got != want { + t.Errorf("Line(%q) = %q, want %q", in, got, want) + } + } +} + +func TestWildcardMatch(t *testing.T) { + for _, c := range []struct { + pat, str string + want bool + }{ + {"a?b", "abb", true}, + {"ab", "abc", false}, + {"abc", "ab", false}, + {"a*b", "axxxb", true}, + {"a*b", "axbxb", true}, + {"a*b", "axbxbc", false}, + {"a*?", "axbxc", true}, + {"a*b*", "axxbxxxxxx", true}, + {"a*b*c", "axxbxxxxxxc", true}, + {"a*b*?", "axxbxxxxxxc", true}, + {"a*b*z", "axxbxxbxxxz", true}, + {"a*b*z", "axxbxxzxxxz", true}, + {"a*b*z", "axxbxxzxxx", false}, + } { + got := wildcardMatch([]byte(c.pat), []byte(c.str)) + if got != c.want { + t.Errorf("wildcardMatch(%q, %q) = %v, want %v", c.pat, c.str, got, c.want) + } + + } +} + +// TODO(hanwen): test coverage for certificates. + +const testHostname = "hostname" + +// generated with keygen -H -f +const encodedTestHostnameHash = "|1|IHXZvQMvTcZTUU29+2vXFgx8Frs=|UGccIWfRVDwilMBnA3WJoRAC75Y=" + +func TestHostHash(t *testing.T) { + testHostHash(t, testHostname, encodedTestHostnameHash) +} + +func TestHashList(t *testing.T) { + encoded := HashHostname(testHostname) + testHostHash(t, testHostname, encoded) +} + +func testHostHash(t *testing.T, hostname, encoded string) { + typ, salt, hash, err := decodeHash(encoded) + if err != nil { + t.Fatalf("decodeHash: %v", err) + } + + if got := encodeHash(typ, salt, hash); got != encoded { + t.Errorf("got encoding %s want %s", got, encoded) + } + + if typ != sha1HashType { + t.Fatalf("got hash type %q, want %q", typ, sha1HashType) + } + + got := hashHost(hostname, salt) + if !bytes.Equal(got, hash) { + t.Errorf("got hash %x want %x", got, hash) + } +} + +func TestNormalize(t *testing.T) { + for in, want := range map[string]string{ + "127.0.0.1:22": "127.0.0.1", + "[127.0.0.1]:22": "127.0.0.1", + "[127.0.0.1]:23": "[127.0.0.1]:23", + "127.0.0.1:23": "[127.0.0.1]:23", + "[a.b.c]:22": "a.b.c", + "[abcd:abcd:abcd:abcd]": "[abcd:abcd:abcd:abcd]", + "[abcd:abcd:abcd:abcd]:22": "[abcd:abcd:abcd:abcd]", + "[abcd:abcd:abcd:abcd]:23": "[abcd:abcd:abcd:abcd]:23", + } { + got := Normalize(in) + if got != want { + t.Errorf("Normalize(%q) = %q, want %q", in, got, want) + } + } +} + +func TestHashedHostkeyCheck(t *testing.T) { + str := fmt.Sprintf("%s %s", HashHostname(testHostname), edKeyStr) + db := testDB(t, str) + if err := db.check(testHostname+":22", testAddr, edKey); err != nil { + t.Errorf("check(%s): %v", testHostname, err) + } + want := &KeyError{ + Want: []KnownKey{{ + Filename: "testdb", + Line: 1, + Key: edKey, + }}, + } + if got := db.check(testHostname+":22", testAddr, alternateEdKey); !reflect.DeepEqual(got, want) { + t.Errorf("got error %v, want %v", got, want) + } +} diff --git a/vendor/golang.org/x/crypto/ssh/mac.go b/vendor/golang.org/x/crypto/ssh/mac.go new file mode 100644 index 0000000000000000000000000000000000000000..c07a06285e66617febc7bac604e91ba10a967e34 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/mac.go @@ -0,0 +1,61 @@ +// 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 ssh + +// Message authentication support + +import ( + "crypto/hmac" + "crypto/sha1" + "crypto/sha256" + "hash" +) + +type macMode struct { + keySize int + etm bool + new func(key []byte) hash.Hash +} + +// truncatingMAC wraps around a hash.Hash and truncates the output digest to +// a given size. +type truncatingMAC struct { + length int + hmac hash.Hash +} + +func (t truncatingMAC) Write(data []byte) (int, error) { + return t.hmac.Write(data) +} + +func (t truncatingMAC) Sum(in []byte) []byte { + out := t.hmac.Sum(in) + return out[:len(in)+t.length] +} + +func (t truncatingMAC) Reset() { + t.hmac.Reset() +} + +func (t truncatingMAC) Size() int { + return t.length +} + +func (t truncatingMAC) BlockSize() int { return t.hmac.BlockSize() } + +var macModes = map[string]*macMode{ + "hmac-sha2-256-etm@openssh.com": {32, true, func(key []byte) hash.Hash { + return hmac.New(sha256.New, key) + }}, + "hmac-sha2-256": {32, false, func(key []byte) hash.Hash { + return hmac.New(sha256.New, key) + }}, + "hmac-sha1": {20, false, func(key []byte) hash.Hash { + return hmac.New(sha1.New, key) + }}, + "hmac-sha1-96": {20, false, func(key []byte) hash.Hash { + return truncatingMAC{12, hmac.New(sha1.New, key)} + }}, +} diff --git a/vendor/golang.org/x/crypto/ssh/mempipe_test.go b/vendor/golang.org/x/crypto/ssh/mempipe_test.go new file mode 100644 index 0000000000000000000000000000000000000000..8697cd6140a737ececd84a37482d17065c5c3461 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/mempipe_test.go @@ -0,0 +1,110 @@ +// 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. + +package ssh + +import ( + "io" + "sync" + "testing" +) + +// An in-memory packetConn. It is safe to call Close and writePacket +// from different goroutines. +type memTransport struct { + eof bool + pending [][]byte + write *memTransport + sync.Mutex + *sync.Cond +} + +func (t *memTransport) readPacket() ([]byte, error) { + t.Lock() + defer t.Unlock() + for { + if len(t.pending) > 0 { + r := t.pending[0] + t.pending = t.pending[1:] + return r, nil + } + if t.eof { + return nil, io.EOF + } + t.Cond.Wait() + } +} + +func (t *memTransport) closeSelf() error { + t.Lock() + defer t.Unlock() + if t.eof { + return io.EOF + } + t.eof = true + t.Cond.Broadcast() + return nil +} + +func (t *memTransport) Close() error { + err := t.write.closeSelf() + t.closeSelf() + return err +} + +func (t *memTransport) writePacket(p []byte) error { + t.write.Lock() + defer t.write.Unlock() + if t.write.eof { + return io.EOF + } + c := make([]byte, len(p)) + copy(c, p) + t.write.pending = append(t.write.pending, c) + t.write.Cond.Signal() + return nil +} + +func memPipe() (a, b packetConn) { + t1 := memTransport{} + t2 := memTransport{} + t1.write = &t2 + t2.write = &t1 + t1.Cond = sync.NewCond(&t1.Mutex) + t2.Cond = sync.NewCond(&t2.Mutex) + return &t1, &t2 +} + +func TestMemPipe(t *testing.T) { + a, b := memPipe() + if err := a.writePacket([]byte{42}); err != nil { + t.Fatalf("writePacket: %v", err) + } + if err := a.Close(); err != nil { + t.Fatal("Close: ", err) + } + p, err := b.readPacket() + if err != nil { + t.Fatal("readPacket: ", err) + } + if len(p) != 1 || p[0] != 42 { + t.Fatalf("got %v, want {42}", p) + } + p, err = b.readPacket() + if err != io.EOF { + t.Fatalf("got %v, %v, want EOF", p, err) + } +} + +func TestDoubleClose(t *testing.T) { + a, _ := memPipe() + err := a.Close() + if err != nil { + t.Errorf("Close: %v", err) + } + err = a.Close() + if err != io.EOF { + t.Errorf("expect EOF on double close.") + } +} diff --git a/vendor/golang.org/x/crypto/ssh/messages.go b/vendor/golang.org/x/crypto/ssh/messages.go new file mode 100644 index 0000000000000000000000000000000000000000..08d28117305d9d3ec4c6cfeef36931203e1aac96 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/messages.go @@ -0,0 +1,766 @@ +// 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 ssh + +import ( + "bytes" + "encoding/binary" + "errors" + "fmt" + "io" + "math/big" + "reflect" + "strconv" + "strings" +) + +// These are SSH message type numbers. They are scattered around several +// documents but many were taken from [SSH-PARAMETERS]. +const ( + msgIgnore = 2 + msgUnimplemented = 3 + msgDebug = 4 + msgNewKeys = 21 +) + +// SSH messages: +// +// These structures mirror the wire format of the corresponding SSH messages. +// They are marshaled using reflection with the marshal and unmarshal functions +// in this file. The only wrinkle is that a final member of type []byte with a +// ssh tag of "rest" receives the remainder of a packet when unmarshaling. + +// See RFC 4253, section 11.1. +const msgDisconnect = 1 + +// disconnectMsg is the message that signals a disconnect. It is also +// the error type returned from mux.Wait() +type disconnectMsg struct { + Reason uint32 `sshtype:"1"` + Message string + Language string +} + +func (d *disconnectMsg) Error() string { + return fmt.Sprintf("ssh: disconnect, reason %d: %s", d.Reason, d.Message) +} + +// See RFC 4253, section 7.1. +const msgKexInit = 20 + +type kexInitMsg struct { + Cookie [16]byte `sshtype:"20"` + KexAlgos []string + ServerHostKeyAlgos []string + CiphersClientServer []string + CiphersServerClient []string + MACsClientServer []string + MACsServerClient []string + CompressionClientServer []string + CompressionServerClient []string + LanguagesClientServer []string + LanguagesServerClient []string + FirstKexFollows bool + Reserved uint32 +} + +// See RFC 4253, section 8. + +// Diffie-Helman +const msgKexDHInit = 30 + +type kexDHInitMsg struct { + X *big.Int `sshtype:"30"` +} + +const msgKexECDHInit = 30 + +type kexECDHInitMsg struct { + ClientPubKey []byte `sshtype:"30"` +} + +const msgKexECDHReply = 31 + +type kexECDHReplyMsg struct { + HostKey []byte `sshtype:"31"` + EphemeralPubKey []byte + Signature []byte +} + +const msgKexDHReply = 31 + +type kexDHReplyMsg struct { + HostKey []byte `sshtype:"31"` + Y *big.Int + Signature []byte +} + +// See RFC 4253, section 10. +const msgServiceRequest = 5 + +type serviceRequestMsg struct { + Service string `sshtype:"5"` +} + +// See RFC 4253, section 10. +const msgServiceAccept = 6 + +type serviceAcceptMsg struct { + Service string `sshtype:"6"` +} + +// See RFC 4252, section 5. +const msgUserAuthRequest = 50 + +type userAuthRequestMsg struct { + User string `sshtype:"50"` + Service string + Method string + Payload []byte `ssh:"rest"` +} + +// Used for debug printouts of packets. +type userAuthSuccessMsg struct { +} + +// See RFC 4252, section 5.1 +const msgUserAuthFailure = 51 + +type userAuthFailureMsg struct { + Methods []string `sshtype:"51"` + PartialSuccess bool +} + +// See RFC 4252, section 5.1 +const msgUserAuthSuccess = 52 + +// See RFC 4252, section 5.4 +const msgUserAuthBanner = 53 + +type userAuthBannerMsg struct { + Message string `sshtype:"53"` + // unused, but required to allow message parsing + Language string +} + +// See RFC 4256, section 3.2 +const msgUserAuthInfoRequest = 60 +const msgUserAuthInfoResponse = 61 + +type userAuthInfoRequestMsg struct { + User string `sshtype:"60"` + Instruction string + DeprecatedLanguage string + NumPrompts uint32 + Prompts []byte `ssh:"rest"` +} + +// See RFC 4254, section 5.1. +const msgChannelOpen = 90 + +type channelOpenMsg struct { + ChanType string `sshtype:"90"` + PeersID uint32 + PeersWindow uint32 + MaxPacketSize uint32 + TypeSpecificData []byte `ssh:"rest"` +} + +const msgChannelExtendedData = 95 +const msgChannelData = 94 + +// Used for debug print outs of packets. +type channelDataMsg struct { + PeersID uint32 `sshtype:"94"` + Length uint32 + Rest []byte `ssh:"rest"` +} + +// See RFC 4254, section 5.1. +const msgChannelOpenConfirm = 91 + +type channelOpenConfirmMsg struct { + PeersID uint32 `sshtype:"91"` + MyID uint32 + MyWindow uint32 + MaxPacketSize uint32 + TypeSpecificData []byte `ssh:"rest"` +} + +// See RFC 4254, section 5.1. +const msgChannelOpenFailure = 92 + +type channelOpenFailureMsg struct { + PeersID uint32 `sshtype:"92"` + Reason RejectionReason + Message string + Language string +} + +const msgChannelRequest = 98 + +type channelRequestMsg struct { + PeersID uint32 `sshtype:"98"` + Request string + WantReply bool + RequestSpecificData []byte `ssh:"rest"` +} + +// See RFC 4254, section 5.4. +const msgChannelSuccess = 99 + +type channelRequestSuccessMsg struct { + PeersID uint32 `sshtype:"99"` +} + +// See RFC 4254, section 5.4. +const msgChannelFailure = 100 + +type channelRequestFailureMsg struct { + PeersID uint32 `sshtype:"100"` +} + +// See RFC 4254, section 5.3 +const msgChannelClose = 97 + +type channelCloseMsg struct { + PeersID uint32 `sshtype:"97"` +} + +// See RFC 4254, section 5.3 +const msgChannelEOF = 96 + +type channelEOFMsg struct { + PeersID uint32 `sshtype:"96"` +} + +// See RFC 4254, section 4 +const msgGlobalRequest = 80 + +type globalRequestMsg struct { + Type string `sshtype:"80"` + WantReply bool + Data []byte `ssh:"rest"` +} + +// See RFC 4254, section 4 +const msgRequestSuccess = 81 + +type globalRequestSuccessMsg struct { + Data []byte `ssh:"rest" sshtype:"81"` +} + +// See RFC 4254, section 4 +const msgRequestFailure = 82 + +type globalRequestFailureMsg struct { + Data []byte `ssh:"rest" sshtype:"82"` +} + +// See RFC 4254, section 5.2 +const msgChannelWindowAdjust = 93 + +type windowAdjustMsg struct { + PeersID uint32 `sshtype:"93"` + AdditionalBytes uint32 +} + +// See RFC 4252, section 7 +const msgUserAuthPubKeyOk = 60 + +type userAuthPubKeyOkMsg struct { + Algo string `sshtype:"60"` + PubKey []byte +} + +// typeTags returns the possible type bytes for the given reflect.Type, which +// should be a struct. The possible values are separated by a '|' character. +func typeTags(structType reflect.Type) (tags []byte) { + tagStr := structType.Field(0).Tag.Get("sshtype") + + for _, tag := range strings.Split(tagStr, "|") { + i, err := strconv.Atoi(tag) + if err == nil { + tags = append(tags, byte(i)) + } + } + + return tags +} + +func fieldError(t reflect.Type, field int, problem string) error { + if problem != "" { + problem = ": " + problem + } + return fmt.Errorf("ssh: unmarshal error for field %s of type %s%s", t.Field(field).Name, t.Name(), problem) +} + +var errShortRead = errors.New("ssh: short read") + +// Unmarshal parses data in SSH wire format into a structure. The out +// argument should be a pointer to struct. If the first member of the +// struct has the "sshtype" tag set to a '|'-separated set of numbers +// in decimal, the packet must start with one of those numbers. In +// case of error, Unmarshal returns a ParseError or +// UnexpectedMessageError. +func Unmarshal(data []byte, out interface{}) error { + v := reflect.ValueOf(out).Elem() + structType := v.Type() + expectedTypes := typeTags(structType) + + var expectedType byte + if len(expectedTypes) > 0 { + expectedType = expectedTypes[0] + } + + if len(data) == 0 { + return parseError(expectedType) + } + + if len(expectedTypes) > 0 { + goodType := false + for _, e := range expectedTypes { + if e > 0 && data[0] == e { + goodType = true + break + } + } + if !goodType { + return fmt.Errorf("ssh: unexpected message type %d (expected one of %v)", data[0], expectedTypes) + } + data = data[1:] + } + + var ok bool + for i := 0; i < v.NumField(); i++ { + field := v.Field(i) + t := field.Type() + switch t.Kind() { + case reflect.Bool: + if len(data) < 1 { + return errShortRead + } + field.SetBool(data[0] != 0) + data = data[1:] + case reflect.Array: + if t.Elem().Kind() != reflect.Uint8 { + return fieldError(structType, i, "array of unsupported type") + } + if len(data) < t.Len() { + return errShortRead + } + for j, n := 0, t.Len(); j < n; j++ { + field.Index(j).Set(reflect.ValueOf(data[j])) + } + data = data[t.Len():] + case reflect.Uint64: + var u64 uint64 + if u64, data, ok = parseUint64(data); !ok { + return errShortRead + } + field.SetUint(u64) + case reflect.Uint32: + var u32 uint32 + if u32, data, ok = parseUint32(data); !ok { + return errShortRead + } + field.SetUint(uint64(u32)) + case reflect.Uint8: + if len(data) < 1 { + return errShortRead + } + field.SetUint(uint64(data[0])) + data = data[1:] + case reflect.String: + var s []byte + if s, data, ok = parseString(data); !ok { + return fieldError(structType, i, "") + } + field.SetString(string(s)) + case reflect.Slice: + switch t.Elem().Kind() { + case reflect.Uint8: + if structType.Field(i).Tag.Get("ssh") == "rest" { + field.Set(reflect.ValueOf(data)) + data = nil + } else { + var s []byte + if s, data, ok = parseString(data); !ok { + return errShortRead + } + field.Set(reflect.ValueOf(s)) + } + case reflect.String: + var nl []string + if nl, data, ok = parseNameList(data); !ok { + return errShortRead + } + field.Set(reflect.ValueOf(nl)) + default: + return fieldError(structType, i, "slice of unsupported type") + } + case reflect.Ptr: + if t == bigIntType { + var n *big.Int + if n, data, ok = parseInt(data); !ok { + return errShortRead + } + field.Set(reflect.ValueOf(n)) + } else { + return fieldError(structType, i, "pointer to unsupported type") + } + default: + return fieldError(structType, i, fmt.Sprintf("unsupported type: %v", t)) + } + } + + if len(data) != 0 { + return parseError(expectedType) + } + + return nil +} + +// Marshal serializes the message in msg to SSH wire format. The msg +// argument should be a struct or pointer to struct. If the first +// member has the "sshtype" tag set to a number in decimal, that +// number is prepended to the result. If the last of member has the +// "ssh" tag set to "rest", its contents are appended to the output. +func Marshal(msg interface{}) []byte { + out := make([]byte, 0, 64) + return marshalStruct(out, msg) +} + +func marshalStruct(out []byte, msg interface{}) []byte { + v := reflect.Indirect(reflect.ValueOf(msg)) + msgTypes := typeTags(v.Type()) + if len(msgTypes) > 0 { + out = append(out, msgTypes[0]) + } + + for i, n := 0, v.NumField(); i < n; i++ { + field := v.Field(i) + switch t := field.Type(); t.Kind() { + case reflect.Bool: + var v uint8 + if field.Bool() { + v = 1 + } + out = append(out, v) + case reflect.Array: + if t.Elem().Kind() != reflect.Uint8 { + panic(fmt.Sprintf("array of non-uint8 in field %d: %T", i, field.Interface())) + } + for j, l := 0, t.Len(); j < l; j++ { + out = append(out, uint8(field.Index(j).Uint())) + } + case reflect.Uint32: + out = appendU32(out, uint32(field.Uint())) + case reflect.Uint64: + out = appendU64(out, uint64(field.Uint())) + case reflect.Uint8: + out = append(out, uint8(field.Uint())) + case reflect.String: + s := field.String() + out = appendInt(out, len(s)) + out = append(out, s...) + case reflect.Slice: + switch t.Elem().Kind() { + case reflect.Uint8: + if v.Type().Field(i).Tag.Get("ssh") != "rest" { + out = appendInt(out, field.Len()) + } + out = append(out, field.Bytes()...) + case reflect.String: + offset := len(out) + out = appendU32(out, 0) + if n := field.Len(); n > 0 { + for j := 0; j < n; j++ { + f := field.Index(j) + if j != 0 { + out = append(out, ',') + } + out = append(out, f.String()...) + } + // overwrite length value + binary.BigEndian.PutUint32(out[offset:], uint32(len(out)-offset-4)) + } + default: + panic(fmt.Sprintf("slice of unknown type in field %d: %T", i, field.Interface())) + } + case reflect.Ptr: + if t == bigIntType { + var n *big.Int + nValue := reflect.ValueOf(&n) + nValue.Elem().Set(field) + needed := intLength(n) + oldLength := len(out) + + if cap(out)-len(out) < needed { + newOut := make([]byte, len(out), 2*(len(out)+needed)) + copy(newOut, out) + out = newOut + } + out = out[:oldLength+needed] + marshalInt(out[oldLength:], n) + } else { + panic(fmt.Sprintf("pointer to unknown type in field %d: %T", i, field.Interface())) + } + } + } + + return out +} + +var bigOne = big.NewInt(1) + +func parseString(in []byte) (out, rest []byte, ok bool) { + if len(in) < 4 { + return + } + length := binary.BigEndian.Uint32(in) + in = in[4:] + if uint32(len(in)) < length { + return + } + out = in[:length] + rest = in[length:] + ok = true + return +} + +var ( + comma = []byte{','} + emptyNameList = []string{} +) + +func parseNameList(in []byte) (out []string, rest []byte, ok bool) { + contents, rest, ok := parseString(in) + if !ok { + return + } + if len(contents) == 0 { + out = emptyNameList + return + } + parts := bytes.Split(contents, comma) + out = make([]string, len(parts)) + for i, part := range parts { + out[i] = string(part) + } + return +} + +func parseInt(in []byte) (out *big.Int, rest []byte, ok bool) { + contents, rest, ok := parseString(in) + if !ok { + return + } + out = new(big.Int) + + if len(contents) > 0 && contents[0]&0x80 == 0x80 { + // This is a negative number + notBytes := make([]byte, len(contents)) + for i := range notBytes { + notBytes[i] = ^contents[i] + } + out.SetBytes(notBytes) + out.Add(out, bigOne) + out.Neg(out) + } else { + // Positive number + out.SetBytes(contents) + } + ok = true + return +} + +func parseUint32(in []byte) (uint32, []byte, bool) { + if len(in) < 4 { + return 0, nil, false + } + return binary.BigEndian.Uint32(in), in[4:], true +} + +func parseUint64(in []byte) (uint64, []byte, bool) { + if len(in) < 8 { + return 0, nil, false + } + return binary.BigEndian.Uint64(in), in[8:], true +} + +func intLength(n *big.Int) int { + length := 4 /* length bytes */ + if n.Sign() < 0 { + nMinus1 := new(big.Int).Neg(n) + nMinus1.Sub(nMinus1, bigOne) + bitLen := nMinus1.BitLen() + if bitLen%8 == 0 { + // The number will need 0xff padding + length++ + } + length += (bitLen + 7) / 8 + } else if n.Sign() == 0 { + // A zero is the zero length string + } else { + bitLen := n.BitLen() + if bitLen%8 == 0 { + // The number will need 0x00 padding + length++ + } + length += (bitLen + 7) / 8 + } + + return length +} + +func marshalUint32(to []byte, n uint32) []byte { + binary.BigEndian.PutUint32(to, n) + return to[4:] +} + +func marshalUint64(to []byte, n uint64) []byte { + binary.BigEndian.PutUint64(to, n) + return to[8:] +} + +func marshalInt(to []byte, n *big.Int) []byte { + lengthBytes := to + to = to[4:] + length := 0 + + if n.Sign() < 0 { + // A negative number has to be converted to two's-complement + // form. So we'll subtract 1 and invert. If the + // most-significant-bit isn't set then we'll need to pad the + // beginning with 0xff in order to keep the number negative. + nMinus1 := new(big.Int).Neg(n) + nMinus1.Sub(nMinus1, bigOne) + bytes := nMinus1.Bytes() + for i := range bytes { + bytes[i] ^= 0xff + } + if len(bytes) == 0 || bytes[0]&0x80 == 0 { + to[0] = 0xff + to = to[1:] + length++ + } + nBytes := copy(to, bytes) + to = to[nBytes:] + length += nBytes + } else if n.Sign() == 0 { + // A zero is the zero length string + } else { + bytes := n.Bytes() + if len(bytes) > 0 && bytes[0]&0x80 != 0 { + // We'll have to pad this with a 0x00 in order to + // stop it looking like a negative number. + to[0] = 0 + to = to[1:] + length++ + } + nBytes := copy(to, bytes) + to = to[nBytes:] + length += nBytes + } + + lengthBytes[0] = byte(length >> 24) + lengthBytes[1] = byte(length >> 16) + lengthBytes[2] = byte(length >> 8) + lengthBytes[3] = byte(length) + return to +} + +func writeInt(w io.Writer, n *big.Int) { + length := intLength(n) + buf := make([]byte, length) + marshalInt(buf, n) + w.Write(buf) +} + +func writeString(w io.Writer, s []byte) { + var lengthBytes [4]byte + lengthBytes[0] = byte(len(s) >> 24) + lengthBytes[1] = byte(len(s) >> 16) + lengthBytes[2] = byte(len(s) >> 8) + lengthBytes[3] = byte(len(s)) + w.Write(lengthBytes[:]) + w.Write(s) +} + +func stringLength(n int) int { + return 4 + n +} + +func marshalString(to []byte, s []byte) []byte { + to[0] = byte(len(s) >> 24) + to[1] = byte(len(s) >> 16) + to[2] = byte(len(s) >> 8) + to[3] = byte(len(s)) + to = to[4:] + copy(to, s) + return to[len(s):] +} + +var bigIntType = reflect.TypeOf((*big.Int)(nil)) + +// Decode a packet into its corresponding message. +func decode(packet []byte) (interface{}, error) { + var msg interface{} + switch packet[0] { + case msgDisconnect: + msg = new(disconnectMsg) + case msgServiceRequest: + msg = new(serviceRequestMsg) + case msgServiceAccept: + msg = new(serviceAcceptMsg) + case msgKexInit: + msg = new(kexInitMsg) + case msgKexDHInit: + msg = new(kexDHInitMsg) + case msgKexDHReply: + msg = new(kexDHReplyMsg) + case msgUserAuthRequest: + msg = new(userAuthRequestMsg) + case msgUserAuthSuccess: + return new(userAuthSuccessMsg), nil + case msgUserAuthFailure: + msg = new(userAuthFailureMsg) + case msgUserAuthPubKeyOk: + msg = new(userAuthPubKeyOkMsg) + case msgGlobalRequest: + msg = new(globalRequestMsg) + case msgRequestSuccess: + msg = new(globalRequestSuccessMsg) + case msgRequestFailure: + msg = new(globalRequestFailureMsg) + case msgChannelOpen: + msg = new(channelOpenMsg) + case msgChannelData: + msg = new(channelDataMsg) + case msgChannelOpenConfirm: + msg = new(channelOpenConfirmMsg) + case msgChannelOpenFailure: + msg = new(channelOpenFailureMsg) + case msgChannelWindowAdjust: + msg = new(windowAdjustMsg) + case msgChannelEOF: + msg = new(channelEOFMsg) + case msgChannelClose: + msg = new(channelCloseMsg) + case msgChannelRequest: + msg = new(channelRequestMsg) + case msgChannelSuccess: + msg = new(channelRequestSuccessMsg) + case msgChannelFailure: + msg = new(channelRequestFailureMsg) + default: + return nil, unexpectedMessageError(0, packet[0]) + } + if err := Unmarshal(packet, msg); err != nil { + return nil, err + } + return msg, nil +} diff --git a/vendor/golang.org/x/crypto/ssh/messages_test.go b/vendor/golang.org/x/crypto/ssh/messages_test.go new file mode 100644 index 0000000000000000000000000000000000000000..e79076412ab49f8cd5c72a790b3978dace234342 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/messages_test.go @@ -0,0 +1,288 @@ +// 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 ssh + +import ( + "bytes" + "math/big" + "math/rand" + "reflect" + "testing" + "testing/quick" +) + +var intLengthTests = []struct { + val, length int +}{ + {0, 4 + 0}, + {1, 4 + 1}, + {127, 4 + 1}, + {128, 4 + 2}, + {-1, 4 + 1}, +} + +func TestIntLength(t *testing.T) { + for _, test := range intLengthTests { + v := new(big.Int).SetInt64(int64(test.val)) + length := intLength(v) + if length != test.length { + t.Errorf("For %d, got length %d but expected %d", test.val, length, test.length) + } + } +} + +type msgAllTypes struct { + Bool bool `sshtype:"21"` + Array [16]byte + Uint64 uint64 + Uint32 uint32 + Uint8 uint8 + String string + Strings []string + Bytes []byte + Int *big.Int + Rest []byte `ssh:"rest"` +} + +func (t *msgAllTypes) Generate(rand *rand.Rand, size int) reflect.Value { + m := &msgAllTypes{} + m.Bool = rand.Intn(2) == 1 + randomBytes(m.Array[:], rand) + m.Uint64 = uint64(rand.Int63n(1<<63 - 1)) + m.Uint32 = uint32(rand.Intn((1 << 31) - 1)) + m.Uint8 = uint8(rand.Intn(1 << 8)) + m.String = string(m.Array[:]) + m.Strings = randomNameList(rand) + m.Bytes = m.Array[:] + m.Int = randomInt(rand) + m.Rest = m.Array[:] + return reflect.ValueOf(m) +} + +func TestMarshalUnmarshal(t *testing.T) { + rand := rand.New(rand.NewSource(0)) + iface := &msgAllTypes{} + ty := reflect.ValueOf(iface).Type() + + n := 100 + if testing.Short() { + n = 5 + } + for j := 0; j < n; j++ { + v, ok := quick.Value(ty, rand) + if !ok { + t.Errorf("failed to create value") + break + } + + m1 := v.Elem().Interface() + m2 := iface + + marshaled := Marshal(m1) + if err := Unmarshal(marshaled, m2); err != nil { + t.Errorf("Unmarshal %#v: %s", m1, err) + break + } + + if !reflect.DeepEqual(v.Interface(), m2) { + t.Errorf("got: %#v\nwant:%#v\n%x", m2, m1, marshaled) + break + } + } +} + +func TestUnmarshalEmptyPacket(t *testing.T) { + var b []byte + var m channelRequestSuccessMsg + if err := Unmarshal(b, &m); err == nil { + t.Fatalf("unmarshal of empty slice succeeded") + } +} + +func TestUnmarshalUnexpectedPacket(t *testing.T) { + type S struct { + I uint32 `sshtype:"43"` + S string + B bool + } + + s := S{11, "hello", true} + packet := Marshal(s) + packet[0] = 42 + roundtrip := S{} + err := Unmarshal(packet, &roundtrip) + if err == nil { + t.Fatal("expected error, not nil") + } +} + +func TestMarshalPtr(t *testing.T) { + s := struct { + S string + }{"hello"} + + m1 := Marshal(s) + m2 := Marshal(&s) + if !bytes.Equal(m1, m2) { + t.Errorf("got %q, want %q for marshaled pointer", m2, m1) + } +} + +func TestBareMarshalUnmarshal(t *testing.T) { + type S struct { + I uint32 + S string + B bool + } + + s := S{42, "hello", true} + packet := Marshal(s) + roundtrip := S{} + Unmarshal(packet, &roundtrip) + + if !reflect.DeepEqual(s, roundtrip) { + t.Errorf("got %#v, want %#v", roundtrip, s) + } +} + +func TestBareMarshal(t *testing.T) { + type S2 struct { + I uint32 + } + s := S2{42} + packet := Marshal(s) + i, rest, ok := parseUint32(packet) + if len(rest) > 0 || !ok { + t.Errorf("parseInt(%q): parse error", packet) + } + if i != s.I { + t.Errorf("got %d, want %d", i, s.I) + } +} + +func TestUnmarshalShortKexInitPacket(t *testing.T) { + // This used to panic. + // Issue 11348 + packet := []byte{0x14, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xff, 0xff, 0xff, 0xff} + kim := &kexInitMsg{} + if err := Unmarshal(packet, kim); err == nil { + t.Error("truncated packet unmarshaled without error") + } +} + +func TestMarshalMultiTag(t *testing.T) { + var res struct { + A uint32 `sshtype:"1|2"` + } + + good1 := struct { + A uint32 `sshtype:"1"` + }{ + 1, + } + good2 := struct { + A uint32 `sshtype:"2"` + }{ + 1, + } + + if e := Unmarshal(Marshal(good1), &res); e != nil { + t.Errorf("error unmarshaling multipart tag: %v", e) + } + + if e := Unmarshal(Marshal(good2), &res); e != nil { + t.Errorf("error unmarshaling multipart tag: %v", e) + } + + bad1 := struct { + A uint32 `sshtype:"3"` + }{ + 1, + } + if e := Unmarshal(Marshal(bad1), &res); e == nil { + t.Errorf("bad struct unmarshaled without error") + } +} + +func randomBytes(out []byte, rand *rand.Rand) { + for i := 0; i < len(out); i++ { + out[i] = byte(rand.Int31()) + } +} + +func randomNameList(rand *rand.Rand) []string { + ret := make([]string, rand.Int31()&15) + for i := range ret { + s := make([]byte, 1+(rand.Int31()&15)) + for j := range s { + s[j] = 'a' + uint8(rand.Int31()&15) + } + ret[i] = string(s) + } + return ret +} + +func randomInt(rand *rand.Rand) *big.Int { + return new(big.Int).SetInt64(int64(int32(rand.Uint32()))) +} + +func (*kexInitMsg) Generate(rand *rand.Rand, size int) reflect.Value { + ki := &kexInitMsg{} + randomBytes(ki.Cookie[:], rand) + ki.KexAlgos = randomNameList(rand) + ki.ServerHostKeyAlgos = randomNameList(rand) + ki.CiphersClientServer = randomNameList(rand) + ki.CiphersServerClient = randomNameList(rand) + ki.MACsClientServer = randomNameList(rand) + ki.MACsServerClient = randomNameList(rand) + ki.CompressionClientServer = randomNameList(rand) + ki.CompressionServerClient = randomNameList(rand) + ki.LanguagesClientServer = randomNameList(rand) + ki.LanguagesServerClient = randomNameList(rand) + if rand.Int31()&1 == 1 { + ki.FirstKexFollows = true + } + return reflect.ValueOf(ki) +} + +func (*kexDHInitMsg) Generate(rand *rand.Rand, size int) reflect.Value { + dhi := &kexDHInitMsg{} + dhi.X = randomInt(rand) + return reflect.ValueOf(dhi) +} + +var ( + _kexInitMsg = new(kexInitMsg).Generate(rand.New(rand.NewSource(0)), 10).Elem().Interface() + _kexDHInitMsg = new(kexDHInitMsg).Generate(rand.New(rand.NewSource(0)), 10).Elem().Interface() + + _kexInit = Marshal(_kexInitMsg) + _kexDHInit = Marshal(_kexDHInitMsg) +) + +func BenchmarkMarshalKexInitMsg(b *testing.B) { + for i := 0; i < b.N; i++ { + Marshal(_kexInitMsg) + } +} + +func BenchmarkUnmarshalKexInitMsg(b *testing.B) { + m := new(kexInitMsg) + for i := 0; i < b.N; i++ { + Unmarshal(_kexInit, m) + } +} + +func BenchmarkMarshalKexDHInitMsg(b *testing.B) { + for i := 0; i < b.N; i++ { + Marshal(_kexDHInitMsg) + } +} + +func BenchmarkUnmarshalKexDHInitMsg(b *testing.B) { + m := new(kexDHInitMsg) + for i := 0; i < b.N; i++ { + Unmarshal(_kexDHInit, m) + } +} diff --git a/vendor/golang.org/x/crypto/ssh/mux.go b/vendor/golang.org/x/crypto/ssh/mux.go new file mode 100644 index 0000000000000000000000000000000000000000..f19016270e8f9a27e159277a14ef60c771ed1ba5 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/mux.go @@ -0,0 +1,330 @@ +// 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. + +package ssh + +import ( + "encoding/binary" + "fmt" + "io" + "log" + "sync" + "sync/atomic" +) + +// debugMux, if set, causes messages in the connection protocol to be +// logged. +const debugMux = false + +// chanList is a thread safe channel list. +type chanList struct { + // protects concurrent access to chans + sync.Mutex + + // chans are indexed by the local id of the channel, which the + // other side should send in the PeersId field. + chans []*channel + + // This is a debugging aid: it offsets all IDs by this + // amount. This helps distinguish otherwise identical + // server/client muxes + offset uint32 +} + +// Assigns a channel ID to the given channel. +func (c *chanList) add(ch *channel) uint32 { + c.Lock() + defer c.Unlock() + for i := range c.chans { + if c.chans[i] == nil { + c.chans[i] = ch + return uint32(i) + c.offset + } + } + c.chans = append(c.chans, ch) + return uint32(len(c.chans)-1) + c.offset +} + +// getChan returns the channel for the given ID. +func (c *chanList) getChan(id uint32) *channel { + id -= c.offset + + c.Lock() + defer c.Unlock() + if id < uint32(len(c.chans)) { + return c.chans[id] + } + return nil +} + +func (c *chanList) remove(id uint32) { + id -= c.offset + c.Lock() + if id < uint32(len(c.chans)) { + c.chans[id] = nil + } + c.Unlock() +} + +// dropAll forgets all channels it knows, returning them in a slice. +func (c *chanList) dropAll() []*channel { + c.Lock() + defer c.Unlock() + var r []*channel + + for _, ch := range c.chans { + if ch == nil { + continue + } + r = append(r, ch) + } + c.chans = nil + return r +} + +// mux represents the state for the SSH connection protocol, which +// multiplexes many channels onto a single packet transport. +type mux struct { + conn packetConn + chanList chanList + + incomingChannels chan NewChannel + + globalSentMu sync.Mutex + globalResponses chan interface{} + incomingRequests chan *Request + + errCond *sync.Cond + err error +} + +// When debugging, each new chanList instantiation has a different +// offset. +var globalOff uint32 + +func (m *mux) Wait() error { + m.errCond.L.Lock() + defer m.errCond.L.Unlock() + for m.err == nil { + m.errCond.Wait() + } + return m.err +} + +// newMux returns a mux that runs over the given connection. +func newMux(p packetConn) *mux { + m := &mux{ + conn: p, + incomingChannels: make(chan NewChannel, chanSize), + globalResponses: make(chan interface{}, 1), + incomingRequests: make(chan *Request, chanSize), + errCond: newCond(), + } + if debugMux { + m.chanList.offset = atomic.AddUint32(&globalOff, 1) + } + + go m.loop() + return m +} + +func (m *mux) sendMessage(msg interface{}) error { + p := Marshal(msg) + if debugMux { + log.Printf("send global(%d): %#v", m.chanList.offset, msg) + } + return m.conn.writePacket(p) +} + +func (m *mux) SendRequest(name string, wantReply bool, payload []byte) (bool, []byte, error) { + if wantReply { + m.globalSentMu.Lock() + defer m.globalSentMu.Unlock() + } + + if err := m.sendMessage(globalRequestMsg{ + Type: name, + WantReply: wantReply, + Data: payload, + }); err != nil { + return false, nil, err + } + + if !wantReply { + return false, nil, nil + } + + msg, ok := <-m.globalResponses + if !ok { + return false, nil, io.EOF + } + switch msg := msg.(type) { + case *globalRequestFailureMsg: + return false, msg.Data, nil + case *globalRequestSuccessMsg: + return true, msg.Data, nil + default: + return false, nil, fmt.Errorf("ssh: unexpected response to request: %#v", msg) + } +} + +// ackRequest must be called after processing a global request that +// has WantReply set. +func (m *mux) ackRequest(ok bool, data []byte) error { + if ok { + return m.sendMessage(globalRequestSuccessMsg{Data: data}) + } + return m.sendMessage(globalRequestFailureMsg{Data: data}) +} + +func (m *mux) Close() error { + return m.conn.Close() +} + +// loop runs the connection machine. It will process packets until an +// error is encountered. To synchronize on loop exit, use mux.Wait. +func (m *mux) loop() { + var err error + for err == nil { + err = m.onePacket() + } + + for _, ch := range m.chanList.dropAll() { + ch.close() + } + + close(m.incomingChannels) + close(m.incomingRequests) + close(m.globalResponses) + + m.conn.Close() + + m.errCond.L.Lock() + m.err = err + m.errCond.Broadcast() + m.errCond.L.Unlock() + + if debugMux { + log.Println("loop exit", err) + } +} + +// onePacket reads and processes one packet. +func (m *mux) onePacket() error { + packet, err := m.conn.readPacket() + if err != nil { + return err + } + + if debugMux { + if packet[0] == msgChannelData || packet[0] == msgChannelExtendedData { + log.Printf("decoding(%d): data packet - %d bytes", m.chanList.offset, len(packet)) + } else { + p, _ := decode(packet) + log.Printf("decoding(%d): %d %#v - %d bytes", m.chanList.offset, packet[0], p, len(packet)) + } + } + + switch packet[0] { + case msgChannelOpen: + return m.handleChannelOpen(packet) + case msgGlobalRequest, msgRequestSuccess, msgRequestFailure: + return m.handleGlobalPacket(packet) + } + + // assume a channel packet. + if len(packet) < 5 { + return parseError(packet[0]) + } + id := binary.BigEndian.Uint32(packet[1:]) + ch := m.chanList.getChan(id) + if ch == nil { + return fmt.Errorf("ssh: invalid channel %d", id) + } + + return ch.handlePacket(packet) +} + +func (m *mux) handleGlobalPacket(packet []byte) error { + msg, err := decode(packet) + if err != nil { + return err + } + + switch msg := msg.(type) { + case *globalRequestMsg: + m.incomingRequests <- &Request{ + Type: msg.Type, + WantReply: msg.WantReply, + Payload: msg.Data, + mux: m, + } + case *globalRequestSuccessMsg, *globalRequestFailureMsg: + m.globalResponses <- msg + default: + panic(fmt.Sprintf("not a global message %#v", msg)) + } + + return nil +} + +// handleChannelOpen schedules a channel to be Accept()ed. +func (m *mux) handleChannelOpen(packet []byte) error { + var msg channelOpenMsg + if err := Unmarshal(packet, &msg); err != nil { + return err + } + + if msg.MaxPacketSize < minPacketLength || msg.MaxPacketSize > 1<<31 { + failMsg := channelOpenFailureMsg{ + PeersID: msg.PeersID, + Reason: ConnectionFailed, + Message: "invalid request", + Language: "en_US.UTF-8", + } + return m.sendMessage(failMsg) + } + + c := m.newChannel(msg.ChanType, channelInbound, msg.TypeSpecificData) + c.remoteId = msg.PeersID + c.maxRemotePayload = msg.MaxPacketSize + c.remoteWin.add(msg.PeersWindow) + m.incomingChannels <- c + return nil +} + +func (m *mux) OpenChannel(chanType string, extra []byte) (Channel, <-chan *Request, error) { + ch, err := m.openChannel(chanType, extra) + if err != nil { + return nil, nil, err + } + + return ch, ch.incomingRequests, nil +} + +func (m *mux) openChannel(chanType string, extra []byte) (*channel, error) { + ch := m.newChannel(chanType, channelOutbound, extra) + + ch.maxIncomingPayload = channelMaxPacket + + open := channelOpenMsg{ + ChanType: chanType, + PeersWindow: ch.myWindow, + MaxPacketSize: ch.maxIncomingPayload, + TypeSpecificData: extra, + PeersID: ch.localId, + } + if err := m.sendMessage(open); err != nil { + return nil, err + } + + switch msg := (<-ch.msg).(type) { + case *channelOpenConfirmMsg: + return ch, nil + case *channelOpenFailureMsg: + return nil, &OpenChannelError{msg.Reason, msg.Message} + default: + return nil, fmt.Errorf("ssh: unexpected packet in response to channel open: %T", msg) + } +} diff --git a/vendor/golang.org/x/crypto/ssh/mux_test.go b/vendor/golang.org/x/crypto/ssh/mux_test.go new file mode 100644 index 0000000000000000000000000000000000000000..25d2181d621529f3440418cfd54c2ac405756015 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/mux_test.go @@ -0,0 +1,505 @@ +// 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. + +package ssh + +import ( + "io" + "io/ioutil" + "sync" + "testing" +) + +func muxPair() (*mux, *mux) { + a, b := memPipe() + + s := newMux(a) + c := newMux(b) + + return s, c +} + +// Returns both ends of a channel, and the mux for the the 2nd +// channel. +func channelPair(t *testing.T) (*channel, *channel, *mux) { + c, s := muxPair() + + res := make(chan *channel, 1) + go func() { + newCh, ok := <-s.incomingChannels + if !ok { + t.Fatalf("No incoming channel") + } + if newCh.ChannelType() != "chan" { + t.Fatalf("got type %q want chan", newCh.ChannelType()) + } + ch, _, err := newCh.Accept() + if err != nil { + t.Fatalf("Accept %v", err) + } + res <- ch.(*channel) + }() + + ch, err := c.openChannel("chan", nil) + if err != nil { + t.Fatalf("OpenChannel: %v", err) + } + + return <-res, ch, c +} + +// Test that stderr and stdout can be addressed from different +// goroutines. This is intended for use with the race detector. +func TestMuxChannelExtendedThreadSafety(t *testing.T) { + writer, reader, mux := channelPair(t) + defer writer.Close() + defer reader.Close() + defer mux.Close() + + var wr, rd sync.WaitGroup + magic := "hello world" + + wr.Add(2) + go func() { + io.WriteString(writer, magic) + wr.Done() + }() + go func() { + io.WriteString(writer.Stderr(), magic) + wr.Done() + }() + + rd.Add(2) + go func() { + c, err := ioutil.ReadAll(reader) + if string(c) != magic { + t.Fatalf("stdout read got %q, want %q (error %s)", c, magic, err) + } + rd.Done() + }() + go func() { + c, err := ioutil.ReadAll(reader.Stderr()) + if string(c) != magic { + t.Fatalf("stderr read got %q, want %q (error %s)", c, magic, err) + } + rd.Done() + }() + + wr.Wait() + writer.CloseWrite() + rd.Wait() +} + +func TestMuxReadWrite(t *testing.T) { + s, c, mux := channelPair(t) + defer s.Close() + defer c.Close() + defer mux.Close() + + magic := "hello world" + magicExt := "hello stderr" + go func() { + _, err := s.Write([]byte(magic)) + if err != nil { + t.Fatalf("Write: %v", err) + } + _, err = s.Extended(1).Write([]byte(magicExt)) + if err != nil { + t.Fatalf("Write: %v", err) + } + err = s.Close() + if err != nil { + t.Fatalf("Close: %v", err) + } + }() + + var buf [1024]byte + n, err := c.Read(buf[:]) + if err != nil { + t.Fatalf("server Read: %v", err) + } + got := string(buf[:n]) + if got != magic { + t.Fatalf("server: got %q want %q", got, magic) + } + + n, err = c.Extended(1).Read(buf[:]) + if err != nil { + t.Fatalf("server Read: %v", err) + } + + got = string(buf[:n]) + if got != magicExt { + t.Fatalf("server: got %q want %q", got, magic) + } +} + +func TestMuxChannelOverflow(t *testing.T) { + reader, writer, mux := channelPair(t) + defer reader.Close() + defer writer.Close() + defer mux.Close() + + wDone := make(chan int, 1) + go func() { + if _, err := writer.Write(make([]byte, channelWindowSize)); err != nil { + t.Errorf("could not fill window: %v", err) + } + writer.Write(make([]byte, 1)) + wDone <- 1 + }() + writer.remoteWin.waitWriterBlocked() + + // Send 1 byte. + packet := make([]byte, 1+4+4+1) + packet[0] = msgChannelData + marshalUint32(packet[1:], writer.remoteId) + marshalUint32(packet[5:], uint32(1)) + packet[9] = 42 + + if err := writer.mux.conn.writePacket(packet); err != nil { + t.Errorf("could not send packet") + } + if _, err := reader.SendRequest("hello", true, nil); err == nil { + t.Errorf("SendRequest succeeded.") + } + <-wDone +} + +func TestMuxChannelCloseWriteUnblock(t *testing.T) { + reader, writer, mux := channelPair(t) + defer reader.Close() + defer writer.Close() + defer mux.Close() + + wDone := make(chan int, 1) + go func() { + if _, err := writer.Write(make([]byte, channelWindowSize)); err != nil { + t.Errorf("could not fill window: %v", err) + } + if _, err := writer.Write(make([]byte, 1)); err != io.EOF { + t.Errorf("got %v, want EOF for unblock write", err) + } + wDone <- 1 + }() + + writer.remoteWin.waitWriterBlocked() + reader.Close() + <-wDone +} + +func TestMuxConnectionCloseWriteUnblock(t *testing.T) { + reader, writer, mux := channelPair(t) + defer reader.Close() + defer writer.Close() + defer mux.Close() + + wDone := make(chan int, 1) + go func() { + if _, err := writer.Write(make([]byte, channelWindowSize)); err != nil { + t.Errorf("could not fill window: %v", err) + } + if _, err := writer.Write(make([]byte, 1)); err != io.EOF { + t.Errorf("got %v, want EOF for unblock write", err) + } + wDone <- 1 + }() + + writer.remoteWin.waitWriterBlocked() + mux.Close() + <-wDone +} + +func TestMuxReject(t *testing.T) { + client, server := muxPair() + defer server.Close() + defer client.Close() + + go func() { + ch, ok := <-server.incomingChannels + if !ok { + t.Fatalf("Accept") + } + if ch.ChannelType() != "ch" || string(ch.ExtraData()) != "extra" { + t.Fatalf("unexpected channel: %q, %q", ch.ChannelType(), ch.ExtraData()) + } + ch.Reject(RejectionReason(42), "message") + }() + + ch, err := client.openChannel("ch", []byte("extra")) + if ch != nil { + t.Fatal("openChannel not rejected") + } + + ocf, ok := err.(*OpenChannelError) + if !ok { + t.Errorf("got %#v want *OpenChannelError", err) + } else if ocf.Reason != 42 || ocf.Message != "message" { + t.Errorf("got %#v, want {Reason: 42, Message: %q}", ocf, "message") + } + + want := "ssh: rejected: unknown reason 42 (message)" + if err.Error() != want { + t.Errorf("got %q, want %q", err.Error(), want) + } +} + +func TestMuxChannelRequest(t *testing.T) { + client, server, mux := channelPair(t) + defer server.Close() + defer client.Close() + defer mux.Close() + + var received int + var wg sync.WaitGroup + wg.Add(1) + go func() { + for r := range server.incomingRequests { + received++ + r.Reply(r.Type == "yes", nil) + } + wg.Done() + }() + _, err := client.SendRequest("yes", false, nil) + if err != nil { + t.Fatalf("SendRequest: %v", err) + } + ok, err := client.SendRequest("yes", true, nil) + if err != nil { + t.Fatalf("SendRequest: %v", err) + } + + if !ok { + t.Errorf("SendRequest(yes): %v", ok) + + } + + ok, err = client.SendRequest("no", true, nil) + if err != nil { + t.Fatalf("SendRequest: %v", err) + } + if ok { + t.Errorf("SendRequest(no): %v", ok) + + } + + client.Close() + wg.Wait() + + if received != 3 { + t.Errorf("got %d requests, want %d", received, 3) + } +} + +func TestMuxGlobalRequest(t *testing.T) { + clientMux, serverMux := muxPair() + defer serverMux.Close() + defer clientMux.Close() + + var seen bool + go func() { + for r := range serverMux.incomingRequests { + seen = seen || r.Type == "peek" + if r.WantReply { + err := r.Reply(r.Type == "yes", + append([]byte(r.Type), r.Payload...)) + if err != nil { + t.Errorf("AckRequest: %v", err) + } + } + } + }() + + _, _, err := clientMux.SendRequest("peek", false, nil) + if err != nil { + t.Errorf("SendRequest: %v", err) + } + + ok, data, err := clientMux.SendRequest("yes", true, []byte("a")) + if !ok || string(data) != "yesa" || err != nil { + t.Errorf("SendRequest(\"yes\", true, \"a\"): %v %v %v", + ok, data, err) + } + if ok, data, err := clientMux.SendRequest("yes", true, []byte("a")); !ok || string(data) != "yesa" || err != nil { + t.Errorf("SendRequest(\"yes\", true, \"a\"): %v %v %v", + ok, data, err) + } + + if ok, data, err := clientMux.SendRequest("no", true, []byte("a")); ok || string(data) != "noa" || err != nil { + t.Errorf("SendRequest(\"no\", true, \"a\"): %v %v %v", + ok, data, err) + } + + if !seen { + t.Errorf("never saw 'peek' request") + } +} + +func TestMuxGlobalRequestUnblock(t *testing.T) { + clientMux, serverMux := muxPair() + defer serverMux.Close() + defer clientMux.Close() + + result := make(chan error, 1) + go func() { + _, _, err := clientMux.SendRequest("hello", true, nil) + result <- err + }() + + <-serverMux.incomingRequests + serverMux.conn.Close() + err := <-result + + if err != io.EOF { + t.Errorf("want EOF, got %v", io.EOF) + } +} + +func TestMuxChannelRequestUnblock(t *testing.T) { + a, b, connB := channelPair(t) + defer a.Close() + defer b.Close() + defer connB.Close() + + result := make(chan error, 1) + go func() { + _, err := a.SendRequest("hello", true, nil) + result <- err + }() + + <-b.incomingRequests + connB.conn.Close() + err := <-result + + if err != io.EOF { + t.Errorf("want EOF, got %v", err) + } +} + +func TestMuxCloseChannel(t *testing.T) { + r, w, mux := channelPair(t) + defer mux.Close() + defer r.Close() + defer w.Close() + + result := make(chan error, 1) + go func() { + var b [1024]byte + _, err := r.Read(b[:]) + result <- err + }() + if err := w.Close(); err != nil { + t.Errorf("w.Close: %v", err) + } + + if _, err := w.Write([]byte("hello")); err != io.EOF { + t.Errorf("got err %v, want io.EOF after Close", err) + } + + if err := <-result; err != io.EOF { + t.Errorf("got %v (%T), want io.EOF", err, err) + } +} + +func TestMuxCloseWriteChannel(t *testing.T) { + r, w, mux := channelPair(t) + defer mux.Close() + + result := make(chan error, 1) + go func() { + var b [1024]byte + _, err := r.Read(b[:]) + result <- err + }() + if err := w.CloseWrite(); err != nil { + t.Errorf("w.CloseWrite: %v", err) + } + + if _, err := w.Write([]byte("hello")); err != io.EOF { + t.Errorf("got err %v, want io.EOF after CloseWrite", err) + } + + if err := <-result; err != io.EOF { + t.Errorf("got %v (%T), want io.EOF", err, err) + } +} + +func TestMuxInvalidRecord(t *testing.T) { + a, b := muxPair() + defer a.Close() + defer b.Close() + + packet := make([]byte, 1+4+4+1) + packet[0] = msgChannelData + marshalUint32(packet[1:], 29348723 /* invalid channel id */) + marshalUint32(packet[5:], 1) + packet[9] = 42 + + a.conn.writePacket(packet) + go a.SendRequest("hello", false, nil) + // 'a' wrote an invalid packet, so 'b' has exited. + req, ok := <-b.incomingRequests + if ok { + t.Errorf("got request %#v after receiving invalid packet", req) + } +} + +func TestZeroWindowAdjust(t *testing.T) { + a, b, mux := channelPair(t) + defer a.Close() + defer b.Close() + defer mux.Close() + + go func() { + io.WriteString(a, "hello") + // bogus adjust. + a.sendMessage(windowAdjustMsg{}) + io.WriteString(a, "world") + a.Close() + }() + + want := "helloworld" + c, _ := ioutil.ReadAll(b) + if string(c) != want { + t.Errorf("got %q want %q", c, want) + } +} + +func TestMuxMaxPacketSize(t *testing.T) { + a, b, mux := channelPair(t) + defer a.Close() + defer b.Close() + defer mux.Close() + + large := make([]byte, a.maxRemotePayload+1) + packet := make([]byte, 1+4+4+1+len(large)) + packet[0] = msgChannelData + marshalUint32(packet[1:], a.remoteId) + marshalUint32(packet[5:], uint32(len(large))) + packet[9] = 42 + + if err := a.mux.conn.writePacket(packet); err != nil { + t.Errorf("could not send packet") + } + + go a.SendRequest("hello", false, nil) + + _, ok := <-b.incomingRequests + if ok { + t.Errorf("connection still alive after receiving large packet.") + } +} + +// Don't ship code with debug=true. +func TestDebug(t *testing.T) { + if debugMux { + t.Error("mux debug switched on") + } + if debugHandshake { + t.Error("handshake debug switched on") + } + if debugTransport { + t.Error("transport debug switched on") + } +} diff --git a/vendor/golang.org/x/crypto/ssh/server.go b/vendor/golang.org/x/crypto/ssh/server.go new file mode 100644 index 0000000000000000000000000000000000000000..b83d47388853b567d99d03714728ec8bd699f5cf --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/server.go @@ -0,0 +1,582 @@ +// 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 ssh + +import ( + "bytes" + "errors" + "fmt" + "io" + "net" + "strings" +) + +// The Permissions type holds fine-grained permissions that are +// specific to a user or a specific authentication method for a user. +// The Permissions value for a successful authentication attempt is +// available in ServerConn, so it can be used to pass information from +// the user-authentication phase to the application layer. +type Permissions struct { + // CriticalOptions indicate restrictions to the default + // permissions, and are typically used in conjunction with + // user certificates. The standard for SSH certificates + // defines "force-command" (only allow the given command to + // execute) and "source-address" (only allow connections from + // the given address). The SSH package currently only enforces + // the "source-address" critical option. It is up to server + // implementations to enforce other critical options, such as + // "force-command", by checking them after the SSH handshake + // is successful. In general, SSH servers should reject + // connections that specify critical options that are unknown + // or not supported. + CriticalOptions map[string]string + + // Extensions are extra functionality that the server may + // offer on authenticated connections. Lack of support for an + // extension does not preclude authenticating a user. Common + // extensions are "permit-agent-forwarding", + // "permit-X11-forwarding". The Go SSH library currently does + // not act on any extension, and it is up to server + // implementations to honor them. Extensions can be used to + // pass data from the authentication callbacks to the server + // application layer. + Extensions map[string]string +} + +// ServerConfig holds server specific configuration data. +type ServerConfig struct { + // Config contains configuration shared between client and server. + Config + + hostKeys []Signer + + // NoClientAuth is true if clients are allowed to connect without + // authenticating. + NoClientAuth bool + + // MaxAuthTries specifies the maximum number of authentication attempts + // permitted per connection. If set to a negative number, the number of + // attempts are unlimited. If set to zero, the number of attempts are limited + // to 6. + MaxAuthTries int + + // PasswordCallback, if non-nil, is called when a user + // attempts to authenticate using a password. + PasswordCallback func(conn ConnMetadata, password []byte) (*Permissions, error) + + // PublicKeyCallback, if non-nil, is called when a client + // offers a public key for authentication. It must return a nil error + // if the given public key can be used to authenticate the + // given user. For example, see CertChecker.Authenticate. A + // call to this function does not guarantee that the key + // offered is in fact used to authenticate. To record any data + // depending on the public key, store it inside a + // Permissions.Extensions entry. + PublicKeyCallback func(conn ConnMetadata, key PublicKey) (*Permissions, error) + + // KeyboardInteractiveCallback, if non-nil, is called when + // keyboard-interactive authentication is selected (RFC + // 4256). The client object's Challenge function should be + // used to query the user. The callback may offer multiple + // Challenge rounds. To avoid information leaks, the client + // should be presented a challenge even if the user is + // unknown. + KeyboardInteractiveCallback func(conn ConnMetadata, client KeyboardInteractiveChallenge) (*Permissions, error) + + // AuthLogCallback, if non-nil, is called to log all authentication + // attempts. + AuthLogCallback func(conn ConnMetadata, method string, err error) + + // ServerVersion is the version identification string to announce in + // the public handshake. + // If empty, a reasonable default is used. + // Note that RFC 4253 section 4.2 requires that this string start with + // "SSH-2.0-". + ServerVersion string + + // BannerCallback, if present, is called and the return string is sent to + // the client after key exchange completed but before authentication. + BannerCallback func(conn ConnMetadata) string +} + +// AddHostKey adds a private key as a host key. If an existing host +// key exists with the same algorithm, it is overwritten. Each server +// config must have at least one host key. +func (s *ServerConfig) AddHostKey(key Signer) { + for i, k := range s.hostKeys { + if k.PublicKey().Type() == key.PublicKey().Type() { + s.hostKeys[i] = key + return + } + } + + s.hostKeys = append(s.hostKeys, key) +} + +// cachedPubKey contains the results of querying whether a public key is +// acceptable for a user. +type cachedPubKey struct { + user string + pubKeyData []byte + result error + perms *Permissions +} + +const maxCachedPubKeys = 16 + +// pubKeyCache caches tests for public keys. Since SSH clients +// will query whether a public key is acceptable before attempting to +// authenticate with it, we end up with duplicate queries for public +// key validity. The cache only applies to a single ServerConn. +type pubKeyCache struct { + keys []cachedPubKey +} + +// get returns the result for a given user/algo/key tuple. +func (c *pubKeyCache) get(user string, pubKeyData []byte) (cachedPubKey, bool) { + for _, k := range c.keys { + if k.user == user && bytes.Equal(k.pubKeyData, pubKeyData) { + return k, true + } + } + return cachedPubKey{}, false +} + +// add adds the given tuple to the cache. +func (c *pubKeyCache) add(candidate cachedPubKey) { + if len(c.keys) < maxCachedPubKeys { + c.keys = append(c.keys, candidate) + } +} + +// ServerConn is an authenticated SSH connection, as seen from the +// server +type ServerConn struct { + Conn + + // If the succeeding authentication callback returned a + // non-nil Permissions pointer, it is stored here. + Permissions *Permissions +} + +// NewServerConn starts a new SSH server with c as the underlying +// transport. It starts with a handshake and, if the handshake is +// unsuccessful, it closes the connection and returns an error. The +// Request and NewChannel channels must be serviced, or the connection +// will hang. +func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewChannel, <-chan *Request, error) { + fullConf := *config + fullConf.SetDefaults() + if fullConf.MaxAuthTries == 0 { + fullConf.MaxAuthTries = 6 + } + + s := &connection{ + sshConn: sshConn{conn: c}, + } + perms, err := s.serverHandshake(&fullConf) + if err != nil { + c.Close() + return nil, nil, nil, err + } + return &ServerConn{s, perms}, s.mux.incomingChannels, s.mux.incomingRequests, nil +} + +// signAndMarshal signs the data with the appropriate algorithm, +// and serializes the result in SSH wire format. +func signAndMarshal(k Signer, rand io.Reader, data []byte) ([]byte, error) { + sig, err := k.Sign(rand, data) + if err != nil { + return nil, err + } + + return Marshal(sig), nil +} + +// handshake performs key exchange and user authentication. +func (s *connection) serverHandshake(config *ServerConfig) (*Permissions, error) { + if len(config.hostKeys) == 0 { + return nil, errors.New("ssh: server has no host keys") + } + + if !config.NoClientAuth && config.PasswordCallback == nil && config.PublicKeyCallback == nil && config.KeyboardInteractiveCallback == nil { + return nil, errors.New("ssh: no authentication methods configured but NoClientAuth is also false") + } + + if config.ServerVersion != "" { + s.serverVersion = []byte(config.ServerVersion) + } else { + s.serverVersion = []byte(packageVersion) + } + var err error + s.clientVersion, err = exchangeVersions(s.sshConn.conn, s.serverVersion) + if err != nil { + return nil, err + } + + tr := newTransport(s.sshConn.conn, config.Rand, false /* not client */) + s.transport = newServerTransport(tr, s.clientVersion, s.serverVersion, config) + + if err := s.transport.waitSession(); err != nil { + return nil, err + } + + // We just did the key change, so the session ID is established. + s.sessionID = s.transport.getSessionID() + + var packet []byte + if packet, err = s.transport.readPacket(); err != nil { + return nil, err + } + + var serviceRequest serviceRequestMsg + if err = Unmarshal(packet, &serviceRequest); err != nil { + return nil, err + } + if serviceRequest.Service != serviceUserAuth { + return nil, errors.New("ssh: requested service '" + serviceRequest.Service + "' before authenticating") + } + serviceAccept := serviceAcceptMsg{ + Service: serviceUserAuth, + } + if err := s.transport.writePacket(Marshal(&serviceAccept)); err != nil { + return nil, err + } + + perms, err := s.serverAuthenticate(config) + if err != nil { + return nil, err + } + s.mux = newMux(s.transport) + return perms, err +} + +func isAcceptableAlgo(algo string) bool { + switch algo { + case KeyAlgoRSA, KeyAlgoDSA, KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, KeyAlgoED25519, + CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoED25519v01: + return true + } + return false +} + +func checkSourceAddress(addr net.Addr, sourceAddrs string) error { + if addr == nil { + return errors.New("ssh: no address known for client, but source-address match required") + } + + tcpAddr, ok := addr.(*net.TCPAddr) + if !ok { + return fmt.Errorf("ssh: remote address %v is not an TCP address when checking source-address match", addr) + } + + for _, sourceAddr := range strings.Split(sourceAddrs, ",") { + if allowedIP := net.ParseIP(sourceAddr); allowedIP != nil { + if allowedIP.Equal(tcpAddr.IP) { + return nil + } + } else { + _, ipNet, err := net.ParseCIDR(sourceAddr) + if err != nil { + return fmt.Errorf("ssh: error parsing source-address restriction %q: %v", sourceAddr, err) + } + + if ipNet.Contains(tcpAddr.IP) { + return nil + } + } + } + + return fmt.Errorf("ssh: remote address %v is not allowed because of source-address restriction", addr) +} + +// ServerAuthError implements the error interface. It appends any authentication +// errors that may occur, and is returned if all of the authentication methods +// provided by the user failed to authenticate. +type ServerAuthError struct { + // Errors contains authentication errors returned by the authentication + // callback methods. + Errors []error +} + +func (l ServerAuthError) Error() string { + var errs []string + for _, err := range l.Errors { + errs = append(errs, err.Error()) + } + return "[" + strings.Join(errs, ", ") + "]" +} + +func (s *connection) serverAuthenticate(config *ServerConfig) (*Permissions, error) { + sessionID := s.transport.getSessionID() + var cache pubKeyCache + var perms *Permissions + + authFailures := 0 + var authErrs []error + var displayedBanner bool + +userAuthLoop: + for { + if authFailures >= config.MaxAuthTries && config.MaxAuthTries > 0 { + discMsg := &disconnectMsg{ + Reason: 2, + Message: "too many authentication failures", + } + + if err := s.transport.writePacket(Marshal(discMsg)); err != nil { + return nil, err + } + + return nil, discMsg + } + + var userAuthReq userAuthRequestMsg + if packet, err := s.transport.readPacket(); err != nil { + if err == io.EOF { + return nil, &ServerAuthError{Errors: authErrs} + } + return nil, err + } else if err = Unmarshal(packet, &userAuthReq); err != nil { + return nil, err + } + + if userAuthReq.Service != serviceSSH { + return nil, errors.New("ssh: client attempted to negotiate for unknown service: " + userAuthReq.Service) + } + + s.user = userAuthReq.User + + if !displayedBanner && config.BannerCallback != nil { + displayedBanner = true + msg := config.BannerCallback(s) + if msg != "" { + bannerMsg := &userAuthBannerMsg{ + Message: msg, + } + if err := s.transport.writePacket(Marshal(bannerMsg)); err != nil { + return nil, err + } + } + } + + perms = nil + authErr := errors.New("no auth passed yet") + + switch userAuthReq.Method { + case "none": + if config.NoClientAuth { + authErr = nil + } + + // allow initial attempt of 'none' without penalty + if authFailures == 0 { + authFailures-- + } + case "password": + if config.PasswordCallback == nil { + authErr = errors.New("ssh: password auth not configured") + break + } + payload := userAuthReq.Payload + if len(payload) < 1 || payload[0] != 0 { + return nil, parseError(msgUserAuthRequest) + } + payload = payload[1:] + password, payload, ok := parseString(payload) + if !ok || len(payload) > 0 { + return nil, parseError(msgUserAuthRequest) + } + + perms, authErr = config.PasswordCallback(s, password) + case "keyboard-interactive": + if config.KeyboardInteractiveCallback == nil { + authErr = errors.New("ssh: keyboard-interactive auth not configubred") + break + } + + prompter := &sshClientKeyboardInteractive{s} + perms, authErr = config.KeyboardInteractiveCallback(s, prompter.Challenge) + case "publickey": + if config.PublicKeyCallback == nil { + authErr = errors.New("ssh: publickey auth not configured") + break + } + payload := userAuthReq.Payload + if len(payload) < 1 { + return nil, parseError(msgUserAuthRequest) + } + isQuery := payload[0] == 0 + payload = payload[1:] + algoBytes, payload, ok := parseString(payload) + if !ok { + return nil, parseError(msgUserAuthRequest) + } + algo := string(algoBytes) + if !isAcceptableAlgo(algo) { + authErr = fmt.Errorf("ssh: algorithm %q not accepted", algo) + break + } + + pubKeyData, payload, ok := parseString(payload) + if !ok { + return nil, parseError(msgUserAuthRequest) + } + + pubKey, err := ParsePublicKey(pubKeyData) + if err != nil { + return nil, err + } + + candidate, ok := cache.get(s.user, pubKeyData) + if !ok { + candidate.user = s.user + candidate.pubKeyData = pubKeyData + candidate.perms, candidate.result = config.PublicKeyCallback(s, pubKey) + if candidate.result == nil && candidate.perms != nil && candidate.perms.CriticalOptions != nil && candidate.perms.CriticalOptions[sourceAddressCriticalOption] != "" { + candidate.result = checkSourceAddress( + s.RemoteAddr(), + candidate.perms.CriticalOptions[sourceAddressCriticalOption]) + } + cache.add(candidate) + } + + if isQuery { + // The client can query if the given public key + // would be okay. + + if len(payload) > 0 { + return nil, parseError(msgUserAuthRequest) + } + + if candidate.result == nil { + okMsg := userAuthPubKeyOkMsg{ + Algo: algo, + PubKey: pubKeyData, + } + if err = s.transport.writePacket(Marshal(&okMsg)); err != nil { + return nil, err + } + continue userAuthLoop + } + authErr = candidate.result + } else { + sig, payload, ok := parseSignature(payload) + if !ok || len(payload) > 0 { + return nil, parseError(msgUserAuthRequest) + } + // Ensure the public key algo and signature algo + // are supported. Compare the private key + // algorithm name that corresponds to algo with + // sig.Format. This is usually the same, but + // for certs, the names differ. + if !isAcceptableAlgo(sig.Format) { + break + } + signedData := buildDataSignedForAuth(sessionID, userAuthReq, algoBytes, pubKeyData) + + if err := pubKey.Verify(signedData, sig); err != nil { + return nil, err + } + + authErr = candidate.result + perms = candidate.perms + } + default: + authErr = fmt.Errorf("ssh: unknown method %q", userAuthReq.Method) + } + + authErrs = append(authErrs, authErr) + + if config.AuthLogCallback != nil { + config.AuthLogCallback(s, userAuthReq.Method, authErr) + } + + if authErr == nil { + break userAuthLoop + } + + authFailures++ + + var failureMsg userAuthFailureMsg + if config.PasswordCallback != nil { + failureMsg.Methods = append(failureMsg.Methods, "password") + } + if config.PublicKeyCallback != nil { + failureMsg.Methods = append(failureMsg.Methods, "publickey") + } + if config.KeyboardInteractiveCallback != nil { + failureMsg.Methods = append(failureMsg.Methods, "keyboard-interactive") + } + + if len(failureMsg.Methods) == 0 { + return nil, errors.New("ssh: no authentication methods configured but NoClientAuth is also false") + } + + if err := s.transport.writePacket(Marshal(&failureMsg)); err != nil { + return nil, err + } + } + + if err := s.transport.writePacket([]byte{msgUserAuthSuccess}); err != nil { + return nil, err + } + return perms, nil +} + +// sshClientKeyboardInteractive implements a ClientKeyboardInteractive by +// asking the client on the other side of a ServerConn. +type sshClientKeyboardInteractive struct { + *connection +} + +func (c *sshClientKeyboardInteractive) Challenge(user, instruction string, questions []string, echos []bool) (answers []string, err error) { + if len(questions) != len(echos) { + return nil, errors.New("ssh: echos and questions must have equal length") + } + + var prompts []byte + for i := range questions { + prompts = appendString(prompts, questions[i]) + prompts = appendBool(prompts, echos[i]) + } + + if err := c.transport.writePacket(Marshal(&userAuthInfoRequestMsg{ + Instruction: instruction, + NumPrompts: uint32(len(questions)), + Prompts: prompts, + })); err != nil { + return nil, err + } + + packet, err := c.transport.readPacket() + if err != nil { + return nil, err + } + if packet[0] != msgUserAuthInfoResponse { + return nil, unexpectedMessageError(msgUserAuthInfoResponse, packet[0]) + } + packet = packet[1:] + + n, packet, ok := parseUint32(packet) + if !ok || int(n) != len(questions) { + return nil, parseError(msgUserAuthInfoResponse) + } + + for i := uint32(0); i < n; i++ { + ans, rest, ok := parseString(packet) + if !ok { + return nil, parseError(msgUserAuthInfoResponse) + } + + answers = append(answers, string(ans)) + packet = rest + } + if len(packet) != 0 { + return nil, errors.New("ssh: junk at end of message") + } + + return answers, nil +} diff --git a/vendor/golang.org/x/crypto/ssh/session.go b/vendor/golang.org/x/crypto/ssh/session.go new file mode 100644 index 0000000000000000000000000000000000000000..d3321f6b784b580fddbd7d3f1d4a6ca21b42e497 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/session.go @@ -0,0 +1,647 @@ +// 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 ssh + +// Session implements an interactive session described in +// "RFC 4254, section 6". + +import ( + "bytes" + "encoding/binary" + "errors" + "fmt" + "io" + "io/ioutil" + "sync" +) + +type Signal string + +// POSIX signals as listed in RFC 4254 Section 6.10. +const ( + SIGABRT Signal = "ABRT" + SIGALRM Signal = "ALRM" + SIGFPE Signal = "FPE" + SIGHUP Signal = "HUP" + SIGILL Signal = "ILL" + SIGINT Signal = "INT" + SIGKILL Signal = "KILL" + SIGPIPE Signal = "PIPE" + SIGQUIT Signal = "QUIT" + SIGSEGV Signal = "SEGV" + SIGTERM Signal = "TERM" + SIGUSR1 Signal = "USR1" + SIGUSR2 Signal = "USR2" +) + +var signals = map[Signal]int{ + SIGABRT: 6, + SIGALRM: 14, + SIGFPE: 8, + SIGHUP: 1, + SIGILL: 4, + SIGINT: 2, + SIGKILL: 9, + SIGPIPE: 13, + SIGQUIT: 3, + SIGSEGV: 11, + SIGTERM: 15, +} + +type TerminalModes map[uint8]uint32 + +// POSIX terminal mode flags as listed in RFC 4254 Section 8. +const ( + tty_OP_END = 0 + VINTR = 1 + VQUIT = 2 + VERASE = 3 + VKILL = 4 + VEOF = 5 + VEOL = 6 + VEOL2 = 7 + VSTART = 8 + VSTOP = 9 + VSUSP = 10 + VDSUSP = 11 + VREPRINT = 12 + VWERASE = 13 + VLNEXT = 14 + VFLUSH = 15 + VSWTCH = 16 + VSTATUS = 17 + VDISCARD = 18 + IGNPAR = 30 + PARMRK = 31 + INPCK = 32 + ISTRIP = 33 + INLCR = 34 + IGNCR = 35 + ICRNL = 36 + IUCLC = 37 + IXON = 38 + IXANY = 39 + IXOFF = 40 + IMAXBEL = 41 + ISIG = 50 + ICANON = 51 + XCASE = 52 + ECHO = 53 + ECHOE = 54 + ECHOK = 55 + ECHONL = 56 + NOFLSH = 57 + TOSTOP = 58 + IEXTEN = 59 + ECHOCTL = 60 + ECHOKE = 61 + PENDIN = 62 + OPOST = 70 + OLCUC = 71 + ONLCR = 72 + OCRNL = 73 + ONOCR = 74 + ONLRET = 75 + CS7 = 90 + CS8 = 91 + PARENB = 92 + PARODD = 93 + TTY_OP_ISPEED = 128 + TTY_OP_OSPEED = 129 +) + +// A Session represents a connection to a remote command or shell. +type Session struct { + // Stdin specifies the remote process's standard input. + // If Stdin is nil, the remote process reads from an empty + // bytes.Buffer. + Stdin io.Reader + + // Stdout and Stderr specify the remote process's standard + // output and error. + // + // If either is nil, Run connects the corresponding file + // descriptor to an instance of ioutil.Discard. There is a + // fixed amount of buffering that is shared for the two streams. + // If either blocks it may eventually cause the remote + // command to block. + Stdout io.Writer + Stderr io.Writer + + ch Channel // the channel backing this session + started bool // true once Start, Run or Shell is invoked. + copyFuncs []func() error + errors chan error // one send per copyFunc + + // true if pipe method is active + stdinpipe, stdoutpipe, stderrpipe bool + + // stdinPipeWriter is non-nil if StdinPipe has not been called + // and Stdin was specified by the user; it is the write end of + // a pipe connecting Session.Stdin to the stdin channel. + stdinPipeWriter io.WriteCloser + + exitStatus chan error +} + +// SendRequest sends an out-of-band channel request on the SSH channel +// underlying the session. +func (s *Session) SendRequest(name string, wantReply bool, payload []byte) (bool, error) { + return s.ch.SendRequest(name, wantReply, payload) +} + +func (s *Session) Close() error { + return s.ch.Close() +} + +// RFC 4254 Section 6.4. +type setenvRequest struct { + Name string + Value string +} + +// Setenv sets an environment variable that will be applied to any +// command executed by Shell or Run. +func (s *Session) Setenv(name, value string) error { + msg := setenvRequest{ + Name: name, + Value: value, + } + ok, err := s.ch.SendRequest("env", true, Marshal(&msg)) + if err == nil && !ok { + err = errors.New("ssh: setenv failed") + } + return err +} + +// RFC 4254 Section 6.2. +type ptyRequestMsg struct { + Term string + Columns uint32 + Rows uint32 + Width uint32 + Height uint32 + Modelist string +} + +// RequestPty requests the association of a pty with the session on the remote host. +func (s *Session) RequestPty(term string, h, w int, termmodes TerminalModes) error { + var tm []byte + for k, v := range termmodes { + kv := struct { + Key byte + Val uint32 + }{k, v} + + tm = append(tm, Marshal(&kv)...) + } + tm = append(tm, tty_OP_END) + req := ptyRequestMsg{ + Term: term, + Columns: uint32(w), + Rows: uint32(h), + Width: uint32(w * 8), + Height: uint32(h * 8), + Modelist: string(tm), + } + ok, err := s.ch.SendRequest("pty-req", true, Marshal(&req)) + if err == nil && !ok { + err = errors.New("ssh: pty-req failed") + } + return err +} + +// RFC 4254 Section 6.5. +type subsystemRequestMsg struct { + Subsystem string +} + +// RequestSubsystem requests the association of a subsystem with the session on the remote host. +// A subsystem is a predefined command that runs in the background when the ssh session is initiated +func (s *Session) RequestSubsystem(subsystem string) error { + msg := subsystemRequestMsg{ + Subsystem: subsystem, + } + ok, err := s.ch.SendRequest("subsystem", true, Marshal(&msg)) + if err == nil && !ok { + err = errors.New("ssh: subsystem request failed") + } + return err +} + +// RFC 4254 Section 6.7. +type ptyWindowChangeMsg struct { + Columns uint32 + Rows uint32 + Width uint32 + Height uint32 +} + +// WindowChange informs the remote host about a terminal window dimension change to h rows and w columns. +func (s *Session) WindowChange(h, w int) error { + req := ptyWindowChangeMsg{ + Columns: uint32(w), + Rows: uint32(h), + Width: uint32(w * 8), + Height: uint32(h * 8), + } + _, err := s.ch.SendRequest("window-change", false, Marshal(&req)) + return err +} + +// RFC 4254 Section 6.9. +type signalMsg struct { + Signal string +} + +// Signal sends the given signal to the remote process. +// sig is one of the SIG* constants. +func (s *Session) Signal(sig Signal) error { + msg := signalMsg{ + Signal: string(sig), + } + + _, err := s.ch.SendRequest("signal", false, Marshal(&msg)) + return err +} + +// RFC 4254 Section 6.5. +type execMsg struct { + Command string +} + +// Start runs cmd on the remote host. Typically, the remote +// server passes cmd to the shell for interpretation. +// A Session only accepts one call to Run, Start or Shell. +func (s *Session) Start(cmd string) error { + if s.started { + return errors.New("ssh: session already started") + } + req := execMsg{ + Command: cmd, + } + + ok, err := s.ch.SendRequest("exec", true, Marshal(&req)) + if err == nil && !ok { + err = fmt.Errorf("ssh: command %v failed", cmd) + } + if err != nil { + return err + } + return s.start() +} + +// Run runs cmd on the remote host. Typically, the remote +// server passes cmd to the shell for interpretation. +// A Session only accepts one call to Run, Start, Shell, Output, +// or CombinedOutput. +// +// The returned error is nil if the command runs, has no problems +// copying stdin, stdout, and stderr, and exits with a zero exit +// status. +// +// If the remote server does not send an exit status, an error of type +// *ExitMissingError is returned. If the command completes +// unsuccessfully or is interrupted by a signal, the error is of type +// *ExitError. Other error types may be returned for I/O problems. +func (s *Session) Run(cmd string) error { + err := s.Start(cmd) + if err != nil { + return err + } + return s.Wait() +} + +// Output runs cmd on the remote host and returns its standard output. +func (s *Session) Output(cmd string) ([]byte, error) { + if s.Stdout != nil { + return nil, errors.New("ssh: Stdout already set") + } + var b bytes.Buffer + s.Stdout = &b + err := s.Run(cmd) + return b.Bytes(), err +} + +type singleWriter struct { + b bytes.Buffer + mu sync.Mutex +} + +func (w *singleWriter) Write(p []byte) (int, error) { + w.mu.Lock() + defer w.mu.Unlock() + return w.b.Write(p) +} + +// CombinedOutput runs cmd on the remote host and returns its combined +// standard output and standard error. +func (s *Session) CombinedOutput(cmd string) ([]byte, error) { + if s.Stdout != nil { + return nil, errors.New("ssh: Stdout already set") + } + if s.Stderr != nil { + return nil, errors.New("ssh: Stderr already set") + } + var b singleWriter + s.Stdout = &b + s.Stderr = &b + err := s.Run(cmd) + return b.b.Bytes(), err +} + +// Shell starts a login shell on the remote host. A Session only +// accepts one call to Run, Start, Shell, Output, or CombinedOutput. +func (s *Session) Shell() error { + if s.started { + return errors.New("ssh: session already started") + } + + ok, err := s.ch.SendRequest("shell", true, nil) + if err == nil && !ok { + return errors.New("ssh: could not start shell") + } + if err != nil { + return err + } + return s.start() +} + +func (s *Session) start() error { + s.started = true + + type F func(*Session) + for _, setupFd := range []F{(*Session).stdin, (*Session).stdout, (*Session).stderr} { + setupFd(s) + } + + s.errors = make(chan error, len(s.copyFuncs)) + for _, fn := range s.copyFuncs { + go func(fn func() error) { + s.errors <- fn() + }(fn) + } + return nil +} + +// Wait waits for the remote command to exit. +// +// The returned error is nil if the command runs, has no problems +// copying stdin, stdout, and stderr, and exits with a zero exit +// status. +// +// If the remote server does not send an exit status, an error of type +// *ExitMissingError is returned. If the command completes +// unsuccessfully or is interrupted by a signal, the error is of type +// *ExitError. Other error types may be returned for I/O problems. +func (s *Session) Wait() error { + if !s.started { + return errors.New("ssh: session not started") + } + waitErr := <-s.exitStatus + + if s.stdinPipeWriter != nil { + s.stdinPipeWriter.Close() + } + var copyError error + for range s.copyFuncs { + if err := <-s.errors; err != nil && copyError == nil { + copyError = err + } + } + if waitErr != nil { + return waitErr + } + return copyError +} + +func (s *Session) wait(reqs <-chan *Request) error { + wm := Waitmsg{status: -1} + // Wait for msg channel to be closed before returning. + for msg := range reqs { + switch msg.Type { + case "exit-status": + wm.status = int(binary.BigEndian.Uint32(msg.Payload)) + case "exit-signal": + var sigval struct { + Signal string + CoreDumped bool + Error string + Lang string + } + if err := Unmarshal(msg.Payload, &sigval); err != nil { + return err + } + + // Must sanitize strings? + wm.signal = sigval.Signal + wm.msg = sigval.Error + wm.lang = sigval.Lang + default: + // This handles keepalives and matches + // OpenSSH's behaviour. + if msg.WantReply { + msg.Reply(false, nil) + } + } + } + if wm.status == 0 { + return nil + } + if wm.status == -1 { + // exit-status was never sent from server + if wm.signal == "" { + // signal was not sent either. RFC 4254 + // section 6.10 recommends against this + // behavior, but it is allowed, so we let + // clients handle it. + return &ExitMissingError{} + } + wm.status = 128 + if _, ok := signals[Signal(wm.signal)]; ok { + wm.status += signals[Signal(wm.signal)] + } + } + + return &ExitError{wm} +} + +// ExitMissingError is returned if a session is torn down cleanly, but +// the server sends no confirmation of the exit status. +type ExitMissingError struct{} + +func (e *ExitMissingError) Error() string { + return "wait: remote command exited without exit status or exit signal" +} + +func (s *Session) stdin() { + if s.stdinpipe { + return + } + var stdin io.Reader + if s.Stdin == nil { + stdin = new(bytes.Buffer) + } else { + r, w := io.Pipe() + go func() { + _, err := io.Copy(w, s.Stdin) + w.CloseWithError(err) + }() + stdin, s.stdinPipeWriter = r, w + } + s.copyFuncs = append(s.copyFuncs, func() error { + _, err := io.Copy(s.ch, stdin) + if err1 := s.ch.CloseWrite(); err == nil && err1 != io.EOF { + err = err1 + } + return err + }) +} + +func (s *Session) stdout() { + if s.stdoutpipe { + return + } + if s.Stdout == nil { + s.Stdout = ioutil.Discard + } + s.copyFuncs = append(s.copyFuncs, func() error { + _, err := io.Copy(s.Stdout, s.ch) + return err + }) +} + +func (s *Session) stderr() { + if s.stderrpipe { + return + } + if s.Stderr == nil { + s.Stderr = ioutil.Discard + } + s.copyFuncs = append(s.copyFuncs, func() error { + _, err := io.Copy(s.Stderr, s.ch.Stderr()) + return err + }) +} + +// sessionStdin reroutes Close to CloseWrite. +type sessionStdin struct { + io.Writer + ch Channel +} + +func (s *sessionStdin) Close() error { + return s.ch.CloseWrite() +} + +// StdinPipe returns a pipe that will be connected to the +// remote command's standard input when the command starts. +func (s *Session) StdinPipe() (io.WriteCloser, error) { + if s.Stdin != nil { + return nil, errors.New("ssh: Stdin already set") + } + if s.started { + return nil, errors.New("ssh: StdinPipe after process started") + } + s.stdinpipe = true + return &sessionStdin{s.ch, s.ch}, nil +} + +// StdoutPipe returns a pipe that will be connected to the +// remote command's standard output when the command starts. +// There is a fixed amount of buffering that is shared between +// stdout and stderr streams. If the StdoutPipe reader is +// not serviced fast enough it may eventually cause the +// remote command to block. +func (s *Session) StdoutPipe() (io.Reader, error) { + if s.Stdout != nil { + return nil, errors.New("ssh: Stdout already set") + } + if s.started { + return nil, errors.New("ssh: StdoutPipe after process started") + } + s.stdoutpipe = true + return s.ch, nil +} + +// StderrPipe returns a pipe that will be connected to the +// remote command's standard error when the command starts. +// There is a fixed amount of buffering that is shared between +// stdout and stderr streams. If the StderrPipe reader is +// not serviced fast enough it may eventually cause the +// remote command to block. +func (s *Session) StderrPipe() (io.Reader, error) { + if s.Stderr != nil { + return nil, errors.New("ssh: Stderr already set") + } + if s.started { + return nil, errors.New("ssh: StderrPipe after process started") + } + s.stderrpipe = true + return s.ch.Stderr(), nil +} + +// newSession returns a new interactive session on the remote host. +func newSession(ch Channel, reqs <-chan *Request) (*Session, error) { + s := &Session{ + ch: ch, + } + s.exitStatus = make(chan error, 1) + go func() { + s.exitStatus <- s.wait(reqs) + }() + + return s, nil +} + +// An ExitError reports unsuccessful completion of a remote command. +type ExitError struct { + Waitmsg +} + +func (e *ExitError) Error() string { + return e.Waitmsg.String() +} + +// Waitmsg stores the information about an exited remote command +// as reported by Wait. +type Waitmsg struct { + status int + signal string + msg string + lang string +} + +// ExitStatus returns the exit status of the remote command. +func (w Waitmsg) ExitStatus() int { + return w.status +} + +// Signal returns the exit signal of the remote command if +// it was terminated violently. +func (w Waitmsg) Signal() string { + return w.signal +} + +// Msg returns the exit message given by the remote command +func (w Waitmsg) Msg() string { + return w.msg +} + +// Lang returns the language tag. See RFC 3066 +func (w Waitmsg) Lang() string { + return w.lang +} + +func (w Waitmsg) String() string { + str := fmt.Sprintf("Process exited with status %v", w.status) + if w.signal != "" { + str += fmt.Sprintf(" from signal %v", w.signal) + } + if w.msg != "" { + str += fmt.Sprintf(". Reason was: %v", w.msg) + } + return str +} diff --git a/vendor/golang.org/x/crypto/ssh/session_test.go b/vendor/golang.org/x/crypto/ssh/session_test.go new file mode 100644 index 0000000000000000000000000000000000000000..7dce6dd699bed2f4444afb0cf6aa413f9ee3fc9f --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/session_test.go @@ -0,0 +1,774 @@ +// 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 ssh + +// Session tests. + +import ( + "bytes" + crypto_rand "crypto/rand" + "errors" + "io" + "io/ioutil" + "math/rand" + "net" + "testing" + + "golang.org/x/crypto/ssh/terminal" +) + +type serverType func(Channel, <-chan *Request, *testing.T) + +// dial constructs a new test server and returns a *ClientConn. +func dial(handler serverType, t *testing.T) *Client { + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + + go func() { + defer c1.Close() + conf := ServerConfig{ + NoClientAuth: true, + } + conf.AddHostKey(testSigners["rsa"]) + + _, chans, reqs, err := NewServerConn(c1, &conf) + if err != nil { + t.Fatalf("Unable to handshake: %v", err) + } + go DiscardRequests(reqs) + + for newCh := range chans { + if newCh.ChannelType() != "session" { + newCh.Reject(UnknownChannelType, "unknown channel type") + continue + } + + ch, inReqs, err := newCh.Accept() + if err != nil { + t.Errorf("Accept: %v", err) + continue + } + go func() { + handler(ch, inReqs, t) + }() + } + }() + + config := &ClientConfig{ + User: "testuser", + HostKeyCallback: InsecureIgnoreHostKey(), + } + + conn, chans, reqs, err := NewClientConn(c2, "", config) + if err != nil { + t.Fatalf("unable to dial remote side: %v", err) + } + + return NewClient(conn, chans, reqs) +} + +// Test a simple string is returned to session.Stdout. +func TestSessionShell(t *testing.T) { + conn := dial(shellHandler, t) + defer conn.Close() + session, err := conn.NewSession() + if err != nil { + t.Fatalf("Unable to request new session: %v", err) + } + defer session.Close() + stdout := new(bytes.Buffer) + session.Stdout = stdout + if err := session.Shell(); err != nil { + t.Fatalf("Unable to execute command: %s", err) + } + if err := session.Wait(); err != nil { + t.Fatalf("Remote command did not exit cleanly: %v", err) + } + actual := stdout.String() + if actual != "golang" { + t.Fatalf("Remote shell did not return expected string: expected=golang, actual=%s", actual) + } +} + +// TODO(dfc) add support for Std{in,err}Pipe when the Server supports it. + +// Test a simple string is returned via StdoutPipe. +func TestSessionStdoutPipe(t *testing.T) { + conn := dial(shellHandler, t) + defer conn.Close() + session, err := conn.NewSession() + if err != nil { + t.Fatalf("Unable to request new session: %v", err) + } + defer session.Close() + stdout, err := session.StdoutPipe() + if err != nil { + t.Fatalf("Unable to request StdoutPipe(): %v", err) + } + var buf bytes.Buffer + if err := session.Shell(); err != nil { + t.Fatalf("Unable to execute command: %v", err) + } + done := make(chan bool, 1) + go func() { + if _, err := io.Copy(&buf, stdout); err != nil { + t.Errorf("Copy of stdout failed: %v", err) + } + done <- true + }() + if err := session.Wait(); err != nil { + t.Fatalf("Remote command did not exit cleanly: %v", err) + } + <-done + actual := buf.String() + if actual != "golang" { + t.Fatalf("Remote shell did not return expected string: expected=golang, actual=%s", actual) + } +} + +// Test that a simple string is returned via the Output helper, +// and that stderr is discarded. +func TestSessionOutput(t *testing.T) { + conn := dial(fixedOutputHandler, t) + defer conn.Close() + session, err := conn.NewSession() + if err != nil { + t.Fatalf("Unable to request new session: %v", err) + } + defer session.Close() + + buf, err := session.Output("") // cmd is ignored by fixedOutputHandler + if err != nil { + t.Error("Remote command did not exit cleanly:", err) + } + w := "this-is-stdout." + g := string(buf) + if g != w { + t.Error("Remote command did not return expected string:") + t.Logf("want %q", w) + t.Logf("got %q", g) + } +} + +// Test that both stdout and stderr are returned +// via the CombinedOutput helper. +func TestSessionCombinedOutput(t *testing.T) { + conn := dial(fixedOutputHandler, t) + defer conn.Close() + session, err := conn.NewSession() + if err != nil { + t.Fatalf("Unable to request new session: %v", err) + } + defer session.Close() + + buf, err := session.CombinedOutput("") // cmd is ignored by fixedOutputHandler + if err != nil { + t.Error("Remote command did not exit cleanly:", err) + } + const stdout = "this-is-stdout." + const stderr = "this-is-stderr." + g := string(buf) + if g != stdout+stderr && g != stderr+stdout { + t.Error("Remote command did not return expected string:") + t.Logf("want %q, or %q", stdout+stderr, stderr+stdout) + t.Logf("got %q", g) + } +} + +// Test non-0 exit status is returned correctly. +func TestExitStatusNonZero(t *testing.T) { + conn := dial(exitStatusNonZeroHandler, t) + defer conn.Close() + session, err := conn.NewSession() + if err != nil { + t.Fatalf("Unable to request new session: %v", err) + } + defer session.Close() + if err := session.Shell(); err != nil { + t.Fatalf("Unable to execute command: %v", err) + } + err = session.Wait() + if err == nil { + t.Fatalf("expected command to fail but it didn't") + } + e, ok := err.(*ExitError) + if !ok { + t.Fatalf("expected *ExitError but got %T", err) + } + if e.ExitStatus() != 15 { + t.Fatalf("expected command to exit with 15 but got %v", e.ExitStatus()) + } +} + +// Test 0 exit status is returned correctly. +func TestExitStatusZero(t *testing.T) { + conn := dial(exitStatusZeroHandler, t) + defer conn.Close() + session, err := conn.NewSession() + if err != nil { + t.Fatalf("Unable to request new session: %v", err) + } + defer session.Close() + + if err := session.Shell(); err != nil { + t.Fatalf("Unable to execute command: %v", err) + } + err = session.Wait() + if err != nil { + t.Fatalf("expected nil but got %v", err) + } +} + +// Test exit signal and status are both returned correctly. +func TestExitSignalAndStatus(t *testing.T) { + conn := dial(exitSignalAndStatusHandler, t) + defer conn.Close() + session, err := conn.NewSession() + if err != nil { + t.Fatalf("Unable to request new session: %v", err) + } + defer session.Close() + if err := session.Shell(); err != nil { + t.Fatalf("Unable to execute command: %v", err) + } + err = session.Wait() + if err == nil { + t.Fatalf("expected command to fail but it didn't") + } + e, ok := err.(*ExitError) + if !ok { + t.Fatalf("expected *ExitError but got %T", err) + } + if e.Signal() != "TERM" || e.ExitStatus() != 15 { + t.Fatalf("expected command to exit with signal TERM and status 15 but got signal %s and status %v", e.Signal(), e.ExitStatus()) + } +} + +// Test exit signal and status are both returned correctly. +func TestKnownExitSignalOnly(t *testing.T) { + conn := dial(exitSignalHandler, t) + defer conn.Close() + session, err := conn.NewSession() + if err != nil { + t.Fatalf("Unable to request new session: %v", err) + } + defer session.Close() + if err := session.Shell(); err != nil { + t.Fatalf("Unable to execute command: %v", err) + } + err = session.Wait() + if err == nil { + t.Fatalf("expected command to fail but it didn't") + } + e, ok := err.(*ExitError) + if !ok { + t.Fatalf("expected *ExitError but got %T", err) + } + if e.Signal() != "TERM" || e.ExitStatus() != 143 { + t.Fatalf("expected command to exit with signal TERM and status 143 but got signal %s and status %v", e.Signal(), e.ExitStatus()) + } +} + +// Test exit signal and status are both returned correctly. +func TestUnknownExitSignal(t *testing.T) { + conn := dial(exitSignalUnknownHandler, t) + defer conn.Close() + session, err := conn.NewSession() + if err != nil { + t.Fatalf("Unable to request new session: %v", err) + } + defer session.Close() + if err := session.Shell(); err != nil { + t.Fatalf("Unable to execute command: %v", err) + } + err = session.Wait() + if err == nil { + t.Fatalf("expected command to fail but it didn't") + } + e, ok := err.(*ExitError) + if !ok { + t.Fatalf("expected *ExitError but got %T", err) + } + if e.Signal() != "SYS" || e.ExitStatus() != 128 { + t.Fatalf("expected command to exit with signal SYS and status 128 but got signal %s and status %v", e.Signal(), e.ExitStatus()) + } +} + +func TestExitWithoutStatusOrSignal(t *testing.T) { + conn := dial(exitWithoutSignalOrStatus, t) + defer conn.Close() + session, err := conn.NewSession() + if err != nil { + t.Fatalf("Unable to request new session: %v", err) + } + defer session.Close() + if err := session.Shell(); err != nil { + t.Fatalf("Unable to execute command: %v", err) + } + err = session.Wait() + if err == nil { + t.Fatalf("expected command to fail but it didn't") + } + if _, ok := err.(*ExitMissingError); !ok { + t.Fatalf("got %T want *ExitMissingError", err) + } +} + +// windowTestBytes is the number of bytes that we'll send to the SSH server. +const windowTestBytes = 16000 * 200 + +// TestServerWindow writes random data to the server. The server is expected to echo +// the same data back, which is compared against the original. +func TestServerWindow(t *testing.T) { + origBuf := bytes.NewBuffer(make([]byte, 0, windowTestBytes)) + io.CopyN(origBuf, crypto_rand.Reader, windowTestBytes) + origBytes := origBuf.Bytes() + + conn := dial(echoHandler, t) + defer conn.Close() + session, err := conn.NewSession() + if err != nil { + t.Fatal(err) + } + defer session.Close() + result := make(chan []byte) + + go func() { + defer close(result) + echoedBuf := bytes.NewBuffer(make([]byte, 0, windowTestBytes)) + serverStdout, err := session.StdoutPipe() + if err != nil { + t.Errorf("StdoutPipe failed: %v", err) + return + } + n, err := copyNRandomly("stdout", echoedBuf, serverStdout, windowTestBytes) + if err != nil && err != io.EOF { + t.Errorf("Read only %d bytes from server, expected %d: %v", n, windowTestBytes, err) + } + result <- echoedBuf.Bytes() + }() + + serverStdin, err := session.StdinPipe() + if err != nil { + t.Fatalf("StdinPipe failed: %v", err) + } + written, err := copyNRandomly("stdin", serverStdin, origBuf, windowTestBytes) + if err != nil { + t.Fatalf("failed to copy origBuf to serverStdin: %v", err) + } + if written != windowTestBytes { + t.Fatalf("Wrote only %d of %d bytes to server", written, windowTestBytes) + } + + echoedBytes := <-result + + if !bytes.Equal(origBytes, echoedBytes) { + t.Fatalf("Echoed buffer differed from original, orig %d, echoed %d", len(origBytes), len(echoedBytes)) + } +} + +// Verify the client can handle a keepalive packet from the server. +func TestClientHandlesKeepalives(t *testing.T) { + conn := dial(channelKeepaliveSender, t) + defer conn.Close() + session, err := conn.NewSession() + if err != nil { + t.Fatal(err) + } + defer session.Close() + if err := session.Shell(); err != nil { + t.Fatalf("Unable to execute command: %v", err) + } + err = session.Wait() + if err != nil { + t.Fatalf("expected nil but got: %v", err) + } +} + +type exitStatusMsg struct { + Status uint32 +} + +type exitSignalMsg struct { + Signal string + CoreDumped bool + Errmsg string + Lang string +} + +func handleTerminalRequests(in <-chan *Request) { + for req := range in { + ok := false + switch req.Type { + case "shell": + ok = true + if len(req.Payload) > 0 { + // We don't accept any commands, only the default shell. + ok = false + } + case "env": + ok = true + } + req.Reply(ok, nil) + } +} + +func newServerShell(ch Channel, in <-chan *Request, prompt string) *terminal.Terminal { + term := terminal.NewTerminal(ch, prompt) + go handleTerminalRequests(in) + return term +} + +func exitStatusZeroHandler(ch Channel, in <-chan *Request, t *testing.T) { + defer ch.Close() + // this string is returned to stdout + shell := newServerShell(ch, in, "> ") + readLine(shell, t) + sendStatus(0, ch, t) +} + +func exitStatusNonZeroHandler(ch Channel, in <-chan *Request, t *testing.T) { + defer ch.Close() + shell := newServerShell(ch, in, "> ") + readLine(shell, t) + sendStatus(15, ch, t) +} + +func exitSignalAndStatusHandler(ch Channel, in <-chan *Request, t *testing.T) { + defer ch.Close() + shell := newServerShell(ch, in, "> ") + readLine(shell, t) + sendStatus(15, ch, t) + sendSignal("TERM", ch, t) +} + +func exitSignalHandler(ch Channel, in <-chan *Request, t *testing.T) { + defer ch.Close() + shell := newServerShell(ch, in, "> ") + readLine(shell, t) + sendSignal("TERM", ch, t) +} + +func exitSignalUnknownHandler(ch Channel, in <-chan *Request, t *testing.T) { + defer ch.Close() + shell := newServerShell(ch, in, "> ") + readLine(shell, t) + sendSignal("SYS", ch, t) +} + +func exitWithoutSignalOrStatus(ch Channel, in <-chan *Request, t *testing.T) { + defer ch.Close() + shell := newServerShell(ch, in, "> ") + readLine(shell, t) +} + +func shellHandler(ch Channel, in <-chan *Request, t *testing.T) { + defer ch.Close() + // this string is returned to stdout + shell := newServerShell(ch, in, "golang") + readLine(shell, t) + sendStatus(0, ch, t) +} + +// Ignores the command, writes fixed strings to stderr and stdout. +// Strings are "this-is-stdout." and "this-is-stderr.". +func fixedOutputHandler(ch Channel, in <-chan *Request, t *testing.T) { + defer ch.Close() + _, err := ch.Read(nil) + + req, ok := <-in + if !ok { + t.Fatalf("error: expected channel request, got: %#v", err) + return + } + + // ignore request, always send some text + req.Reply(true, nil) + + _, err = io.WriteString(ch, "this-is-stdout.") + if err != nil { + t.Fatalf("error writing on server: %v", err) + } + _, err = io.WriteString(ch.Stderr(), "this-is-stderr.") + if err != nil { + t.Fatalf("error writing on server: %v", err) + } + sendStatus(0, ch, t) +} + +func readLine(shell *terminal.Terminal, t *testing.T) { + if _, err := shell.ReadLine(); err != nil && err != io.EOF { + t.Errorf("unable to read line: %v", err) + } +} + +func sendStatus(status uint32, ch Channel, t *testing.T) { + msg := exitStatusMsg{ + Status: status, + } + if _, err := ch.SendRequest("exit-status", false, Marshal(&msg)); err != nil { + t.Errorf("unable to send status: %v", err) + } +} + +func sendSignal(signal string, ch Channel, t *testing.T) { + sig := exitSignalMsg{ + Signal: signal, + CoreDumped: false, + Errmsg: "Process terminated", + Lang: "en-GB-oed", + } + if _, err := ch.SendRequest("exit-signal", false, Marshal(&sig)); err != nil { + t.Errorf("unable to send signal: %v", err) + } +} + +func discardHandler(ch Channel, t *testing.T) { + defer ch.Close() + io.Copy(ioutil.Discard, ch) +} + +func echoHandler(ch Channel, in <-chan *Request, t *testing.T) { + defer ch.Close() + if n, err := copyNRandomly("echohandler", ch, ch, windowTestBytes); err != nil { + t.Errorf("short write, wrote %d, expected %d: %v ", n, windowTestBytes, err) + } +} + +// copyNRandomly copies n bytes from src to dst. It uses a variable, and random, +// buffer size to exercise more code paths. +func copyNRandomly(title string, dst io.Writer, src io.Reader, n int) (int, error) { + var ( + buf = make([]byte, 32*1024) + written int + remaining = n + ) + for remaining > 0 { + l := rand.Intn(1 << 15) + if remaining < l { + l = remaining + } + nr, er := src.Read(buf[:l]) + nw, ew := dst.Write(buf[:nr]) + remaining -= nw + written += nw + if ew != nil { + return written, ew + } + if nr != nw { + return written, io.ErrShortWrite + } + if er != nil && er != io.EOF { + return written, er + } + } + return written, nil +} + +func channelKeepaliveSender(ch Channel, in <-chan *Request, t *testing.T) { + defer ch.Close() + shell := newServerShell(ch, in, "> ") + readLine(shell, t) + if _, err := ch.SendRequest("keepalive@openssh.com", true, nil); err != nil { + t.Errorf("unable to send channel keepalive request: %v", err) + } + sendStatus(0, ch, t) +} + +func TestClientWriteEOF(t *testing.T) { + conn := dial(simpleEchoHandler, t) + defer conn.Close() + + session, err := conn.NewSession() + if err != nil { + t.Fatal(err) + } + defer session.Close() + stdin, err := session.StdinPipe() + if err != nil { + t.Fatalf("StdinPipe failed: %v", err) + } + stdout, err := session.StdoutPipe() + if err != nil { + t.Fatalf("StdoutPipe failed: %v", err) + } + + data := []byte(`0000`) + _, err = stdin.Write(data) + if err != nil { + t.Fatalf("Write failed: %v", err) + } + stdin.Close() + + res, err := ioutil.ReadAll(stdout) + if err != nil { + t.Fatalf("Read failed: %v", err) + } + + if !bytes.Equal(data, res) { + t.Fatalf("Read differed from write, wrote: %v, read: %v", data, res) + } +} + +func simpleEchoHandler(ch Channel, in <-chan *Request, t *testing.T) { + defer ch.Close() + data, err := ioutil.ReadAll(ch) + if err != nil { + t.Errorf("handler read error: %v", err) + } + _, err = ch.Write(data) + if err != nil { + t.Errorf("handler write error: %v", err) + } +} + +func TestSessionID(t *testing.T) { + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + + serverID := make(chan []byte, 1) + clientID := make(chan []byte, 1) + + serverConf := &ServerConfig{ + NoClientAuth: true, + } + serverConf.AddHostKey(testSigners["ecdsa"]) + clientConf := &ClientConfig{ + HostKeyCallback: InsecureIgnoreHostKey(), + User: "user", + } + + go func() { + conn, chans, reqs, err := NewServerConn(c1, serverConf) + if err != nil { + t.Fatalf("server handshake: %v", err) + } + serverID <- conn.SessionID() + go DiscardRequests(reqs) + for ch := range chans { + ch.Reject(Prohibited, "") + } + }() + + go func() { + conn, chans, reqs, err := NewClientConn(c2, "", clientConf) + if err != nil { + t.Fatalf("client handshake: %v", err) + } + clientID <- conn.SessionID() + go DiscardRequests(reqs) + for ch := range chans { + ch.Reject(Prohibited, "") + } + }() + + s := <-serverID + c := <-clientID + if bytes.Compare(s, c) != 0 { + t.Errorf("server session ID (%x) != client session ID (%x)", s, c) + } else if len(s) == 0 { + t.Errorf("client and server SessionID were empty.") + } +} + +type noReadConn struct { + readSeen bool + net.Conn +} + +func (c *noReadConn) Close() error { + return nil +} + +func (c *noReadConn) Read(b []byte) (int, error) { + c.readSeen = true + return 0, errors.New("noReadConn error") +} + +func TestInvalidServerConfiguration(t *testing.T) { + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + + serveConn := noReadConn{Conn: c1} + serverConf := &ServerConfig{} + + NewServerConn(&serveConn, serverConf) + if serveConn.readSeen { + t.Fatalf("NewServerConn attempted to Read() from Conn while configuration is missing host key") + } + + serverConf.AddHostKey(testSigners["ecdsa"]) + + NewServerConn(&serveConn, serverConf) + if serveConn.readSeen { + t.Fatalf("NewServerConn attempted to Read() from Conn while configuration is missing authentication method") + } +} + +func TestHostKeyAlgorithms(t *testing.T) { + serverConf := &ServerConfig{ + NoClientAuth: true, + } + serverConf.AddHostKey(testSigners["rsa"]) + serverConf.AddHostKey(testSigners["ecdsa"]) + + connect := func(clientConf *ClientConfig, want string) { + var alg string + clientConf.HostKeyCallback = func(h string, a net.Addr, key PublicKey) error { + alg = key.Type() + return nil + } + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + + go NewServerConn(c1, serverConf) + _, _, _, err = NewClientConn(c2, "", clientConf) + if err != nil { + t.Fatalf("NewClientConn: %v", err) + } + if alg != want { + t.Errorf("selected key algorithm %s, want %s", alg, want) + } + } + + // By default, we get the preferred algorithm, which is ECDSA 256. + + clientConf := &ClientConfig{ + HostKeyCallback: InsecureIgnoreHostKey(), + } + connect(clientConf, KeyAlgoECDSA256) + + // Client asks for RSA explicitly. + clientConf.HostKeyAlgorithms = []string{KeyAlgoRSA} + connect(clientConf, KeyAlgoRSA) + + c1, c2, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + defer c1.Close() + defer c2.Close() + + go NewServerConn(c1, serverConf) + clientConf.HostKeyAlgorithms = []string{"nonexistent-hostkey-algo"} + _, _, _, err = NewClientConn(c2, "", clientConf) + if err == nil { + t.Fatal("succeeded connecting with unknown hostkey algorithm") + } +} diff --git a/vendor/golang.org/x/crypto/ssh/streamlocal.go b/vendor/golang.org/x/crypto/ssh/streamlocal.go new file mode 100644 index 0000000000000000000000000000000000000000..a2dccc64c7efd70c57fff8003fd938169e522bae --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/streamlocal.go @@ -0,0 +1,115 @@ +package ssh + +import ( + "errors" + "io" + "net" +) + +// streamLocalChannelOpenDirectMsg is a struct used for SSH_MSG_CHANNEL_OPEN message +// with "direct-streamlocal@openssh.com" string. +// +// See openssh-portable/PROTOCOL, section 2.4. connection: Unix domain socket forwarding +// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL#L235 +type streamLocalChannelOpenDirectMsg struct { + socketPath string + reserved0 string + reserved1 uint32 +} + +// forwardedStreamLocalPayload is a struct used for SSH_MSG_CHANNEL_OPEN message +// with "forwarded-streamlocal@openssh.com" string. +type forwardedStreamLocalPayload struct { + SocketPath string + Reserved0 string +} + +// streamLocalChannelForwardMsg is a struct used for SSH2_MSG_GLOBAL_REQUEST message +// with "streamlocal-forward@openssh.com"/"cancel-streamlocal-forward@openssh.com" string. +type streamLocalChannelForwardMsg struct { + socketPath string +} + +// ListenUnix is similar to ListenTCP but uses a Unix domain socket. +func (c *Client) ListenUnix(socketPath string) (net.Listener, error) { + m := streamLocalChannelForwardMsg{ + socketPath, + } + // send message + ok, _, err := c.SendRequest("streamlocal-forward@openssh.com", true, Marshal(&m)) + if err != nil { + return nil, err + } + if !ok { + return nil, errors.New("ssh: streamlocal-forward@openssh.com request denied by peer") + } + ch := c.forwards.add(&net.UnixAddr{Name: socketPath, Net: "unix"}) + + return &unixListener{socketPath, c, ch}, nil +} + +func (c *Client) dialStreamLocal(socketPath string) (Channel, error) { + msg := streamLocalChannelOpenDirectMsg{ + socketPath: socketPath, + } + ch, in, err := c.OpenChannel("direct-streamlocal@openssh.com", Marshal(&msg)) + if err != nil { + return nil, err + } + go DiscardRequests(in) + return ch, err +} + +type unixListener struct { + socketPath string + + conn *Client + in <-chan forward +} + +// Accept waits for and returns the next connection to the listener. +func (l *unixListener) Accept() (net.Conn, error) { + s, ok := <-l.in + if !ok { + return nil, io.EOF + } + ch, incoming, err := s.newCh.Accept() + if err != nil { + return nil, err + } + go DiscardRequests(incoming) + + return &chanConn{ + Channel: ch, + laddr: &net.UnixAddr{ + Name: l.socketPath, + Net: "unix", + }, + raddr: &net.UnixAddr{ + Name: "@", + Net: "unix", + }, + }, nil +} + +// Close closes the listener. +func (l *unixListener) Close() error { + // this also closes the listener. + l.conn.forwards.remove(&net.UnixAddr{Name: l.socketPath, Net: "unix"}) + m := streamLocalChannelForwardMsg{ + l.socketPath, + } + ok, _, err := l.conn.SendRequest("cancel-streamlocal-forward@openssh.com", true, Marshal(&m)) + if err == nil && !ok { + err = errors.New("ssh: cancel-streamlocal-forward@openssh.com failed") + } + return err +} + +// Addr returns the listener's network address. +func (l *unixListener) Addr() net.Addr { + return &net.UnixAddr{ + Name: l.socketPath, + Net: "unix", + } +} diff --git a/vendor/golang.org/x/crypto/ssh/tcpip.go b/vendor/golang.org/x/crypto/ssh/tcpip.go new file mode 100644 index 0000000000000000000000000000000000000000..acf17175dffb1f504dc64f668e5b2cfe0a6ebb6a --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/tcpip.go @@ -0,0 +1,465 @@ +// 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 ssh + +import ( + "errors" + "fmt" + "io" + "math/rand" + "net" + "strconv" + "strings" + "sync" + "time" +) + +// Listen requests the remote peer open a listening socket on +// addr. Incoming connections will be available by calling Accept on +// the returned net.Listener. The listener must be serviced, or the +// SSH connection may hang. +// N must be "tcp", "tcp4", "tcp6", or "unix". +func (c *Client) Listen(n, addr string) (net.Listener, error) { + switch n { + case "tcp", "tcp4", "tcp6": + laddr, err := net.ResolveTCPAddr(n, addr) + if err != nil { + return nil, err + } + return c.ListenTCP(laddr) + case "unix": + return c.ListenUnix(addr) + default: + return nil, fmt.Errorf("ssh: unsupported protocol: %s", n) + } +} + +// Automatic port allocation is broken with OpenSSH before 6.0. See +// also https://bugzilla.mindrot.org/show_bug.cgi?id=2017. In +// particular, OpenSSH 5.9 sends a channelOpenMsg with port number 0, +// rather than the actual port number. This means you can never open +// two different listeners with auto allocated ports. We work around +// this by trying explicit ports until we succeed. + +const openSSHPrefix = "OpenSSH_" + +var portRandomizer = rand.New(rand.NewSource(time.Now().UnixNano())) + +// isBrokenOpenSSHVersion returns true if the given version string +// specifies a version of OpenSSH that is known to have a bug in port +// forwarding. +func isBrokenOpenSSHVersion(versionStr string) bool { + i := strings.Index(versionStr, openSSHPrefix) + if i < 0 { + return false + } + i += len(openSSHPrefix) + j := i + for ; j < len(versionStr); j++ { + if versionStr[j] < '0' || versionStr[j] > '9' { + break + } + } + version, _ := strconv.Atoi(versionStr[i:j]) + return version < 6 +} + +// autoPortListenWorkaround simulates automatic port allocation by +// trying random ports repeatedly. +func (c *Client) autoPortListenWorkaround(laddr *net.TCPAddr) (net.Listener, error) { + var sshListener net.Listener + var err error + const tries = 10 + for i := 0; i < tries; i++ { + addr := *laddr + addr.Port = 1024 + portRandomizer.Intn(60000) + sshListener, err = c.ListenTCP(&addr) + if err == nil { + laddr.Port = addr.Port + return sshListener, err + } + } + return nil, fmt.Errorf("ssh: listen on random port failed after %d tries: %v", tries, err) +} + +// RFC 4254 7.1 +type channelForwardMsg struct { + addr string + rport uint32 +} + +// ListenTCP requests the remote peer open a listening socket +// on laddr. Incoming connections will be available by calling +// Accept on the returned net.Listener. +func (c *Client) ListenTCP(laddr *net.TCPAddr) (net.Listener, error) { + if laddr.Port == 0 && isBrokenOpenSSHVersion(string(c.ServerVersion())) { + return c.autoPortListenWorkaround(laddr) + } + + m := channelForwardMsg{ + laddr.IP.String(), + uint32(laddr.Port), + } + // send message + ok, resp, err := c.SendRequest("tcpip-forward", true, Marshal(&m)) + if err != nil { + return nil, err + } + if !ok { + return nil, errors.New("ssh: tcpip-forward request denied by peer") + } + + // If the original port was 0, then the remote side will + // supply a real port number in the response. + if laddr.Port == 0 { + var p struct { + Port uint32 + } + if err := Unmarshal(resp, &p); err != nil { + return nil, err + } + laddr.Port = int(p.Port) + } + + // Register this forward, using the port number we obtained. + ch := c.forwards.add(laddr) + + return &tcpListener{laddr, c, ch}, nil +} + +// forwardList stores a mapping between remote +// forward requests and the tcpListeners. +type forwardList struct { + sync.Mutex + entries []forwardEntry +} + +// forwardEntry represents an established mapping of a laddr on a +// remote ssh server to a channel connected to a tcpListener. +type forwardEntry struct { + laddr net.Addr + c chan forward +} + +// forward represents an incoming forwarded tcpip connection. The +// arguments to add/remove/lookup should be address as specified in +// the original forward-request. +type forward struct { + newCh NewChannel // the ssh client channel underlying this forward + raddr net.Addr // the raddr of the incoming connection +} + +func (l *forwardList) add(addr net.Addr) chan forward { + l.Lock() + defer l.Unlock() + f := forwardEntry{ + laddr: addr, + c: make(chan forward, 1), + } + l.entries = append(l.entries, f) + return f.c +} + +// See RFC 4254, section 7.2 +type forwardedTCPPayload struct { + Addr string + Port uint32 + OriginAddr string + OriginPort uint32 +} + +// parseTCPAddr parses the originating address from the remote into a *net.TCPAddr. +func parseTCPAddr(addr string, port uint32) (*net.TCPAddr, error) { + if port == 0 || port > 65535 { + return nil, fmt.Errorf("ssh: port number out of range: %d", port) + } + ip := net.ParseIP(string(addr)) + if ip == nil { + return nil, fmt.Errorf("ssh: cannot parse IP address %q", addr) + } + return &net.TCPAddr{IP: ip, Port: int(port)}, nil +} + +func (l *forwardList) handleChannels(in <-chan NewChannel) { + for ch := range in { + var ( + laddr net.Addr + raddr net.Addr + err error + ) + switch channelType := ch.ChannelType(); channelType { + case "forwarded-tcpip": + var payload forwardedTCPPayload + if err = Unmarshal(ch.ExtraData(), &payload); err != nil { + ch.Reject(ConnectionFailed, "could not parse forwarded-tcpip payload: "+err.Error()) + continue + } + + // RFC 4254 section 7.2 specifies that incoming + // addresses should list the address, in string + // format. It is implied that this should be an IP + // address, as it would be impossible to connect to it + // otherwise. + laddr, err = parseTCPAddr(payload.Addr, payload.Port) + if err != nil { + ch.Reject(ConnectionFailed, err.Error()) + continue + } + raddr, err = parseTCPAddr(payload.OriginAddr, payload.OriginPort) + if err != nil { + ch.Reject(ConnectionFailed, err.Error()) + continue + } + + case "forwarded-streamlocal@openssh.com": + var payload forwardedStreamLocalPayload + if err = Unmarshal(ch.ExtraData(), &payload); err != nil { + ch.Reject(ConnectionFailed, "could not parse forwarded-streamlocal@openssh.com payload: "+err.Error()) + continue + } + laddr = &net.UnixAddr{ + Name: payload.SocketPath, + Net: "unix", + } + raddr = &net.UnixAddr{ + Name: "@", + Net: "unix", + } + default: + panic(fmt.Errorf("ssh: unknown channel type %s", channelType)) + } + if ok := l.forward(laddr, raddr, ch); !ok { + // Section 7.2, implementations MUST reject spurious incoming + // connections. + ch.Reject(Prohibited, "no forward for address") + continue + } + + } +} + +// remove removes the forward entry, and the channel feeding its +// listener. +func (l *forwardList) remove(addr net.Addr) { + l.Lock() + defer l.Unlock() + for i, f := range l.entries { + if addr.Network() == f.laddr.Network() && addr.String() == f.laddr.String() { + l.entries = append(l.entries[:i], l.entries[i+1:]...) + close(f.c) + return + } + } +} + +// closeAll closes and clears all forwards. +func (l *forwardList) closeAll() { + l.Lock() + defer l.Unlock() + for _, f := range l.entries { + close(f.c) + } + l.entries = nil +} + +func (l *forwardList) forward(laddr, raddr net.Addr, ch NewChannel) bool { + l.Lock() + defer l.Unlock() + for _, f := range l.entries { + if laddr.Network() == f.laddr.Network() && laddr.String() == f.laddr.String() { + f.c <- forward{newCh: ch, raddr: raddr} + return true + } + } + return false +} + +type tcpListener struct { + laddr *net.TCPAddr + + conn *Client + in <-chan forward +} + +// Accept waits for and returns the next connection to the listener. +func (l *tcpListener) Accept() (net.Conn, error) { + s, ok := <-l.in + if !ok { + return nil, io.EOF + } + ch, incoming, err := s.newCh.Accept() + if err != nil { + return nil, err + } + go DiscardRequests(incoming) + + return &chanConn{ + Channel: ch, + laddr: l.laddr, + raddr: s.raddr, + }, nil +} + +// Close closes the listener. +func (l *tcpListener) Close() error { + m := channelForwardMsg{ + l.laddr.IP.String(), + uint32(l.laddr.Port), + } + + // this also closes the listener. + l.conn.forwards.remove(l.laddr) + ok, _, err := l.conn.SendRequest("cancel-tcpip-forward", true, Marshal(&m)) + if err == nil && !ok { + err = errors.New("ssh: cancel-tcpip-forward failed") + } + return err +} + +// Addr returns the listener's network address. +func (l *tcpListener) Addr() net.Addr { + return l.laddr +} + +// Dial initiates a connection to the addr from the remote host. +// The resulting connection has a zero LocalAddr() and RemoteAddr(). +func (c *Client) Dial(n, addr string) (net.Conn, error) { + var ch Channel + switch n { + case "tcp", "tcp4", "tcp6": + // Parse the address into host and numeric port. + host, portString, err := net.SplitHostPort(addr) + if err != nil { + return nil, err + } + port, err := strconv.ParseUint(portString, 10, 16) + if err != nil { + return nil, err + } + ch, err = c.dial(net.IPv4zero.String(), 0, host, int(port)) + if err != nil { + return nil, err + } + // Use a zero address for local and remote address. + zeroAddr := &net.TCPAddr{ + IP: net.IPv4zero, + Port: 0, + } + return &chanConn{ + Channel: ch, + laddr: zeroAddr, + raddr: zeroAddr, + }, nil + case "unix": + var err error + ch, err = c.dialStreamLocal(addr) + if err != nil { + return nil, err + } + return &chanConn{ + Channel: ch, + laddr: &net.UnixAddr{ + Name: "@", + Net: "unix", + }, + raddr: &net.UnixAddr{ + Name: addr, + Net: "unix", + }, + }, nil + default: + return nil, fmt.Errorf("ssh: unsupported protocol: %s", n) + } +} + +// DialTCP connects to the remote address raddr on the network net, +// which must be "tcp", "tcp4", or "tcp6". If laddr is not nil, it is used +// as the local address for the connection. +func (c *Client) DialTCP(n string, laddr, raddr *net.TCPAddr) (net.Conn, error) { + if laddr == nil { + laddr = &net.TCPAddr{ + IP: net.IPv4zero, + Port: 0, + } + } + ch, err := c.dial(laddr.IP.String(), laddr.Port, raddr.IP.String(), raddr.Port) + if err != nil { + return nil, err + } + return &chanConn{ + Channel: ch, + laddr: laddr, + raddr: raddr, + }, nil +} + +// RFC 4254 7.2 +type channelOpenDirectMsg struct { + raddr string + rport uint32 + laddr string + lport uint32 +} + +func (c *Client) dial(laddr string, lport int, raddr string, rport int) (Channel, error) { + msg := channelOpenDirectMsg{ + raddr: raddr, + rport: uint32(rport), + laddr: laddr, + lport: uint32(lport), + } + ch, in, err := c.OpenChannel("direct-tcpip", Marshal(&msg)) + if err != nil { + return nil, err + } + go DiscardRequests(in) + return ch, err +} + +type tcpChan struct { + Channel // the backing channel +} + +// chanConn fulfills the net.Conn interface without +// the tcpChan having to hold laddr or raddr directly. +type chanConn struct { + Channel + laddr, raddr net.Addr +} + +// LocalAddr returns the local network address. +func (t *chanConn) LocalAddr() net.Addr { + return t.laddr +} + +// RemoteAddr returns the remote network address. +func (t *chanConn) RemoteAddr() net.Addr { + return t.raddr +} + +// SetDeadline sets the read and write deadlines associated +// with the connection. +func (t *chanConn) SetDeadline(deadline time.Time) error { + if err := t.SetReadDeadline(deadline); err != nil { + return err + } + return t.SetWriteDeadline(deadline) +} + +// SetReadDeadline sets the read deadline. +// A zero value for t means Read will not time out. +// After the deadline, the error from Read will implement net.Error +// with Timeout() == true. +func (t *chanConn) SetReadDeadline(deadline time.Time) error { + // for compatibility with previous version, + // the error message contains "tcpChan" + return errors.New("ssh: tcpChan: deadline not supported") +} + +// SetWriteDeadline exists to satisfy the net.Conn interface +// but is not implemented by this type. It always returns an error. +func (t *chanConn) SetWriteDeadline(deadline time.Time) error { + return errors.New("ssh: tcpChan: deadline not supported") +} diff --git a/vendor/golang.org/x/crypto/ssh/tcpip_test.go b/vendor/golang.org/x/crypto/ssh/tcpip_test.go new file mode 100644 index 0000000000000000000000000000000000000000..f1265cb4964ede75acc6fb782d89278040656030 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/tcpip_test.go @@ -0,0 +1,20 @@ +// 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 ssh + +import ( + "testing" +) + +func TestAutoPortListenBroken(t *testing.T) { + broken := "SSH-2.0-OpenSSH_5.9hh11" + works := "SSH-2.0-OpenSSH_6.1" + if !isBrokenOpenSSHVersion(broken) { + t.Errorf("version %q not marked as broken", broken) + } + if isBrokenOpenSSHVersion(works) { + t.Errorf("version %q marked as broken", works) + } +} diff --git a/vendor/golang.org/x/crypto/ssh/terminal/terminal.go b/vendor/golang.org/x/crypto/ssh/terminal/terminal.go new file mode 100644 index 0000000000000000000000000000000000000000..9a887598ff40437dae4a6a85dd8502e428917450 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/terminal/terminal.go @@ -0,0 +1,951 @@ +// 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 terminal + +import ( + "bytes" + "io" + "sync" + "unicode/utf8" +) + +// EscapeCodes contains escape sequences that can be written to the terminal in +// order to achieve different styles of text. +type EscapeCodes struct { + // Foreground colors + Black, Red, Green, Yellow, Blue, Magenta, Cyan, White []byte + + // Reset all attributes + Reset []byte +} + +var vt100EscapeCodes = EscapeCodes{ + Black: []byte{keyEscape, '[', '3', '0', 'm'}, + Red: []byte{keyEscape, '[', '3', '1', 'm'}, + Green: []byte{keyEscape, '[', '3', '2', 'm'}, + Yellow: []byte{keyEscape, '[', '3', '3', 'm'}, + Blue: []byte{keyEscape, '[', '3', '4', 'm'}, + Magenta: []byte{keyEscape, '[', '3', '5', 'm'}, + Cyan: []byte{keyEscape, '[', '3', '6', 'm'}, + White: []byte{keyEscape, '[', '3', '7', 'm'}, + + Reset: []byte{keyEscape, '[', '0', 'm'}, +} + +// Terminal contains the state for running a VT100 terminal that is capable of +// reading lines of input. +type Terminal struct { + // AutoCompleteCallback, if non-null, is called for each keypress with + // the full input line and the current position of the cursor (in + // bytes, as an index into |line|). If it returns ok=false, the key + // press is processed normally. Otherwise it returns a replacement line + // and the new cursor position. + AutoCompleteCallback func(line string, pos int, key rune) (newLine string, newPos int, ok bool) + + // Escape contains a pointer to the escape codes for this terminal. + // It's always a valid pointer, although the escape codes themselves + // may be empty if the terminal doesn't support them. + Escape *EscapeCodes + + // lock protects the terminal and the state in this object from + // concurrent processing of a key press and a Write() call. + lock sync.Mutex + + c io.ReadWriter + prompt []rune + + // line is the current line being entered. + line []rune + // pos is the logical position of the cursor in line + pos int + // echo is true if local echo is enabled + echo bool + // pasteActive is true iff there is a bracketed paste operation in + // progress. + pasteActive bool + + // cursorX contains the current X value of the cursor where the left + // edge is 0. cursorY contains the row number where the first row of + // the current line is 0. + cursorX, cursorY int + // maxLine is the greatest value of cursorY so far. + maxLine int + + termWidth, termHeight int + + // outBuf contains the terminal data to be sent. + outBuf []byte + // remainder contains the remainder of any partial key sequences after + // a read. It aliases into inBuf. + remainder []byte + inBuf [256]byte + + // history contains previously entered commands so that they can be + // accessed with the up and down keys. + history stRingBuffer + // historyIndex stores the currently accessed history entry, where zero + // means the immediately previous entry. + historyIndex int + // When navigating up and down the history it's possible to return to + // the incomplete, initial line. That value is stored in + // historyPending. + historyPending string +} + +// NewTerminal runs a VT100 terminal on the given ReadWriter. If the ReadWriter is +// a local terminal, that terminal must first have been put into raw mode. +// prompt is a string that is written at the start of each input line (i.e. +// "> "). +func NewTerminal(c io.ReadWriter, prompt string) *Terminal { + return &Terminal{ + Escape: &vt100EscapeCodes, + c: c, + prompt: []rune(prompt), + termWidth: 80, + termHeight: 24, + echo: true, + historyIndex: -1, + } +} + +const ( + keyCtrlD = 4 + keyCtrlU = 21 + keyEnter = '\r' + keyEscape = 27 + keyBackspace = 127 + keyUnknown = 0xd800 /* UTF-16 surrogate area */ + iota + keyUp + keyDown + keyLeft + keyRight + keyAltLeft + keyAltRight + keyHome + keyEnd + keyDeleteWord + keyDeleteLine + keyClearScreen + keyPasteStart + keyPasteEnd +) + +var ( + crlf = []byte{'\r', '\n'} + pasteStart = []byte{keyEscape, '[', '2', '0', '0', '~'} + pasteEnd = []byte{keyEscape, '[', '2', '0', '1', '~'} +) + +// bytesToKey tries to parse a key sequence from b. If successful, it returns +// the key and the remainder of the input. Otherwise it returns utf8.RuneError. +func bytesToKey(b []byte, pasteActive bool) (rune, []byte) { + if len(b) == 0 { + return utf8.RuneError, nil + } + + if !pasteActive { + switch b[0] { + case 1: // ^A + return keyHome, b[1:] + case 5: // ^E + return keyEnd, b[1:] + case 8: // ^H + return keyBackspace, b[1:] + case 11: // ^K + return keyDeleteLine, b[1:] + case 12: // ^L + return keyClearScreen, b[1:] + case 23: // ^W + return keyDeleteWord, b[1:] + } + } + + if b[0] != keyEscape { + if !utf8.FullRune(b) { + return utf8.RuneError, b + } + r, l := utf8.DecodeRune(b) + return r, b[l:] + } + + if !pasteActive && len(b) >= 3 && b[0] == keyEscape && b[1] == '[' { + switch b[2] { + case 'A': + return keyUp, b[3:] + case 'B': + return keyDown, b[3:] + case 'C': + return keyRight, b[3:] + case 'D': + return keyLeft, b[3:] + case 'H': + return keyHome, b[3:] + case 'F': + return keyEnd, b[3:] + } + } + + if !pasteActive && len(b) >= 6 && b[0] == keyEscape && b[1] == '[' && b[2] == '1' && b[3] == ';' && b[4] == '3' { + switch b[5] { + case 'C': + return keyAltRight, b[6:] + case 'D': + return keyAltLeft, b[6:] + } + } + + if !pasteActive && len(b) >= 6 && bytes.Equal(b[:6], pasteStart) { + return keyPasteStart, b[6:] + } + + if pasteActive && len(b) >= 6 && bytes.Equal(b[:6], pasteEnd) { + return keyPasteEnd, b[6:] + } + + // If we get here then we have a key that we don't recognise, or a + // partial sequence. It's not clear how one should find the end of a + // sequence without knowing them all, but it seems that [a-zA-Z~] only + // appears at the end of a sequence. + for i, c := range b[0:] { + if c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '~' { + return keyUnknown, b[i+1:] + } + } + + return utf8.RuneError, b +} + +// queue appends data to the end of t.outBuf +func (t *Terminal) queue(data []rune) { + t.outBuf = append(t.outBuf, []byte(string(data))...) +} + +var eraseUnderCursor = []rune{' ', keyEscape, '[', 'D'} +var space = []rune{' '} + +func isPrintable(key rune) bool { + isInSurrogateArea := key >= 0xd800 && key <= 0xdbff + return key >= 32 && !isInSurrogateArea +} + +// moveCursorToPos appends data to t.outBuf which will move the cursor to the +// given, logical position in the text. +func (t *Terminal) moveCursorToPos(pos int) { + if !t.echo { + return + } + + x := visualLength(t.prompt) + pos + y := x / t.termWidth + x = x % t.termWidth + + up := 0 + if y < t.cursorY { + up = t.cursorY - y + } + + down := 0 + if y > t.cursorY { + down = y - t.cursorY + } + + left := 0 + if x < t.cursorX { + left = t.cursorX - x + } + + right := 0 + if x > t.cursorX { + right = x - t.cursorX + } + + t.cursorX = x + t.cursorY = y + t.move(up, down, left, right) +} + +func (t *Terminal) move(up, down, left, right int) { + movement := make([]rune, 3*(up+down+left+right)) + m := movement + for i := 0; i < up; i++ { + m[0] = keyEscape + m[1] = '[' + m[2] = 'A' + m = m[3:] + } + for i := 0; i < down; i++ { + m[0] = keyEscape + m[1] = '[' + m[2] = 'B' + m = m[3:] + } + for i := 0; i < left; i++ { + m[0] = keyEscape + m[1] = '[' + m[2] = 'D' + m = m[3:] + } + for i := 0; i < right; i++ { + m[0] = keyEscape + m[1] = '[' + m[2] = 'C' + m = m[3:] + } + + t.queue(movement) +} + +func (t *Terminal) clearLineToRight() { + op := []rune{keyEscape, '[', 'K'} + t.queue(op) +} + +const maxLineLength = 4096 + +func (t *Terminal) setLine(newLine []rune, newPos int) { + if t.echo { + t.moveCursorToPos(0) + t.writeLine(newLine) + for i := len(newLine); i < len(t.line); i++ { + t.writeLine(space) + } + t.moveCursorToPos(newPos) + } + t.line = newLine + t.pos = newPos +} + +func (t *Terminal) advanceCursor(places int) { + t.cursorX += places + t.cursorY += t.cursorX / t.termWidth + if t.cursorY > t.maxLine { + t.maxLine = t.cursorY + } + t.cursorX = t.cursorX % t.termWidth + + if places > 0 && t.cursorX == 0 { + // Normally terminals will advance the current position + // when writing a character. But that doesn't happen + // for the last character in a line. However, when + // writing a character (except a new line) that causes + // a line wrap, the position will be advanced two + // places. + // + // So, if we are stopping at the end of a line, we + // need to write a newline so that our cursor can be + // advanced to the next line. + t.outBuf = append(t.outBuf, '\r', '\n') + } +} + +func (t *Terminal) eraseNPreviousChars(n int) { + if n == 0 { + return + } + + if t.pos < n { + n = t.pos + } + t.pos -= n + t.moveCursorToPos(t.pos) + + copy(t.line[t.pos:], t.line[n+t.pos:]) + t.line = t.line[:len(t.line)-n] + if t.echo { + t.writeLine(t.line[t.pos:]) + for i := 0; i < n; i++ { + t.queue(space) + } + t.advanceCursor(n) + t.moveCursorToPos(t.pos) + } +} + +// countToLeftWord returns then number of characters from the cursor to the +// start of the previous word. +func (t *Terminal) countToLeftWord() int { + if t.pos == 0 { + return 0 + } + + pos := t.pos - 1 + for pos > 0 { + if t.line[pos] != ' ' { + break + } + pos-- + } + for pos > 0 { + if t.line[pos] == ' ' { + pos++ + break + } + pos-- + } + + return t.pos - pos +} + +// countToRightWord returns then number of characters from the cursor to the +// start of the next word. +func (t *Terminal) countToRightWord() int { + pos := t.pos + for pos < len(t.line) { + if t.line[pos] == ' ' { + break + } + pos++ + } + for pos < len(t.line) { + if t.line[pos] != ' ' { + break + } + pos++ + } + return pos - t.pos +} + +// visualLength returns the number of visible glyphs in s. +func visualLength(runes []rune) int { + inEscapeSeq := false + length := 0 + + for _, r := range runes { + switch { + case inEscapeSeq: + if (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') { + inEscapeSeq = false + } + case r == '\x1b': + inEscapeSeq = true + default: + length++ + } + } + + return length +} + +// handleKey processes the given key and, optionally, returns a line of text +// that the user has entered. +func (t *Terminal) handleKey(key rune) (line string, ok bool) { + if t.pasteActive && key != keyEnter { + t.addKeyToLine(key) + return + } + + switch key { + case keyBackspace: + if t.pos == 0 { + return + } + t.eraseNPreviousChars(1) + case keyAltLeft: + // move left by a word. + t.pos -= t.countToLeftWord() + t.moveCursorToPos(t.pos) + case keyAltRight: + // move right by a word. + t.pos += t.countToRightWord() + t.moveCursorToPos(t.pos) + case keyLeft: + if t.pos == 0 { + return + } + t.pos-- + t.moveCursorToPos(t.pos) + case keyRight: + if t.pos == len(t.line) { + return + } + t.pos++ + t.moveCursorToPos(t.pos) + case keyHome: + if t.pos == 0 { + return + } + t.pos = 0 + t.moveCursorToPos(t.pos) + case keyEnd: + if t.pos == len(t.line) { + return + } + t.pos = len(t.line) + t.moveCursorToPos(t.pos) + case keyUp: + entry, ok := t.history.NthPreviousEntry(t.historyIndex + 1) + if !ok { + return "", false + } + if t.historyIndex == -1 { + t.historyPending = string(t.line) + } + t.historyIndex++ + runes := []rune(entry) + t.setLine(runes, len(runes)) + case keyDown: + switch t.historyIndex { + case -1: + return + case 0: + runes := []rune(t.historyPending) + t.setLine(runes, len(runes)) + t.historyIndex-- + default: + entry, ok := t.history.NthPreviousEntry(t.historyIndex - 1) + if ok { + t.historyIndex-- + runes := []rune(entry) + t.setLine(runes, len(runes)) + } + } + case keyEnter: + t.moveCursorToPos(len(t.line)) + t.queue([]rune("\r\n")) + line = string(t.line) + ok = true + t.line = t.line[:0] + t.pos = 0 + t.cursorX = 0 + t.cursorY = 0 + t.maxLine = 0 + case keyDeleteWord: + // Delete zero or more spaces and then one or more characters. + t.eraseNPreviousChars(t.countToLeftWord()) + case keyDeleteLine: + // Delete everything from the current cursor position to the + // end of line. + for i := t.pos; i < len(t.line); i++ { + t.queue(space) + t.advanceCursor(1) + } + t.line = t.line[:t.pos] + t.moveCursorToPos(t.pos) + case keyCtrlD: + // Erase the character under the current position. + // The EOF case when the line is empty is handled in + // readLine(). + if t.pos < len(t.line) { + t.pos++ + t.eraseNPreviousChars(1) + } + case keyCtrlU: + t.eraseNPreviousChars(t.pos) + case keyClearScreen: + // Erases the screen and moves the cursor to the home position. + t.queue([]rune("\x1b[2J\x1b[H")) + t.queue(t.prompt) + t.cursorX, t.cursorY = 0, 0 + t.advanceCursor(visualLength(t.prompt)) + t.setLine(t.line, t.pos) + default: + if t.AutoCompleteCallback != nil { + prefix := string(t.line[:t.pos]) + suffix := string(t.line[t.pos:]) + + t.lock.Unlock() + newLine, newPos, completeOk := t.AutoCompleteCallback(prefix+suffix, len(prefix), key) + t.lock.Lock() + + if completeOk { + t.setLine([]rune(newLine), utf8.RuneCount([]byte(newLine)[:newPos])) + return + } + } + if !isPrintable(key) { + return + } + if len(t.line) == maxLineLength { + return + } + t.addKeyToLine(key) + } + return +} + +// addKeyToLine inserts the given key at the current position in the current +// line. +func (t *Terminal) addKeyToLine(key rune) { + if len(t.line) == cap(t.line) { + newLine := make([]rune, len(t.line), 2*(1+len(t.line))) + copy(newLine, t.line) + t.line = newLine + } + t.line = t.line[:len(t.line)+1] + copy(t.line[t.pos+1:], t.line[t.pos:]) + t.line[t.pos] = key + if t.echo { + t.writeLine(t.line[t.pos:]) + } + t.pos++ + t.moveCursorToPos(t.pos) +} + +func (t *Terminal) writeLine(line []rune) { + for len(line) != 0 { + remainingOnLine := t.termWidth - t.cursorX + todo := len(line) + if todo > remainingOnLine { + todo = remainingOnLine + } + t.queue(line[:todo]) + t.advanceCursor(visualLength(line[:todo])) + line = line[todo:] + } +} + +// writeWithCRLF writes buf to w but replaces all occurrences of \n with \r\n. +func writeWithCRLF(w io.Writer, buf []byte) (n int, err error) { + for len(buf) > 0 { + i := bytes.IndexByte(buf, '\n') + todo := len(buf) + if i >= 0 { + todo = i + } + + var nn int + nn, err = w.Write(buf[:todo]) + n += nn + if err != nil { + return n, err + } + buf = buf[todo:] + + if i >= 0 { + if _, err = w.Write(crlf); err != nil { + return n, err + } + n++ + buf = buf[1:] + } + } + + return n, nil +} + +func (t *Terminal) Write(buf []byte) (n int, err error) { + t.lock.Lock() + defer t.lock.Unlock() + + if t.cursorX == 0 && t.cursorY == 0 { + // This is the easy case: there's nothing on the screen that we + // have to move out of the way. + return writeWithCRLF(t.c, buf) + } + + // We have a prompt and possibly user input on the screen. We + // have to clear it first. + t.move(0 /* up */, 0 /* down */, t.cursorX /* left */, 0 /* right */) + t.cursorX = 0 + t.clearLineToRight() + + for t.cursorY > 0 { + t.move(1 /* up */, 0, 0, 0) + t.cursorY-- + t.clearLineToRight() + } + + if _, err = t.c.Write(t.outBuf); err != nil { + return + } + t.outBuf = t.outBuf[:0] + + if n, err = writeWithCRLF(t.c, buf); err != nil { + return + } + + t.writeLine(t.prompt) + if t.echo { + t.writeLine(t.line) + } + + t.moveCursorToPos(t.pos) + + if _, err = t.c.Write(t.outBuf); err != nil { + return + } + t.outBuf = t.outBuf[:0] + return +} + +// ReadPassword temporarily changes the prompt and reads a password, without +// echo, from the terminal. +func (t *Terminal) ReadPassword(prompt string) (line string, err error) { + t.lock.Lock() + defer t.lock.Unlock() + + oldPrompt := t.prompt + t.prompt = []rune(prompt) + t.echo = false + + line, err = t.readLine() + + t.prompt = oldPrompt + t.echo = true + + return +} + +// ReadLine returns a line of input from the terminal. +func (t *Terminal) ReadLine() (line string, err error) { + t.lock.Lock() + defer t.lock.Unlock() + + return t.readLine() +} + +func (t *Terminal) readLine() (line string, err error) { + // t.lock must be held at this point + + if t.cursorX == 0 && t.cursorY == 0 { + t.writeLine(t.prompt) + t.c.Write(t.outBuf) + t.outBuf = t.outBuf[:0] + } + + lineIsPasted := t.pasteActive + + for { + rest := t.remainder + lineOk := false + for !lineOk { + var key rune + key, rest = bytesToKey(rest, t.pasteActive) + if key == utf8.RuneError { + break + } + if !t.pasteActive { + if key == keyCtrlD { + if len(t.line) == 0 { + return "", io.EOF + } + } + if key == keyPasteStart { + t.pasteActive = true + if len(t.line) == 0 { + lineIsPasted = true + } + continue + } + } else if key == keyPasteEnd { + t.pasteActive = false + continue + } + if !t.pasteActive { + lineIsPasted = false + } + line, lineOk = t.handleKey(key) + } + if len(rest) > 0 { + n := copy(t.inBuf[:], rest) + t.remainder = t.inBuf[:n] + } else { + t.remainder = nil + } + t.c.Write(t.outBuf) + t.outBuf = t.outBuf[:0] + if lineOk { + if t.echo { + t.historyIndex = -1 + t.history.Add(line) + } + if lineIsPasted { + err = ErrPasteIndicator + } + return + } + + // t.remainder is a slice at the beginning of t.inBuf + // containing a partial key sequence + readBuf := t.inBuf[len(t.remainder):] + var n int + + t.lock.Unlock() + n, err = t.c.Read(readBuf) + t.lock.Lock() + + if err != nil { + return + } + + t.remainder = t.inBuf[:n+len(t.remainder)] + } +} + +// SetPrompt sets the prompt to be used when reading subsequent lines. +func (t *Terminal) SetPrompt(prompt string) { + t.lock.Lock() + defer t.lock.Unlock() + + t.prompt = []rune(prompt) +} + +func (t *Terminal) clearAndRepaintLinePlusNPrevious(numPrevLines int) { + // Move cursor to column zero at the start of the line. + t.move(t.cursorY, 0, t.cursorX, 0) + t.cursorX, t.cursorY = 0, 0 + t.clearLineToRight() + for t.cursorY < numPrevLines { + // Move down a line + t.move(0, 1, 0, 0) + t.cursorY++ + t.clearLineToRight() + } + // Move back to beginning. + t.move(t.cursorY, 0, 0, 0) + t.cursorX, t.cursorY = 0, 0 + + t.queue(t.prompt) + t.advanceCursor(visualLength(t.prompt)) + t.writeLine(t.line) + t.moveCursorToPos(t.pos) +} + +func (t *Terminal) SetSize(width, height int) error { + t.lock.Lock() + defer t.lock.Unlock() + + if width == 0 { + width = 1 + } + + oldWidth := t.termWidth + t.termWidth, t.termHeight = width, height + + switch { + case width == oldWidth: + // If the width didn't change then nothing else needs to be + // done. + return nil + case len(t.line) == 0 && t.cursorX == 0 && t.cursorY == 0: + // If there is nothing on current line and no prompt printed, + // just do nothing + return nil + case width < oldWidth: + // Some terminals (e.g. xterm) will truncate lines that were + // too long when shinking. Others, (e.g. gnome-terminal) will + // attempt to wrap them. For the former, repainting t.maxLine + // works great, but that behaviour goes badly wrong in the case + // of the latter because they have doubled every full line. + + // We assume that we are working on a terminal that wraps lines + // and adjust the cursor position based on every previous line + // wrapping and turning into two. This causes the prompt on + // xterms to move upwards, which isn't great, but it avoids a + // huge mess with gnome-terminal. + if t.cursorX >= t.termWidth { + t.cursorX = t.termWidth - 1 + } + t.cursorY *= 2 + t.clearAndRepaintLinePlusNPrevious(t.maxLine * 2) + case width > oldWidth: + // If the terminal expands then our position calculations will + // be wrong in the future because we think the cursor is + // |t.pos| chars into the string, but there will be a gap at + // the end of any wrapped line. + // + // But the position will actually be correct until we move, so + // we can move back to the beginning and repaint everything. + t.clearAndRepaintLinePlusNPrevious(t.maxLine) + } + + _, err := t.c.Write(t.outBuf) + t.outBuf = t.outBuf[:0] + return err +} + +type pasteIndicatorError struct{} + +func (pasteIndicatorError) Error() string { + return "terminal: ErrPasteIndicator not correctly handled" +} + +// ErrPasteIndicator may be returned from ReadLine as the error, in addition +// to valid line data. It indicates that bracketed paste mode is enabled and +// that the returned line consists only of pasted data. Programs may wish to +// interpret pasted data more literally than typed data. +var ErrPasteIndicator = pasteIndicatorError{} + +// SetBracketedPasteMode requests that the terminal bracket paste operations +// with markers. Not all terminals support this but, if it is supported, then +// enabling this mode will stop any autocomplete callback from running due to +// pastes. Additionally, any lines that are completely pasted will be returned +// from ReadLine with the error set to ErrPasteIndicator. +func (t *Terminal) SetBracketedPasteMode(on bool) { + if on { + io.WriteString(t.c, "\x1b[?2004h") + } else { + io.WriteString(t.c, "\x1b[?2004l") + } +} + +// stRingBuffer is a ring buffer of strings. +type stRingBuffer struct { + // entries contains max elements. + entries []string + max int + // head contains the index of the element most recently added to the ring. + head int + // size contains the number of elements in the ring. + size int +} + +func (s *stRingBuffer) Add(a string) { + if s.entries == nil { + const defaultNumEntries = 100 + s.entries = make([]string, defaultNumEntries) + s.max = defaultNumEntries + } + + s.head = (s.head + 1) % s.max + s.entries[s.head] = a + if s.size < s.max { + s.size++ + } +} + +// NthPreviousEntry returns the value passed to the nth previous call to Add. +// If n is zero then the immediately prior value is returned, if one, then the +// next most recent, and so on. If such an element doesn't exist then ok is +// false. +func (s *stRingBuffer) NthPreviousEntry(n int) (value string, ok bool) { + if n >= s.size { + return "", false + } + index := s.head - n + if index < 0 { + index += s.max + } + return s.entries[index], true +} + +// readPasswordLine reads from reader until it finds \n or io.EOF. +// The slice returned does not include the \n. +// readPasswordLine also ignores any \r it finds. +func readPasswordLine(reader io.Reader) ([]byte, error) { + var buf [1]byte + var ret []byte + + for { + n, err := reader.Read(buf[:]) + if n > 0 { + switch buf[0] { + case '\n': + return ret, nil + case '\r': + // remove \r from passwords on Windows + default: + ret = append(ret, buf[0]) + } + continue + } + if err != nil { + if err == io.EOF && len(ret) > 0 { + return ret, nil + } + return ret, err + } + } +} diff --git a/vendor/golang.org/x/crypto/ssh/terminal/terminal_test.go b/vendor/golang.org/x/crypto/ssh/terminal/terminal_test.go new file mode 100644 index 0000000000000000000000000000000000000000..901c72ab354cdaf1659e6bdc1ccb21f50a817092 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/terminal/terminal_test.go @@ -0,0 +1,350 @@ +// 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 terminal + +import ( + "bytes" + "io" + "os" + "testing" +) + +type MockTerminal struct { + toSend []byte + bytesPerRead int + received []byte +} + +func (c *MockTerminal) Read(data []byte) (n int, err error) { + n = len(data) + if n == 0 { + return + } + if n > len(c.toSend) { + n = len(c.toSend) + } + if n == 0 { + return 0, io.EOF + } + if c.bytesPerRead > 0 && n > c.bytesPerRead { + n = c.bytesPerRead + } + copy(data, c.toSend[:n]) + c.toSend = c.toSend[n:] + return +} + +func (c *MockTerminal) Write(data []byte) (n int, err error) { + c.received = append(c.received, data...) + return len(data), nil +} + +func TestClose(t *testing.T) { + c := &MockTerminal{} + ss := NewTerminal(c, "> ") + line, err := ss.ReadLine() + if line != "" { + t.Errorf("Expected empty line but got: %s", line) + } + if err != io.EOF { + t.Errorf("Error should have been EOF but got: %s", err) + } +} + +var keyPressTests = []struct { + in string + line string + err error + throwAwayLines int +}{ + { + err: io.EOF, + }, + { + in: "\r", + line: "", + }, + { + in: "foo\r", + line: "foo", + }, + { + in: "a\x1b[Cb\r", // right + line: "ab", + }, + { + in: "a\x1b[Db\r", // left + line: "ba", + }, + { + in: "a\177b\r", // backspace + line: "b", + }, + { + in: "\x1b[A\r", // up + }, + { + in: "\x1b[B\r", // down + }, + { + in: "line\x1b[A\x1b[B\r", // up then down + line: "line", + }, + { + in: "line1\rline2\x1b[A\r", // recall previous line. + line: "line1", + throwAwayLines: 1, + }, + { + // recall two previous lines and append. + in: "line1\rline2\rline3\x1b[A\x1b[Axxx\r", + line: "line1xxx", + throwAwayLines: 2, + }, + { + // Ctrl-A to move to beginning of line followed by ^K to kill + // line. + in: "a b \001\013\r", + line: "", + }, + { + // Ctrl-A to move to beginning of line, Ctrl-E to move to end, + // finally ^K to kill nothing. + in: "a b \001\005\013\r", + line: "a b ", + }, + { + in: "\027\r", + line: "", + }, + { + in: "a\027\r", + line: "", + }, + { + in: "a \027\r", + line: "", + }, + { + in: "a b\027\r", + line: "a ", + }, + { + in: "a b \027\r", + line: "a ", + }, + { + in: "one two thr\x1b[D\027\r", + line: "one two r", + }, + { + in: "\013\r", + line: "", + }, + { + in: "a\013\r", + line: "a", + }, + { + in: "ab\x1b[D\013\r", + line: "a", + }, + { + in: "Ξεσκεπάζω\r", + line: "Ξεσκεπάζω", + }, + { + in: "£\r\x1b[A\177\r", // non-ASCII char, enter, up, backspace. + line: "", + throwAwayLines: 1, + }, + { + in: "£\r££\x1b[A\x1b[B\177\r", // non-ASCII char, enter, 2x non-ASCII, up, down, backspace, enter. + line: "£", + throwAwayLines: 1, + }, + { + // Ctrl-D at the end of the line should be ignored. + in: "a\004\r", + line: "a", + }, + { + // a, b, left, Ctrl-D should erase the b. + in: "ab\x1b[D\004\r", + line: "a", + }, + { + // a, b, c, d, left, left, ^U should erase to the beginning of + // the line. + in: "abcd\x1b[D\x1b[D\025\r", + line: "cd", + }, + { + // Bracketed paste mode: control sequences should be returned + // verbatim in paste mode. + in: "abc\x1b[200~de\177f\x1b[201~\177\r", + line: "abcde\177", + }, + { + // Enter in bracketed paste mode should still work. + in: "abc\x1b[200~d\refg\x1b[201~h\r", + line: "efgh", + throwAwayLines: 1, + }, + { + // Lines consisting entirely of pasted data should be indicated as such. + in: "\x1b[200~a\r", + line: "a", + err: ErrPasteIndicator, + }, +} + +func TestKeyPresses(t *testing.T) { + for i, test := range keyPressTests { + for j := 1; j < len(test.in); j++ { + c := &MockTerminal{ + toSend: []byte(test.in), + bytesPerRead: j, + } + ss := NewTerminal(c, "> ") + for k := 0; k < test.throwAwayLines; k++ { + _, err := ss.ReadLine() + if err != nil { + t.Errorf("Throwaway line %d from test %d resulted in error: %s", k, i, err) + } + } + line, err := ss.ReadLine() + if line != test.line { + t.Errorf("Line resulting from test %d (%d bytes per read) was '%s', expected '%s'", i, j, line, test.line) + break + } + if err != test.err { + t.Errorf("Error resulting from test %d (%d bytes per read) was '%v', expected '%v'", i, j, err, test.err) + break + } + } + } +} + +func TestPasswordNotSaved(t *testing.T) { + c := &MockTerminal{ + toSend: []byte("password\r\x1b[A\r"), + bytesPerRead: 1, + } + ss := NewTerminal(c, "> ") + pw, _ := ss.ReadPassword("> ") + if pw != "password" { + t.Fatalf("failed to read password, got %s", pw) + } + line, _ := ss.ReadLine() + if len(line) > 0 { + t.Fatalf("password was saved in history") + } +} + +var setSizeTests = []struct { + width, height int +}{ + {40, 13}, + {80, 24}, + {132, 43}, +} + +func TestTerminalSetSize(t *testing.T) { + for _, setSize := range setSizeTests { + c := &MockTerminal{ + toSend: []byte("password\r\x1b[A\r"), + bytesPerRead: 1, + } + ss := NewTerminal(c, "> ") + ss.SetSize(setSize.width, setSize.height) + pw, _ := ss.ReadPassword("Password: ") + if pw != "password" { + t.Fatalf("failed to read password, got %s", pw) + } + if string(c.received) != "Password: \r\n" { + t.Errorf("failed to set the temporary prompt expected %q, got %q", "Password: ", c.received) + } + } +} + +func TestReadPasswordLineEnd(t *testing.T) { + var tests = []struct { + input string + want string + }{ + {"\n", ""}, + {"\r\n", ""}, + {"test\r\n", "test"}, + {"testtesttesttes\n", "testtesttesttes"}, + {"testtesttesttes\r\n", "testtesttesttes"}, + {"testtesttesttesttest\n", "testtesttesttesttest"}, + {"testtesttesttesttest\r\n", "testtesttesttesttest"}, + } + for _, test := range tests { + buf := new(bytes.Buffer) + if _, err := buf.WriteString(test.input); err != nil { + t.Fatal(err) + } + + have, err := readPasswordLine(buf) + if err != nil { + t.Errorf("readPasswordLine(%q) failed: %v", test.input, err) + continue + } + if string(have) != test.want { + t.Errorf("readPasswordLine(%q) returns %q, but %q is expected", test.input, string(have), test.want) + continue + } + + if _, err = buf.WriteString(test.input); err != nil { + t.Fatal(err) + } + have, err = readPasswordLine(buf) + if err != nil { + t.Errorf("readPasswordLine(%q) failed: %v", test.input, err) + continue + } + if string(have) != test.want { + t.Errorf("readPasswordLine(%q) returns %q, but %q is expected", test.input, string(have), test.want) + continue + } + } +} + +func TestMakeRawState(t *testing.T) { + fd := int(os.Stdout.Fd()) + if !IsTerminal(fd) { + t.Skip("stdout is not a terminal; skipping test") + } + + st, err := GetState(fd) + if err != nil { + t.Fatalf("failed to get terminal state from GetState: %s", err) + } + defer Restore(fd, st) + raw, err := MakeRaw(fd) + if err != nil { + t.Fatalf("failed to get terminal state from MakeRaw: %s", err) + } + + if *st != *raw { + t.Errorf("states do not match; was %v, expected %v", raw, st) + } +} + +func TestOutputNewlines(t *testing.T) { + // \n should be changed to \r\n in terminal output. + buf := new(bytes.Buffer) + term := NewTerminal(buf, ">") + + term.Write([]byte("1\n2\n")) + output := string(buf.Bytes()) + const expected = "1\r\n2\r\n" + + if output != expected { + t.Errorf("incorrect output: was %q, expected %q", output, expected) + } +} diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util.go b/vendor/golang.org/x/crypto/ssh/terminal/util.go new file mode 100644 index 0000000000000000000000000000000000000000..02dad484e5cfccc10fd75d2a48ceb2a50ea9ed57 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/terminal/util.go @@ -0,0 +1,116 @@ +// 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. + +// +build darwin dragonfly freebsd linux,!appengine netbsd openbsd + +// Package terminal provides support functions for dealing with terminals, as +// commonly found on UNIX systems. +// +// Putting a terminal into raw mode is the most common requirement: +// +// oldState, err := terminal.MakeRaw(0) +// if err != nil { +// panic(err) +// } +// defer terminal.Restore(0, oldState) +package terminal // import "golang.org/x/crypto/ssh/terminal" + +import ( + "golang.org/x/sys/unix" +) + +// State contains the state of a terminal. +type State struct { + termios unix.Termios +} + +// IsTerminal returns true if the given file descriptor is a terminal. +func IsTerminal(fd int) bool { + _, err := unix.IoctlGetTermios(fd, ioctlReadTermios) + return err == nil +} + +// MakeRaw put the terminal connected to the given file descriptor into raw +// mode and returns the previous state of the terminal so that it can be +// restored. +func MakeRaw(fd int) (*State, error) { + termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios) + if err != nil { + return nil, err + } + + oldState := State{termios: *termios} + + // This attempts to replicate the behaviour documented for cfmakeraw in + // the termios(3) manpage. + termios.Iflag &^= unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON + termios.Oflag &^= unix.OPOST + termios.Lflag &^= unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN + termios.Cflag &^= unix.CSIZE | unix.PARENB + termios.Cflag |= unix.CS8 + termios.Cc[unix.VMIN] = 1 + termios.Cc[unix.VTIME] = 0 + if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, termios); err != nil { + return nil, err + } + + return &oldState, nil +} + +// GetState returns the current state of a terminal which may be useful to +// restore the terminal after a signal. +func GetState(fd int) (*State, error) { + termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios) + if err != nil { + return nil, err + } + + return &State{termios: *termios}, nil +} + +// Restore restores the terminal connected to the given file descriptor to a +// previous state. +func Restore(fd int, state *State) error { + return unix.IoctlSetTermios(fd, ioctlWriteTermios, &state.termios) +} + +// GetSize returns the dimensions of the given terminal. +func GetSize(fd int) (width, height int, err error) { + ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ) + if err != nil { + return -1, -1, err + } + return int(ws.Col), int(ws.Row), nil +} + +// passwordReader is an io.Reader that reads from a specific file descriptor. +type passwordReader int + +func (r passwordReader) Read(buf []byte) (int, error) { + return unix.Read(int(r), buf) +} + +// ReadPassword reads a line of input from a terminal without local echo. This +// is commonly used for inputting passwords and other sensitive data. The slice +// returned does not include the \n. +func ReadPassword(fd int) ([]byte, error) { + termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios) + if err != nil { + return nil, err + } + + newState := *termios + newState.Lflag &^= unix.ECHO + newState.Lflag |= unix.ICANON | unix.ISIG + newState.Iflag |= unix.ICRNL + if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, &newState); err != nil { + return nil, err + } + + defer func() { + unix.IoctlSetTermios(fd, ioctlWriteTermios, termios) + }() + + return readPasswordLine(passwordReader(fd)) +} diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go b/vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go new file mode 100644 index 0000000000000000000000000000000000000000..cb23a590494015a5689166d40852762b777dd994 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go @@ -0,0 +1,12 @@ +// 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 darwin dragonfly freebsd netbsd openbsd + +package terminal + +import "golang.org/x/sys/unix" + +const ioctlReadTermios = unix.TIOCGETA +const ioctlWriteTermios = unix.TIOCSETA diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util_linux.go b/vendor/golang.org/x/crypto/ssh/terminal/util_linux.go new file mode 100644 index 0000000000000000000000000000000000000000..5fadfe8a1d50ba10d6d4fea349fe5c7a983eb5da --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/terminal/util_linux.go @@ -0,0 +1,10 @@ +// 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. + +package terminal + +import "golang.org/x/sys/unix" + +const ioctlReadTermios = unix.TCGETS +const ioctlWriteTermios = unix.TCSETS diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util_plan9.go b/vendor/golang.org/x/crypto/ssh/terminal/util_plan9.go new file mode 100644 index 0000000000000000000000000000000000000000..799f049f04ea0ce665e44e018780921e2bed0d02 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/terminal/util_plan9.go @@ -0,0 +1,58 @@ +// Copyright 2016 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 terminal provides support functions for dealing with terminals, as +// commonly found on UNIX systems. +// +// Putting a terminal into raw mode is the most common requirement: +// +// oldState, err := terminal.MakeRaw(0) +// if err != nil { +// panic(err) +// } +// defer terminal.Restore(0, oldState) +package terminal + +import ( + "fmt" + "runtime" +) + +type State struct{} + +// IsTerminal returns true if the given file descriptor is a terminal. +func IsTerminal(fd int) bool { + return false +} + +// MakeRaw put the terminal connected to the given file descriptor into raw +// mode and returns the previous state of the terminal so that it can be +// restored. +func MakeRaw(fd int) (*State, error) { + return nil, fmt.Errorf("terminal: MakeRaw not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) +} + +// GetState returns the current state of a terminal which may be useful to +// restore the terminal after a signal. +func GetState(fd int) (*State, error) { + return nil, fmt.Errorf("terminal: GetState not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) +} + +// Restore restores the terminal connected to the given file descriptor to a +// previous state. +func Restore(fd int, state *State) error { + return fmt.Errorf("terminal: Restore not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) +} + +// GetSize returns the dimensions of the given terminal. +func GetSize(fd int) (width, height int, err error) { + return 0, 0, fmt.Errorf("terminal: GetSize not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) +} + +// ReadPassword reads a line of input from a terminal without local echo. This +// is commonly used for inputting passwords and other sensitive data. The slice +// returned does not include the \n. +func ReadPassword(fd int) ([]byte, error) { + return nil, fmt.Errorf("terminal: ReadPassword not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) +} diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util_solaris.go b/vendor/golang.org/x/crypto/ssh/terminal/util_solaris.go new file mode 100644 index 0000000000000000000000000000000000000000..a2e1b57dc1486a0478d4d0b753122da4228ed1aa --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/terminal/util_solaris.go @@ -0,0 +1,128 @@ +// Copyright 2015 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 solaris + +package terminal // import "golang.org/x/crypto/ssh/terminal" + +import ( + "golang.org/x/sys/unix" + "io" + "syscall" +) + +// State contains the state of a terminal. +type State struct { + state *unix.Termios +} + +// 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 +} + +// ReadPassword reads a line of input from a terminal without local echo. This +// is commonly used for inputting passwords and other sensitive data. The slice +// returned does not include the \n. +func ReadPassword(fd int) ([]byte, error) { + // see also: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libast/common/uwin/getpass.c + val, err := unix.IoctlGetTermios(fd, unix.TCGETS) + if err != nil { + return nil, err + } + oldState := *val + + newState := oldState + newState.Lflag &^= syscall.ECHO + newState.Lflag |= syscall.ICANON | syscall.ISIG + newState.Iflag |= syscall.ICRNL + err = unix.IoctlSetTermios(fd, unix.TCSETS, &newState) + if err != nil { + return nil, err + } + + defer unix.IoctlSetTermios(fd, unix.TCSETS, &oldState) + + var buf [16]byte + var ret []byte + for { + n, err := syscall.Read(fd, buf[:]) + if err != nil { + return nil, err + } + if n == 0 { + if len(ret) == 0 { + return nil, io.EOF + } + break + } + if buf[n-1] == '\n' { + n-- + } + ret = append(ret, buf[:n]...) + if n < len(buf) { + break + } + } + + return ret, nil +} + +// MakeRaw puts the terminal connected to the given file descriptor into raw +// mode and returns the previous state of the terminal so that it can be +// restored. +// see http://cr.illumos.org/~webrev/andy_js/1060/ +func MakeRaw(fd int) (*State, error) { + oldTermiosPtr, err := unix.IoctlGetTermios(fd, unix.TCGETS) + if err != nil { + return nil, err + } + oldTermios := *oldTermiosPtr + + newTermios := oldTermios + newTermios.Iflag &^= syscall.IGNBRK | syscall.BRKINT | syscall.PARMRK | syscall.ISTRIP | syscall.INLCR | syscall.IGNCR | syscall.ICRNL | syscall.IXON + newTermios.Oflag &^= syscall.OPOST + newTermios.Lflag &^= syscall.ECHO | syscall.ECHONL | syscall.ICANON | syscall.ISIG | syscall.IEXTEN + newTermios.Cflag &^= syscall.CSIZE | syscall.PARENB + newTermios.Cflag |= syscall.CS8 + newTermios.Cc[unix.VMIN] = 1 + newTermios.Cc[unix.VTIME] = 0 + + if err := unix.IoctlSetTermios(fd, unix.TCSETS, &newTermios); err != nil { + return nil, err + } + + return &State{ + state: oldTermiosPtr, + }, nil +} + +// Restore restores the terminal connected to the given file descriptor to a +// previous state. +func Restore(fd int, oldState *State) error { + return unix.IoctlSetTermios(fd, unix.TCSETS, oldState.state) +} + +// GetState returns the current state of a terminal which may be useful to +// restore the terminal after a signal. +func GetState(fd int) (*State, error) { + oldTermiosPtr, err := unix.IoctlGetTermios(fd, unix.TCGETS) + if err != nil { + return nil, err + } + + return &State{ + state: oldTermiosPtr, + }, nil +} + +// GetSize returns the dimensions of the given terminal. +func GetSize(fd int) (width, height int, err error) { + ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ) + if err != nil { + return 0, 0, err + } + return int(ws.Col), int(ws.Row), nil +} diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go b/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go new file mode 100644 index 0000000000000000000000000000000000000000..4933ac36118f748f97c795427d0535a1a930c2ee --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go @@ -0,0 +1,105 @@ +// 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. + +// +build windows + +// Package terminal provides support functions for dealing with terminals, as +// commonly found on UNIX systems. +// +// Putting a terminal into raw mode is the most common requirement: +// +// oldState, err := terminal.MakeRaw(0) +// if err != nil { +// panic(err) +// } +// defer terminal.Restore(0, oldState) +package terminal + +import ( + "os" + + "golang.org/x/sys/windows" +) + +type State struct { + mode uint32 +} + +// IsTerminal returns true if the given file descriptor is a terminal. +func IsTerminal(fd int) bool { + var st uint32 + err := windows.GetConsoleMode(windows.Handle(fd), &st) + return err == nil +} + +// MakeRaw put the terminal connected to the given file descriptor into raw +// mode and returns the previous state of the terminal so that it can be +// restored. +func MakeRaw(fd int) (*State, error) { + var st uint32 + if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil { + return nil, err + } + raw := st &^ (windows.ENABLE_ECHO_INPUT | windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT) + if err := windows.SetConsoleMode(windows.Handle(fd), raw); err != nil { + return nil, err + } + return &State{st}, nil +} + +// GetState returns the current state of a terminal which may be useful to +// restore the terminal after a signal. +func GetState(fd int) (*State, error) { + var st uint32 + if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil { + return nil, err + } + return &State{st}, nil +} + +// Restore restores the terminal connected to the given file descriptor to a +// previous state. +func Restore(fd int, state *State) error { + return windows.SetConsoleMode(windows.Handle(fd), state.mode) +} + +// GetSize returns the dimensions of the given terminal. +func GetSize(fd int) (width, height int, err error) { + var info windows.ConsoleScreenBufferInfo + if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil { + return 0, 0, err + } + return int(info.Size.X), int(info.Size.Y), nil +} + +// ReadPassword reads a line of input from a terminal without local echo. This +// is commonly used for inputting passwords and other sensitive data. The slice +// returned does not include the \n. +func ReadPassword(fd int) ([]byte, error) { + var st uint32 + if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil { + return nil, err + } + old := st + + st &^= (windows.ENABLE_ECHO_INPUT) + st |= (windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT) + if err := windows.SetConsoleMode(windows.Handle(fd), st); err != nil { + return nil, err + } + + defer func() { + windows.SetConsoleMode(windows.Handle(fd), old) + }() + + var h windows.Handle + p, _ := windows.GetCurrentProcess() + if err := windows.DuplicateHandle(p, windows.Handle(fd), p, &h, 0, false, windows.DUPLICATE_SAME_ACCESS); err != nil { + return nil, err + } + + f := os.NewFile(uintptr(h), "stdin") + defer f.Close() + return readPasswordLine(f) +} diff --git a/vendor/golang.org/x/crypto/ssh/test/agent_unix_test.go b/vendor/golang.org/x/crypto/ssh/test/agent_unix_test.go new file mode 100644 index 0000000000000000000000000000000000000000..f481253c9ebb67a72fca32ff2df332e97bd20ade --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/test/agent_unix_test.go @@ -0,0 +1,59 @@ +// 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. + +// +build darwin dragonfly freebsd linux netbsd openbsd + +package test + +import ( + "bytes" + "testing" + + "golang.org/x/crypto/ssh" + "golang.org/x/crypto/ssh/agent" +) + +func TestAgentForward(t *testing.T) { + server := newServer(t) + defer server.Shutdown() + conn := server.Dial(clientConfig()) + defer conn.Close() + + keyring := agent.NewKeyring() + if err := keyring.Add(agent.AddedKey{PrivateKey: testPrivateKeys["dsa"]}); err != nil { + t.Fatalf("Error adding key: %s", err) + } + if err := keyring.Add(agent.AddedKey{ + PrivateKey: testPrivateKeys["dsa"], + ConfirmBeforeUse: true, + LifetimeSecs: 3600, + }); err != nil { + t.Fatalf("Error adding key with constraints: %s", err) + } + pub := testPublicKeys["dsa"] + + sess, err := conn.NewSession() + if err != nil { + t.Fatalf("NewSession: %v", err) + } + if err := agent.RequestAgentForwarding(sess); err != nil { + t.Fatalf("RequestAgentForwarding: %v", err) + } + + if err := agent.ForwardToAgent(conn, keyring); err != nil { + t.Fatalf("SetupForwardKeyring: %v", err) + } + out, err := sess.CombinedOutput("ssh-add -L") + if err != nil { + t.Fatalf("running ssh-add: %v, out %s", err, out) + } + key, _, _, _, err := ssh.ParseAuthorizedKey(out) + if err != nil { + t.Fatalf("ParseAuthorizedKey(%q): %v", out, err) + } + + if !bytes.Equal(key.Marshal(), pub.Marshal()) { + t.Fatalf("got key %s, want %s", ssh.MarshalAuthorizedKey(key), ssh.MarshalAuthorizedKey(pub)) + } +} diff --git a/vendor/golang.org/x/crypto/ssh/test/banner_test.go b/vendor/golang.org/x/crypto/ssh/test/banner_test.go new file mode 100644 index 0000000000000000000000000000000000000000..d3b21ac763a4b73efc0aaf36da0c775ffdacf4e6 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/test/banner_test.go @@ -0,0 +1,32 @@ +// 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. + +// +build darwin dragonfly freebsd linux netbsd openbsd + +package test + +import ( + "testing" +) + +func TestBannerCallbackAgainstOpenSSH(t *testing.T) { + server := newServer(t) + defer server.Shutdown() + + clientConf := clientConfig() + + var receivedBanner string + clientConf.BannerCallback = func(message string) error { + receivedBanner = message + return nil + } + + conn := server.Dial(clientConf) + defer conn.Close() + + expected := "Server Banner" + if receivedBanner != expected { + t.Fatalf("got %v; want %v", receivedBanner, expected) + } +} diff --git a/vendor/golang.org/x/crypto/ssh/test/cert_test.go b/vendor/golang.org/x/crypto/ssh/test/cert_test.go new file mode 100644 index 0000000000000000000000000000000000000000..b231dd80c651a344411a64e170a8cd8f507efd6a --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/test/cert_test.go @@ -0,0 +1,77 @@ +// 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. + +// +build darwin dragonfly freebsd linux netbsd openbsd + +package test + +import ( + "bytes" + "crypto/rand" + "testing" + + "golang.org/x/crypto/ssh" +) + +// Test both logging in with a cert, and also that the certificate presented by an OpenSSH host can be validated correctly +func TestCertLogin(t *testing.T) { + s := newServer(t) + defer s.Shutdown() + + // Use a key different from the default. + clientKey := testSigners["dsa"] + caAuthKey := testSigners["ecdsa"] + cert := &ssh.Certificate{ + Key: clientKey.PublicKey(), + ValidPrincipals: []string{username()}, + CertType: ssh.UserCert, + ValidBefore: ssh.CertTimeInfinity, + } + if err := cert.SignCert(rand.Reader, caAuthKey); err != nil { + t.Fatalf("SetSignature: %v", err) + } + + certSigner, err := ssh.NewCertSigner(cert, clientKey) + if err != nil { + t.Fatalf("NewCertSigner: %v", err) + } + + conf := &ssh.ClientConfig{ + User: username(), + HostKeyCallback: (&ssh.CertChecker{ + IsHostAuthority: func(pk ssh.PublicKey, addr string) bool { + return bytes.Equal(pk.Marshal(), testPublicKeys["ca"].Marshal()) + }, + }).CheckHostKey, + } + conf.Auth = append(conf.Auth, ssh.PublicKeys(certSigner)) + + for _, test := range []struct { + addr string + succeed bool + }{ + {addr: "host.example.com:22", succeed: true}, + {addr: "host.example.com:10000", succeed: true}, // non-standard port must be OK + {addr: "host.example.com", succeed: false}, // port must be specified + {addr: "host.ex4mple.com:22", succeed: false}, // wrong host + } { + client, err := s.TryDialWithAddr(conf, test.addr) + + // Always close client if opened successfully + if err == nil { + client.Close() + } + + // Now evaluate whether the test failed or passed + if test.succeed { + if err != nil { + t.Fatalf("TryDialWithAddr: %v", err) + } + } else { + if err == nil { + t.Fatalf("TryDialWithAddr, unexpected success") + } + } + } +} diff --git a/vendor/golang.org/x/crypto/ssh/test/dial_unix_test.go b/vendor/golang.org/x/crypto/ssh/test/dial_unix_test.go new file mode 100644 index 0000000000000000000000000000000000000000..091e48cc1d1378dd6c7a23a9b49994e5d21ec405 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/test/dial_unix_test.go @@ -0,0 +1,128 @@ +// 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 !windows + +package test + +// direct-tcpip and direct-streamlocal functional tests + +import ( + "fmt" + "io" + "io/ioutil" + "net" + "strings" + "testing" +) + +type dialTester interface { + TestServerConn(t *testing.T, c net.Conn) + TestClientConn(t *testing.T, c net.Conn) +} + +func testDial(t *testing.T, n, listenAddr string, x dialTester) { + server := newServer(t) + defer server.Shutdown() + sshConn := server.Dial(clientConfig()) + defer sshConn.Close() + + l, err := net.Listen(n, listenAddr) + if err != nil { + t.Fatalf("Listen: %v", err) + } + defer l.Close() + + testData := fmt.Sprintf("hello from %s, %s", n, listenAddr) + go func() { + for { + c, err := l.Accept() + if err != nil { + break + } + x.TestServerConn(t, c) + + io.WriteString(c, testData) + c.Close() + } + }() + + conn, err := sshConn.Dial(n, l.Addr().String()) + if err != nil { + t.Fatalf("Dial: %v", err) + } + x.TestClientConn(t, conn) + defer conn.Close() + b, err := ioutil.ReadAll(conn) + if err != nil { + t.Fatalf("ReadAll: %v", err) + } + t.Logf("got %q", string(b)) + if string(b) != testData { + t.Fatalf("expected %q, got %q", testData, string(b)) + } +} + +type tcpDialTester struct { + listenAddr string +} + +func (x *tcpDialTester) TestServerConn(t *testing.T, c net.Conn) { + host := strings.Split(x.listenAddr, ":")[0] + prefix := host + ":" + if !strings.HasPrefix(c.LocalAddr().String(), prefix) { + t.Fatalf("expected to start with %q, got %q", prefix, c.LocalAddr().String()) + } + if !strings.HasPrefix(c.RemoteAddr().String(), prefix) { + t.Fatalf("expected to start with %q, got %q", prefix, c.RemoteAddr().String()) + } +} + +func (x *tcpDialTester) TestClientConn(t *testing.T, c net.Conn) { + // we use zero addresses. see *Client.Dial. + if c.LocalAddr().String() != "0.0.0.0:0" { + t.Fatalf("expected \"0.0.0.0:0\", got %q", c.LocalAddr().String()) + } + if c.RemoteAddr().String() != "0.0.0.0:0" { + t.Fatalf("expected \"0.0.0.0:0\", got %q", c.RemoteAddr().String()) + } +} + +func TestDialTCP(t *testing.T) { + x := &tcpDialTester{ + listenAddr: "127.0.0.1:0", + } + testDial(t, "tcp", x.listenAddr, x) +} + +type unixDialTester struct { + listenAddr string +} + +func (x *unixDialTester) TestServerConn(t *testing.T, c net.Conn) { + if c.LocalAddr().String() != x.listenAddr { + t.Fatalf("expected %q, got %q", x.listenAddr, c.LocalAddr().String()) + } + if c.RemoteAddr().String() != "@" { + t.Fatalf("expected \"@\", got %q", c.RemoteAddr().String()) + } +} + +func (x *unixDialTester) TestClientConn(t *testing.T, c net.Conn) { + if c.RemoteAddr().String() != x.listenAddr { + t.Fatalf("expected %q, got %q", x.listenAddr, c.RemoteAddr().String()) + } + if c.LocalAddr().String() != "@" { + t.Fatalf("expected \"@\", got %q", c.LocalAddr().String()) + } +} + +func TestDialUnix(t *testing.T) { + addr, cleanup := newTempSocket(t) + defer cleanup() + x := &unixDialTester{ + listenAddr: addr, + } + testDial(t, "unix", x.listenAddr, x) +} diff --git a/vendor/golang.org/x/crypto/ssh/test/doc.go b/vendor/golang.org/x/crypto/ssh/test/doc.go new file mode 100644 index 0000000000000000000000000000000000000000..198f0ca1e20570e4a8247d44958fd0dce3f78f2a --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/test/doc.go @@ -0,0 +1,7 @@ +// 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 test contains integration tests for the +// golang.org/x/crypto/ssh package. +package test // import "golang.org/x/crypto/ssh/test" diff --git a/vendor/golang.org/x/crypto/ssh/test/forward_unix_test.go b/vendor/golang.org/x/crypto/ssh/test/forward_unix_test.go new file mode 100644 index 0000000000000000000000000000000000000000..ea819378038ed238b627cac3d0ee383c5a2e1c9e --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/test/forward_unix_test.go @@ -0,0 +1,194 @@ +// 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 darwin dragonfly freebsd linux netbsd openbsd + +package test + +import ( + "bytes" + "io" + "io/ioutil" + "math/rand" + "net" + "testing" + "time" +) + +type closeWriter interface { + CloseWrite() error +} + +func testPortForward(t *testing.T, n, listenAddr string) { + server := newServer(t) + defer server.Shutdown() + conn := server.Dial(clientConfig()) + defer conn.Close() + + sshListener, err := conn.Listen(n, listenAddr) + if err != nil { + t.Fatal(err) + } + + go func() { + sshConn, err := sshListener.Accept() + if err != nil { + t.Fatalf("listen.Accept failed: %v", err) + } + + _, err = io.Copy(sshConn, sshConn) + if err != nil && err != io.EOF { + t.Fatalf("ssh client copy: %v", err) + } + sshConn.Close() + }() + + forwardedAddr := sshListener.Addr().String() + netConn, err := net.Dial(n, forwardedAddr) + if err != nil { + t.Fatalf("net dial failed: %v", err) + } + + readChan := make(chan []byte) + go func() { + data, _ := ioutil.ReadAll(netConn) + readChan <- data + }() + + // Invent some data. + data := make([]byte, 100*1000) + for i := range data { + data[i] = byte(i % 255) + } + + var sent []byte + for len(sent) < 1000*1000 { + // Send random sized chunks + m := rand.Intn(len(data)) + n, err := netConn.Write(data[:m]) + if err != nil { + break + } + sent = append(sent, data[:n]...) + } + if err := netConn.(closeWriter).CloseWrite(); err != nil { + t.Errorf("netConn.CloseWrite: %v", err) + } + + read := <-readChan + + if len(sent) != len(read) { + t.Fatalf("got %d bytes, want %d", len(read), len(sent)) + } + if bytes.Compare(sent, read) != 0 { + t.Fatalf("read back data does not match") + } + + if err := sshListener.Close(); err != nil { + t.Fatalf("sshListener.Close: %v", err) + } + + // Check that the forward disappeared. + netConn, err = net.Dial(n, forwardedAddr) + if err == nil { + netConn.Close() + t.Errorf("still listening to %s after closing", forwardedAddr) + } +} + +func TestPortForwardTCP(t *testing.T) { + testPortForward(t, "tcp", "localhost:0") +} + +func TestPortForwardUnix(t *testing.T) { + addr, cleanup := newTempSocket(t) + defer cleanup() + testPortForward(t, "unix", addr) +} + +func testAcceptClose(t *testing.T, n, listenAddr string) { + server := newServer(t) + defer server.Shutdown() + conn := server.Dial(clientConfig()) + + sshListener, err := conn.Listen(n, listenAddr) + if err != nil { + t.Fatal(err) + } + + quit := make(chan error, 1) + go func() { + for { + c, err := sshListener.Accept() + if err != nil { + quit <- err + break + } + c.Close() + } + }() + sshListener.Close() + + select { + case <-time.After(1 * time.Second): + t.Errorf("timeout: listener did not close.") + case err := <-quit: + t.Logf("quit as expected (error %v)", err) + } +} + +func TestAcceptCloseTCP(t *testing.T) { + testAcceptClose(t, "tcp", "localhost:0") +} + +func TestAcceptCloseUnix(t *testing.T) { + addr, cleanup := newTempSocket(t) + defer cleanup() + testAcceptClose(t, "unix", addr) +} + +// Check that listeners exit if the underlying client transport dies. +func testPortForwardConnectionClose(t *testing.T, n, listenAddr string) { + server := newServer(t) + defer server.Shutdown() + conn := server.Dial(clientConfig()) + + sshListener, err := conn.Listen(n, listenAddr) + if err != nil { + t.Fatal(err) + } + + quit := make(chan error, 1) + go func() { + for { + c, err := sshListener.Accept() + if err != nil { + quit <- err + break + } + c.Close() + } + }() + + // It would be even nicer if we closed the server side, but it + // is more involved as the fd for that side is dup()ed. + server.clientConn.Close() + + select { + case <-time.After(1 * time.Second): + t.Errorf("timeout: listener did not close.") + case err := <-quit: + t.Logf("quit as expected (error %v)", err) + } +} + +func TestPortForwardConnectionCloseTCP(t *testing.T) { + testPortForwardConnectionClose(t, "tcp", "localhost:0") +} + +func TestPortForwardConnectionCloseUnix(t *testing.T) { + addr, cleanup := newTempSocket(t) + defer cleanup() + testPortForwardConnectionClose(t, "unix", addr) +} diff --git a/vendor/golang.org/x/crypto/ssh/test/session_test.go b/vendor/golang.org/x/crypto/ssh/test/session_test.go new file mode 100644 index 0000000000000000000000000000000000000000..4eb7afde87015a9e9c017f8ecb964aa3f5b94c3d --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/test/session_test.go @@ -0,0 +1,443 @@ +// 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 !windows + +package test + +// Session functional tests. + +import ( + "bytes" + "errors" + "fmt" + "io" + "strings" + "testing" + + "golang.org/x/crypto/ssh" +) + +func TestRunCommandSuccess(t *testing.T) { + server := newServer(t) + defer server.Shutdown() + conn := server.Dial(clientConfig()) + defer conn.Close() + + session, err := conn.NewSession() + if err != nil { + t.Fatalf("session failed: %v", err) + } + defer session.Close() + err = session.Run("true") + if err != nil { + t.Fatalf("session failed: %v", err) + } +} + +func TestHostKeyCheck(t *testing.T) { + server := newServer(t) + defer server.Shutdown() + + conf := clientConfig() + hostDB := hostKeyDB() + conf.HostKeyCallback = hostDB.Check + + // change the keys. + hostDB.keys[ssh.KeyAlgoRSA][25]++ + hostDB.keys[ssh.KeyAlgoDSA][25]++ + hostDB.keys[ssh.KeyAlgoECDSA256][25]++ + + conn, err := server.TryDial(conf) + if err == nil { + conn.Close() + t.Fatalf("dial should have failed.") + } else if !strings.Contains(err.Error(), "host key mismatch") { + t.Fatalf("'host key mismatch' not found in %v", err) + } +} + +func TestRunCommandStdin(t *testing.T) { + server := newServer(t) + defer server.Shutdown() + conn := server.Dial(clientConfig()) + defer conn.Close() + + session, err := conn.NewSession() + if err != nil { + t.Fatalf("session failed: %v", err) + } + defer session.Close() + + r, w := io.Pipe() + defer r.Close() + defer w.Close() + session.Stdin = r + + err = session.Run("true") + if err != nil { + t.Fatalf("session failed: %v", err) + } +} + +func TestRunCommandStdinError(t *testing.T) { + server := newServer(t) + defer server.Shutdown() + conn := server.Dial(clientConfig()) + defer conn.Close() + + session, err := conn.NewSession() + if err != nil { + t.Fatalf("session failed: %v", err) + } + defer session.Close() + + r, w := io.Pipe() + defer r.Close() + session.Stdin = r + pipeErr := errors.New("closing write end of pipe") + w.CloseWithError(pipeErr) + + err = session.Run("true") + if err != pipeErr { + t.Fatalf("expected %v, found %v", pipeErr, err) + } +} + +func TestRunCommandFailed(t *testing.T) { + server := newServer(t) + defer server.Shutdown() + conn := server.Dial(clientConfig()) + defer conn.Close() + + session, err := conn.NewSession() + if err != nil { + t.Fatalf("session failed: %v", err) + } + defer session.Close() + err = session.Run(`bash -c "kill -9 $$"`) + if err == nil { + t.Fatalf("session succeeded: %v", err) + } +} + +func TestRunCommandWeClosed(t *testing.T) { + server := newServer(t) + defer server.Shutdown() + conn := server.Dial(clientConfig()) + defer conn.Close() + + session, err := conn.NewSession() + if err != nil { + t.Fatalf("session failed: %v", err) + } + err = session.Shell() + if err != nil { + t.Fatalf("shell failed: %v", err) + } + err = session.Close() + if err != nil { + t.Fatalf("shell failed: %v", err) + } +} + +func TestFuncLargeRead(t *testing.T) { + server := newServer(t) + defer server.Shutdown() + conn := server.Dial(clientConfig()) + defer conn.Close() + + session, err := conn.NewSession() + if err != nil { + t.Fatalf("unable to create new session: %s", err) + } + + stdout, err := session.StdoutPipe() + if err != nil { + t.Fatalf("unable to acquire stdout pipe: %s", err) + } + + err = session.Start("dd if=/dev/urandom bs=2048 count=1024") + if err != nil { + t.Fatalf("unable to execute remote command: %s", err) + } + + buf := new(bytes.Buffer) + n, err := io.Copy(buf, stdout) + if err != nil { + t.Fatalf("error reading from remote stdout: %s", err) + } + + if n != 2048*1024 { + t.Fatalf("Expected %d bytes but read only %d from remote command", 2048, n) + } +} + +func TestKeyChange(t *testing.T) { + server := newServer(t) + defer server.Shutdown() + conf := clientConfig() + hostDB := hostKeyDB() + conf.HostKeyCallback = hostDB.Check + conf.RekeyThreshold = 1024 + conn := server.Dial(conf) + defer conn.Close() + + for i := 0; i < 4; i++ { + session, err := conn.NewSession() + if err != nil { + t.Fatalf("unable to create new session: %s", err) + } + + stdout, err := session.StdoutPipe() + if err != nil { + t.Fatalf("unable to acquire stdout pipe: %s", err) + } + + err = session.Start("dd if=/dev/urandom bs=1024 count=1") + if err != nil { + t.Fatalf("unable to execute remote command: %s", err) + } + buf := new(bytes.Buffer) + n, err := io.Copy(buf, stdout) + if err != nil { + t.Fatalf("error reading from remote stdout: %s", err) + } + + want := int64(1024) + if n != want { + t.Fatalf("Expected %d bytes but read only %d from remote command", want, n) + } + } + + if changes := hostDB.checkCount; changes < 4 { + t.Errorf("got %d key changes, want 4", changes) + } +} + +func TestInvalidTerminalMode(t *testing.T) { + server := newServer(t) + defer server.Shutdown() + conn := server.Dial(clientConfig()) + defer conn.Close() + + session, err := conn.NewSession() + if err != nil { + t.Fatalf("session failed: %v", err) + } + defer session.Close() + + if err = session.RequestPty("vt100", 80, 40, ssh.TerminalModes{255: 1984}); err == nil { + t.Fatalf("req-pty failed: successful request with invalid mode") + } +} + +func TestValidTerminalMode(t *testing.T) { + server := newServer(t) + defer server.Shutdown() + conn := server.Dial(clientConfig()) + defer conn.Close() + + session, err := conn.NewSession() + if err != nil { + t.Fatalf("session failed: %v", err) + } + defer session.Close() + + stdout, err := session.StdoutPipe() + if err != nil { + t.Fatalf("unable to acquire stdout pipe: %s", err) + } + + stdin, err := session.StdinPipe() + if err != nil { + t.Fatalf("unable to acquire stdin pipe: %s", err) + } + + tm := ssh.TerminalModes{ssh.ECHO: 0} + if err = session.RequestPty("xterm", 80, 40, tm); err != nil { + t.Fatalf("req-pty failed: %s", err) + } + + err = session.Shell() + if err != nil { + t.Fatalf("session failed: %s", err) + } + + stdin.Write([]byte("stty -a && exit\n")) + + var buf bytes.Buffer + if _, err := io.Copy(&buf, stdout); err != nil { + t.Fatalf("reading failed: %s", err) + } + + if sttyOutput := buf.String(); !strings.Contains(sttyOutput, "-echo ") { + t.Fatalf("terminal mode failure: expected -echo in stty output, got %s", sttyOutput) + } +} + +func TestWindowChange(t *testing.T) { + server := newServer(t) + defer server.Shutdown() + conn := server.Dial(clientConfig()) + defer conn.Close() + + session, err := conn.NewSession() + if err != nil { + t.Fatalf("session failed: %v", err) + } + defer session.Close() + + stdout, err := session.StdoutPipe() + if err != nil { + t.Fatalf("unable to acquire stdout pipe: %s", err) + } + + stdin, err := session.StdinPipe() + if err != nil { + t.Fatalf("unable to acquire stdin pipe: %s", err) + } + + tm := ssh.TerminalModes{ssh.ECHO: 0} + if err = session.RequestPty("xterm", 80, 40, tm); err != nil { + t.Fatalf("req-pty failed: %s", err) + } + + if err := session.WindowChange(100, 100); err != nil { + t.Fatalf("window-change failed: %s", err) + } + + err = session.Shell() + if err != nil { + t.Fatalf("session failed: %s", err) + } + + stdin.Write([]byte("stty size && exit\n")) + + var buf bytes.Buffer + if _, err := io.Copy(&buf, stdout); err != nil { + t.Fatalf("reading failed: %s", err) + } + + if sttyOutput := buf.String(); !strings.Contains(sttyOutput, "100 100") { + t.Fatalf("terminal WindowChange failure: expected \"100 100\" stty output, got %s", sttyOutput) + } +} + +func testOneCipher(t *testing.T, cipher string, cipherOrder []string) { + server := newServer(t) + defer server.Shutdown() + conf := clientConfig() + conf.Ciphers = []string{cipher} + // Don't fail if sshd doesn't have the cipher. + conf.Ciphers = append(conf.Ciphers, cipherOrder...) + conn, err := server.TryDial(conf) + if err != nil { + t.Fatalf("TryDial: %v", err) + } + defer conn.Close() + + numBytes := 4096 + + // Exercise sending data to the server + if _, _, err := conn.Conn.SendRequest("drop-me", false, make([]byte, numBytes)); err != nil { + t.Fatalf("SendRequest: %v", err) + } + + // Exercise receiving data from the server + session, err := conn.NewSession() + if err != nil { + t.Fatalf("NewSession: %v", err) + } + + out, err := session.Output(fmt.Sprintf("dd if=/dev/zero of=/dev/stdout bs=%d count=1", numBytes)) + if err != nil { + t.Fatalf("Output: %v", err) + } + + if len(out) != numBytes { + t.Fatalf("got %d bytes, want %d bytes", len(out), numBytes) + } +} + +var deprecatedCiphers = []string{ + "aes128-cbc", "3des-cbc", + "arcfour128", "arcfour256", +} + +func TestCiphers(t *testing.T) { + var config ssh.Config + config.SetDefaults() + cipherOrder := append(config.Ciphers, deprecatedCiphers...) + + for _, ciph := range cipherOrder { + t.Run(ciph, func(t *testing.T) { + testOneCipher(t, ciph, cipherOrder) + }) + } +} + +func TestMACs(t *testing.T) { + var config ssh.Config + config.SetDefaults() + macOrder := config.MACs + + for _, mac := range macOrder { + server := newServer(t) + defer server.Shutdown() + conf := clientConfig() + conf.MACs = []string{mac} + // Don't fail if sshd doesn't have the MAC. + conf.MACs = append(conf.MACs, macOrder...) + if conn, err := server.TryDial(conf); err == nil { + conn.Close() + } else { + t.Fatalf("failed for MAC %q", mac) + } + } +} + +func TestKeyExchanges(t *testing.T) { + var config ssh.Config + config.SetDefaults() + kexOrder := config.KeyExchanges + for _, kex := range kexOrder { + server := newServer(t) + defer server.Shutdown() + conf := clientConfig() + // Don't fail if sshd doesn't have the kex. + conf.KeyExchanges = append([]string{kex}, kexOrder...) + conn, err := server.TryDial(conf) + if err == nil { + conn.Close() + } else { + t.Errorf("failed for kex %q", kex) + } + } +} + +func TestClientAuthAlgorithms(t *testing.T) { + for _, key := range []string{ + "rsa", + "dsa", + "ecdsa", + "ed25519", + } { + server := newServer(t) + conf := clientConfig() + conf.SetDefaults() + conf.Auth = []ssh.AuthMethod{ + ssh.PublicKeys(testSigners[key]), + } + + conn, err := server.TryDial(conf) + if err == nil { + conn.Close() + } else { + t.Errorf("failed for key %q", key) + } + + server.Shutdown() + } +} diff --git a/vendor/golang.org/x/crypto/ssh/test/test_unix_test.go b/vendor/golang.org/x/crypto/ssh/test/test_unix_test.go new file mode 100644 index 0000000000000000000000000000000000000000..15b879d35348d5658015afba66b2202557e22f40 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/test/test_unix_test.go @@ -0,0 +1,298 @@ +// 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 darwin dragonfly freebsd linux netbsd openbsd plan9 + +package test + +// functional test harness for unix. + +import ( + "bytes" + "fmt" + "io/ioutil" + "log" + "net" + "os" + "os/exec" + "os/user" + "path/filepath" + "testing" + "text/template" + + "golang.org/x/crypto/ssh" + "golang.org/x/crypto/ssh/testdata" +) + +const sshdConfig = ` +Protocol 2 +Banner {{.Dir}}/banner +HostKey {{.Dir}}/id_rsa +HostKey {{.Dir}}/id_dsa +HostKey {{.Dir}}/id_ecdsa +HostCertificate {{.Dir}}/id_rsa-cert.pub +Pidfile {{.Dir}}/sshd.pid +#UsePrivilegeSeparation no +KeyRegenerationInterval 3600 +ServerKeyBits 768 +SyslogFacility AUTH +LogLevel DEBUG2 +LoginGraceTime 120 +PermitRootLogin no +StrictModes no +RSAAuthentication yes +PubkeyAuthentication yes +AuthorizedKeysFile {{.Dir}}/authorized_keys +TrustedUserCAKeys {{.Dir}}/id_ecdsa.pub +IgnoreRhosts yes +RhostsRSAAuthentication no +HostbasedAuthentication no +PubkeyAcceptedKeyTypes=* +` + +var configTmpl = template.Must(template.New("").Parse(sshdConfig)) + +type server struct { + t *testing.T + cleanup func() // executed during Shutdown + configfile string + cmd *exec.Cmd + output bytes.Buffer // holds stderr from sshd process + + // Client half of the network connection. + clientConn net.Conn +} + +func username() string { + var username string + if user, err := user.Current(); err == nil { + username = user.Username + } else { + // user.Current() currently requires cgo. If an error is + // returned attempt to get the username from the environment. + log.Printf("user.Current: %v; falling back on $USER", err) + username = os.Getenv("USER") + } + if username == "" { + panic("Unable to get username") + } + return username +} + +type storedHostKey struct { + // keys map from an algorithm string to binary key data. + keys map[string][]byte + + // checkCount counts the Check calls. Used for testing + // rekeying. + checkCount int +} + +func (k *storedHostKey) Add(key ssh.PublicKey) { + if k.keys == nil { + k.keys = map[string][]byte{} + } + k.keys[key.Type()] = key.Marshal() +} + +func (k *storedHostKey) Check(addr string, remote net.Addr, key ssh.PublicKey) error { + k.checkCount++ + algo := key.Type() + + if k.keys == nil || bytes.Compare(key.Marshal(), k.keys[algo]) != 0 { + return fmt.Errorf("host key mismatch. Got %q, want %q", key, k.keys[algo]) + } + return nil +} + +func hostKeyDB() *storedHostKey { + keyChecker := &storedHostKey{} + keyChecker.Add(testPublicKeys["ecdsa"]) + keyChecker.Add(testPublicKeys["rsa"]) + keyChecker.Add(testPublicKeys["dsa"]) + return keyChecker +} + +func clientConfig() *ssh.ClientConfig { + config := &ssh.ClientConfig{ + User: username(), + Auth: []ssh.AuthMethod{ + ssh.PublicKeys(testSigners["user"]), + }, + HostKeyCallback: hostKeyDB().Check, + HostKeyAlgorithms: []string{ // by default, don't allow certs as this affects the hostKeyDB checker + ssh.KeyAlgoECDSA256, ssh.KeyAlgoECDSA384, ssh.KeyAlgoECDSA521, + ssh.KeyAlgoRSA, ssh.KeyAlgoDSA, + ssh.KeyAlgoED25519, + }, + } + return config +} + +// unixConnection creates two halves of a connected net.UnixConn. It +// is used for connecting the Go SSH client with sshd without opening +// ports. +func unixConnection() (*net.UnixConn, *net.UnixConn, error) { + dir, err := ioutil.TempDir("", "unixConnection") + if err != nil { + return nil, nil, err + } + defer os.Remove(dir) + + addr := filepath.Join(dir, "ssh") + listener, err := net.Listen("unix", addr) + if err != nil { + return nil, nil, err + } + defer listener.Close() + c1, err := net.Dial("unix", addr) + if err != nil { + return nil, nil, err + } + + c2, err := listener.Accept() + if err != nil { + c1.Close() + return nil, nil, err + } + + return c1.(*net.UnixConn), c2.(*net.UnixConn), nil +} + +func (s *server) TryDial(config *ssh.ClientConfig) (*ssh.Client, error) { + return s.TryDialWithAddr(config, "") +} + +// addr is the user specified host:port. While we don't actually dial it, +// we need to know this for host key matching +func (s *server) TryDialWithAddr(config *ssh.ClientConfig, addr string) (*ssh.Client, error) { + sshd, err := exec.LookPath("sshd") + if err != nil { + s.t.Skipf("skipping test: %v", err) + } + + c1, c2, err := unixConnection() + if err != nil { + s.t.Fatalf("unixConnection: %v", err) + } + + s.cmd = exec.Command(sshd, "-f", s.configfile, "-i", "-e") + f, err := c2.File() + if err != nil { + s.t.Fatalf("UnixConn.File: %v", err) + } + defer f.Close() + s.cmd.Stdin = f + s.cmd.Stdout = f + s.cmd.Stderr = &s.output + if err := s.cmd.Start(); err != nil { + s.t.Fail() + s.Shutdown() + s.t.Fatalf("s.cmd.Start: %v", err) + } + s.clientConn = c1 + conn, chans, reqs, err := ssh.NewClientConn(c1, addr, config) + if err != nil { + return nil, err + } + return ssh.NewClient(conn, chans, reqs), nil +} + +func (s *server) Dial(config *ssh.ClientConfig) *ssh.Client { + conn, err := s.TryDial(config) + if err != nil { + s.t.Fail() + s.Shutdown() + s.t.Fatalf("ssh.Client: %v", err) + } + return conn +} + +func (s *server) Shutdown() { + if s.cmd != nil && s.cmd.Process != nil { + // Don't check for errors; if it fails it's most + // likely "os: process already finished", and we don't + // care about that. Use os.Interrupt, so child + // processes are killed too. + s.cmd.Process.Signal(os.Interrupt) + s.cmd.Wait() + } + if s.t.Failed() { + // log any output from sshd process + s.t.Logf("sshd: %s", s.output.String()) + } + s.cleanup() +} + +func writeFile(path string, contents []byte) { + f, err := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0600) + if err != nil { + panic(err) + } + defer f.Close() + if _, err := f.Write(contents); err != nil { + panic(err) + } +} + +// newServer returns a new mock ssh server. +func newServer(t *testing.T) *server { + if testing.Short() { + t.Skip("skipping test due to -short") + } + dir, err := ioutil.TempDir("", "sshtest") + if err != nil { + t.Fatal(err) + } + f, err := os.Create(filepath.Join(dir, "sshd_config")) + if err != nil { + t.Fatal(err) + } + err = configTmpl.Execute(f, map[string]string{ + "Dir": dir, + }) + if err != nil { + t.Fatal(err) + } + f.Close() + + writeFile(filepath.Join(dir, "banner"), []byte("Server Banner")) + + for k, v := range testdata.PEMBytes { + filename := "id_" + k + writeFile(filepath.Join(dir, filename), v) + writeFile(filepath.Join(dir, filename+".pub"), ssh.MarshalAuthorizedKey(testPublicKeys[k])) + } + + for k, v := range testdata.SSHCertificates { + filename := "id_" + k + "-cert.pub" + writeFile(filepath.Join(dir, filename), v) + } + + var authkeys bytes.Buffer + for k := range testdata.PEMBytes { + authkeys.Write(ssh.MarshalAuthorizedKey(testPublicKeys[k])) + } + writeFile(filepath.Join(dir, "authorized_keys"), authkeys.Bytes()) + + return &server{ + t: t, + configfile: f.Name(), + cleanup: func() { + if err := os.RemoveAll(dir); err != nil { + t.Error(err) + } + }, + } +} + +func newTempSocket(t *testing.T) (string, func()) { + dir, err := ioutil.TempDir("", "socket") + if err != nil { + t.Fatal(err) + } + deferFunc := func() { os.RemoveAll(dir) } + addr := filepath.Join(dir, "sock") + return addr, deferFunc +} diff --git a/vendor/golang.org/x/crypto/ssh/test/testdata_test.go b/vendor/golang.org/x/crypto/ssh/test/testdata_test.go new file mode 100644 index 0000000000000000000000000000000000000000..a053f67eabed4c2d8ce70595a3f8534c634581e4 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/test/testdata_test.go @@ -0,0 +1,64 @@ +// 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. + +// IMPLEMENTATION NOTE: To avoid a package loop, this file is in three places: +// ssh/, ssh/agent, and ssh/test/. It should be kept in sync across all three +// instances. + +package test + +import ( + "crypto/rand" + "fmt" + + "golang.org/x/crypto/ssh" + "golang.org/x/crypto/ssh/testdata" +) + +var ( + testPrivateKeys map[string]interface{} + testSigners map[string]ssh.Signer + testPublicKeys map[string]ssh.PublicKey +) + +func init() { + var err error + + n := len(testdata.PEMBytes) + testPrivateKeys = make(map[string]interface{}, n) + testSigners = make(map[string]ssh.Signer, n) + testPublicKeys = make(map[string]ssh.PublicKey, n) + for t, k := range testdata.PEMBytes { + testPrivateKeys[t], err = ssh.ParseRawPrivateKey(k) + if err != nil { + panic(fmt.Sprintf("Unable to parse test key %s: %v", t, err)) + } + testSigners[t], err = ssh.NewSignerFromKey(testPrivateKeys[t]) + if err != nil { + panic(fmt.Sprintf("Unable to create signer for test key %s: %v", t, err)) + } + testPublicKeys[t] = testSigners[t].PublicKey() + } + + // Create a cert and sign it for use in tests. + testCert := &ssh.Certificate{ + Nonce: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil + ValidPrincipals: []string{"gopher1", "gopher2"}, // increases test coverage + ValidAfter: 0, // unix epoch + ValidBefore: ssh.CertTimeInfinity, // The end of currently representable time. + Reserved: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil + Key: testPublicKeys["ecdsa"], + SignatureKey: testPublicKeys["rsa"], + Permissions: ssh.Permissions{ + CriticalOptions: map[string]string{}, + Extensions: map[string]string{}, + }, + } + testCert.SignCert(rand.Reader, testSigners["rsa"]) + testPrivateKeys["cert"] = testPrivateKeys["ecdsa"] + testSigners["cert"], err = ssh.NewCertSigner(testCert, testSigners["ecdsa"]) + if err != nil { + panic(fmt.Sprintf("Unable to create certificate signer: %v", err)) + } +} diff --git a/vendor/golang.org/x/crypto/ssh/testdata/doc.go b/vendor/golang.org/x/crypto/ssh/testdata/doc.go new file mode 100644 index 0000000000000000000000000000000000000000..fcae47ca6878b4c5f4a026bdc1483fd699bfc5d3 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/testdata/doc.go @@ -0,0 +1,8 @@ +// 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. + +// This package contains test data shared between the various subpackages of +// the golang.org/x/crypto/ssh package. Under no circumstance should +// this data be used for production code. +package testdata // import "golang.org/x/crypto/ssh/testdata" diff --git a/vendor/golang.org/x/crypto/ssh/testdata/keys.go b/vendor/golang.org/x/crypto/ssh/testdata/keys.go new file mode 100644 index 0000000000000000000000000000000000000000..521b6be97f63209438b5670b2fb1e4eec0794789 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/testdata/keys.go @@ -0,0 +1,198 @@ +// 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 testdata + +var PEMBytes = map[string][]byte{ + "dsa": []byte(`-----BEGIN DSA PRIVATE KEY----- +MIIBuwIBAAKBgQD6PDSEyXiI9jfNs97WuM46MSDCYlOqWw80ajN16AohtBncs1YB +lHk//dQOvCYOsYaE+gNix2jtoRjwXhDsc25/IqQbU1ahb7mB8/rsaILRGIbA5WH3 +EgFtJmXFovDz3if6F6TzvhFpHgJRmLYVR8cqsezL3hEZOvvs2iH7MorkxwIVAJHD +nD82+lxh2fb4PMsIiaXudAsBAoGAQRf7Q/iaPRn43ZquUhd6WwvirqUj+tkIu6eV +2nZWYmXLlqFQKEy4Tejl7Wkyzr2OSYvbXLzo7TNxLKoWor6ips0phYPPMyXld14r +juhT24CrhOzuLMhDduMDi032wDIZG4Y+K7ElU8Oufn8Sj5Wge8r6ANmmVgmFfynr +FhdYCngCgYEA3ucGJ93/Mx4q4eKRDxcWD3QzWyqpbRVRRV1Vmih9Ha/qC994nJFz +DQIdjxDIT2Rk2AGzMqFEB68Zc3O+Wcsmz5eWWzEwFxaTwOGWTyDqsDRLm3fD+QYj +nOwuxb0Kce+gWI8voWcqC9cyRm09jGzu2Ab3Bhtpg8JJ8L7gS3MRZK4CFEx4UAfY +Fmsr0W6fHB9nhS4/UXM8 +-----END DSA PRIVATE KEY----- +`), + "ecdsa": []byte(`-----BEGIN EC PRIVATE KEY----- +MHcCAQEEINGWx0zo6fhJ/0EAfrPzVFyFC9s18lBt3cRoEDhS3ARooAoGCCqGSM49 +AwEHoUQDQgAEi9Hdw6KvZcWxfg2IDhA7UkpDtzzt6ZqJXSsFdLd+Kx4S3Sx4cVO+ +6/ZOXRnPmNAlLUqjShUsUBBngG0u2fqEqA== +-----END EC PRIVATE KEY----- +`), + "ecdsap256": []byte(`-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIAPCE25zK0PQSnsgVcEbM1mbKTASH4pqb5QJajplDwDZoAoGCCqGSM49 +AwEHoUQDQgAEWy8TxGcIHRh5XGpO4dFVfDjeNY+VkgubQrf/eyFJZHxAn1SKraXU +qJUjTKj1z622OxYtJ5P7s9CfAEVsTzLCzg== +-----END EC PRIVATE KEY----- +`), + "ecdsap384": []byte(`-----BEGIN EC PRIVATE KEY----- +MIGkAgEBBDBWfSnMuNKq8J9rQLzzEkx3KAoEohSXqhE/4CdjEYtoU2i22HW80DDS +qQhYNHRAduygBwYFK4EEACKhZANiAAQWaDMAd0HUd8ZiXCX7mYDDnC54gwH/nG43 +VhCUEYmF7HMZm/B9Yn3GjFk3qYEDEvuF/52+NvUKBKKaLbh32AWxMv0ibcoba4cz +hL9+hWYhUD9XIUlzMWiZ2y6eBE9PdRI= +-----END EC PRIVATE KEY----- +`), + "ecdsap521": []byte(`-----BEGIN EC PRIVATE KEY----- +MIHcAgEBBEIBrkYpQcy8KTVHNiAkjlFZwee90224Bu6wz94R4OBo+Ts0eoAQG7SF +iaygEDMUbx6kTgXTBcKZ0jrWPKakayNZ/kigBwYFK4EEACOhgYkDgYYABADFuvLV +UoaCDGHcw5uNfdRIsvaLKuWSpLsl48eWGZAwdNG432GDVKduO+pceuE+8XzcyJb+ +uMv+D2b11Q/LQUcHJwE6fqbm8m3EtDKPsoKs0u/XUJb0JsH4J8lkZzbUTjvGYamn +FFlRjzoB3Oxu8UQgb+MWPedtH9XYBbg9biz4jJLkXQ== +-----END EC PRIVATE KEY----- +`), + "rsa": []byte(`-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQC8A6FGHDiWCSREAXCq6yBfNVr0xCVG2CzvktFNRpue+RXrGs/2 +a6ySEJQb3IYquw7HlJgu6fg3WIWhOmHCjfpG0PrL4CRwbqQ2LaPPXhJErWYejcD8 +Di00cF3677+G10KMZk9RXbmHtuBFZT98wxg8j+ZsBMqGM1+7yrWUvynswQIDAQAB +AoGAJMCk5vqfSRzyXOTXLGIYCuR4Kj6pdsbNSeuuRGfYBeR1F2c/XdFAg7D/8s5R +38p/Ih52/Ty5S8BfJtwtvgVY9ecf/JlU/rl/QzhG8/8KC0NG7KsyXklbQ7gJT8UT +Ojmw5QpMk+rKv17ipDVkQQmPaj+gJXYNAHqImke5mm/K/h0CQQDciPmviQ+DOhOq +2ZBqUfH8oXHgFmp7/6pXw80DpMIxgV3CwkxxIVx6a8lVH9bT/AFySJ6vXq4zTuV9 +6QmZcZzDAkEA2j/UXJPIs1fQ8z/6sONOkU/BjtoePFIWJlRxdN35cZjXnBraX5UR +fFHkePv4YwqmXNqrBOvSu+w2WdSDci+IKwJAcsPRc/jWmsrJW1q3Ha0hSf/WG/Bu +X7MPuXaKpP/DkzGoUmb8ks7yqj6XWnYkPNLjCc8izU5vRwIiyWBRf4mxMwJBAILa +NDvRS0rjwt6lJGv7zPZoqDc65VfrK2aNyHx2PgFyzwrEOtuF57bu7pnvEIxpLTeM +z26i6XVMeYXAWZMTloMCQBbpGgEERQpeUknLBqUHhg/wXF6+lFA+vEGnkY+Dwab2 +KCXFGd+SQ5GdUcEMe9isUH6DYj/6/yCDoFrXXmpQb+M= +-----END RSA PRIVATE KEY----- +`), + "ed25519": []byte(`-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW +QyNTUxOQAAACA+3f7hS7g5UWwXOGVTrMfhmxyrjqz7Sxxbx7I1j8DvvwAAAJhAFfkOQBX5 +DgAAAAtzc2gtZWQyNTUxOQAAACA+3f7hS7g5UWwXOGVTrMfhmxyrjqz7Sxxbx7I1j8Dvvw +AAAEAaYmXltfW6nhRo3iWGglRB48lYq0z0Q3I3KyrdutEr6j7d/uFLuDlRbBc4ZVOsx+Gb +HKuOrPtLHFvHsjWPwO+/AAAAE2dhcnRvbm1AZ2FydG9ubS14cHMBAg== +-----END OPENSSH PRIVATE KEY----- +`), + "rsa-openssh-format": []byte(`-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAlwAAAAdzc2gtcn +NhAAAAAwEAAQAAAIEAwa48yfWFi3uIdqzuf9X7C2Zxfea/Iaaw0zIwHudpF8U92WVIiC5l +oEuW1+OaVi3UWfIEjWMV1tHGysrHOwtwc34BPCJqJknUQO/KtDTBTJ4Pryhw1bWPC999Lz +a+yrCTdNQYBzoROXKExZgPFh9pTMi5wqpHDuOQ2qZFIEI3lT0AAAIQWL0H31i9B98AAAAH +c3NoLXJzYQAAAIEAwa48yfWFi3uIdqzuf9X7C2Zxfea/Iaaw0zIwHudpF8U92WVIiC5loE +uW1+OaVi3UWfIEjWMV1tHGysrHOwtwc34BPCJqJknUQO/KtDTBTJ4Pryhw1bWPC999Lza+ +yrCTdNQYBzoROXKExZgPFh9pTMi5wqpHDuOQ2qZFIEI3lT0AAAADAQABAAAAgCThyTGsT4 +IARDxVMhWl6eiB2ZrgFgWSeJm/NOqtppWgOebsIqPMMg4UVuVFsl422/lE3RkPhVkjGXgE +pWvZAdCnmLmApK8wK12vF334lZhZT7t3Z9EzJps88PWEHo7kguf285HcnUM7FlFeissJdk +kXly34y7/3X/a6Tclm+iABAAAAQE0xR/KxZ39slwfMv64Rz7WKk1PPskaryI29aHE3mKHk +pY2QA+P3QlrKxT/VWUMjHUbNNdYfJm48xu0SGNMRdKMAAABBAORh2NP/06JUV3J9W/2Hju +X1ViJuqqcQnJPVzpgSL826EC2xwOECTqoY8uvFpUdD7CtpksIxNVqRIhuNOlz0lqEAAABB +ANkaHTTaPojClO0dKJ/Zjs7pWOCGliebBYprQ/Y4r9QLBkC/XaWMS26gFIrjgC7D2Rv+rZ +wSD0v0RcmkITP1ZR0AAAAYcHF1ZXJuYUBMdWNreUh5ZHJvLmxvY2FsAQID +-----END OPENSSH PRIVATE KEY-----`), + "user": []byte(`-----BEGIN EC PRIVATE KEY----- +MHcCAQEEILYCAeq8f7V4vSSypRw7pxy8yz3V5W4qg8kSC3zJhqpQoAoGCCqGSM49 +AwEHoUQDQgAEYcO2xNKiRUYOLEHM7VYAp57HNyKbOdYtHD83Z4hzNPVC4tM5mdGD +PLL8IEwvYu2wq+lpXfGQnNMbzYf9gspG0w== +-----END EC PRIVATE KEY----- +`), + "ca": []byte(`-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAvg9dQ9IRG59lYJb+GESfKWTch4yBpr7Ydw1jkK6vvtrx9jLo +5hkA8X6+ElRPRqTAZSlN5cBm6YCAcQIOsmXDUn6Oj1lVPQAoOjTBTvsjM3NjGhvv +52kHTY0nsMsBeY9q5DTtlzmlYkVUq2a6Htgf2mNi01dIw5fJ7uTTo8EbNf7O0i3u +c9a8P19HaZl5NKiWN4EIZkfB2WdXYRJCVBsGgQj3dE/GrEmH9QINq1A+GkNvK96u +vZm8H1jjmuqzHplWa7lFeXcx8FTVTbVb/iJrZ2Lc/JvIPitKZWhqbR59yrGjpwEp +Id7bo4WhO5L3OB0fSIJYvfu+o4WYnt4f3UzecwIDAQABAoIBABRD9yHgKErVuC2Q +bA+SYZY8VvdtF/X7q4EmQFORDNRA7EPgMc03JU6awRGbQ8i4kHs46EFzPoXvWcKz +AXYsO6N0Myc900Tp22A5d9NAHATEbPC/wdje7hRq1KyZONMJY9BphFv3nZbY5apR +Dc90JBFZP5RhXjTc3n9GjvqLAKfFEKVmPRCvqxCOZunw6XR+SgIQLJo36nsIsbhW +QUXIVaCI6cXMN8bRPm8EITdBNZu06Fpu4ZHm6VaxlXN9smERCDkgBSNXNWHKxmmA +c3Glo2DByUr2/JFBOrLEe9fkYgr24KNCQkHVcSaFxEcZvTggr7StjKISVHlCNEaB +7Q+kPoECgYEA3zE9FmvFGoQCU4g4Nl3dpQHs6kaAW8vJlrmq3xsireIuaJoa2HMe +wYdIvgCnK9DIjyxd5OWnE4jXtAEYPsyGD32B5rSLQrRO96lgb3f4bESCLUb3Bsn/ +sdgeE3p1xZMA0B59htqCrvVgN9k8WxyevBxYl3/gSBm/p8OVH1RTW/ECgYEA2f9Z +95OLj0KQHQtxQXf+I3VjhCw3LkLW39QZOXVI0QrCJfqqP7uxsJXH9NYX0l0GFTcR +kRrlyoaSU1EGQosZh+n1MvplGBTkTSV47/bPsTzFpgK2NfEZuFm9RoWgltS+nYeH +Y2k4mnAN3PhReCMwuprmJz8GRLsO3Cs2s2YylKMCgYEA2UX+uO/q7jgqZ5UJW+ue +1H5+W0aMuFA3i7JtZEnvRaUVFqFGlwXin/WJ2+WY1++k/rPrJ+Rk9IBXtBUIvEGw +FC5TIfsKQsJyyWgqx/jbbtJ2g4s8+W/1qfTAuqeRNOg5d2DnRDs90wJuS4//0JaY +9HkHyVwkQyxFxhSA/AHEMJECgYA2MvyFR1O9bIk0D3I7GsA+xKLXa77Ua53MzIjw +9i4CezBGDQpjCiFli/fI8am+jY5DnAtsDknvjoG24UAzLy5L0mk6IXMdB6SzYYut +7ak5oahqW+Y9hxIj+XvLmtGQbphtxhJtLu35x75KoBpxSh6FZpmuTEccs31AVCYn +eFM/DQKBgQDOPUwbLKqVi6ddFGgrV9MrWw+SWsDa43bPuyvYppMM3oqesvyaX1Dt +qDvN7owaNxNM4OnfKcZr91z8YPVCFo4RbBif3DXRzjNNBlxEjHBtuMOikwvsmucN +vIrbeEpjTiUMTEAr6PoTiVHjsfS8WAM6MDlF5M+2PNswDsBpa2yLgA== +-----END RSA PRIVATE KEY----- +`), +} + +var SSHCertificates = map[string][]byte{ + // The following are corresponding certificates for the private keys above, signed by the CA key + // Generated by the following commands: + // + // 1. Assumes "rsa" key above in file named "rsa", write out the public key to "rsa.pub": + // ssh-keygen -y -f rsa > rsa.pu + // + // 2. Assumes "ca" key above in file named "ca", sign a cert for "rsa.pub": + // ssh-keygen -s ca -h -n host.example.com -V +500w -I host.example.com-key rsa.pub + "rsa": []byte(`ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgLjYqmmuTSEmjVhSfLQphBSTJMLwIZhRgmpn8FHKLiEIAAAADAQABAAAAgQC8A6FGHDiWCSREAXCq6yBfNVr0xCVG2CzvktFNRpue+RXrGs/2a6ySEJQb3IYquw7HlJgu6fg3WIWhOmHCjfpG0PrL4CRwbqQ2LaPPXhJErWYejcD8Di00cF3677+G10KMZk9RXbmHtuBFZT98wxg8j+ZsBMqGM1+7yrWUvynswQAAAAAAAAAAAAAAAgAAABRob3N0LmV4YW1wbGUuY29tLWtleQAAABQAAAAQaG9zdC5leGFtcGxlLmNvbQAAAABZHN8UAAAAAGsjIYUAAAAAAAAAAAAAAAAAAAEXAAAAB3NzaC1yc2EAAAADAQABAAABAQC+D11D0hEbn2Vglv4YRJ8pZNyHjIGmvth3DWOQrq++2vH2MujmGQDxfr4SVE9GpMBlKU3lwGbpgIBxAg6yZcNSfo6PWVU9ACg6NMFO+yMzc2MaG+/naQdNjSewywF5j2rkNO2XOaViRVSrZroe2B/aY2LTV0jDl8nu5NOjwRs1/s7SLe5z1rw/X0dpmXk0qJY3gQhmR8HZZ1dhEkJUGwaBCPd0T8asSYf1Ag2rUD4aQ28r3q69mbwfWOOa6rMemVZruUV5dzHwVNVNtVv+ImtnYtz8m8g+K0plaGptHn3KsaOnASkh3tujhaE7kvc4HR9Igli9+76jhZie3h/dTN5zAAABDwAAAAdzc2gtcnNhAAABALeDea+60H6xJGhktAyosHaSY7AYzLocaqd8hJQjEIDifBwzoTlnBmcK9CxGhKuaoJFThdCLdaevCeOSuquh8HTkf+2ebZZc/G5T+2thPvPqmcuEcmMosWo+SIjYhbP3S6KD49aLC1X0kz8IBQeauFvURhkZ5ZjhA1L4aQYt9NjL73nqOl8PplRui+Ov5w8b4ldul4zOvYAFrzfcP6wnnXk3c1Zzwwf5wynD5jakO8GpYKBuhM7Z4crzkKSQjU3hla7xqgfomC5Gz4XbR2TNjcQiRrJQ0UlKtX3X3ObRCEhuvG0Kzjklhv+Ddw6txrhKjMjiSi/Yyius/AE8TmC1p4U= host.example.com +`), +} + +var PEMEncryptedKeys = []struct { + Name string + EncryptionKey string + PEMBytes []byte +}{ + 0: { + Name: "rsa-encrypted", + EncryptionKey: "r54-G0pher_t3st$", + PEMBytes: []byte(`-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-128-CBC,3E1714DE130BC5E81327F36564B05462 + +MqW88sud4fnWk/Jk3fkjh7ydu51ZkHLN5qlQgA4SkAXORPPMj2XvqZOv1v2LOgUV +dUevUn8PZK7a9zbZg4QShUSzwE5k6wdB7XKPyBgI39mJ79GBd2U4W3h6KT6jIdWA +goQpluxkrzr2/X602IaxLEre97FT9mpKC6zxKCLvyFWVIP9n3OSFS47cTTXyFr+l +7PdRhe60nn6jSBgUNk/Q1lAvEQ9fufdPwDYY93F1wyJ6lOr0F1+mzRrMbH67NyKs +rG8J1Fa7cIIre7ueKIAXTIne7OAWqpU9UDgQatDtZTbvA7ciqGsSFgiwwW13N+Rr +hN8MkODKs9cjtONxSKi05s206A3NDU6STtZ3KuPDjFE1gMJODotOuqSM+cxKfyFq +wxpk/CHYCDdMAVBSwxb/vraOHamylL4uCHpJdBHypzf2HABt+lS8Su23uAmL87DR +yvyCS/lmpuNTndef6qHPRkoW2EV3xqD3ovosGf7kgwGJUk2ZpCLVteqmYehKlZDK +r/Jy+J26ooI2jIg9bjvD1PZq+Mv+2dQ1RlDrPG3PB+rEixw6vBaL9x3jatCd4ej7 +XG7lb3qO9xFpLsx89tkEcvpGR+broSpUJ6Mu5LBCVmrvqHjvnDhrZVz1brMiQtU9 +iMZbgXqDLXHd6ERWygk7OTU03u+l1gs+KGMfmS0h0ZYw6KGVLgMnsoxqd6cFSKNB +8Ohk9ZTZGCiovlXBUepyu8wKat1k8YlHSfIHoRUJRhhcd7DrmojC+bcbMIZBU22T +Pl2ftVRGtcQY23lYd0NNKfebF7ncjuLWQGy+vZW+7cgfI6wPIbfYfP6g7QAutk6W +KQx0AoX5woZ6cNxtpIrymaVjSMRRBkKQrJKmRp3pC/lul5E5P2cueMs1fj4OHTbJ +lAUv88ywr+R+mRgYQlFW/XQ653f6DT4t6+njfO9oBcPrQDASZel3LjXLpjjYG/N5 ++BWnVexuJX9ika8HJiFl55oqaKb+WknfNhk5cPY+x7SDV9ywQeMiDZpr0ffeYAEP +LlwwiWRDYpO+uwXHSFF3+JjWwjhs8m8g99iFb7U93yKgBB12dCEPPa2ZeH9wUHMJ +sreYhNuq6f4iWWSXpzN45inQqtTi8jrJhuNLTT543ErW7DtntBO2rWMhff3aiXbn +Uy3qzZM1nPbuCGuBmP9L2dJ3Z5ifDWB4JmOyWY4swTZGt9AVmUxMIKdZpRONx8vz +I9u9nbVPGZBcou50Pa0qTLbkWsSL94MNXrARBxzhHC9Zs6XNEtwN7mOuii7uMkVc +adrxgknBH1J1N+NX/eTKzUwJuPvDtA+Z5ILWNN9wpZT/7ed8zEnKHPNUexyeT5g3 +uw9z9jH7ffGxFYlx87oiVPHGOrCXYZYW5uoZE31SCBkbtNuffNRJRKIFeipmpJ3P +7bpAG+kGHMelQH6b+5K1Qgsv4tpuSyKeTKpPFH9Av5nN4P1ZBm9N80tzbNWqjSJm +S7rYdHnuNEVnUGnRmEUMmVuYZnNBEVN/fP2m2SEwXcP3Uh7TiYlcWw10ygaGmOr7 +MvMLGkYgQ4Utwnd98mtqa0jr0hK2TcOSFir3AqVvXN3XJj4cVULkrXe4Im1laWgp +-----END RSA PRIVATE KEY----- +`), + }, + + 1: { + Name: "dsa-encrypted", + EncryptionKey: "qG0pher-dsa_t3st$", + PEMBytes: []byte(`-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-128-CBC,7CE7A6E4A647DC01AF860210B15ADE3E + +hvnBpI99Hceq/55pYRdOzBLntIEis02JFNXuLEydWL+RJBFDn7tA+vXec0ERJd6J +G8JXlSOAhmC2H4uK3q2xR8/Y3yL95n6OIcjvCBiLsV+o3jj1MYJmErxP6zRtq4w3 +JjIjGHWmaYFSxPKQ6e8fs74HEqaeMV9ONUoTtB+aISmgaBL15Fcoayg245dkBvVl +h5Kqspe7yvOBmzA3zjRuxmSCqKJmasXM7mqs3vIrMxZE3XPo1/fWKcPuExgpVQoT +HkJZEoIEIIPnPMwT2uYbFJSGgPJVMDT84xz7yvjCdhLmqrsXgs5Qw7Pw0i0c0BUJ +b7fDJ2UhdiwSckWGmIhTLlJZzr8K+JpjCDlP+REYBI5meB7kosBnlvCEHdw2EJkH +0QDc/2F4xlVrHOLbPRFyu1Oi2Gvbeoo9EsM/DThpd1hKAlb0sF5Y0y0d+owv0PnE +R/4X3HWfIdOHsDUvJ8xVWZ4BZk9Zk9qol045DcFCehpr/3hslCrKSZHakLt9GI58 +vVQJ4L0aYp5nloLfzhViZtKJXRLkySMKdzYkIlNmW1oVGl7tce5UCNI8Nok4j6yn +IiHM7GBn+0nJoKTXsOGMIBe3ulKlKVxLjEuk9yivh/8= +-----END DSA PRIVATE KEY----- +`), + }, +} diff --git a/vendor/golang.org/x/crypto/ssh/testdata_test.go b/vendor/golang.org/x/crypto/ssh/testdata_test.go new file mode 100644 index 0000000000000000000000000000000000000000..2da8c79dc64a43bf3faf7750f4351aec2899f243 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/testdata_test.go @@ -0,0 +1,63 @@ +// 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. + +// IMPLEMENTATION NOTE: To avoid a package loop, this file is in three places: +// ssh/, ssh/agent, and ssh/test/. It should be kept in sync across all three +// instances. + +package ssh + +import ( + "crypto/rand" + "fmt" + + "golang.org/x/crypto/ssh/testdata" +) + +var ( + testPrivateKeys map[string]interface{} + testSigners map[string]Signer + testPublicKeys map[string]PublicKey +) + +func init() { + var err error + + n := len(testdata.PEMBytes) + testPrivateKeys = make(map[string]interface{}, n) + testSigners = make(map[string]Signer, n) + testPublicKeys = make(map[string]PublicKey, n) + for t, k := range testdata.PEMBytes { + testPrivateKeys[t], err = ParseRawPrivateKey(k) + if err != nil { + panic(fmt.Sprintf("Unable to parse test key %s: %v", t, err)) + } + testSigners[t], err = NewSignerFromKey(testPrivateKeys[t]) + if err != nil { + panic(fmt.Sprintf("Unable to create signer for test key %s: %v", t, err)) + } + testPublicKeys[t] = testSigners[t].PublicKey() + } + + // Create a cert and sign it for use in tests. + testCert := &Certificate{ + Nonce: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil + ValidPrincipals: []string{"gopher1", "gopher2"}, // increases test coverage + ValidAfter: 0, // unix epoch + ValidBefore: CertTimeInfinity, // The end of currently representable time. + Reserved: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil + Key: testPublicKeys["ecdsa"], + SignatureKey: testPublicKeys["rsa"], + Permissions: Permissions{ + CriticalOptions: map[string]string{}, + Extensions: map[string]string{}, + }, + } + testCert.SignCert(rand.Reader, testSigners["rsa"]) + testPrivateKeys["cert"] = testPrivateKeys["ecdsa"] + testSigners["cert"], err = NewCertSigner(testCert, testSigners["ecdsa"]) + if err != nil { + panic(fmt.Sprintf("Unable to create certificate signer: %v", err)) + } +} diff --git a/vendor/golang.org/x/crypto/ssh/transport.go b/vendor/golang.org/x/crypto/ssh/transport.go new file mode 100644 index 0000000000000000000000000000000000000000..f6fae1db460465b4991e6ff07e12e31508367aaa --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/transport.go @@ -0,0 +1,353 @@ +// 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 ssh + +import ( + "bufio" + "bytes" + "errors" + "io" + "log" +) + +// debugTransport if set, will print packet types as they go over the +// wire. No message decoding is done, to minimize the impact on timing. +const debugTransport = false + +const ( + gcmCipherID = "aes128-gcm@openssh.com" + aes128cbcID = "aes128-cbc" + tripledescbcID = "3des-cbc" +) + +// packetConn represents a transport that implements packet based +// operations. +type packetConn interface { + // Encrypt and send a packet of data to the remote peer. + writePacket(packet []byte) error + + // Read a packet from the connection. The read is blocking, + // i.e. if error is nil, then the returned byte slice is + // always non-empty. + readPacket() ([]byte, error) + + // Close closes the write-side of the connection. + Close() error +} + +// transport is the keyingTransport that implements the SSH packet +// protocol. +type transport struct { + reader connectionState + writer connectionState + + bufReader *bufio.Reader + bufWriter *bufio.Writer + rand io.Reader + isClient bool + io.Closer +} + +// packetCipher represents a combination of SSH encryption/MAC +// protocol. A single instance should be used for one direction only. +type packetCipher interface { + // writePacket encrypts the packet and writes it to w. The + // contents of the packet are generally scrambled. + writePacket(seqnum uint32, w io.Writer, rand io.Reader, packet []byte) error + + // readPacket reads and decrypts a packet of data. The + // returned packet may be overwritten by future calls of + // readPacket. + readPacket(seqnum uint32, r io.Reader) ([]byte, error) +} + +// connectionState represents one side (read or write) of the +// connection. This is necessary because each direction has its own +// keys, and can even have its own algorithms +type connectionState struct { + packetCipher + seqNum uint32 + dir direction + pendingKeyChange chan packetCipher +} + +// prepareKeyChange sets up key material for a keychange. The key changes in +// both directions are triggered by reading and writing a msgNewKey packet +// respectively. +func (t *transport) prepareKeyChange(algs *algorithms, kexResult *kexResult) error { + ciph, err := newPacketCipher(t.reader.dir, algs.r, kexResult) + if err != nil { + return err + } + t.reader.pendingKeyChange <- ciph + + ciph, err = newPacketCipher(t.writer.dir, algs.w, kexResult) + if err != nil { + return err + } + t.writer.pendingKeyChange <- ciph + + return nil +} + +func (t *transport) printPacket(p []byte, write bool) { + if len(p) == 0 { + return + } + who := "server" + if t.isClient { + who = "client" + } + what := "read" + if write { + what = "write" + } + + log.Println(what, who, p[0]) +} + +// Read and decrypt next packet. +func (t *transport) readPacket() (p []byte, err error) { + for { + p, err = t.reader.readPacket(t.bufReader) + if err != nil { + break + } + if len(p) == 0 || (p[0] != msgIgnore && p[0] != msgDebug) { + break + } + } + if debugTransport { + t.printPacket(p, false) + } + + return p, err +} + +func (s *connectionState) readPacket(r *bufio.Reader) ([]byte, error) { + packet, err := s.packetCipher.readPacket(s.seqNum, r) + s.seqNum++ + if err == nil && len(packet) == 0 { + err = errors.New("ssh: zero length packet") + } + + if len(packet) > 0 { + switch packet[0] { + case msgNewKeys: + select { + case cipher := <-s.pendingKeyChange: + s.packetCipher = cipher + default: + return nil, errors.New("ssh: got bogus newkeys message") + } + + case msgDisconnect: + // Transform a disconnect message into an + // error. Since this is lowest level at which + // we interpret message types, doing it here + // ensures that we don't have to handle it + // elsewhere. + var msg disconnectMsg + if err := Unmarshal(packet, &msg); err != nil { + return nil, err + } + return nil, &msg + } + } + + // The packet may point to an internal buffer, so copy the + // packet out here. + fresh := make([]byte, len(packet)) + copy(fresh, packet) + + return fresh, err +} + +func (t *transport) writePacket(packet []byte) error { + if debugTransport { + t.printPacket(packet, true) + } + return t.writer.writePacket(t.bufWriter, t.rand, packet) +} + +func (s *connectionState) writePacket(w *bufio.Writer, rand io.Reader, packet []byte) error { + changeKeys := len(packet) > 0 && packet[0] == msgNewKeys + + err := s.packetCipher.writePacket(s.seqNum, w, rand, packet) + if err != nil { + return err + } + if err = w.Flush(); err != nil { + return err + } + s.seqNum++ + if changeKeys { + select { + case cipher := <-s.pendingKeyChange: + s.packetCipher = cipher + default: + panic("ssh: no key material for msgNewKeys") + } + } + return err +} + +func newTransport(rwc io.ReadWriteCloser, rand io.Reader, isClient bool) *transport { + t := &transport{ + bufReader: bufio.NewReader(rwc), + bufWriter: bufio.NewWriter(rwc), + rand: rand, + reader: connectionState{ + packetCipher: &streamPacketCipher{cipher: noneCipher{}}, + pendingKeyChange: make(chan packetCipher, 1), + }, + writer: connectionState{ + packetCipher: &streamPacketCipher{cipher: noneCipher{}}, + pendingKeyChange: make(chan packetCipher, 1), + }, + Closer: rwc, + } + t.isClient = isClient + + if isClient { + t.reader.dir = serverKeys + t.writer.dir = clientKeys + } else { + t.reader.dir = clientKeys + t.writer.dir = serverKeys + } + + return t +} + +type direction struct { + ivTag []byte + keyTag []byte + macKeyTag []byte +} + +var ( + serverKeys = direction{[]byte{'B'}, []byte{'D'}, []byte{'F'}} + clientKeys = direction{[]byte{'A'}, []byte{'C'}, []byte{'E'}} +) + +// setupKeys sets the cipher and MAC keys from kex.K, kex.H and sessionId, as +// described in RFC 4253, section 6.4. direction should either be serverKeys +// (to setup server->client keys) or clientKeys (for client->server keys). +func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (packetCipher, error) { + cipherMode := cipherModes[algs.Cipher] + macMode := macModes[algs.MAC] + + iv := make([]byte, cipherMode.ivSize) + key := make([]byte, cipherMode.keySize) + macKey := make([]byte, macMode.keySize) + + generateKeyMaterial(iv, d.ivTag, kex) + generateKeyMaterial(key, d.keyTag, kex) + generateKeyMaterial(macKey, d.macKeyTag, kex) + + return cipherModes[algs.Cipher].create(key, iv, macKey, algs) +} + +// generateKeyMaterial fills out with key material generated from tag, K, H +// and sessionId, as specified in RFC 4253, section 7.2. +func generateKeyMaterial(out, tag []byte, r *kexResult) { + var digestsSoFar []byte + + h := r.Hash.New() + for len(out) > 0 { + h.Reset() + h.Write(r.K) + h.Write(r.H) + + if len(digestsSoFar) == 0 { + h.Write(tag) + h.Write(r.SessionID) + } else { + h.Write(digestsSoFar) + } + + digest := h.Sum(nil) + n := copy(out, digest) + out = out[n:] + if len(out) > 0 { + digestsSoFar = append(digestsSoFar, digest...) + } + } +} + +const packageVersion = "SSH-2.0-Go" + +// Sends and receives a version line. The versionLine string should +// be US ASCII, start with "SSH-2.0-", and should not include a +// newline. exchangeVersions returns the other side's version line. +func exchangeVersions(rw io.ReadWriter, versionLine []byte) (them []byte, err error) { + // Contrary to the RFC, we do not ignore lines that don't + // start with "SSH-2.0-" to make the library usable with + // nonconforming servers. + for _, c := range versionLine { + // The spec disallows non US-ASCII chars, and + // specifically forbids null chars. + if c < 32 { + return nil, errors.New("ssh: junk character in version line") + } + } + if _, err = rw.Write(append(versionLine, '\r', '\n')); err != nil { + return + } + + them, err = readVersion(rw) + return them, err +} + +// maxVersionStringBytes is the maximum number of bytes that we'll +// accept as a version string. RFC 4253 section 4.2 limits this at 255 +// chars +const maxVersionStringBytes = 255 + +// Read version string as specified by RFC 4253, section 4.2. +func readVersion(r io.Reader) ([]byte, error) { + versionString := make([]byte, 0, 64) + var ok bool + var buf [1]byte + + for length := 0; length < maxVersionStringBytes; length++ { + _, err := io.ReadFull(r, buf[:]) + if err != nil { + return nil, err + } + // The RFC says that the version should be terminated with \r\n + // but several SSH servers actually only send a \n. + if buf[0] == '\n' { + if !bytes.HasPrefix(versionString, []byte("SSH-")) { + // RFC 4253 says we need to ignore all version string lines + // except the one containing the SSH version (provided that + // all the lines do not exceed 255 bytes in total). + versionString = versionString[:0] + continue + } + ok = true + break + } + + // non ASCII chars are disallowed, but we are lenient, + // since Go doesn't use null-terminated strings. + + // The RFC allows a comment after a space, however, + // all of it (version and comments) goes into the + // session hash. + versionString = append(versionString, buf[0]) + } + + if !ok { + return nil, errors.New("ssh: overflow reading version string") + } + + // There might be a '\r' on the end which we should remove. + if len(versionString) > 0 && versionString[len(versionString)-1] == '\r' { + versionString = versionString[:len(versionString)-1] + } + return versionString, nil +} diff --git a/vendor/golang.org/x/crypto/ssh/transport_test.go b/vendor/golang.org/x/crypto/ssh/transport_test.go new file mode 100644 index 0000000000000000000000000000000000000000..8445e1e561c15a23bcad1c22685b9f0b2d2fb037 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/transport_test.go @@ -0,0 +1,113 @@ +// 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 ssh + +import ( + "bytes" + "crypto/rand" + "encoding/binary" + "strings" + "testing" +) + +func TestReadVersion(t *testing.T) { + longVersion := strings.Repeat("SSH-2.0-bla", 50)[:253] + multiLineVersion := strings.Repeat("ignored\r\n", 20) + "SSH-2.0-bla\r\n" + cases := map[string]string{ + "SSH-2.0-bla\r\n": "SSH-2.0-bla", + "SSH-2.0-bla\n": "SSH-2.0-bla", + multiLineVersion: "SSH-2.0-bla", + longVersion + "\r\n": longVersion, + } + + for in, want := range cases { + result, err := readVersion(bytes.NewBufferString(in)) + if err != nil { + t.Errorf("readVersion(%q): %s", in, err) + } + got := string(result) + if got != want { + t.Errorf("got %q, want %q", got, want) + } + } +} + +func TestReadVersionError(t *testing.T) { + longVersion := strings.Repeat("SSH-2.0-bla", 50)[:253] + multiLineVersion := strings.Repeat("ignored\r\n", 50) + "SSH-2.0-bla\r\n" + cases := []string{ + longVersion + "too-long\r\n", + multiLineVersion, + } + for _, in := range cases { + if _, err := readVersion(bytes.NewBufferString(in)); err == nil { + t.Errorf("readVersion(%q) should have failed", in) + } + } +} + +func TestExchangeVersionsBasic(t *testing.T) { + v := "SSH-2.0-bla" + buf := bytes.NewBufferString(v + "\r\n") + them, err := exchangeVersions(buf, []byte("xyz")) + if err != nil { + t.Errorf("exchangeVersions: %v", err) + } + + if want := "SSH-2.0-bla"; string(them) != want { + t.Errorf("got %q want %q for our version", them, want) + } +} + +func TestExchangeVersions(t *testing.T) { + cases := []string{ + "not\x000allowed", + "not allowed\x01\r\n", + } + for _, c := range cases { + buf := bytes.NewBufferString("SSH-2.0-bla\r\n") + if _, err := exchangeVersions(buf, []byte(c)); err == nil { + t.Errorf("exchangeVersions(%q): should have failed", c) + } + } +} + +type closerBuffer struct { + bytes.Buffer +} + +func (b *closerBuffer) Close() error { + return nil +} + +func TestTransportMaxPacketWrite(t *testing.T) { + buf := &closerBuffer{} + tr := newTransport(buf, rand.Reader, true) + huge := make([]byte, maxPacket+1) + err := tr.writePacket(huge) + if err == nil { + t.Errorf("transport accepted write for a huge packet.") + } +} + +func TestTransportMaxPacketReader(t *testing.T) { + var header [5]byte + huge := make([]byte, maxPacket+128) + binary.BigEndian.PutUint32(header[0:], uint32(len(huge))) + // padding. + header[4] = 0 + + buf := &closerBuffer{} + buf.Write(header[:]) + buf.Write(huge) + + tr := newTransport(buf, rand.Reader, true) + _, err := tr.readPacket() + if err == nil { + t.Errorf("transport succeeded reading huge packet.") + } else if !strings.Contains(err.Error(), "large") { + t.Errorf("got %q, should mention %q", err.Error(), "large") + } +} diff --git a/vendor/golang.org/x/crypto/tea/cipher.go b/vendor/golang.org/x/crypto/tea/cipher.go new file mode 100644 index 0000000000000000000000000000000000000000..ce223b2c2dd5bb09a4883d8dbcb364529c0674cf --- /dev/null +++ b/vendor/golang.org/x/crypto/tea/cipher.go @@ -0,0 +1,108 @@ +// Copyright 2015 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 tea implements the TEA algorithm, as defined in Needham and +// Wheeler's 1994 technical report, “TEA, a Tiny Encryption Algorithmâ€. See +// http://www.cix.co.uk/~klockstone/tea.pdf for details. +package tea + +import ( + "crypto/cipher" + "encoding/binary" + "errors" +) + +const ( + // BlockSize is the size of a TEA block, in bytes. + BlockSize = 8 + + // KeySize is the size of a TEA key, in bytes. + KeySize = 16 + + // delta is the TEA key schedule constant. + delta = 0x9e3779b9 + + // numRounds is the standard number of rounds in TEA. + numRounds = 64 +) + +// tea is an instance of the TEA cipher with a particular key. +type tea struct { + key [16]byte + rounds int +} + +// NewCipher returns an instance of the TEA cipher with the standard number of +// rounds. The key argument must be 16 bytes long. +func NewCipher(key []byte) (cipher.Block, error) { + return NewCipherWithRounds(key, numRounds) +} + +// NewCipherWithRounds returns an instance of the TEA cipher with a given +// number of rounds, which must be even. The key argument must be 16 bytes +// long. +func NewCipherWithRounds(key []byte, rounds int) (cipher.Block, error) { + if len(key) != 16 { + return nil, errors.New("tea: incorrect key size") + } + + if rounds&1 != 0 { + return nil, errors.New("tea: odd number of rounds specified") + } + + c := &tea{ + rounds: rounds, + } + copy(c.key[:], key) + + return c, nil +} + +// BlockSize returns the TEA block size, which is eight bytes. It is necessary +// to satisfy the Block interface in the package "crypto/cipher". +func (*tea) BlockSize() int { + return BlockSize +} + +// Encrypt encrypts the 8 byte buffer src using the key in t 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 (t *tea) Encrypt(dst, src []byte) { + e := binary.BigEndian + v0, v1 := e.Uint32(src), e.Uint32(src[4:]) + k0, k1, k2, k3 := e.Uint32(t.key[0:]), e.Uint32(t.key[4:]), e.Uint32(t.key[8:]), e.Uint32(t.key[12:]) + + sum := uint32(0) + delta := uint32(delta) + + for i := 0; i < t.rounds/2; i++ { + sum += delta + v0 += ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1) + v1 += ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3) + } + + e.PutUint32(dst, v0) + e.PutUint32(dst[4:], v1) +} + +// Decrypt decrypts the 8 byte buffer src using the key in t and stores the +// result in dst. +func (t *tea) Decrypt(dst, src []byte) { + e := binary.BigEndian + v0, v1 := e.Uint32(src), e.Uint32(src[4:]) + k0, k1, k2, k3 := e.Uint32(t.key[0:]), e.Uint32(t.key[4:]), e.Uint32(t.key[8:]), e.Uint32(t.key[12:]) + + delta := uint32(delta) + sum := delta * uint32(t.rounds/2) // in general, sum = delta * n + + for i := 0; i < t.rounds/2; i++ { + v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3) + v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1) + sum -= delta + } + + e.PutUint32(dst, v0) + e.PutUint32(dst[4:], v1) +} diff --git a/vendor/golang.org/x/crypto/tea/tea_test.go b/vendor/golang.org/x/crypto/tea/tea_test.go new file mode 100644 index 0000000000000000000000000000000000000000..eb98d1e0e03e6492c96e504f5be33777861e8242 --- /dev/null +++ b/vendor/golang.org/x/crypto/tea/tea_test.go @@ -0,0 +1,93 @@ +// Copyright 2015 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 tea + +import ( + "bytes" + "testing" +) + +// A sample test key for when we just want to initialize a cipher +var testKey = []byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF} + +// Test that the block size for tea is correct +func TestBlocksize(t *testing.T) { + c, err := NewCipher(testKey) + if err != nil { + t.Fatalf("NewCipher returned error: %s", err) + } + + if result := c.BlockSize(); result != BlockSize { + t.Errorf("cipher.BlockSize returned %d, but expected %d", result, BlockSize) + } +} + +// Test that invalid key sizes return an error +func TestInvalidKeySize(t *testing.T) { + var key [KeySize + 1]byte + + if _, err := NewCipher(key[:]); err == nil { + t.Errorf("invalid key size %d didn't result in an error.", len(key)) + } + + if _, err := NewCipher(key[:KeySize-1]); err == nil { + t.Errorf("invalid key size %d didn't result in an error.", KeySize-1) + } +} + +// Test Vectors +type teaTest struct { + rounds int + key []byte + plaintext []byte + ciphertext []byte +} + +var teaTests = []teaTest{ + // These were sourced from https://github.com/froydnj/ironclad/blob/master/testing/test-vectors/tea.testvec + { + numRounds, + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0x41, 0xea, 0x3a, 0x0a, 0x94, 0xba, 0xa9, 0x40}, + }, + { + numRounds, + []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + []byte{0x31, 0x9b, 0xbe, 0xfb, 0x01, 0x6a, 0xbd, 0xb2}, + }, + { + 16, + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0xed, 0x28, 0x5d, 0xa1, 0x45, 0x5b, 0x33, 0xc1}, + }, +} + +// Test encryption +func TestCipherEncrypt(t *testing.T) { + // Test encryption with standard 64 rounds + for i, test := range teaTests { + c, err := NewCipherWithRounds(test.key, test.rounds) + if err != nil { + t.Fatalf("#%d: NewCipher returned error: %s", i, err) + } + + var ciphertext [BlockSize]byte + c.Encrypt(ciphertext[:], test.plaintext) + + if !bytes.Equal(ciphertext[:], test.ciphertext) { + t.Errorf("#%d: incorrect ciphertext. Got %x, wanted %x", i, ciphertext, test.ciphertext) + } + + var plaintext2 [BlockSize]byte + c.Decrypt(plaintext2[:], ciphertext[:]) + + if !bytes.Equal(plaintext2[:], test.plaintext) { + t.Errorf("#%d: incorrect plaintext. Got %x, wanted %x", i, plaintext2, test.plaintext) + } + } +} diff --git a/vendor/golang.org/x/crypto/twofish/twofish.go b/vendor/golang.org/x/crypto/twofish/twofish.go new file mode 100644 index 0000000000000000000000000000000000000000..6db01fcf45a160835e81e334b29984c17b7bd61b --- /dev/null +++ b/vendor/golang.org/x/crypto/twofish/twofish.go @@ -0,0 +1,342 @@ +// 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 twofish implements Bruce Schneier's Twofish encryption algorithm. +package twofish // import "golang.org/x/crypto/twofish" + +// Twofish is defined in https://www.schneier.com/paper-twofish-paper.pdf [TWOFISH] + +// This code is a port of the LibTom C implementation. +// See http://libtom.org/?page=features&newsitems=5&whatfile=crypt. +// LibTomCrypt is free for all purposes under the public domain. +// It was heavily inspired by the go blowfish package. + +import "strconv" + +// BlockSize is the constant block size of Twofish. +const BlockSize = 16 + +const mdsPolynomial = 0x169 // x^8 + x^6 + x^5 + x^3 + 1, see [TWOFISH] 4.2 +const rsPolynomial = 0x14d // x^8 + x^6 + x^3 + x^2 + 1, see [TWOFISH] 4.3 + +// A Cipher is an instance of Twofish encryption using a particular key. +type Cipher struct { + s [4][256]uint32 + k [40]uint32 +} + +type KeySizeError int + +func (k KeySizeError) Error() string { + return "crypto/twofish: invalid key size " + strconv.Itoa(int(k)) +} + +// NewCipher creates and returns a Cipher. +// The key argument should be the Twofish key, 16, 24 or 32 bytes. +func NewCipher(key []byte) (*Cipher, error) { + keylen := len(key) + + if keylen != 16 && keylen != 24 && keylen != 32 { + return nil, KeySizeError(keylen) + } + + // k is the number of 64 bit words in key + k := keylen / 8 + + // Create the S[..] words + var S [4 * 4]byte + for i := 0; i < k; i++ { + // Computes [y0 y1 y2 y3] = rs . [x0 x1 x2 x3 x4 x5 x6 x7] + for j, rsRow := range rs { + for k, rsVal := range rsRow { + S[4*i+j] ^= gfMult(key[8*i+k], rsVal, rsPolynomial) + } + } + } + + // Calculate subkeys + c := new(Cipher) + var tmp [4]byte + for i := byte(0); i < 20; i++ { + // A = h(p * 2x, Me) + for j := range tmp { + tmp[j] = 2 * i + } + A := h(tmp[:], key, 0) + + // B = rolc(h(p * (2x + 1), Mo), 8) + for j := range tmp { + tmp[j] = 2*i + 1 + } + B := h(tmp[:], key, 1) + B = rol(B, 8) + + c.k[2*i] = A + B + + // K[2i+1] = (A + 2B) <<< 9 + c.k[2*i+1] = rol(2*B+A, 9) + } + + // Calculate sboxes + switch k { + case 2: + for i := range c.s[0] { + c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][byte(i)]^S[0]]^S[4]], 0) + c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][byte(i)]^S[1]]^S[5]], 1) + c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][byte(i)]^S[2]]^S[6]], 2) + c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][byte(i)]^S[3]]^S[7]], 3) + } + case 3: + for i := range c.s[0] { + c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][sbox[1][byte(i)]^S[0]]^S[4]]^S[8]], 0) + c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][sbox[1][byte(i)]^S[1]]^S[5]]^S[9]], 1) + c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][sbox[0][byte(i)]^S[2]]^S[6]]^S[10]], 2) + c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][sbox[0][byte(i)]^S[3]]^S[7]]^S[11]], 3) + } + default: + for i := range c.s[0] { + c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][sbox[1][sbox[1][byte(i)]^S[0]]^S[4]]^S[8]]^S[12]], 0) + c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][sbox[1][sbox[0][byte(i)]^S[1]]^S[5]]^S[9]]^S[13]], 1) + c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][sbox[0][sbox[0][byte(i)]^S[2]]^S[6]]^S[10]]^S[14]], 2) + c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][sbox[0][sbox[1][byte(i)]^S[3]]^S[7]]^S[11]]^S[15]], 3) + } + } + + return c, nil +} + +// BlockSize returns the Twofish block size, 16 bytes. +func (c *Cipher) BlockSize() int { return BlockSize } + +// store32l stores src in dst in little-endian form. +func store32l(dst []byte, src uint32) { + dst[0] = byte(src) + dst[1] = byte(src >> 8) + dst[2] = byte(src >> 16) + dst[3] = byte(src >> 24) + return +} + +// load32l reads a little-endian uint32 from src. +func load32l(src []byte) uint32 { + return uint32(src[0]) | uint32(src[1])<<8 | uint32(src[2])<<16 | uint32(src[3])<<24 +} + +// rol returns x after a left circular rotation of y bits. +func rol(x, y uint32) uint32 { + return (x << (y & 31)) | (x >> (32 - (y & 31))) +} + +// ror returns x after a right circular rotation of y bits. +func ror(x, y uint32) uint32 { + return (x >> (y & 31)) | (x << (32 - (y & 31))) +} + +// The RS matrix. See [TWOFISH] 4.3 +var rs = [4][8]byte{ + {0x01, 0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E}, + {0xA4, 0x56, 0x82, 0xF3, 0x1E, 0xC6, 0x68, 0xE5}, + {0x02, 0xA1, 0xFC, 0xC1, 0x47, 0xAE, 0x3D, 0x19}, + {0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E, 0x03}, +} + +// sbox tables +var sbox = [2][256]byte{ + { + 0xa9, 0x67, 0xb3, 0xe8, 0x04, 0xfd, 0xa3, 0x76, 0x9a, 0x92, 0x80, 0x78, 0xe4, 0xdd, 0xd1, 0x38, + 0x0d, 0xc6, 0x35, 0x98, 0x18, 0xf7, 0xec, 0x6c, 0x43, 0x75, 0x37, 0x26, 0xfa, 0x13, 0x94, 0x48, + 0xf2, 0xd0, 0x8b, 0x30, 0x84, 0x54, 0xdf, 0x23, 0x19, 0x5b, 0x3d, 0x59, 0xf3, 0xae, 0xa2, 0x82, + 0x63, 0x01, 0x83, 0x2e, 0xd9, 0x51, 0x9b, 0x7c, 0xa6, 0xeb, 0xa5, 0xbe, 0x16, 0x0c, 0xe3, 0x61, + 0xc0, 0x8c, 0x3a, 0xf5, 0x73, 0x2c, 0x25, 0x0b, 0xbb, 0x4e, 0x89, 0x6b, 0x53, 0x6a, 0xb4, 0xf1, + 0xe1, 0xe6, 0xbd, 0x45, 0xe2, 0xf4, 0xb6, 0x66, 0xcc, 0x95, 0x03, 0x56, 0xd4, 0x1c, 0x1e, 0xd7, + 0xfb, 0xc3, 0x8e, 0xb5, 0xe9, 0xcf, 0xbf, 0xba, 0xea, 0x77, 0x39, 0xaf, 0x33, 0xc9, 0x62, 0x71, + 0x81, 0x79, 0x09, 0xad, 0x24, 0xcd, 0xf9, 0xd8, 0xe5, 0xc5, 0xb9, 0x4d, 0x44, 0x08, 0x86, 0xe7, + 0xa1, 0x1d, 0xaa, 0xed, 0x06, 0x70, 0xb2, 0xd2, 0x41, 0x7b, 0xa0, 0x11, 0x31, 0xc2, 0x27, 0x90, + 0x20, 0xf6, 0x60, 0xff, 0x96, 0x5c, 0xb1, 0xab, 0x9e, 0x9c, 0x52, 0x1b, 0x5f, 0x93, 0x0a, 0xef, + 0x91, 0x85, 0x49, 0xee, 0x2d, 0x4f, 0x8f, 0x3b, 0x47, 0x87, 0x6d, 0x46, 0xd6, 0x3e, 0x69, 0x64, + 0x2a, 0xce, 0xcb, 0x2f, 0xfc, 0x97, 0x05, 0x7a, 0xac, 0x7f, 0xd5, 0x1a, 0x4b, 0x0e, 0xa7, 0x5a, + 0x28, 0x14, 0x3f, 0x29, 0x88, 0x3c, 0x4c, 0x02, 0xb8, 0xda, 0xb0, 0x17, 0x55, 0x1f, 0x8a, 0x7d, + 0x57, 0xc7, 0x8d, 0x74, 0xb7, 0xc4, 0x9f, 0x72, 0x7e, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34, + 0x6e, 0x50, 0xde, 0x68, 0x65, 0xbc, 0xdb, 0xf8, 0xc8, 0xa8, 0x2b, 0x40, 0xdc, 0xfe, 0x32, 0xa4, + 0xca, 0x10, 0x21, 0xf0, 0xd3, 0x5d, 0x0f, 0x00, 0x6f, 0x9d, 0x36, 0x42, 0x4a, 0x5e, 0xc1, 0xe0, + }, + { + 0x75, 0xf3, 0xc6, 0xf4, 0xdb, 0x7b, 0xfb, 0xc8, 0x4a, 0xd3, 0xe6, 0x6b, 0x45, 0x7d, 0xe8, 0x4b, + 0xd6, 0x32, 0xd8, 0xfd, 0x37, 0x71, 0xf1, 0xe1, 0x30, 0x0f, 0xf8, 0x1b, 0x87, 0xfa, 0x06, 0x3f, + 0x5e, 0xba, 0xae, 0x5b, 0x8a, 0x00, 0xbc, 0x9d, 0x6d, 0xc1, 0xb1, 0x0e, 0x80, 0x5d, 0xd2, 0xd5, + 0xa0, 0x84, 0x07, 0x14, 0xb5, 0x90, 0x2c, 0xa3, 0xb2, 0x73, 0x4c, 0x54, 0x92, 0x74, 0x36, 0x51, + 0x38, 0xb0, 0xbd, 0x5a, 0xfc, 0x60, 0x62, 0x96, 0x6c, 0x42, 0xf7, 0x10, 0x7c, 0x28, 0x27, 0x8c, + 0x13, 0x95, 0x9c, 0xc7, 0x24, 0x46, 0x3b, 0x70, 0xca, 0xe3, 0x85, 0xcb, 0x11, 0xd0, 0x93, 0xb8, + 0xa6, 0x83, 0x20, 0xff, 0x9f, 0x77, 0xc3, 0xcc, 0x03, 0x6f, 0x08, 0xbf, 0x40, 0xe7, 0x2b, 0xe2, + 0x79, 0x0c, 0xaa, 0x82, 0x41, 0x3a, 0xea, 0xb9, 0xe4, 0x9a, 0xa4, 0x97, 0x7e, 0xda, 0x7a, 0x17, + 0x66, 0x94, 0xa1, 0x1d, 0x3d, 0xf0, 0xde, 0xb3, 0x0b, 0x72, 0xa7, 0x1c, 0xef, 0xd1, 0x53, 0x3e, + 0x8f, 0x33, 0x26, 0x5f, 0xec, 0x76, 0x2a, 0x49, 0x81, 0x88, 0xee, 0x21, 0xc4, 0x1a, 0xeb, 0xd9, + 0xc5, 0x39, 0x99, 0xcd, 0xad, 0x31, 0x8b, 0x01, 0x18, 0x23, 0xdd, 0x1f, 0x4e, 0x2d, 0xf9, 0x48, + 0x4f, 0xf2, 0x65, 0x8e, 0x78, 0x5c, 0x58, 0x19, 0x8d, 0xe5, 0x98, 0x57, 0x67, 0x7f, 0x05, 0x64, + 0xaf, 0x63, 0xb6, 0xfe, 0xf5, 0xb7, 0x3c, 0xa5, 0xce, 0xe9, 0x68, 0x44, 0xe0, 0x4d, 0x43, 0x69, + 0x29, 0x2e, 0xac, 0x15, 0x59, 0xa8, 0x0a, 0x9e, 0x6e, 0x47, 0xdf, 0x34, 0x35, 0x6a, 0xcf, 0xdc, + 0x22, 0xc9, 0xc0, 0x9b, 0x89, 0xd4, 0xed, 0xab, 0x12, 0xa2, 0x0d, 0x52, 0xbb, 0x02, 0x2f, 0xa9, + 0xd7, 0x61, 0x1e, 0xb4, 0x50, 0x04, 0xf6, 0xc2, 0x16, 0x25, 0x86, 0x56, 0x55, 0x09, 0xbe, 0x91, + }, +} + +// gfMult returns a·b in GF(2^8)/p +func gfMult(a, b byte, p uint32) byte { + B := [2]uint32{0, uint32(b)} + P := [2]uint32{0, p} + var result uint32 + + // branchless GF multiplier + for i := 0; i < 7; i++ { + result ^= B[a&1] + a >>= 1 + B[1] = P[B[1]>>7] ^ (B[1] << 1) + } + result ^= B[a&1] + return byte(result) +} + +// mdsColumnMult calculates y{col} where [y0 y1 y2 y3] = MDS · [x0] +func mdsColumnMult(in byte, col int) uint32 { + mul01 := in + mul5B := gfMult(in, 0x5B, mdsPolynomial) + mulEF := gfMult(in, 0xEF, mdsPolynomial) + + switch col { + case 0: + return uint32(mul01) | uint32(mul5B)<<8 | uint32(mulEF)<<16 | uint32(mulEF)<<24 + case 1: + return uint32(mulEF) | uint32(mulEF)<<8 | uint32(mul5B)<<16 | uint32(mul01)<<24 + case 2: + return uint32(mul5B) | uint32(mulEF)<<8 | uint32(mul01)<<16 | uint32(mulEF)<<24 + case 3: + return uint32(mul5B) | uint32(mul01)<<8 | uint32(mulEF)<<16 | uint32(mul5B)<<24 + } + + panic("unreachable") +} + +// h implements the S-box generation function. See [TWOFISH] 4.3.5 +func h(in, key []byte, offset int) uint32 { + var y [4]byte + for x := range y { + y[x] = in[x] + } + switch len(key) / 8 { + case 4: + y[0] = sbox[1][y[0]] ^ key[4*(6+offset)+0] + y[1] = sbox[0][y[1]] ^ key[4*(6+offset)+1] + y[2] = sbox[0][y[2]] ^ key[4*(6+offset)+2] + y[3] = sbox[1][y[3]] ^ key[4*(6+offset)+3] + fallthrough + case 3: + y[0] = sbox[1][y[0]] ^ key[4*(4+offset)+0] + y[1] = sbox[1][y[1]] ^ key[4*(4+offset)+1] + y[2] = sbox[0][y[2]] ^ key[4*(4+offset)+2] + y[3] = sbox[0][y[3]] ^ key[4*(4+offset)+3] + fallthrough + case 2: + y[0] = sbox[1][sbox[0][sbox[0][y[0]]^key[4*(2+offset)+0]]^key[4*(0+offset)+0]] + y[1] = sbox[0][sbox[0][sbox[1][y[1]]^key[4*(2+offset)+1]]^key[4*(0+offset)+1]] + y[2] = sbox[1][sbox[1][sbox[0][y[2]]^key[4*(2+offset)+2]]^key[4*(0+offset)+2]] + y[3] = sbox[0][sbox[1][sbox[1][y[3]]^key[4*(2+offset)+3]]^key[4*(0+offset)+3]] + } + // [y0 y1 y2 y3] = MDS . [x0 x1 x2 x3] + var mdsMult uint32 + for i := range y { + mdsMult ^= mdsColumnMult(y[i], i) + } + return mdsMult +} + +// Encrypt encrypts a 16-byte block from src to dst, which may overlap. +// 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) { + S1 := c.s[0] + S2 := c.s[1] + S3 := c.s[2] + S4 := c.s[3] + + // Load input + ia := load32l(src[0:4]) + ib := load32l(src[4:8]) + ic := load32l(src[8:12]) + id := load32l(src[12:16]) + + // Pre-whitening + ia ^= c.k[0] + ib ^= c.k[1] + ic ^= c.k[2] + id ^= c.k[3] + + for i := 0; i < 8; i++ { + k := c.k[8+i*4 : 12+i*4] + t2 := S2[byte(ib)] ^ S3[byte(ib>>8)] ^ S4[byte(ib>>16)] ^ S1[byte(ib>>24)] + t1 := S1[byte(ia)] ^ S2[byte(ia>>8)] ^ S3[byte(ia>>16)] ^ S4[byte(ia>>24)] + t2 + ic = ror(ic^(t1+k[0]), 1) + id = rol(id, 1) ^ (t2 + t1 + k[1]) + + t2 = S2[byte(id)] ^ S3[byte(id>>8)] ^ S4[byte(id>>16)] ^ S1[byte(id>>24)] + t1 = S1[byte(ic)] ^ S2[byte(ic>>8)] ^ S3[byte(ic>>16)] ^ S4[byte(ic>>24)] + t2 + ia = ror(ia^(t1+k[2]), 1) + ib = rol(ib, 1) ^ (t2 + t1 + k[3]) + } + + // Output with "undo last swap" + ta := ic ^ c.k[4] + tb := id ^ c.k[5] + tc := ia ^ c.k[6] + td := ib ^ c.k[7] + + store32l(dst[0:4], ta) + store32l(dst[4:8], tb) + store32l(dst[8:12], tc) + store32l(dst[12:16], td) +} + +// Decrypt decrypts a 16-byte block from src to dst, which may overlap. +func (c *Cipher) Decrypt(dst, src []byte) { + S1 := c.s[0] + S2 := c.s[1] + S3 := c.s[2] + S4 := c.s[3] + + // Load input + ta := load32l(src[0:4]) + tb := load32l(src[4:8]) + tc := load32l(src[8:12]) + td := load32l(src[12:16]) + + // Undo undo final swap + ia := tc ^ c.k[6] + ib := td ^ c.k[7] + ic := ta ^ c.k[4] + id := tb ^ c.k[5] + + for i := 8; i > 0; i-- { + k := c.k[4+i*4 : 8+i*4] + t2 := S2[byte(id)] ^ S3[byte(id>>8)] ^ S4[byte(id>>16)] ^ S1[byte(id>>24)] + t1 := S1[byte(ic)] ^ S2[byte(ic>>8)] ^ S3[byte(ic>>16)] ^ S4[byte(ic>>24)] + t2 + ia = rol(ia, 1) ^ (t1 + k[2]) + ib = ror(ib^(t2+t1+k[3]), 1) + + t2 = S2[byte(ib)] ^ S3[byte(ib>>8)] ^ S4[byte(ib>>16)] ^ S1[byte(ib>>24)] + t1 = S1[byte(ia)] ^ S2[byte(ia>>8)] ^ S3[byte(ia>>16)] ^ S4[byte(ia>>24)] + t2 + ic = rol(ic, 1) ^ (t1 + k[0]) + id = ror(id^(t2+t1+k[1]), 1) + } + + // Undo pre-whitening + ia ^= c.k[0] + ib ^= c.k[1] + ic ^= c.k[2] + id ^= c.k[3] + + store32l(dst[0:4], ia) + store32l(dst[4:8], ib) + store32l(dst[8:12], ic) + store32l(dst[12:16], id) +} diff --git a/vendor/golang.org/x/crypto/twofish/twofish_test.go b/vendor/golang.org/x/crypto/twofish/twofish_test.go new file mode 100644 index 0000000000000000000000000000000000000000..ed6a1a8fdbb788ada76a71e1906229519b4fcc98 --- /dev/null +++ b/vendor/golang.org/x/crypto/twofish/twofish_test.go @@ -0,0 +1,129 @@ +// 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 twofish + +import ( + "bytes" + "testing" +) + +var qbox = [2][4][16]byte{ + { + {0x8, 0x1, 0x7, 0xD, 0x6, 0xF, 0x3, 0x2, 0x0, 0xB, 0x5, 0x9, 0xE, 0xC, 0xA, 0x4}, + {0xE, 0xC, 0xB, 0x8, 0x1, 0x2, 0x3, 0x5, 0xF, 0x4, 0xA, 0x6, 0x7, 0x0, 0x9, 0xD}, + {0xB, 0xA, 0x5, 0xE, 0x6, 0xD, 0x9, 0x0, 0xC, 0x8, 0xF, 0x3, 0x2, 0x4, 0x7, 0x1}, + {0xD, 0x7, 0xF, 0x4, 0x1, 0x2, 0x6, 0xE, 0x9, 0xB, 0x3, 0x0, 0x8, 0x5, 0xC, 0xA}, + }, + { + {0x2, 0x8, 0xB, 0xD, 0xF, 0x7, 0x6, 0xE, 0x3, 0x1, 0x9, 0x4, 0x0, 0xA, 0xC, 0x5}, + {0x1, 0xE, 0x2, 0xB, 0x4, 0xC, 0x3, 0x7, 0x6, 0xD, 0xA, 0x5, 0xF, 0x9, 0x0, 0x8}, + {0x4, 0xC, 0x7, 0x5, 0x1, 0x6, 0x9, 0xA, 0x0, 0xE, 0xD, 0x8, 0x2, 0xB, 0x3, 0xF}, + {0xB, 0x9, 0x5, 0x1, 0xC, 0x3, 0xD, 0xE, 0x6, 0x4, 0x7, 0xF, 0x2, 0x0, 0x8, 0xA}, + }, +} + +// genSbox generates the variable sbox +func genSbox(qi int, x byte) byte { + a0, b0 := x/16, x%16 + for i := 0; i < 2; i++ { + a1 := a0 ^ b0 + b1 := (a0 ^ ((b0 << 3) | (b0 >> 1)) ^ (a0 << 3)) & 15 + a0 = qbox[qi][2*i][a1] + b0 = qbox[qi][2*i+1][b1] + } + return (b0 << 4) + a0 +} + +func TestSbox(t *testing.T) { + for n := range sbox { + for m := range sbox[n] { + if genSbox(n, byte(m)) != sbox[n][m] { + t.Errorf("#%d|%d: sbox value = %d want %d", n, m, sbox[n][m], genSbox(n, byte(m))) + } + } + } +} + +var testVectors = []struct { + key []byte + dec []byte + enc []byte +}{ + // These tests are extracted from LibTom + { + []byte{0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32, 0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A}, + []byte{0xD4, 0x91, 0xDB, 0x16, 0xE7, 0xB1, 0xC3, 0x9E, 0x86, 0xCB, 0x08, 0x6B, 0x78, 0x9F, 0x54, 0x19}, + []byte{0x01, 0x9F, 0x98, 0x09, 0xDE, 0x17, 0x11, 0x85, 0x8F, 0xAA, 0xC3, 0xA3, 0xBA, 0x20, 0xFB, 0xC3}, + }, + { + []byte{0x88, 0xB2, 0xB2, 0x70, 0x6B, 0x10, 0x5E, 0x36, 0xB4, 0x46, 0xBB, 0x6D, 0x73, 0x1A, 0x1E, 0x88, + 0xEF, 0xA7, 0x1F, 0x78, 0x89, 0x65, 0xBD, 0x44}, + []byte{0x39, 0xDA, 0x69, 0xD6, 0xBA, 0x49, 0x97, 0xD5, 0x85, 0xB6, 0xDC, 0x07, 0x3C, 0xA3, 0x41, 0xB2}, + []byte{0x18, 0x2B, 0x02, 0xD8, 0x14, 0x97, 0xEA, 0x45, 0xF9, 0xDA, 0xAC, 0xDC, 0x29, 0x19, 0x3A, 0x65}, + }, + { + []byte{0xD4, 0x3B, 0xB7, 0x55, 0x6E, 0xA3, 0x2E, 0x46, 0xF2, 0xA2, 0x82, 0xB7, 0xD4, 0x5B, 0x4E, 0x0D, + 0x57, 0xFF, 0x73, 0x9D, 0x4D, 0xC9, 0x2C, 0x1B, 0xD7, 0xFC, 0x01, 0x70, 0x0C, 0xC8, 0x21, 0x6F}, + []byte{0x90, 0xAF, 0xE9, 0x1B, 0xB2, 0x88, 0x54, 0x4F, 0x2C, 0x32, 0xDC, 0x23, 0x9B, 0x26, 0x35, 0xE6}, + []byte{0x6C, 0xB4, 0x56, 0x1C, 0x40, 0xBF, 0x0A, 0x97, 0x05, 0x93, 0x1C, 0xB6, 0xD4, 0x08, 0xE7, 0xFA}, + }, + // These tests are derived from https://www.schneier.com/code/ecb_ival.txt + { + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32, 0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A}, + }, + { + []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + }, + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0xCF, 0xD1, 0xD2, 0xE5, 0xA9, 0xBE, 0x9C, 0xDF, 0x50, 0x1F, 0x13, 0xB8, 0x92, 0xBD, 0x22, 0x48}, + }, + { + []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, + }, + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0x37, 0x52, 0x7B, 0xE0, 0x05, 0x23, 0x34, 0xB8, 0x9F, 0x0C, 0xFC, 0xCA, 0xE8, 0x7C, 0xFA, 0x20}, + }, +} + +func TestCipher(t *testing.T) { + for n, tt := range testVectors { + // Test if the plaintext (dec) is encrypts to the given + // ciphertext (enc) using the given key. Test also if enc can + // be decrypted again into dec. + c, err := NewCipher(tt.key) + if err != nil { + t.Errorf("#%d: NewCipher: %v", n, err) + return + } + + buf := make([]byte, 16) + c.Encrypt(buf, tt.dec) + if !bytes.Equal(buf, tt.enc) { + t.Errorf("#%d: encrypt = %x want %x", n, buf, tt.enc) + } + c.Decrypt(buf, tt.enc) + if !bytes.Equal(buf, tt.dec) { + t.Errorf("#%d: decrypt = %x want %x", n, buf, tt.dec) + } + + // Test that 16 zero bytes, encrypted 1000 times then decrypted + // 1000 times results in zero bytes again. + zero := make([]byte, 16) + buf = make([]byte, 16) + for i := 0; i < 1000; i++ { + c.Encrypt(buf, buf) + } + for i := 0; i < 1000; i++ { + c.Decrypt(buf, buf) + } + if !bytes.Equal(buf, zero) { + t.Errorf("#%d: encrypt/decrypt 1000: have %x want %x", n, buf, zero) + } + } +} diff --git a/vendor/golang.org/x/crypto/xtea/block.go b/vendor/golang.org/x/crypto/xtea/block.go new file mode 100644 index 0000000000000000000000000000000000000000..bf5d245992d99dfba447c1b4e52b811a7e7653a6 --- /dev/null +++ b/vendor/golang.org/x/crypto/xtea/block.go @@ -0,0 +1,66 @@ +// Copyright 2009 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. + +/* + Implementation adapted from Needham and Wheeler's paper: + http://www.cix.co.uk/~klockstone/xtea.pdf + + A precalculated look up table is used during encryption/decryption for values that are based purely on the key. +*/ + +package xtea + +// XTEA is based on 64 rounds. +const numRounds = 64 + +// blockToUint32 reads an 8 byte slice into two uint32s. +// The block is treated as big endian. +func blockToUint32(src []byte) (uint32, uint32) { + r0 := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3]) + r1 := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7]) + return r0, r1 +} + +// uint32ToBlock writes two uint32s into an 8 byte data block. +// Values are written as big endian. +func uint32ToBlock(v0, v1 uint32, dst []byte) { + dst[0] = byte(v0 >> 24) + dst[1] = byte(v0 >> 16) + dst[2] = byte(v0 >> 8) + dst[3] = byte(v0) + dst[4] = byte(v1 >> 24) + dst[5] = byte(v1 >> 16) + dst[6] = byte(v1 >> 8) + dst[7] = byte(v1 >> 0) +} + +// encryptBlock encrypts a single 8 byte block using XTEA. +func encryptBlock(c *Cipher, dst, src []byte) { + v0, v1 := blockToUint32(src) + + // Two rounds of XTEA applied per loop + for i := 0; i < numRounds; { + v0 += ((v1<<4 ^ v1>>5) + v1) ^ c.table[i] + i++ + v1 += ((v0<<4 ^ v0>>5) + v0) ^ c.table[i] + i++ + } + + uint32ToBlock(v0, v1, dst) +} + +// decryptBlock decrypt a single 8 byte block using XTEA. +func decryptBlock(c *Cipher, dst, src []byte) { + v0, v1 := blockToUint32(src) + + // Two rounds of XTEA applied per loop + for i := numRounds; i > 0; { + i-- + v1 -= ((v0<<4 ^ v0>>5) + v0) ^ c.table[i] + i-- + v0 -= ((v1<<4 ^ v1>>5) + v1) ^ c.table[i] + } + + uint32ToBlock(v0, v1, dst) +} diff --git a/vendor/golang.org/x/crypto/xtea/cipher.go b/vendor/golang.org/x/crypto/xtea/cipher.go new file mode 100644 index 0000000000000000000000000000000000000000..66ea0df1655a316fd6cb1555c457cb991f5f8869 --- /dev/null +++ b/vendor/golang.org/x/crypto/xtea/cipher.go @@ -0,0 +1,82 @@ +// Copyright 2009 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 xtea implements XTEA encryption, as defined in Needham and Wheeler's +// 1997 technical report, "Tea extensions." +package xtea // import "golang.org/x/crypto/xtea" + +// For details, see http://www.cix.co.uk/~klockstone/xtea.pdf + +import "strconv" + +// The XTEA block size in bytes. +const BlockSize = 8 + +// A Cipher is an instance of an XTEA cipher using a particular key. +// table contains a series of precalculated values that are used each round. +type Cipher struct { + table [64]uint32 +} + +type KeySizeError int + +func (k KeySizeError) Error() string { + return "crypto/xtea: invalid key size " + strconv.Itoa(int(k)) +} + +// NewCipher creates and returns a new Cipher. +// The key argument should be the XTEA key. +// XTEA only supports 128 bit (16 byte) keys. +func NewCipher(key []byte) (*Cipher, error) { + k := len(key) + switch k { + default: + return nil, KeySizeError(k) + case 16: + break + } + + c := new(Cipher) + initCipher(c, key) + + return c, nil +} + +// BlockSize returns the XTEA 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 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) { encryptBlock(c, dst, src) } + +// Decrypt decrypts the 8 byte buffer src using the key k and stores the result in dst. +func (c *Cipher) Decrypt(dst, src []byte) { decryptBlock(c, dst, src) } + +// initCipher initializes the cipher context by creating a look up table +// of precalculated values that are based on the key. +func initCipher(c *Cipher, key []byte) { + // Load the key into four uint32s + var k [4]uint32 + for i := 0; i < len(k); i++ { + j := i << 2 // Multiply by 4 + k[i] = uint32(key[j+0])<<24 | uint32(key[j+1])<<16 | uint32(key[j+2])<<8 | uint32(key[j+3]) + } + + // Precalculate the table + const delta = 0x9E3779B9 + var sum uint32 + + // Two rounds of XTEA applied per loop + for i := 0; i < numRounds; { + c.table[i] = sum + k[sum&3] + i++ + sum += delta + c.table[i] = sum + k[(sum>>11)&3] + i++ + } +} diff --git a/vendor/golang.org/x/crypto/xtea/xtea_test.go b/vendor/golang.org/x/crypto/xtea/xtea_test.go new file mode 100644 index 0000000000000000000000000000000000000000..be711bf5af00322dd4a4e385c502a9aa3673aaf5 --- /dev/null +++ b/vendor/golang.org/x/crypto/xtea/xtea_test.go @@ -0,0 +1,229 @@ +// Copyright 2009 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 xtea + +import ( + "testing" +) + +// A sample test key for when we just want to initialize a cipher +var testKey = []byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF} + +// Test that the block size for XTEA is correct +func TestBlocksize(t *testing.T) { + if BlockSize != 8 { + t.Errorf("BlockSize constant - expected 8, got %d", BlockSize) + return + } + + c, err := NewCipher(testKey) + if err != nil { + t.Errorf("NewCipher(%d bytes) = %s", len(testKey), err) + return + } + + result := c.BlockSize() + if result != 8 { + t.Errorf("BlockSize function - expected 8, got %d", result) + return + } +} + +// A series of test values to confirm that the Cipher.table array was initialized correctly +var testTable = []uint32{ + 0x00112233, 0x6B1568B8, 0xE28CE030, 0xC5089E2D, 0xC5089E2D, 0x1EFBD3A2, 0xA7845C2A, 0x78EF0917, + 0x78EF0917, 0x172682D0, 0x5B6AC714, 0x822AC955, 0x3DE68511, 0xDC1DFECA, 0x2062430E, 0x3611343F, + 0xF1CCEFFB, 0x900469B4, 0xD448ADF8, 0x2E3BE36D, 0xB6C46BF5, 0x994029F2, 0x994029F2, 0xF3335F67, + 0x6AAAD6DF, 0x4D2694DC, 0x4D2694DC, 0xEB5E0E95, 0x2FA252D9, 0x4551440A, 0x121E10D6, 0xB0558A8F, + 0xE388BDC3, 0x0A48C004, 0xC6047BC0, 0x643BF579, 0xA88039BD, 0x02736F32, 0x8AFBF7BA, 0x5C66A4A7, + 0x5C66A4A7, 0xC76AEB2C, 0x3EE262A4, 0x215E20A1, 0x215E20A1, 0x7B515616, 0x03D9DE9E, 0x1988CFCF, + 0xD5448B8B, 0x737C0544, 0xB7C04988, 0xDE804BC9, 0x9A3C0785, 0x3873813E, 0x7CB7C582, 0xD6AAFAF7, + 0x4E22726F, 0x309E306C, 0x309E306C, 0x8A9165E1, 0x1319EE69, 0xF595AC66, 0xF595AC66, 0x4F88E1DB, +} + +// Test that the cipher context is initialized correctly +func TestCipherInit(t *testing.T) { + c, err := NewCipher(testKey) + if err != nil { + t.Errorf("NewCipher(%d bytes) = %s", len(testKey), err) + return + } + + for i := 0; i < len(c.table); i++ { + if c.table[i] != testTable[i] { + t.Errorf("NewCipher() failed to initialize Cipher.table[%d] correctly. Expected %08X, got %08X", i, testTable[i], c.table[i]) + break + } + } +} + +// Test that invalid key sizes return an error +func TestInvalidKeySize(t *testing.T) { + // Test a long key + key := []byte{ + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, + } + + _, err := NewCipher(key) + if err == nil { + t.Errorf("Invalid key size %d didn't result in an error.", len(key)) + } + + // Test a short key + key = []byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77} + + _, err = NewCipher(key) + if err == nil { + t.Errorf("Invalid key size %d didn't result in an error.", len(key)) + } +} + +// Test that we can correctly decode some bytes we have encoded +func TestEncodeDecode(t *testing.T) { + original := []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF} + input := original + output := make([]byte, BlockSize) + + c, err := NewCipher(testKey) + if err != nil { + t.Errorf("NewCipher(%d bytes) = %s", len(testKey), err) + return + } + + // Encrypt the input block + c.Encrypt(output, input) + + // Check that the output does not match the input + differs := false + for i := 0; i < len(input); i++ { + if output[i] != input[i] { + differs = true + break + } + } + if differs == false { + t.Error("Cipher.Encrypt: Failed to encrypt the input block.") + return + } + + // Decrypt the block we just encrypted + input = output + output = make([]byte, BlockSize) + c.Decrypt(output, input) + + // Check that the output from decrypt matches our initial input + for i := 0; i < len(input); i++ { + if output[i] != original[i] { + t.Errorf("Decrypted byte %d differed. Expected %02X, got %02X\n", i, original[i], output[i]) + return + } + } +} + +// Test Vectors +type CryptTest struct { + key []byte + plainText []byte + cipherText []byte +} + +var CryptTests = []CryptTest{ + // These were sourced from http://www.freemedialibrary.com/index.php/XTEA_test_vectors + { + []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}, + []byte{0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48}, + []byte{0x49, 0x7d, 0xf3, 0xd0, 0x72, 0x61, 0x2c, 0xb5}, + }, + { + []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}, + []byte{0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41}, + []byte{0xe7, 0x8f, 0x2d, 0x13, 0x74, 0x43, 0x41, 0xd8}, + }, + { + []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}, + []byte{0x5a, 0x5b, 0x6e, 0x27, 0x89, 0x48, 0xd7, 0x7f}, + []byte{0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41}, + }, + { + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48}, + []byte{0xa0, 0x39, 0x05, 0x89, 0xf8, 0xb8, 0xef, 0xa5}, + }, + { + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41}, + []byte{0xed, 0x23, 0x37, 0x5a, 0x82, 0x1a, 0x8c, 0x2d}, + }, + { + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0x70, 0xe1, 0x22, 0x5d, 0x6e, 0x4e, 0x76, 0x55}, + []byte{0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41}, + }, + + // These vectors are from http://wiki.secondlife.com/wiki/XTEA_Strong_Encryption_Implementation#Bouncy_Castle_C.23_API + { + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0xDE, 0xE9, 0xD4, 0xD8, 0xF7, 0x13, 0x1E, 0xD9}, + }, + { + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}, + []byte{0x06, 0x5C, 0x1B, 0x89, 0x75, 0xC6, 0xA8, 0x16}, + }, + { + []byte{0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A}, + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{0x1F, 0xF9, 0xA0, 0x26, 0x1A, 0xC6, 0x42, 0x64}, + }, + { + []byte{0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A}, + []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}, + []byte{0x8C, 0x67, 0x15, 0x5B, 0x2E, 0xF9, 0x1E, 0xAD}, + }, +} + +// Test encryption +func TestCipherEncrypt(t *testing.T) { + for i, tt := range CryptTests { + c, err := NewCipher(tt.key) + if err != nil { + t.Errorf("NewCipher(%d bytes), vector %d = %s", len(tt.key), i, err) + continue + } + + out := make([]byte, len(tt.plainText)) + c.Encrypt(out, tt.plainText) + + for j := 0; j < len(out); j++ { + if out[j] != tt.cipherText[j] { + t.Errorf("Cipher.Encrypt %d: out[%d] = %02X, expected %02X", i, j, out[j], tt.cipherText[j]) + break + } + } + } +} + +// Test decryption +func TestCipherDecrypt(t *testing.T) { + for i, tt := range CryptTests { + c, err := NewCipher(tt.key) + if err != nil { + t.Errorf("NewCipher(%d bytes), vector %d = %s", len(tt.key), i, err) + continue + } + + out := make([]byte, len(tt.cipherText)) + c.Decrypt(out, tt.cipherText) + + for j := 0; j < len(out); j++ { + if out[j] != tt.plainText[j] { + t.Errorf("Cipher.Decrypt %d: out[%d] = %02X, expected %02X", i, j, out[j], tt.plainText[j]) + break + } + } + } +} diff --git a/vendor/golang.org/x/crypto/xts/xts.go b/vendor/golang.org/x/crypto/xts/xts.go new file mode 100644 index 0000000000000000000000000000000000000000..92cbce99b90da8092e7da59cf12e7264a644b256 --- /dev/null +++ b/vendor/golang.org/x/crypto/xts/xts.go @@ -0,0 +1,137 @@ +// 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 xts implements the XTS cipher mode as specified in IEEE P1619/D16. +// +// XTS mode is typically used for disk encryption, which presents a number of +// novel problems that make more common modes inapplicable. The disk is +// conceptually an array of sectors and we must be able to encrypt and decrypt +// a sector in isolation. However, an attacker must not be able to transpose +// two sectors of plaintext by transposing their ciphertext. +// +// XTS wraps a block cipher with Rogaway's XEX mode in order to build a +// tweakable block cipher. This allows each sector to have a unique tweak and +// effectively create a unique key for each sector. +// +// XTS does not provide any authentication. An attacker can manipulate the +// ciphertext and randomise a block (16 bytes) of the plaintext. +// +// (Note: this package does not implement ciphertext-stealing so sectors must +// be a multiple of 16 bytes.) +package xts // import "golang.org/x/crypto/xts" + +import ( + "crypto/cipher" + "encoding/binary" + "errors" +) + +// Cipher contains an expanded key structure. It doesn't contain mutable state +// and therefore can be used concurrently. +type Cipher struct { + k1, k2 cipher.Block +} + +// blockSize is the block size that the underlying cipher must have. XTS is +// only defined for 16-byte ciphers. +const blockSize = 16 + +// NewCipher creates a Cipher given a function for creating the underlying +// block cipher (which must have a block size of 16 bytes). The key must be +// twice the length of the underlying cipher's key. +func NewCipher(cipherFunc func([]byte) (cipher.Block, error), key []byte) (c *Cipher, err error) { + c = new(Cipher) + if c.k1, err = cipherFunc(key[:len(key)/2]); err != nil { + return + } + c.k2, err = cipherFunc(key[len(key)/2:]) + + if c.k1.BlockSize() != blockSize { + err = errors.New("xts: cipher does not have a block size of 16") + } + + return +} + +// Encrypt encrypts a sector of plaintext and puts the result into ciphertext. +// Plaintext and ciphertext must overlap entirely or not at all. +// Sectors must be a multiple of 16 bytes and less than 2²ⴠbytes. +func (c *Cipher) Encrypt(ciphertext, plaintext []byte, sectorNum uint64) { + if len(ciphertext) < len(plaintext) { + panic("xts: ciphertext is smaller than plaintext") + } + if len(plaintext)%blockSize != 0 { + panic("xts: plaintext is not a multiple of the block size") + } + + var tweak [blockSize]byte + binary.LittleEndian.PutUint64(tweak[:8], sectorNum) + + c.k2.Encrypt(tweak[:], tweak[:]) + + for len(plaintext) > 0 { + for j := range tweak { + ciphertext[j] = plaintext[j] ^ tweak[j] + } + c.k1.Encrypt(ciphertext, ciphertext) + for j := range tweak { + ciphertext[j] ^= tweak[j] + } + plaintext = plaintext[blockSize:] + ciphertext = ciphertext[blockSize:] + + mul2(&tweak) + } +} + +// Decrypt decrypts a sector of ciphertext and puts the result into plaintext. +// Plaintext and ciphertext must overlap entirely or not at all. +// Sectors must be a multiple of 16 bytes and less than 2²ⴠbytes. +func (c *Cipher) Decrypt(plaintext, ciphertext []byte, sectorNum uint64) { + if len(plaintext) < len(ciphertext) { + panic("xts: plaintext is smaller than ciphertext") + } + if len(ciphertext)%blockSize != 0 { + panic("xts: ciphertext is not a multiple of the block size") + } + + var tweak [blockSize]byte + binary.LittleEndian.PutUint64(tweak[:8], sectorNum) + + c.k2.Encrypt(tweak[:], tweak[:]) + + for len(ciphertext) > 0 { + for j := range tweak { + plaintext[j] = ciphertext[j] ^ tweak[j] + } + c.k1.Decrypt(plaintext, plaintext) + for j := range tweak { + plaintext[j] ^= tweak[j] + } + plaintext = plaintext[blockSize:] + ciphertext = ciphertext[blockSize:] + + mul2(&tweak) + } +} + +// mul2 multiplies tweak by 2 in GF(2¹²â¸) with an irreducible polynomial of +// x¹²⸠+ xâ· + x² + x + 1. +func mul2(tweak *[blockSize]byte) { + var carryIn byte + for j := range tweak { + carryOut := tweak[j] >> 7 + tweak[j] = (tweak[j] << 1) + carryIn + carryIn = carryOut + } + if carryIn != 0 { + // If we have a carry bit then we need to subtract a multiple + // of the irreducible polynomial (x¹²⸠+ xâ· + x² + x + 1). + // By dropping the carry bit, we're subtracting the x^128 term + // so all that remains is to subtract xâ· + x² + x + 1. + // Subtraction (and addition) in this representation is just + // XOR. + tweak[0] ^= 1<<7 | 1<<2 | 1<<1 | 1 + } +} diff --git a/vendor/golang.org/x/crypto/xts/xts_test.go b/vendor/golang.org/x/crypto/xts/xts_test.go new file mode 100644 index 0000000000000000000000000000000000000000..96d3b6cbc6289487e8ea536b95b5e93a1c2b6097 --- /dev/null +++ b/vendor/golang.org/x/crypto/xts/xts_test.go @@ -0,0 +1,105 @@ +// 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 xts + +import ( + "bytes" + "crypto/aes" + "encoding/hex" + "testing" +) + +// These test vectors have been taken from IEEE P1619/D16, Annex B. +var xtsTestVectors = []struct { + key string + sector uint64 + plaintext string + ciphertext string +}{ + { + "0000000000000000000000000000000000000000000000000000000000000000", + 0, + "0000000000000000000000000000000000000000000000000000000000000000", + "917cf69ebd68b2ec9b9fe9a3eadda692cd43d2f59598ed858c02c2652fbf922e", + }, { + "1111111111111111111111111111111122222222222222222222222222222222", + 0x3333333333, + "4444444444444444444444444444444444444444444444444444444444444444", + "c454185e6a16936e39334038acef838bfb186fff7480adc4289382ecd6d394f0", + }, { + "fffefdfcfbfaf9f8f7f6f5f4f3f2f1f022222222222222222222222222222222", + 0x3333333333, + "4444444444444444444444444444444444444444444444444444444444444444", + "af85336b597afc1a900b2eb21ec949d292df4c047e0b21532186a5971a227a89", + }, { + "2718281828459045235360287471352631415926535897932384626433832795", + 0, + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", + "27a7479befa1d476489f308cd4cfa6e2a96e4bbe3208ff25287dd3819616e89cc78cf7f5e543445f8333d8fa7f56000005279fa5d8b5e4ad40e736ddb4d35412328063fd2aab53e5ea1e0a9f332500a5df9487d07a5c92cc512c8866c7e860ce93fdf166a24912b422976146ae20ce846bb7dc9ba94a767aaef20c0d61ad02655ea92dc4c4e41a8952c651d33174be51a10c421110e6d81588ede82103a252d8a750e8768defffed9122810aaeb99f9172af82b604dc4b8e51bcb08235a6f4341332e4ca60482a4ba1a03b3e65008fc5da76b70bf1690db4eae29c5f1badd03c5ccf2a55d705ddcd86d449511ceb7ec30bf12b1fa35b913f9f747a8afd1b130e94bff94effd01a91735ca1726acd0b197c4e5b03393697e126826fb6bbde8ecc1e08298516e2c9ed03ff3c1b7860f6de76d4cecd94c8119855ef5297ca67e9f3e7ff72b1e99785ca0a7e7720c5b36dc6d72cac9574c8cbbc2f801e23e56fd344b07f22154beba0f08ce8891e643ed995c94d9a69c9f1b5f499027a78572aeebd74d20cc39881c213ee770b1010e4bea718846977ae119f7a023ab58cca0ad752afe656bb3c17256a9f6e9bf19fdd5a38fc82bbe872c5539edb609ef4f79c203ebb140f2e583cb2ad15b4aa5b655016a8449277dbd477ef2c8d6c017db738b18deb4a427d1923ce3ff262735779a418f20a282df920147beabe421ee5319d0568", + }, { + "2718281828459045235360287471352631415926535897932384626433832795", + 1, + "27a7479befa1d476489f308cd4cfa6e2a96e4bbe3208ff25287dd3819616e89cc78cf7f5e543445f8333d8fa7f56000005279fa5d8b5e4ad40e736ddb4d35412328063fd2aab53e5ea1e0a9f332500a5df9487d07a5c92cc512c8866c7e860ce93fdf166a24912b422976146ae20ce846bb7dc9ba94a767aaef20c0d61ad02655ea92dc4c4e41a8952c651d33174be51a10c421110e6d81588ede82103a252d8a750e8768defffed9122810aaeb99f9172af82b604dc4b8e51bcb08235a6f4341332e4ca60482a4ba1a03b3e65008fc5da76b70bf1690db4eae29c5f1badd03c5ccf2a55d705ddcd86d449511ceb7ec30bf12b1fa35b913f9f747a8afd1b130e94bff94effd01a91735ca1726acd0b197c4e5b03393697e126826fb6bbde8ecc1e08298516e2c9ed03ff3c1b7860f6de76d4cecd94c8119855ef5297ca67e9f3e7ff72b1e99785ca0a7e7720c5b36dc6d72cac9574c8cbbc2f801e23e56fd344b07f22154beba0f08ce8891e643ed995c94d9a69c9f1b5f499027a78572aeebd74d20cc39881c213ee770b1010e4bea718846977ae119f7a023ab58cca0ad752afe656bb3c17256a9f6e9bf19fdd5a38fc82bbe872c5539edb609ef4f79c203ebb140f2e583cb2ad15b4aa5b655016a8449277dbd477ef2c8d6c017db738b18deb4a427d1923ce3ff262735779a418f20a282df920147beabe421ee5319d0568", + "264d3ca8512194fec312c8c9891f279fefdd608d0c027b60483a3fa811d65ee59d52d9e40ec5672d81532b38b6b089ce951f0f9c35590b8b978d175213f329bb1c2fd30f2f7f30492a61a532a79f51d36f5e31a7c9a12c286082ff7d2394d18f783e1a8e72c722caaaa52d8f065657d2631fd25bfd8e5baad6e527d763517501c68c5edc3cdd55435c532d7125c8614deed9adaa3acade5888b87bef641c4c994c8091b5bcd387f3963fb5bc37aa922fbfe3df4e5b915e6eb514717bdd2a74079a5073f5c4bfd46adf7d282e7a393a52579d11a028da4d9cd9c77124f9648ee383b1ac763930e7162a8d37f350b2f74b8472cf09902063c6b32e8c2d9290cefbd7346d1c779a0df50edcde4531da07b099c638e83a755944df2aef1aa31752fd323dcb710fb4bfbb9d22b925bc3577e1b8949e729a90bbafeacf7f7879e7b1147e28ba0bae940db795a61b15ecf4df8db07b824bb062802cc98a9545bb2aaeed77cb3fc6db15dcd7d80d7d5bc406c4970a3478ada8899b329198eb61c193fb6275aa8ca340344a75a862aebe92eee1ce032fd950b47d7704a3876923b4ad62844bf4a09c4dbe8b4397184b7471360c9564880aedddb9baa4af2e75394b08cd32ff479c57a07d3eab5d54de5f9738b8d27f27a9f0ab11799d7b7ffefb2704c95c6ad12c39f1e867a4b7b1d7818a4b753dfd2a89ccb45e001a03a867b187f225dd", + }, { + "27182818284590452353602874713526624977572470936999595749669676273141592653589793238462643383279502884197169399375105820974944592", + 0xff, + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", + "1c3b3a102f770386e4836c99e370cf9bea00803f5e482357a4ae12d414a3e63b5d31e276f8fe4a8d66b317f9ac683f44680a86ac35adfc3345befecb4bb188fd5776926c49a3095eb108fd1098baec70aaa66999a72a82f27d848b21d4a741b0c5cd4d5fff9dac89aeba122961d03a757123e9870f8acf1000020887891429ca2a3e7a7d7df7b10355165c8b9a6d0a7de8b062c4500dc4cd120c0f7418dae3d0b5781c34803fa75421c790dfe1de1834f280d7667b327f6c8cd7557e12ac3a0f93ec05c52e0493ef31a12d3d9260f79a289d6a379bc70c50841473d1a8cc81ec583e9645e07b8d9670655ba5bbcfecc6dc3966380ad8fecb17b6ba02469a020a84e18e8f84252070c13e9f1f289be54fbc481457778f616015e1327a02b140f1505eb309326d68378f8374595c849d84f4c333ec4423885143cb47bd71c5edae9be69a2ffeceb1bec9de244fbe15992b11b77c040f12bd8f6a975a44a0f90c29a9abc3d4d893927284c58754cce294529f8614dcd2aba991925fedc4ae74ffac6e333b93eb4aff0479da9a410e4450e0dd7ae4c6e2910900575da401fc07059f645e8b7e9bfdef33943054ff84011493c27b3429eaedb4ed5376441a77ed43851ad77f16f541dfd269d50d6a5f14fb0aab1cbb4c1550be97f7ab4066193c4caa773dad38014bd2092fa755c824bb5e54c4f36ffda9fcea70b9c6e693e148c151", + }, +} + +func fromHex(s string) []byte { + ret, err := hex.DecodeString(s) + if err != nil { + panic("xts: invalid hex in test") + } + return ret +} + +func TestXTS(t *testing.T) { + for i, test := range xtsTestVectors { + c, err := NewCipher(aes.NewCipher, fromHex(test.key)) + if err != nil { + t.Errorf("#%d: failed to create cipher: %s", i, err) + continue + } + plaintext := fromHex(test.plaintext) + ciphertext := make([]byte, len(plaintext)) + c.Encrypt(ciphertext, plaintext, test.sector) + + expectedCiphertext := fromHex(test.ciphertext) + if !bytes.Equal(ciphertext, expectedCiphertext) { + t.Errorf("#%d: encrypted failed, got: %x, want: %x", i, ciphertext, expectedCiphertext) + continue + } + + decrypted := make([]byte, len(ciphertext)) + c.Decrypt(decrypted, ciphertext, test.sector) + if !bytes.Equal(decrypted, plaintext) { + t.Errorf("#%d: decryption failed, got: %x, want: %x", i, decrypted, plaintext) + } + } +} + +func TestShorterCiphertext(t *testing.T) { + // Decrypt used to panic if the input was shorter than the output. See + // https://go-review.googlesource.com/c/39954/ + c, err := NewCipher(aes.NewCipher, make([]byte, 32)) + if err != nil { + t.Fatalf("NewCipher failed: %s", err) + } + + plaintext := make([]byte, 32) + encrypted := make([]byte, 48) + decrypted := make([]byte, 48) + + c.Encrypt(encrypted, plaintext, 0) + c.Decrypt(decrypted, encrypted[:len(plaintext)], 0) + + if !bytes.Equal(plaintext, decrypted[:len(plaintext)]) { + t.Errorf("En/Decryption is not inverse") + } +} diff --git a/vendor/golang.org/x/net/dns/dnsmessage/message.go b/vendor/golang.org/x/net/dns/dnsmessage/message.go index ea94bd4950d1d3cc7a18677260a90653e4e686b3..e98fda66ee60db91c4cc53ae0f50b572044883cb 100644 --- a/vendor/golang.org/x/net/dns/dnsmessage/message.go +++ b/vendor/golang.org/x/net/dns/dnsmessage/message.go @@ -436,7 +436,13 @@ func (p *Parser) Question() (Question, error) { // AllQuestions parses all Questions. func (p *Parser) AllQuestions() ([]Question, error) { - qs := make([]Question, 0, p.header.questions) + // Multiple questions are valid according to the spec, + // but servers don't actually support them. There will + // be at most one question here. + // + // Do not pre-allocate based on info in p.header, since + // the data is untrusted. + qs := []Question{} for { q, err := p.Question() if err == ErrSectionDone { @@ -492,7 +498,16 @@ func (p *Parser) Answer() (Resource, error) { // AllAnswers parses all Answer Resources. func (p *Parser) AllAnswers() ([]Resource, error) { - as := make([]Resource, 0, p.header.answers) + // The most common query is for A/AAAA, which usually returns + // a handful of IPs. + // + // Pre-allocate up to a certain limit, since p.header is + // untrusted data. + n := int(p.header.answers) + if n > 20 { + n = 20 + } + as := make([]Resource, 0, n) for { a, err := p.Answer() if err == ErrSectionDone { @@ -533,7 +548,16 @@ func (p *Parser) Authority() (Resource, error) { // AllAuthorities parses all Authority Resources. func (p *Parser) AllAuthorities() ([]Resource, error) { - as := make([]Resource, 0, p.header.authorities) + // Authorities contains SOA in case of NXDOMAIN and friends, + // otherwise it is empty. + // + // Pre-allocate up to a certain limit, since p.header is + // untrusted data. + n := int(p.header.authorities) + if n > 10 { + n = 10 + } + as := make([]Resource, 0, n) for { a, err := p.Authority() if err == ErrSectionDone { @@ -574,7 +598,16 @@ func (p *Parser) Additional() (Resource, error) { // AllAdditionals parses all Additional Resources. func (p *Parser) AllAdditionals() ([]Resource, error) { - as := make([]Resource, 0, p.header.additionals) + // Additionals usually contain OPT, and sometimes A/AAAA + // glue records. + // + // Pre-allocate up to a certain limit, since p.header is + // untrusted data. + n := int(p.header.additionals) + if n > 10 { + n = 10 + } + as := make([]Resource, 0, n) for { a, err := p.Additional() if err == ErrSectionDone { diff --git a/vendor/golang.org/x/net/html/atom/gen.go b/vendor/golang.org/x/net/html/atom/gen.go index cc5dc5dbceeb800435f1811be39fe9acf61e63ca..56cd842514eebf1bcd812e01a1369fbc457c68ee 100644 --- a/vendor/golang.org/x/net/html/atom/gen.go +++ b/vendor/golang.org/x/net/html/atom/gen.go @@ -665,6 +665,7 @@ var eventHandlers = []string{ // extra are ad-hoc values not covered by any of the lists above. var extra = []string{ + "acronym", "align", "annotation", "annotation-xml", diff --git a/vendor/golang.org/x/net/html/atom/table.go b/vendor/golang.org/x/net/html/atom/table.go index f74018ecea176c27ca28a0d7746cd47f777aece8..a91bd6475c1a581750c8017a12c421ac8332a0f4 100644 --- a/vendor/golang.org/x/net/html/atom/table.go +++ b/vendor/golang.org/x/net/html/atom/table.go @@ -10,366 +10,367 @@ const ( Accept Atom = 0x1a06 AcceptCharset Atom = 0x1a0e Accesskey Atom = 0x2c09 - Action Atom = 0x25a06 - Address Atom = 0x6ed07 - Align Atom = 0x6d405 - Allowfullscreen Atom = 0x1f00f - Allowpaymentrequest Atom = 0x6913 - Allowusermedia Atom = 0x850e - Alt Atom = 0xb003 - Annotation Atom = 0x1b90a - AnnotationXml Atom = 0x1b90e - Applet Atom = 0x30106 - Area Atom = 0x34a04 - Article Atom = 0x3f007 - As Atom = 0xb902 - Aside Atom = 0xc105 - Async Atom = 0xb905 - Audio Atom = 0xcf05 - Autocomplete Atom = 0x2600c - Autofocus Atom = 0xeb09 - Autoplay Atom = 0x10608 + Acronym Atom = 0x6907 + Action Atom = 0x26a06 + Address Atom = 0x6f307 + Align Atom = 0x7005 + Allowfullscreen Atom = 0x2000f + Allowpaymentrequest Atom = 0x8013 + Allowusermedia Atom = 0x9c0e + Alt Atom = 0xc703 + Annotation Atom = 0x1c90a + AnnotationXml Atom = 0x1c90e + Applet Atom = 0x31106 + Area Atom = 0x34e04 + Article Atom = 0x3f407 + As Atom = 0xd002 + Aside Atom = 0xd805 + Async Atom = 0xd005 + Audio Atom = 0xe605 + Autocomplete Atom = 0x2700c + Autofocus Atom = 0x10209 + Autoplay Atom = 0x11d08 B Atom = 0x101 - Base Atom = 0x11504 - Basefont Atom = 0x11508 - Bdi Atom = 0x16103 - Bdo Atom = 0x13403 - Bgsound Atom = 0x14707 - Big Atom = 0x15903 - Blink Atom = 0x15c05 - Blockquote Atom = 0x1680a + Base Atom = 0x12c04 + Basefont Atom = 0x12c08 + Bdi Atom = 0x7903 + Bdo Atom = 0x14b03 + Bgsound Atom = 0x15e07 + Big Atom = 0x17003 + Blink Atom = 0x17305 + Blockquote Atom = 0x1870a Body Atom = 0x2804 Br Atom = 0x202 - Button Atom = 0x17206 - Canvas Atom = 0xbd06 - Caption Atom = 0x21907 - Center Atom = 0x20806 - Challenge Atom = 0x28309 + Button Atom = 0x19106 + Canvas Atom = 0xd406 + Caption Atom = 0x22907 + Center Atom = 0x21806 + Challenge Atom = 0x29309 Charset Atom = 0x2107 - Checked Atom = 0x46d07 - Cite Atom = 0x55804 - Class Atom = 0x5b905 - Code Atom = 0x19004 - Col Atom = 0x19703 - Colgroup Atom = 0x19708 - Color Atom = 0x1af05 - Cols Atom = 0x1b404 - Colspan Atom = 0x1b407 - Command Atom = 0x1c707 - Content Atom = 0x57f07 - Contenteditable Atom = 0x57f0f - Contextmenu Atom = 0x3740b - Controls Atom = 0x1ce08 - Coords Atom = 0x1da06 - Crossorigin Atom = 0x1e30b - Data Atom = 0x49904 - Datalist Atom = 0x49908 - Datetime Atom = 0x2a008 - Dd Atom = 0x2bf02 - Default Atom = 0xc407 - Defer Atom = 0x19205 - Del Atom = 0x44603 - Desc Atom = 0x55504 + Checked Atom = 0x47107 + Cite Atom = 0x55c04 + Class Atom = 0x5bd05 + Code Atom = 0x1a004 + Col Atom = 0x1a703 + Colgroup Atom = 0x1a708 + Color Atom = 0x1bf05 + Cols Atom = 0x1c404 + Colspan Atom = 0x1c407 + Command Atom = 0x1d707 + Content Atom = 0x58307 + Contenteditable Atom = 0x5830f + Contextmenu Atom = 0x3780b + Controls Atom = 0x1de08 + Coords Atom = 0x1ea06 + Crossorigin Atom = 0x1f30b + Data Atom = 0x49d04 + Datalist Atom = 0x49d08 + Datetime Atom = 0x2b008 + Dd Atom = 0x2cf02 + Default Atom = 0xdb07 + Defer Atom = 0x1a205 + Del Atom = 0x44a03 + Desc Atom = 0x55904 Details Atom = 0x4607 Dfn Atom = 0x5f03 - Dialog Atom = 0x16206 - Dir Atom = 0xa303 - Dirname Atom = 0xa307 - Disabled Atom = 0x14d08 - Div Atom = 0x15403 - Dl Atom = 0x5e202 - Download Atom = 0x45708 - Draggable Atom = 0x18309 - Dropzone Atom = 0x3f908 - Dt Atom = 0x64702 + Dialog Atom = 0x7a06 + Dir Atom = 0xba03 + Dirname Atom = 0xba07 + Disabled Atom = 0x16408 + Div Atom = 0x16b03 + Dl Atom = 0x5e602 + Download Atom = 0x45b08 + Draggable Atom = 0x17a09 + Dropzone Atom = 0x3fd08 + Dt Atom = 0x64b02 Em Atom = 0x4202 Embed Atom = 0x4205 - Enctype Atom = 0x27507 - Face Atom = 0x20604 - Fieldset Atom = 0x20e08 - Figcaption Atom = 0x2160a - Figure Atom = 0x23006 - Font Atom = 0x11904 - Footer Atom = 0xb306 - For Atom = 0x23c03 - ForeignObject Atom = 0x23c0d - Foreignobject Atom = 0x2490d - Form Atom = 0x25604 - Formaction Atom = 0x2560a - Formenctype Atom = 0x2710b - Formmethod Atom = 0x28c0a - Formnovalidate Atom = 0x2960e - Formtarget Atom = 0x2a80a + Enctype Atom = 0x28507 + Face Atom = 0x21604 + Fieldset Atom = 0x21e08 + Figcaption Atom = 0x2260a + Figure Atom = 0x24006 + Font Atom = 0x13004 + Footer Atom = 0xca06 + For Atom = 0x24c03 + ForeignObject Atom = 0x24c0d + Foreignobject Atom = 0x2590d + Form Atom = 0x26604 + Formaction Atom = 0x2660a + Formenctype Atom = 0x2810b + Formmethod Atom = 0x29c0a + Formnovalidate Atom = 0x2a60e + Formtarget Atom = 0x2b80a Frame Atom = 0x5705 Frameset Atom = 0x5708 - H1 Atom = 0x14502 - H2 Atom = 0x2c602 - H3 Atom = 0x2f502 - H4 Atom = 0x33902 - H5 Atom = 0x34302 - H6 Atom = 0x64902 - Head Atom = 0x32504 - Header Atom = 0x32506 - Headers Atom = 0x32507 - Height Atom = 0x12c06 - Hgroup Atom = 0x2b206 - Hidden Atom = 0x2bd06 - High Atom = 0x2c304 - Hr Atom = 0x14002 - Href Atom = 0x2c804 - Hreflang Atom = 0x2c808 - Html Atom = 0x13004 - HttpEquiv Atom = 0x2d00a + H1 Atom = 0x15c02 + H2 Atom = 0x2d602 + H3 Atom = 0x30502 + H4 Atom = 0x33d02 + H5 Atom = 0x34702 + H6 Atom = 0x64d02 + Head Atom = 0x32904 + Header Atom = 0x32906 + Headers Atom = 0x32907 + Height Atom = 0x14306 + Hgroup Atom = 0x2c206 + Hidden Atom = 0x2cd06 + High Atom = 0x2d304 + Hr Atom = 0x15702 + Href Atom = 0x2d804 + Hreflang Atom = 0x2d808 + Html Atom = 0x14704 + HttpEquiv Atom = 0x2e00a I Atom = 0x601 - Icon Atom = 0x57e04 - Id Atom = 0xc302 - Iframe Atom = 0x2e406 - Image Atom = 0x2ea05 - Img Atom = 0x2ef03 - Input Atom = 0x43f05 - Inputmode Atom = 0x43f09 - Ins Atom = 0x1ec03 - Integrity Atom = 0x22709 - Is Atom = 0x14e02 - Isindex Atom = 0x2f707 - Ismap Atom = 0x2fe05 - Itemid Atom = 0x37f06 - Itemprop Atom = 0x55908 - Itemref Atom = 0x3c107 - Itemscope Atom = 0x66d09 - Itemtype Atom = 0x30708 - Kbd Atom = 0x16003 + Icon Atom = 0x58204 + Id Atom = 0xda02 + Iframe Atom = 0x2f406 + Image Atom = 0x2fa05 + Img Atom = 0x2ff03 + Input Atom = 0x44305 + Inputmode Atom = 0x44309 + Ins Atom = 0x1fc03 + Integrity Atom = 0x23709 + Is Atom = 0x16502 + Isindex Atom = 0x30707 + Ismap Atom = 0x30e05 + Itemid Atom = 0x38306 + Itemprop Atom = 0x55d08 + Itemref Atom = 0x3c507 + Itemscope Atom = 0x67109 + Itemtype Atom = 0x31708 + Kbd Atom = 0x7803 Keygen Atom = 0x3206 - Keytype Atom = 0x7e07 - Kind Atom = 0x18004 - Label Atom = 0xda05 - Lang Atom = 0x2cc04 - Legend Atom = 0x18a06 - Li Atom = 0x11102 - Link Atom = 0x15d04 - List Atom = 0x49d04 - Listing Atom = 0x49d07 - Loop Atom = 0xde04 - Low Atom = 0x6b03 + Keytype Atom = 0x9507 + Kind Atom = 0x17704 + Label Atom = 0xf105 + Lang Atom = 0x2dc04 + Legend Atom = 0x18106 + Li Atom = 0x7102 + Link Atom = 0x17404 + List Atom = 0x4a104 + Listing Atom = 0x4a107 + Loop Atom = 0xf504 + Low Atom = 0x8203 Main Atom = 0x1004 - Malignmark Atom = 0x6d30a - Manifest Atom = 0x30f08 - Map Atom = 0x30003 - Mark Atom = 0x6d904 - Marquee Atom = 0x31b07 - Math Atom = 0x32204 - Max Atom = 0x33103 - Maxlength Atom = 0x33109 - Media Atom = 0x8e05 - Mediagroup Atom = 0x8e0a - Menu Atom = 0x37b04 - Menuitem Atom = 0x37b08 - Meta Atom = 0x4ac04 - Meter Atom = 0xa805 - Method Atom = 0x29006 - Mglyph Atom = 0x2f006 - Mi Atom = 0x33b02 - Min Atom = 0x33b03 - Minlength Atom = 0x33b09 - Mn Atom = 0x29902 + Malignmark Atom = 0x6f0a + Manifest Atom = 0x6d708 + Map Atom = 0x31003 + Mark Atom = 0x7504 + Marquee Atom = 0x31f07 + Math Atom = 0x32604 + Max Atom = 0x33503 + Maxlength Atom = 0x33509 + Media Atom = 0xa505 + Mediagroup Atom = 0xa50a + Menu Atom = 0x37f04 + Menuitem Atom = 0x37f08 + Meta Atom = 0x4b004 + Meter Atom = 0xbf05 + Method Atom = 0x2a006 + Mglyph Atom = 0x30006 + Mi Atom = 0x33f02 + Min Atom = 0x33f03 + Minlength Atom = 0x33f09 + Mn Atom = 0x2a902 Mo Atom = 0x6302 - Ms Atom = 0x67002 - Mtext Atom = 0x34505 - Multiple Atom = 0x35308 - Muted Atom = 0x35b05 - Name Atom = 0xa604 + Ms Atom = 0x67402 + Mtext Atom = 0x34905 + Multiple Atom = 0x35708 + Muted Atom = 0x35f05 + Name Atom = 0xbd04 Nav Atom = 0x1303 Nobr Atom = 0x3704 Noembed Atom = 0x4007 Noframes Atom = 0x5508 Nomodule Atom = 0x6108 - Nonce Atom = 0x56205 - Noscript Atom = 0x1fe08 - Novalidate Atom = 0x29a0a - Object Atom = 0x25006 - Ol Atom = 0x10102 - Onabort Atom = 0x17607 - Onafterprint Atom = 0x21e0c - Onautocomplete Atom = 0x25e0e - Onautocompleteerror Atom = 0x25e13 - Onauxclick Atom = 0x61b0a - Onbeforeprint Atom = 0x69a0d - Onbeforeunload Atom = 0x6e10e - Onblur Atom = 0x5c206 - Oncancel Atom = 0xd308 - Oncanplay Atom = 0x13609 - Oncanplaythrough Atom = 0x13610 - Onchange Atom = 0x40f08 - Onclick Atom = 0x2dd07 - Onclose Atom = 0x36007 - Oncontextmenu Atom = 0x3720d - Oncopy Atom = 0x38506 - Oncuechange Atom = 0x38b0b - Oncut Atom = 0x39605 - Ondblclick Atom = 0x39b0a - Ondrag Atom = 0x3a506 - Ondragend Atom = 0x3a509 - Ondragenter Atom = 0x3ae0b - Ondragexit Atom = 0x3b90a - Ondragleave Atom = 0x3d30b - Ondragover Atom = 0x3de0a - Ondragstart Atom = 0x3e80b - Ondrop Atom = 0x3f706 - Ondurationchange Atom = 0x40710 - Onemptied Atom = 0x3fe09 - Onended Atom = 0x41707 - Onerror Atom = 0x41e07 - Onfocus Atom = 0x42507 - Onhashchange Atom = 0x4310c - Oninput Atom = 0x43d07 - Oninvalid Atom = 0x44909 - Onkeydown Atom = 0x45209 - Onkeypress Atom = 0x45f0a - Onkeyup Atom = 0x47407 - Onlanguagechange Atom = 0x48110 - Onload Atom = 0x49106 - Onloadeddata Atom = 0x4910c - Onloadedmetadata Atom = 0x4a410 - Onloadend Atom = 0x4ba09 - Onloadstart Atom = 0x4c30b - Onmessage Atom = 0x4ce09 - Onmessageerror Atom = 0x4ce0e - Onmousedown Atom = 0x4dc0b - Onmouseenter Atom = 0x4e70c - Onmouseleave Atom = 0x4f30c - Onmousemove Atom = 0x4ff0b - Onmouseout Atom = 0x50a0a - Onmouseover Atom = 0x5170b - Onmouseup Atom = 0x52209 - Onmousewheel Atom = 0x5300c - Onoffline Atom = 0x53c09 - Ononline Atom = 0x54508 - Onpagehide Atom = 0x54d0a - Onpageshow Atom = 0x5670a - Onpaste Atom = 0x57307 - Onpause Atom = 0x58e07 - Onplay Atom = 0x59806 - Onplaying Atom = 0x59809 - Onpopstate Atom = 0x5a10a - Onprogress Atom = 0x5ab0a - Onratechange Atom = 0x5c80c - Onrejectionhandled Atom = 0x5d412 - Onreset Atom = 0x5e607 - Onresize Atom = 0x5ed08 - Onscroll Atom = 0x5fc08 - Onsecuritypolicyviolation Atom = 0x60419 - Onseeked Atom = 0x62508 - Onseeking Atom = 0x62d09 - Onselect Atom = 0x63608 - Onshow Atom = 0x64006 - Onsort Atom = 0x64b06 - Onstalled Atom = 0x65509 - Onstorage Atom = 0x65e09 - Onsubmit Atom = 0x66708 - Onsuspend Atom = 0x67709 - Ontimeupdate Atom = 0x11a0c - Ontoggle Atom = 0x68008 - Onunhandledrejection Atom = 0x68814 - Onunload Atom = 0x6a708 - Onvolumechange Atom = 0x6af0e - Onwaiting Atom = 0x6bd09 - Onwheel Atom = 0x6c607 - Open Atom = 0x55f04 - Optgroup Atom = 0xe008 - Optimum Atom = 0x6cd07 - Option Atom = 0x6dd06 - Output Atom = 0x51106 + Nonce Atom = 0x56605 + Noscript Atom = 0x20e08 + Novalidate Atom = 0x2aa0a + Object Atom = 0x26006 + Ol Atom = 0x11802 + Onabort Atom = 0x19507 + Onafterprint Atom = 0x22e0c + Onautocomplete Atom = 0x26e0e + Onautocompleteerror Atom = 0x26e13 + Onauxclick Atom = 0x61f0a + Onbeforeprint Atom = 0x69e0d + Onbeforeunload Atom = 0x6e70e + Onblur Atom = 0x5c606 + Oncancel Atom = 0xea08 + Oncanplay Atom = 0x14d09 + Oncanplaythrough Atom = 0x14d10 + Onchange Atom = 0x41308 + Onclick Atom = 0x2ed07 + Onclose Atom = 0x36407 + Oncontextmenu Atom = 0x3760d + Oncopy Atom = 0x38906 + Oncuechange Atom = 0x38f0b + Oncut Atom = 0x39a05 + Ondblclick Atom = 0x39f0a + Ondrag Atom = 0x3a906 + Ondragend Atom = 0x3a909 + Ondragenter Atom = 0x3b20b + Ondragexit Atom = 0x3bd0a + Ondragleave Atom = 0x3d70b + Ondragover Atom = 0x3e20a + Ondragstart Atom = 0x3ec0b + Ondrop Atom = 0x3fb06 + Ondurationchange Atom = 0x40b10 + Onemptied Atom = 0x40209 + Onended Atom = 0x41b07 + Onerror Atom = 0x42207 + Onfocus Atom = 0x42907 + Onhashchange Atom = 0x4350c + Oninput Atom = 0x44107 + Oninvalid Atom = 0x44d09 + Onkeydown Atom = 0x45609 + Onkeypress Atom = 0x4630a + Onkeyup Atom = 0x47807 + Onlanguagechange Atom = 0x48510 + Onload Atom = 0x49506 + Onloadeddata Atom = 0x4950c + Onloadedmetadata Atom = 0x4a810 + Onloadend Atom = 0x4be09 + Onloadstart Atom = 0x4c70b + Onmessage Atom = 0x4d209 + Onmessageerror Atom = 0x4d20e + Onmousedown Atom = 0x4e00b + Onmouseenter Atom = 0x4eb0c + Onmouseleave Atom = 0x4f70c + Onmousemove Atom = 0x5030b + Onmouseout Atom = 0x50e0a + Onmouseover Atom = 0x51b0b + Onmouseup Atom = 0x52609 + Onmousewheel Atom = 0x5340c + Onoffline Atom = 0x54009 + Ononline Atom = 0x54908 + Onpagehide Atom = 0x5510a + Onpageshow Atom = 0x56b0a + Onpaste Atom = 0x57707 + Onpause Atom = 0x59207 + Onplay Atom = 0x59c06 + Onplaying Atom = 0x59c09 + Onpopstate Atom = 0x5a50a + Onprogress Atom = 0x5af0a + Onratechange Atom = 0x5cc0c + Onrejectionhandled Atom = 0x5d812 + Onreset Atom = 0x5ea07 + Onresize Atom = 0x5f108 + Onscroll Atom = 0x60008 + Onsecuritypolicyviolation Atom = 0x60819 + Onseeked Atom = 0x62908 + Onseeking Atom = 0x63109 + Onselect Atom = 0x63a08 + Onshow Atom = 0x64406 + Onsort Atom = 0x64f06 + Onstalled Atom = 0x65909 + Onstorage Atom = 0x66209 + Onsubmit Atom = 0x66b08 + Onsuspend Atom = 0x67b09 + Ontimeupdate Atom = 0x1310c + Ontoggle Atom = 0x68408 + Onunhandledrejection Atom = 0x68c14 + Onunload Atom = 0x6ab08 + Onvolumechange Atom = 0x6b30e + Onwaiting Atom = 0x6c109 + Onwheel Atom = 0x6ca07 + Open Atom = 0x56304 + Optgroup Atom = 0xf708 + Optimum Atom = 0x6d107 + Option Atom = 0x6e306 + Output Atom = 0x51506 P Atom = 0xc01 Param Atom = 0xc05 Pattern Atom = 0x4f07 - Picture Atom = 0x9707 - Ping Atom = 0xe704 - Placeholder Atom = 0xfb0b - Plaintext Atom = 0x19e09 - Playsinline Atom = 0x10a0b - Poster Atom = 0x2b706 - Pre Atom = 0x46403 - Preload Atom = 0x47a07 - Progress Atom = 0x5ad08 - Prompt Atom = 0x52a06 - Public Atom = 0x57a06 - Q Atom = 0x7701 + Picture Atom = 0xae07 + Ping Atom = 0xfe04 + Placeholder Atom = 0x1120b + Plaintext Atom = 0x1ae09 + Playsinline Atom = 0x1210b + Poster Atom = 0x2c706 + Pre Atom = 0x46803 + Preload Atom = 0x47e07 + Progress Atom = 0x5b108 + Prompt Atom = 0x52e06 + Public Atom = 0x57e06 + Q Atom = 0x8e01 Radiogroup Atom = 0x30a - Readonly Atom = 0x34b08 - Referrerpolicy Atom = 0x3c50e - Rel Atom = 0x47b03 - Required Atom = 0x23408 - Reversed Atom = 0x9c08 + Readonly Atom = 0x34f08 + Referrerpolicy Atom = 0x3c90e + Rel Atom = 0x47f03 + Required Atom = 0x24408 + Reversed Atom = 0xb308 Rows Atom = 0x3a04 Rowspan Atom = 0x3a07 - Rp Atom = 0x22402 - Rt Atom = 0x17b02 - Ruby Atom = 0xac04 + Rp Atom = 0x23402 + Rt Atom = 0x19a02 + Ruby Atom = 0xc304 S Atom = 0x2501 Samp Atom = 0x4c04 - Sandbox Atom = 0xf307 - Scope Atom = 0x67105 - Scoped Atom = 0x67106 - Script Atom = 0x20006 - Seamless Atom = 0x36508 - Section Atom = 0x5bd07 - Select Atom = 0x63806 - Selected Atom = 0x63808 - Shape Atom = 0x1d505 - Size Atom = 0x5f104 - Sizes Atom = 0x5f105 - Slot Atom = 0x1df04 - Small Atom = 0x1ee05 - Sortable Atom = 0x64d08 - Sorted Atom = 0x32b06 - Source Atom = 0x36c06 - Spacer Atom = 0x42b06 + Sandbox Atom = 0x10a07 + Scope Atom = 0x67505 + Scoped Atom = 0x67506 + Script Atom = 0x21006 + Seamless Atom = 0x36908 + Section Atom = 0x5c107 + Select Atom = 0x63c06 + Selected Atom = 0x63c08 + Shape Atom = 0x1e505 + Size Atom = 0x5f504 + Sizes Atom = 0x5f505 + Slot Atom = 0x1ef04 + Small Atom = 0x1fe05 + Sortable Atom = 0x65108 + Sorted Atom = 0x32f06 + Source Atom = 0x37006 + Spacer Atom = 0x42f06 Span Atom = 0x3d04 - Spellcheck Atom = 0x4680a - Src Atom = 0x5b403 - Srcdoc Atom = 0x5b406 - Srclang Atom = 0x5f507 - Srcset Atom = 0x6f306 - Start Atom = 0x3ee05 - Step Atom = 0x57704 - Strike Atom = 0x7a06 - Strong Atom = 0x31506 - Style Atom = 0x6f905 - Sub Atom = 0x66903 - Summary Atom = 0x6fe07 - Sup Atom = 0x70503 - Svg Atom = 0x70803 - System Atom = 0x70b06 - Tabindex Atom = 0x4b208 - Table Atom = 0x58905 - Target Atom = 0x2ac06 + Spellcheck Atom = 0x46c0a + Src Atom = 0x5b803 + Srcdoc Atom = 0x5b806 + Srclang Atom = 0x5f907 + Srcset Atom = 0x6f906 + Start Atom = 0x3f205 + Step Atom = 0x57b04 + Strike Atom = 0x9106 + Strong Atom = 0x6dd06 + Style Atom = 0x6ff05 + Sub Atom = 0x66d03 + Summary Atom = 0x70407 + Sup Atom = 0x70b03 + Svg Atom = 0x70e03 + System Atom = 0x71106 + Tabindex Atom = 0x4b608 + Table Atom = 0x58d05 + Target Atom = 0x2bc06 Tbody Atom = 0x2705 Td Atom = 0x5e02 - Template Atom = 0x70e08 - Textarea Atom = 0x34608 - Tfoot Atom = 0xb205 - Th Atom = 0x13f02 - Thead Atom = 0x32405 - Time Atom = 0x11c04 - Title Atom = 0xca05 - Tr Atom = 0x7402 - Track Atom = 0x17c05 - Translate Atom = 0x1a609 + Template Atom = 0x71408 + Textarea Atom = 0x34a08 + Tfoot Atom = 0xc905 + Th Atom = 0x15602 + Thead Atom = 0x32805 + Time Atom = 0x13304 + Title Atom = 0xe105 + Tr Atom = 0x8b02 + Track Atom = 0x19b05 + Translate Atom = 0x1b609 Tt Atom = 0x5102 - Type Atom = 0x8104 - Typemustmatch Atom = 0x2780d + Type Atom = 0x9804 + Typemustmatch Atom = 0x2880d U Atom = 0xb01 Ul Atom = 0x6602 - Updateviacache Atom = 0x1200e - Usemap Atom = 0x59206 + Updateviacache Atom = 0x1370e + Usemap Atom = 0x59606 Value Atom = 0x1505 - Var Atom = 0x15603 - Video Atom = 0x2d905 - Wbr Atom = 0x57003 - Width Atom = 0x64505 - Workertype Atom = 0x7160a - Wrap Atom = 0x72004 - Xmp Atom = 0xf903 + Var Atom = 0x16d03 + Video Atom = 0x2e905 + Wbr Atom = 0x57403 + Width Atom = 0x64905 + Workertype Atom = 0x71c0a + Wrap Atom = 0x72604 + Xmp Atom = 0x11003 ) const hash0 = 0x81cdf10e @@ -377,401 +378,402 @@ const hash0 = 0x81cdf10e const maxAtomLen = 25 var table = [1 << 9]Atom{ - 0x1: 0x8e0a, // mediagroup - 0x2: 0x2cc04, // lang + 0x1: 0xa50a, // mediagroup + 0x2: 0x2dc04, // lang 0x4: 0x2c09, // accesskey 0x5: 0x5708, // frameset - 0x7: 0x63608, // onselect - 0x8: 0x70b06, // system - 0xa: 0x64505, // width - 0xc: 0x2710b, // formenctype - 0xd: 0x10102, // ol - 0xe: 0x38b0b, // oncuechange - 0x10: 0x13403, // bdo - 0x11: 0xcf05, // audio - 0x12: 0x18309, // draggable - 0x14: 0x2d905, // video - 0x15: 0x29902, // mn - 0x16: 0x37b04, // menu - 0x17: 0x2b706, // poster - 0x19: 0xb306, // footer - 0x1a: 0x29006, // method - 0x1b: 0x2a008, // datetime - 0x1c: 0x17607, // onabort - 0x1d: 0x1200e, // updateviacache - 0x1e: 0xb905, // async - 0x1f: 0x49106, // onload - 0x21: 0xd308, // oncancel - 0x22: 0x62508, // onseeked - 0x23: 0x2ea05, // image - 0x24: 0x5d412, // onrejectionhandled - 0x26: 0x15d04, // link - 0x27: 0x51106, // output - 0x28: 0x32504, // head - 0x29: 0x4f30c, // onmouseleave - 0x2a: 0x57307, // onpaste - 0x2b: 0x59809, // onplaying - 0x2c: 0x1b407, // colspan - 0x2f: 0x1af05, // color - 0x30: 0x5f104, // size - 0x31: 0x2d00a, // http-equiv + 0x7: 0x63a08, // onselect + 0x8: 0x71106, // system + 0xa: 0x64905, // width + 0xc: 0x2810b, // formenctype + 0xd: 0x11802, // ol + 0xe: 0x38f0b, // oncuechange + 0x10: 0x14b03, // bdo + 0x11: 0xe605, // audio + 0x12: 0x17a09, // draggable + 0x14: 0x2e905, // video + 0x15: 0x2a902, // mn + 0x16: 0x37f04, // menu + 0x17: 0x2c706, // poster + 0x19: 0xca06, // footer + 0x1a: 0x2a006, // method + 0x1b: 0x2b008, // datetime + 0x1c: 0x19507, // onabort + 0x1d: 0x1370e, // updateviacache + 0x1e: 0xd005, // async + 0x1f: 0x49506, // onload + 0x21: 0xea08, // oncancel + 0x22: 0x62908, // onseeked + 0x23: 0x2fa05, // image + 0x24: 0x5d812, // onrejectionhandled + 0x26: 0x17404, // link + 0x27: 0x51506, // output + 0x28: 0x32904, // head + 0x29: 0x4f70c, // onmouseleave + 0x2a: 0x57707, // onpaste + 0x2b: 0x59c09, // onplaying + 0x2c: 0x1c407, // colspan + 0x2f: 0x1bf05, // color + 0x30: 0x5f504, // size + 0x31: 0x2e00a, // http-equiv 0x33: 0x601, // i - 0x34: 0x54d0a, // onpagehide - 0x35: 0x68814, // onunhandledrejection - 0x37: 0x41e07, // onerror - 0x3a: 0x11508, // basefont + 0x34: 0x5510a, // onpagehide + 0x35: 0x68c14, // onunhandledrejection + 0x37: 0x42207, // onerror + 0x3a: 0x12c08, // basefont 0x3f: 0x1303, // nav - 0x40: 0x18004, // kind - 0x41: 0x34b08, // readonly - 0x42: 0x2f006, // mglyph - 0x44: 0x11102, // li - 0x46: 0x2bd06, // hidden - 0x47: 0x70803, // svg - 0x48: 0x57704, // step - 0x49: 0x22709, // integrity - 0x4a: 0x57a06, // public - 0x4c: 0x19703, // col - 0x4d: 0x1680a, // blockquote - 0x4e: 0x34302, // h5 - 0x50: 0x5ad08, // progress - 0x51: 0x5f105, // sizes - 0x52: 0x33902, // h4 - 0x56: 0x32405, // thead - 0x57: 0x7e07, // keytype - 0x58: 0x5ab0a, // onprogress - 0x59: 0x43f09, // inputmode - 0x5a: 0x3a509, // ondragend - 0x5d: 0x39605, // oncut - 0x5e: 0x42b06, // spacer - 0x5f: 0x19708, // colgroup - 0x62: 0x14e02, // is - 0x65: 0xb902, // as - 0x66: 0x53c09, // onoffline - 0x67: 0x32b06, // sorted - 0x69: 0x48110, // onlanguagechange - 0x6c: 0x4310c, // onhashchange - 0x6d: 0xa604, // name - 0x6e: 0xb205, // tfoot - 0x6f: 0x55504, // desc - 0x70: 0x33103, // max - 0x72: 0x1da06, // coords - 0x73: 0x2f502, // h3 - 0x74: 0x6e10e, // onbeforeunload + 0x40: 0x17704, // kind + 0x41: 0x34f08, // readonly + 0x42: 0x30006, // mglyph + 0x44: 0x7102, // li + 0x46: 0x2cd06, // hidden + 0x47: 0x70e03, // svg + 0x48: 0x57b04, // step + 0x49: 0x23709, // integrity + 0x4a: 0x57e06, // public + 0x4c: 0x1a703, // col + 0x4d: 0x1870a, // blockquote + 0x4e: 0x34702, // h5 + 0x50: 0x5b108, // progress + 0x51: 0x5f505, // sizes + 0x52: 0x33d02, // h4 + 0x56: 0x32805, // thead + 0x57: 0x9507, // keytype + 0x58: 0x5af0a, // onprogress + 0x59: 0x44309, // inputmode + 0x5a: 0x3a909, // ondragend + 0x5d: 0x39a05, // oncut + 0x5e: 0x42f06, // spacer + 0x5f: 0x1a708, // colgroup + 0x62: 0x16502, // is + 0x65: 0xd002, // as + 0x66: 0x54009, // onoffline + 0x67: 0x32f06, // sorted + 0x69: 0x48510, // onlanguagechange + 0x6c: 0x4350c, // onhashchange + 0x6d: 0xbd04, // name + 0x6e: 0xc905, // tfoot + 0x6f: 0x55904, // desc + 0x70: 0x33503, // max + 0x72: 0x1ea06, // coords + 0x73: 0x30502, // h3 + 0x74: 0x6e70e, // onbeforeunload 0x75: 0x3a04, // rows - 0x76: 0x63806, // select - 0x77: 0xa805, // meter - 0x78: 0x37f06, // itemid - 0x79: 0x5300c, // onmousewheel - 0x7a: 0x5b406, // srcdoc - 0x7d: 0x17c05, // track - 0x7f: 0x30708, // itemtype + 0x76: 0x63c06, // select + 0x77: 0xbf05, // meter + 0x78: 0x38306, // itemid + 0x79: 0x5340c, // onmousewheel + 0x7a: 0x5b806, // srcdoc + 0x7d: 0x19b05, // track + 0x7f: 0x31708, // itemtype 0x82: 0x6302, // mo - 0x83: 0x40f08, // onchange - 0x84: 0x32507, // headers - 0x85: 0x5c80c, // onratechange - 0x86: 0x60419, // onsecuritypolicyviolation - 0x88: 0x49908, // datalist - 0x89: 0x4dc0b, // onmousedown - 0x8a: 0x1df04, // slot - 0x8b: 0x4a410, // onloadedmetadata + 0x83: 0x41308, // onchange + 0x84: 0x32907, // headers + 0x85: 0x5cc0c, // onratechange + 0x86: 0x60819, // onsecuritypolicyviolation + 0x88: 0x49d08, // datalist + 0x89: 0x4e00b, // onmousedown + 0x8a: 0x1ef04, // slot + 0x8b: 0x4a810, // onloadedmetadata 0x8c: 0x1a06, // accept - 0x8d: 0x25006, // object - 0x91: 0x6af0e, // onvolumechange + 0x8d: 0x26006, // object + 0x91: 0x6b30e, // onvolumechange 0x92: 0x2107, // charset - 0x93: 0x25e13, // onautocompleteerror - 0x94: 0x6913, // allowpaymentrequest + 0x93: 0x26e13, // onautocompleteerror + 0x94: 0x8013, // allowpaymentrequest 0x95: 0x2804, // body - 0x96: 0xc407, // default - 0x97: 0x63808, // selected - 0x98: 0x20604, // face - 0x99: 0x1d505, // shape - 0x9b: 0x68008, // ontoggle - 0x9e: 0x64702, // dt - 0x9f: 0x6d904, // mark + 0x96: 0xdb07, // default + 0x97: 0x63c08, // selected + 0x98: 0x21604, // face + 0x99: 0x1e505, // shape + 0x9b: 0x68408, // ontoggle + 0x9e: 0x64b02, // dt + 0x9f: 0x7504, // mark 0xa1: 0xb01, // u - 0xa4: 0x6a708, // onunload - 0xa5: 0xde04, // loop - 0xa6: 0x14d08, // disabled - 0xaa: 0x41707, // onended - 0xab: 0x6d30a, // malignmark - 0xad: 0x67709, // onsuspend - 0xae: 0x34505, // mtext - 0xaf: 0x64b06, // onsort - 0xb0: 0x55908, // itemprop - 0xb3: 0x66d09, // itemscope - 0xb4: 0x15c05, // blink - 0xb6: 0x3a506, // ondrag + 0xa4: 0x6ab08, // onunload + 0xa5: 0xf504, // loop + 0xa6: 0x16408, // disabled + 0xaa: 0x41b07, // onended + 0xab: 0x6f0a, // malignmark + 0xad: 0x67b09, // onsuspend + 0xae: 0x34905, // mtext + 0xaf: 0x64f06, // onsort + 0xb0: 0x55d08, // itemprop + 0xb3: 0x67109, // itemscope + 0xb4: 0x17305, // blink + 0xb6: 0x3a906, // ondrag 0xb7: 0x6602, // ul - 0xb8: 0x25604, // form - 0xb9: 0xf307, // sandbox + 0xb8: 0x26604, // form + 0xb9: 0x10a07, // sandbox 0xba: 0x5705, // frame 0xbb: 0x1505, // value - 0xbc: 0x65e09, // onstorage - 0xc0: 0x17b02, // rt + 0xbc: 0x66209, // onstorage + 0xbf: 0x6907, // acronym + 0xc0: 0x19a02, // rt 0xc2: 0x202, // br - 0xc3: 0x20e08, // fieldset - 0xc4: 0x2780d, // typemustmatch + 0xc3: 0x21e08, // fieldset + 0xc4: 0x2880d, // typemustmatch 0xc5: 0x6108, // nomodule 0xc6: 0x4007, // noembed - 0xc7: 0x69a0d, // onbeforeprint - 0xc8: 0x17206, // button - 0xc9: 0x2dd07, // onclick - 0xca: 0x6fe07, // summary - 0xcd: 0xac04, // ruby - 0xce: 0x5b905, // class - 0xcf: 0x3e80b, // ondragstart - 0xd0: 0x21907, // caption - 0xd4: 0x850e, // allowusermedia - 0xd5: 0x4c30b, // onloadstart - 0xd9: 0x15403, // div - 0xda: 0x49d04, // list - 0xdb: 0x32204, // math - 0xdc: 0x43f05, // input - 0xdf: 0x3de0a, // ondragover - 0xe0: 0x2c602, // h2 - 0xe2: 0x19e09, // plaintext - 0xe4: 0x4e70c, // onmouseenter - 0xe7: 0x46d07, // checked - 0xe8: 0x46403, // pre - 0xea: 0x35308, // multiple - 0xeb: 0x16103, // bdi - 0xec: 0x33109, // maxlength - 0xed: 0x7701, // q - 0xee: 0x61b0a, // onauxclick - 0xf0: 0x57003, // wbr - 0xf2: 0x11504, // base - 0xf3: 0x6dd06, // option - 0xf5: 0x40710, // ondurationchange + 0xc7: 0x69e0d, // onbeforeprint + 0xc8: 0x19106, // button + 0xc9: 0x2ed07, // onclick + 0xca: 0x70407, // summary + 0xcd: 0xc304, // ruby + 0xce: 0x5bd05, // class + 0xcf: 0x3ec0b, // ondragstart + 0xd0: 0x22907, // caption + 0xd4: 0x9c0e, // allowusermedia + 0xd5: 0x4c70b, // onloadstart + 0xd9: 0x16b03, // div + 0xda: 0x4a104, // list + 0xdb: 0x32604, // math + 0xdc: 0x44305, // input + 0xdf: 0x3e20a, // ondragover + 0xe0: 0x2d602, // h2 + 0xe2: 0x1ae09, // plaintext + 0xe4: 0x4eb0c, // onmouseenter + 0xe7: 0x47107, // checked + 0xe8: 0x46803, // pre + 0xea: 0x35708, // multiple + 0xeb: 0x7903, // bdi + 0xec: 0x33509, // maxlength + 0xed: 0x8e01, // q + 0xee: 0x61f0a, // onauxclick + 0xf0: 0x57403, // wbr + 0xf2: 0x12c04, // base + 0xf3: 0x6e306, // option + 0xf5: 0x40b10, // ondurationchange 0xf7: 0x5508, // noframes - 0xf9: 0x3f908, // dropzone - 0xfb: 0x67105, // scope - 0xfc: 0x9c08, // reversed - 0xfd: 0x3ae0b, // ondragenter - 0xfe: 0x3ee05, // start - 0xff: 0xf903, // xmp - 0x100: 0x5f507, // srclang - 0x101: 0x2ef03, // img + 0xf9: 0x3fd08, // dropzone + 0xfb: 0x67505, // scope + 0xfc: 0xb308, // reversed + 0xfd: 0x3b20b, // ondragenter + 0xfe: 0x3f205, // start + 0xff: 0x11003, // xmp + 0x100: 0x5f907, // srclang + 0x101: 0x2ff03, // img 0x104: 0x101, // b - 0x105: 0x23c03, // for - 0x106: 0xc105, // aside - 0x107: 0x43d07, // oninput - 0x108: 0x34a04, // area - 0x109: 0x28c0a, // formmethod - 0x10a: 0x72004, // wrap - 0x10c: 0x22402, // rp - 0x10d: 0x45f0a, // onkeypress + 0x105: 0x24c03, // for + 0x106: 0xd805, // aside + 0x107: 0x44107, // oninput + 0x108: 0x34e04, // area + 0x109: 0x29c0a, // formmethod + 0x10a: 0x72604, // wrap + 0x10c: 0x23402, // rp + 0x10d: 0x4630a, // onkeypress 0x10e: 0x5102, // tt - 0x110: 0x33b02, // mi - 0x111: 0x35b05, // muted - 0x112: 0xb003, // alt - 0x113: 0x19004, // code + 0x110: 0x33f02, // mi + 0x111: 0x35f05, // muted + 0x112: 0xc703, // alt + 0x113: 0x1a004, // code 0x114: 0x4202, // em - 0x115: 0x3b90a, // ondragexit + 0x115: 0x3bd0a, // ondragexit 0x117: 0x3d04, // span - 0x119: 0x30f08, // manifest - 0x11a: 0x37b08, // menuitem - 0x11b: 0x57f07, // content - 0x11d: 0x6bd09, // onwaiting - 0x11f: 0x4ba09, // onloadend - 0x121: 0x3720d, // oncontextmenu - 0x123: 0x5c206, // onblur - 0x124: 0x3f007, // article - 0x125: 0xa303, // dir - 0x126: 0xe704, // ping - 0x127: 0x23408, // required - 0x128: 0x44909, // oninvalid - 0x129: 0x6d405, // align - 0x12b: 0x57e04, // icon - 0x12c: 0x64902, // h6 - 0x12d: 0x1b404, // cols - 0x12e: 0x2160a, // figcaption - 0x12f: 0x45209, // onkeydown - 0x130: 0x66708, // onsubmit - 0x131: 0x13609, // oncanplay - 0x132: 0x70503, // sup + 0x119: 0x6d708, // manifest + 0x11a: 0x37f08, // menuitem + 0x11b: 0x58307, // content + 0x11d: 0x6c109, // onwaiting + 0x11f: 0x4be09, // onloadend + 0x121: 0x3760d, // oncontextmenu + 0x123: 0x5c606, // onblur + 0x124: 0x3f407, // article + 0x125: 0xba03, // dir + 0x126: 0xfe04, // ping + 0x127: 0x24408, // required + 0x128: 0x44d09, // oninvalid + 0x129: 0x7005, // align + 0x12b: 0x58204, // icon + 0x12c: 0x64d02, // h6 + 0x12d: 0x1c404, // cols + 0x12e: 0x2260a, // figcaption + 0x12f: 0x45609, // onkeydown + 0x130: 0x66b08, // onsubmit + 0x131: 0x14d09, // oncanplay + 0x132: 0x70b03, // sup 0x133: 0xc01, // p - 0x135: 0x3fe09, // onemptied - 0x136: 0x38506, // oncopy - 0x137: 0x55804, // cite - 0x138: 0x39b0a, // ondblclick - 0x13a: 0x4ff0b, // onmousemove - 0x13c: 0x66903, // sub - 0x13d: 0x47b03, // rel - 0x13e: 0xe008, // optgroup + 0x135: 0x40209, // onemptied + 0x136: 0x38906, // oncopy + 0x137: 0x55c04, // cite + 0x138: 0x39f0a, // ondblclick + 0x13a: 0x5030b, // onmousemove + 0x13c: 0x66d03, // sub + 0x13d: 0x47f03, // rel + 0x13e: 0xf708, // optgroup 0x142: 0x3a07, // rowspan - 0x143: 0x36c06, // source - 0x144: 0x1fe08, // noscript - 0x145: 0x55f04, // open - 0x146: 0x1ec03, // ins - 0x147: 0x23c0d, // foreignObject - 0x148: 0x5a10a, // onpopstate - 0x14a: 0x27507, // enctype - 0x14b: 0x25e0e, // onautocomplete - 0x14c: 0x34608, // textarea - 0x14e: 0x2600c, // autocomplete - 0x14f: 0x14002, // hr - 0x150: 0x1ce08, // controls - 0x151: 0xc302, // id - 0x153: 0x21e0c, // onafterprint - 0x155: 0x2490d, // foreignobject - 0x156: 0x31b07, // marquee - 0x157: 0x58e07, // onpause - 0x158: 0x5e202, // dl - 0x159: 0x12c06, // height - 0x15a: 0x33b03, // min - 0x15b: 0xa307, // dirname - 0x15c: 0x1a609, // translate - 0x15d: 0x13004, // html - 0x15e: 0x33b09, // minlength - 0x15f: 0x47a07, // preload - 0x160: 0x70e08, // template - 0x161: 0x3d30b, // ondragleave - 0x164: 0x5b403, // src - 0x165: 0x31506, // strong + 0x143: 0x37006, // source + 0x144: 0x20e08, // noscript + 0x145: 0x56304, // open + 0x146: 0x1fc03, // ins + 0x147: 0x24c0d, // foreignObject + 0x148: 0x5a50a, // onpopstate + 0x14a: 0x28507, // enctype + 0x14b: 0x26e0e, // onautocomplete + 0x14c: 0x34a08, // textarea + 0x14e: 0x2700c, // autocomplete + 0x14f: 0x15702, // hr + 0x150: 0x1de08, // controls + 0x151: 0xda02, // id + 0x153: 0x22e0c, // onafterprint + 0x155: 0x2590d, // foreignobject + 0x156: 0x31f07, // marquee + 0x157: 0x59207, // onpause + 0x158: 0x5e602, // dl + 0x159: 0x14306, // height + 0x15a: 0x33f03, // min + 0x15b: 0xba07, // dirname + 0x15c: 0x1b609, // translate + 0x15d: 0x14704, // html + 0x15e: 0x33f09, // minlength + 0x15f: 0x47e07, // preload + 0x160: 0x71408, // template + 0x161: 0x3d70b, // ondragleave + 0x164: 0x5b803, // src + 0x165: 0x6dd06, // strong 0x167: 0x4c04, // samp - 0x168: 0x6ed07, // address - 0x169: 0x54508, // ononline - 0x16b: 0xfb0b, // placeholder - 0x16c: 0x2ac06, // target - 0x16d: 0x1ee05, // small - 0x16e: 0x6c607, // onwheel - 0x16f: 0x1b90a, // annotation - 0x170: 0x4680a, // spellcheck + 0x168: 0x6f307, // address + 0x169: 0x54908, // ononline + 0x16b: 0x1120b, // placeholder + 0x16c: 0x2bc06, // target + 0x16d: 0x1fe05, // small + 0x16e: 0x6ca07, // onwheel + 0x16f: 0x1c90a, // annotation + 0x170: 0x46c0a, // spellcheck 0x171: 0x4607, // details - 0x172: 0xbd06, // canvas - 0x173: 0xeb09, // autofocus + 0x172: 0xd406, // canvas + 0x173: 0x10209, // autofocus 0x174: 0xc05, // param - 0x176: 0x45708, // download - 0x177: 0x44603, // del - 0x178: 0x36007, // onclose - 0x179: 0x16003, // kbd - 0x17a: 0x30106, // applet - 0x17b: 0x2c804, // href - 0x17c: 0x5ed08, // onresize - 0x17e: 0x4910c, // onloadeddata - 0x180: 0x7402, // tr - 0x181: 0x2a80a, // formtarget - 0x182: 0xca05, // title - 0x183: 0x6f905, // style - 0x184: 0x7a06, // strike - 0x185: 0x59206, // usemap - 0x186: 0x2e406, // iframe + 0x176: 0x45b08, // download + 0x177: 0x44a03, // del + 0x178: 0x36407, // onclose + 0x179: 0x7803, // kbd + 0x17a: 0x31106, // applet + 0x17b: 0x2d804, // href + 0x17c: 0x5f108, // onresize + 0x17e: 0x4950c, // onloadeddata + 0x180: 0x8b02, // tr + 0x181: 0x2b80a, // formtarget + 0x182: 0xe105, // title + 0x183: 0x6ff05, // style + 0x184: 0x9106, // strike + 0x185: 0x59606, // usemap + 0x186: 0x2f406, // iframe 0x187: 0x1004, // main - 0x189: 0x9707, // picture - 0x18c: 0x2fe05, // ismap - 0x18e: 0x49904, // data - 0x18f: 0xda05, // label - 0x191: 0x3c50e, // referrerpolicy - 0x192: 0x13f02, // th - 0x194: 0x52a06, // prompt - 0x195: 0x5bd07, // section - 0x197: 0x6cd07, // optimum - 0x198: 0x2c304, // high - 0x199: 0x14502, // h1 - 0x19a: 0x65509, // onstalled - 0x19b: 0x15603, // var - 0x19c: 0x11c04, // time - 0x19e: 0x67002, // ms - 0x19f: 0x32506, // header - 0x1a0: 0x4ce09, // onmessage - 0x1a1: 0x56205, // nonce - 0x1a2: 0x2560a, // formaction - 0x1a3: 0x20806, // center + 0x189: 0xae07, // picture + 0x18c: 0x30e05, // ismap + 0x18e: 0x49d04, // data + 0x18f: 0xf105, // label + 0x191: 0x3c90e, // referrerpolicy + 0x192: 0x15602, // th + 0x194: 0x52e06, // prompt + 0x195: 0x5c107, // section + 0x197: 0x6d107, // optimum + 0x198: 0x2d304, // high + 0x199: 0x15c02, // h1 + 0x19a: 0x65909, // onstalled + 0x19b: 0x16d03, // var + 0x19c: 0x13304, // time + 0x19e: 0x67402, // ms + 0x19f: 0x32906, // header + 0x1a0: 0x4d209, // onmessage + 0x1a1: 0x56605, // nonce + 0x1a2: 0x2660a, // formaction + 0x1a3: 0x21806, // center 0x1a4: 0x3704, // nobr - 0x1a5: 0x58905, // table - 0x1a6: 0x49d07, // listing - 0x1a7: 0x18a06, // legend - 0x1a9: 0x28309, // challenge - 0x1aa: 0x23006, // figure - 0x1ab: 0x8e05, // media - 0x1ae: 0x8104, // type - 0x1af: 0x11904, // font - 0x1b0: 0x4ce0e, // onmessageerror - 0x1b1: 0x36508, // seamless + 0x1a5: 0x58d05, // table + 0x1a6: 0x4a107, // listing + 0x1a7: 0x18106, // legend + 0x1a9: 0x29309, // challenge + 0x1aa: 0x24006, // figure + 0x1ab: 0xa505, // media + 0x1ae: 0x9804, // type + 0x1af: 0x13004, // font + 0x1b0: 0x4d20e, // onmessageerror + 0x1b1: 0x36908, // seamless 0x1b2: 0x5f03, // dfn - 0x1b3: 0x19205, // defer - 0x1b4: 0x6b03, // low - 0x1b5: 0x62d09, // onseeking - 0x1b6: 0x5170b, // onmouseover - 0x1b7: 0x29a0a, // novalidate - 0x1b8: 0x7160a, // workertype - 0x1ba: 0x3c107, // itemref + 0x1b3: 0x1a205, // defer + 0x1b4: 0x8203, // low + 0x1b5: 0x63109, // onseeking + 0x1b6: 0x51b0b, // onmouseover + 0x1b7: 0x2aa0a, // novalidate + 0x1b8: 0x71c0a, // workertype + 0x1ba: 0x3c507, // itemref 0x1bd: 0x1, // a - 0x1be: 0x30003, // map - 0x1bf: 0x11a0c, // ontimeupdate - 0x1c0: 0x14707, // bgsound + 0x1be: 0x31003, // map + 0x1bf: 0x1310c, // ontimeupdate + 0x1c0: 0x15e07, // bgsound 0x1c1: 0x3206, // keygen 0x1c2: 0x2705, // tbody - 0x1c5: 0x64006, // onshow + 0x1c5: 0x64406, // onshow 0x1c7: 0x2501, // s 0x1c8: 0x4f07, // pattern - 0x1cc: 0x13610, // oncanplaythrough - 0x1ce: 0x2bf02, // dd - 0x1cf: 0x6f306, // srcset - 0x1d0: 0x15903, // big - 0x1d2: 0x64d08, // sortable - 0x1d3: 0x47407, // onkeyup - 0x1d5: 0x59806, // onplay - 0x1d7: 0x4ac04, // meta - 0x1d8: 0x3f706, // ondrop - 0x1da: 0x5fc08, // onscroll - 0x1db: 0x1e30b, // crossorigin - 0x1dc: 0x5670a, // onpageshow + 0x1cc: 0x14d10, // oncanplaythrough + 0x1ce: 0x2cf02, // dd + 0x1cf: 0x6f906, // srcset + 0x1d0: 0x17003, // big + 0x1d2: 0x65108, // sortable + 0x1d3: 0x47807, // onkeyup + 0x1d5: 0x59c06, // onplay + 0x1d7: 0x4b004, // meta + 0x1d8: 0x3fb06, // ondrop + 0x1da: 0x60008, // onscroll + 0x1db: 0x1f30b, // crossorigin + 0x1dc: 0x56b0a, // onpageshow 0x1dd: 0x4, // abbr 0x1de: 0x5e02, // td - 0x1df: 0x57f0f, // contenteditable - 0x1e0: 0x25a06, // action - 0x1e1: 0x10a0b, // playsinline - 0x1e2: 0x42507, // onfocus - 0x1e3: 0x2c808, // hreflang - 0x1e5: 0x50a0a, // onmouseout - 0x1e6: 0x5e607, // onreset - 0x1e7: 0x10608, // autoplay - 0x1ea: 0x67106, // scoped + 0x1df: 0x5830f, // contenteditable + 0x1e0: 0x26a06, // action + 0x1e1: 0x1210b, // playsinline + 0x1e2: 0x42907, // onfocus + 0x1e3: 0x2d808, // hreflang + 0x1e5: 0x50e0a, // onmouseout + 0x1e6: 0x5ea07, // onreset + 0x1e7: 0x11d08, // autoplay + 0x1ea: 0x67506, // scoped 0x1ec: 0x30a, // radiogroup - 0x1ee: 0x3740b, // contextmenu - 0x1ef: 0x52209, // onmouseup - 0x1f1: 0x2b206, // hgroup - 0x1f2: 0x1f00f, // allowfullscreen - 0x1f3: 0x4b208, // tabindex - 0x1f6: 0x2f707, // isindex + 0x1ee: 0x3780b, // contextmenu + 0x1ef: 0x52609, // onmouseup + 0x1f1: 0x2c206, // hgroup + 0x1f2: 0x2000f, // allowfullscreen + 0x1f3: 0x4b608, // tabindex + 0x1f6: 0x30707, // isindex 0x1f7: 0x1a0e, // accept-charset - 0x1f8: 0x2960e, // formnovalidate - 0x1fb: 0x1b90e, // annotation-xml + 0x1f8: 0x2a60e, // formnovalidate + 0x1fb: 0x1c90e, // annotation-xml 0x1fc: 0x4205, // embed - 0x1fd: 0x20006, // script - 0x1fe: 0x16206, // dialog - 0x1ff: 0x1c707, // command + 0x1fd: 0x21006, // script + 0x1fe: 0x7a06, // dialog + 0x1ff: 0x1d707, // command } const atomText = "abbradiogrouparamainavalueaccept-charsetbodyaccesskeygenobro" + - "wspanoembedetailsampatternoframesetdfnomoduleallowpaymentreq" + - "uestrikeytypeallowusermediagroupictureversedirnameterubyaltf" + - "ooterasyncanvasidefaultitleaudioncancelabelooptgroupingautof" + - "ocusandboxmplaceholderautoplaysinlinebasefontimeupdateviacac" + - "heightmlbdoncanplaythrough1bgsoundisabledivarbigblinkbdialog" + - "blockquotebuttonabortrackindraggablegendcodefercolgrouplaint" + - "extranslatecolorcolspannotation-xmlcommandcontrolshapecoords" + - "lotcrossoriginsmallowfullscreenoscriptfacenterfieldsetfigcap" + - "tionafterprintegrityfigurequiredforeignObjectforeignobjectfo" + - "rmactionautocompleteerrorformenctypemustmatchallengeformmeth" + - "odformnovalidatetimeformtargethgrouposterhiddenhigh2hreflang" + - "http-equivideonclickiframeimageimglyph3isindexismappletitemt" + - "ypemanifestrongmarqueematheadersortedmaxlength4minlength5mte" + - "xtareadonlymultiplemutedoncloseamlessourceoncontextmenuitemi" + - "doncopyoncuechangeoncutondblclickondragendondragenterondrage" + - "xitemreferrerpolicyondragleaveondragoverondragstarticleondro" + - "pzonemptiedondurationchangeonendedonerroronfocuspaceronhashc" + - "hangeoninputmodeloninvalidonkeydownloadonkeypresspellchecked" + - "onkeyupreloadonlanguagechangeonloadeddatalistingonloadedmeta" + - "databindexonloadendonloadstartonmessageerroronmousedownonmou" + - "seenteronmouseleaveonmousemoveonmouseoutputonmouseoveronmous" + - "eupromptonmousewheelonofflineononlineonpagehidescitempropeno" + - "nceonpageshowbronpastepublicontenteditableonpausemaponplayin" + - "gonpopstateonprogressrcdoclassectionbluronratechangeonreject" + - "ionhandledonresetonresizesrclangonscrollonsecuritypolicyviol" + - "ationauxclickonseekedonseekingonselectedonshowidth6onsortabl" + - "eonstalledonstorageonsubmitemscopedonsuspendontoggleonunhand" + - "ledrejectionbeforeprintonunloadonvolumechangeonwaitingonwhee" + - "loptimumalignmarkoptionbeforeunloaddressrcsetstylesummarysup" + - "svgsystemplateworkertypewrap" + "wspanoembedetailsampatternoframesetdfnomoduleacronymalignmar" + + "kbdialogallowpaymentrequestrikeytypeallowusermediagroupictur" + + "eversedirnameterubyaltfooterasyncanvasidefaultitleaudioncanc" + + "elabelooptgroupingautofocusandboxmplaceholderautoplaysinline" + + "basefontimeupdateviacacheightmlbdoncanplaythrough1bgsoundisa" + + "bledivarbigblinkindraggablegendblockquotebuttonabortrackcode" + + "fercolgrouplaintextranslatecolorcolspannotation-xmlcommandco" + + "ntrolshapecoordslotcrossoriginsmallowfullscreenoscriptfacent" + + "erfieldsetfigcaptionafterprintegrityfigurequiredforeignObjec" + + "tforeignobjectformactionautocompleteerrorformenctypemustmatc" + + "hallengeformmethodformnovalidatetimeformtargethgrouposterhid" + + "denhigh2hreflanghttp-equivideonclickiframeimageimglyph3isind" + + "exismappletitemtypemarqueematheadersortedmaxlength4minlength" + + "5mtextareadonlymultiplemutedoncloseamlessourceoncontextmenui" + + "temidoncopyoncuechangeoncutondblclickondragendondragenterond" + + "ragexitemreferrerpolicyondragleaveondragoverondragstarticleo" + + "ndropzonemptiedondurationchangeonendedonerroronfocuspaceronh" + + "ashchangeoninputmodeloninvalidonkeydownloadonkeypresspellche" + + "ckedonkeyupreloadonlanguagechangeonloadeddatalistingonloaded" + + "metadatabindexonloadendonloadstartonmessageerroronmousedowno" + + "nmouseenteronmouseleaveonmousemoveonmouseoutputonmouseoveron" + + "mouseupromptonmousewheelonofflineononlineonpagehidescitempro" + + "penonceonpageshowbronpastepublicontenteditableonpausemaponpl" + + "ayingonpopstateonprogressrcdoclassectionbluronratechangeonre" + + "jectionhandledonresetonresizesrclangonscrollonsecuritypolicy" + + "violationauxclickonseekedonseekingonselectedonshowidth6onsor" + + "tableonstalledonstorageonsubmitemscopedonsuspendontoggleonun" + + "handledrejectionbeforeprintonunloadonvolumechangeonwaitingon" + + "wheeloptimumanifestrongoptionbeforeunloaddressrcsetstylesumm" + + "arysupsvgsystemplateworkertypewrap" diff --git a/vendor/golang.org/x/net/html/atom/table_test.go b/vendor/golang.org/x/net/html/atom/table_test.go index 16891054fc8474e5f82f1cbbc8d677356d7a685c..46d9d701a1f0d65b060b241ac26e94e2d4938ca3 100644 --- a/vendor/golang.org/x/net/html/atom/table_test.go +++ b/vendor/golang.org/x/net/html/atom/table_test.go @@ -10,6 +10,7 @@ var testAtomList = []string{ "accept", "accept-charset", "accesskey", + "acronym", "action", "address", "align", diff --git a/vendor/golang.org/x/net/http2/ciphers.go b/vendor/golang.org/x/net/http2/ciphers.go index 698860b77755d8fbcd805ac280c3e1f61ad1babd..c9a0cf3b422c698dd66f753813afc04c20a5dcd8 100644 --- a/vendor/golang.org/x/net/http2/ciphers.go +++ b/vendor/golang.org/x/net/http2/ciphers.go @@ -5,7 +5,7 @@ package http2 // A list of the possible cipher suite ids. Taken from -// http://www.iana.org/assignments/tls-parameters/tls-parameters.txt +// https://www.iana.org/assignments/tls-parameters/tls-parameters.txt const ( cipher_TLS_NULL_WITH_NULL_NULL uint16 = 0x0000 diff --git a/vendor/golang.org/x/net/http2/h2demo/.gitignore b/vendor/golang.org/x/net/http2/h2demo/.gitignore index 0de86ddbc5fbdd17a2d2f8cae12b5e50b985bf9b..8a1133fc647eaf5169bba98cbca031da7ff6ab04 100644 --- a/vendor/golang.org/x/net/http2/h2demo/.gitignore +++ b/vendor/golang.org/x/net/http2/h2demo/.gitignore @@ -3,3 +3,4 @@ h2demo.linux client-id.dat client-secret.dat token.dat +ca-certificates.crt diff --git a/vendor/golang.org/x/net/http2/h2demo/Dockerfile b/vendor/golang.org/x/net/http2/h2demo/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..9238673309b17a9c29f022688f39878e128fdef1 --- /dev/null +++ b/vendor/golang.org/x/net/http2/h2demo/Dockerfile @@ -0,0 +1,11 @@ +# Copyright 2018 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. + +FROM scratch +LABEL maintainer "golang-dev@googlegroups.com" + +COPY ca-certificates.crt /etc/ssl/certs/ +COPY h2demo / +ENTRYPOINT ["/h2demo", "-prod"] + diff --git a/vendor/golang.org/x/net/http2/h2demo/Dockerfile.0 b/vendor/golang.org/x/net/http2/h2demo/Dockerfile.0 new file mode 100644 index 0000000000000000000000000000000000000000..fd8435d31211a693bae511267d5cae67d0ad726a --- /dev/null +++ b/vendor/golang.org/x/net/http2/h2demo/Dockerfile.0 @@ -0,0 +1,134 @@ +# Copyright 2018 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. + +FROM golang:1.9 +LABEL maintainer "golang-dev@googlegroups.com" + +ENV CGO_ENABLED=0 + +# BEGIN deps (run `make update-deps` to update) + +# Repo cloud.google.com/go at 1d0c2da (2018-01-30) +ENV REV=1d0c2da40456a9b47f5376165f275424acc15c09 +RUN go get -d cloud.google.com/go/compute/metadata `#and 6 other pkgs` &&\ + (cd /go/src/cloud.google.com/go && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV) + +# Repo github.com/golang/protobuf at 9255415 (2018-01-25) +ENV REV=925541529c1fa6821df4e44ce2723319eb2be768 +RUN go get -d github.com/golang/protobuf/proto `#and 6 other pkgs` &&\ + (cd /go/src/github.com/golang/protobuf && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV) + +# Repo github.com/googleapis/gax-go at 317e000 (2017-09-15) +ENV REV=317e0006254c44a0ac427cc52a0e083ff0b9622f +RUN go get -d github.com/googleapis/gax-go &&\ + (cd /go/src/github.com/googleapis/gax-go && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV) + +# Repo go4.org at 034d17a (2017-05-25) +ENV REV=034d17a462f7b2dcd1a4a73553ec5357ff6e6c6e +RUN go get -d go4.org/syncutil/singleflight &&\ + (cd /go/src/go4.org && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV) + +# Repo golang.org/x/build at 8aa9ee0 (2018-02-01) +ENV REV=8aa9ee0e557fd49c14113e5ba106e13a5b455460 +RUN go get -d golang.org/x/build/autocertcache &&\ + (cd /go/src/golang.org/x/build && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV) + +# Repo golang.org/x/crypto at 1875d0a (2018-01-27) +ENV REV=1875d0a70c90e57f11972aefd42276df65e895b9 +RUN go get -d golang.org/x/crypto/acme `#and 2 other pkgs` &&\ + (cd /go/src/golang.org/x/crypto && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV) + +# Repo golang.org/x/oauth2 at 30785a2 (2018-01-04) +ENV REV=30785a2c434e431ef7c507b54617d6a951d5f2b4 +RUN go get -d golang.org/x/oauth2 `#and 5 other pkgs` &&\ + (cd /go/src/golang.org/x/oauth2 && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV) + +# Repo golang.org/x/text at e19ae14 (2017-12-27) +ENV REV=e19ae1496984b1c655b8044a65c0300a3c878dd3 +RUN go get -d golang.org/x/text/secure/bidirule `#and 4 other pkgs` &&\ + (cd /go/src/golang.org/x/text && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV) + +# Repo google.golang.org/api at 7d0e2d3 (2018-01-30) +ENV REV=7d0e2d350555821bef5a5b8aecf0d12cc1def633 +RUN go get -d google.golang.org/api/gensupport `#and 9 other pkgs` &&\ + (cd /go/src/google.golang.org/api && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV) + +# Repo google.golang.org/genproto at 4eb30f4 (2018-01-25) +ENV REV=4eb30f4778eed4c258ba66527a0d4f9ec8a36c45 +RUN go get -d google.golang.org/genproto/googleapis/api/annotations `#and 3 other pkgs` &&\ + (cd /go/src/google.golang.org/genproto && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV) + +# Repo google.golang.org/grpc at 0bd008f (2018-01-25) +ENV REV=0bd008f5fadb62d228f12b18d016709e8139a7af +RUN go get -d google.golang.org/grpc `#and 23 other pkgs` &&\ + (cd /go/src/google.golang.org/grpc && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV) + +# Optimization to speed up iterative development, not necessary for correctness: +RUN go install cloud.google.com/go/compute/metadata \ + cloud.google.com/go/iam \ + cloud.google.com/go/internal \ + cloud.google.com/go/internal/optional \ + cloud.google.com/go/internal/version \ + cloud.google.com/go/storage \ + github.com/golang/protobuf/proto \ + github.com/golang/protobuf/protoc-gen-go/descriptor \ + github.com/golang/protobuf/ptypes \ + github.com/golang/protobuf/ptypes/any \ + github.com/golang/protobuf/ptypes/duration \ + github.com/golang/protobuf/ptypes/timestamp \ + github.com/googleapis/gax-go \ + go4.org/syncutil/singleflight \ + golang.org/x/build/autocertcache \ + golang.org/x/crypto/acme \ + golang.org/x/crypto/acme/autocert \ + golang.org/x/oauth2 \ + golang.org/x/oauth2/google \ + golang.org/x/oauth2/internal \ + golang.org/x/oauth2/jws \ + golang.org/x/oauth2/jwt \ + golang.org/x/text/secure/bidirule \ + golang.org/x/text/transform \ + golang.org/x/text/unicode/bidi \ + golang.org/x/text/unicode/norm \ + google.golang.org/api/gensupport \ + google.golang.org/api/googleapi \ + google.golang.org/api/googleapi/internal/uritemplates \ + google.golang.org/api/googleapi/transport \ + google.golang.org/api/internal \ + google.golang.org/api/iterator \ + google.golang.org/api/option \ + google.golang.org/api/storage/v1 \ + google.golang.org/api/transport/http \ + google.golang.org/genproto/googleapis/api/annotations \ + google.golang.org/genproto/googleapis/iam/v1 \ + google.golang.org/genproto/googleapis/rpc/status \ + google.golang.org/grpc \ + google.golang.org/grpc/balancer \ + google.golang.org/grpc/balancer/base \ + google.golang.org/grpc/balancer/roundrobin \ + google.golang.org/grpc/codes \ + google.golang.org/grpc/connectivity \ + google.golang.org/grpc/credentials \ + google.golang.org/grpc/encoding \ + google.golang.org/grpc/encoding/proto \ + google.golang.org/grpc/grpclb/grpc_lb_v1/messages \ + google.golang.org/grpc/grpclog \ + google.golang.org/grpc/internal \ + google.golang.org/grpc/keepalive \ + google.golang.org/grpc/metadata \ + google.golang.org/grpc/naming \ + google.golang.org/grpc/peer \ + google.golang.org/grpc/resolver \ + google.golang.org/grpc/resolver/dns \ + google.golang.org/grpc/resolver/passthrough \ + google.golang.org/grpc/stats \ + google.golang.org/grpc/status \ + google.golang.org/grpc/tap \ + google.golang.org/grpc/transport +# END deps + +COPY . /go/src/golang.org/x/net/ + +RUN go install -tags "h2demo netgo" -ldflags "-linkmode=external -extldflags '-static -pthread'" golang.org/x/net/http2/h2demo + diff --git a/vendor/golang.org/x/net/http2/h2demo/Makefile b/vendor/golang.org/x/net/http2/h2demo/Makefile index f5c31ef3e2212ac9f5bd056fbdb7db7f7f1e5a96..306d1986c66a26a449ee749e62cc5b8e1717489b 100644 --- a/vendor/golang.org/x/net/http2/h2demo/Makefile +++ b/vendor/golang.org/x/net/http2/h2demo/Makefile @@ -1,8 +1,55 @@ -h2demo.linux: h2demo.go - GOOS=linux go build --tags=h2demo -o h2demo.linux . +# Copyright 2018 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. -FORCE: +MUTABLE_VERSION ?= latest +VERSION ?= $(shell git rev-parse --short HEAD) + +IMAGE_STAGING := gcr.io/go-dashboard-dev/h2demo +IMAGE_PROD := gcr.io/symbolic-datum-552/h2demo + +DOCKER_IMAGE_build0=build0/h2demo:latest +DOCKER_CTR_build0=h2demo-build0 + +build0: *.go Dockerfile.0 + docker build --force-rm -f Dockerfile.0 --tag=$(DOCKER_IMAGE_build0) ../.. + +h2demo: build0 + docker create --name $(DOCKER_CTR_build0) $(DOCKER_IMAGE_build0) + docker cp $(DOCKER_CTR_build0):/go/bin/$@ $@ + docker rm $(DOCKER_CTR_build0) + +ca-certificates.crt: + docker create --name $(DOCKER_CTR_build0) $(DOCKER_IMAGE_build0) + docker cp $(DOCKER_CTR_build0):/etc/ssl/certs/$@ $@ + docker rm $(DOCKER_CTR_build0) -upload: FORCE - go install golang.org/x/build/cmd/upload - upload --verbose --osarch=linux-amd64 --tags=h2demo --file=go:golang.org/x/net/http2/h2demo --public http2-demo-server-tls/h2demo +update-deps: + go install golang.org/x/build/cmd/gitlock + gitlock --update=Dockerfile.0 --ignore=golang.org/x/net --tags=h2demo golang.org/x/net/http2/h2demo + +docker-prod: Dockerfile h2demo ca-certificates.crt + docker build --force-rm --tag=$(IMAGE_PROD):$(VERSION) . + docker tag $(IMAGE_PROD):$(VERSION) $(IMAGE_PROD):$(MUTABLE_VERSION) +docker-staging: Dockerfile h2demo ca-certificates.crt + docker build --force-rm --tag=$(IMAGE_STAGING):$(VERSION) . + docker tag $(IMAGE_STAGING):$(VERSION) $(IMAGE_STAGING):$(MUTABLE_VERSION) + +push-prod: docker-prod + gcloud docker -- push $(IMAGE_PROD):$(MUTABLE_VERSION) + gcloud docker -- push $(IMAGE_PROD):$(VERSION) +push-staging: docker-staging + gcloud docker -- push $(IMAGE_STAGING):$(MUTABLE_VERSION) + gcloud docker -- push $(IMAGE_STAGING):$(VERSION) + +deploy-prod: push-prod + kubectl set image deployment/h2demo-deployment h2demo=$(IMAGE_PROD):$(VERSION) +deploy-staging: push-staging + kubectl set image deployment/h2demo-deployment h2demo=$(IMAGE_STAGING):$(VERSION) + +.PHONY: clean +clean: + $(RM) h2demo + $(RM) ca-certificates.crt + +FORCE: diff --git a/vendor/golang.org/x/net/http2/h2demo/deployment-prod.yaml b/vendor/golang.org/x/net/http2/h2demo/deployment-prod.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a3a20a42c430bff014990e1c3bc6ab1b8d70e95f --- /dev/null +++ b/vendor/golang.org/x/net/http2/h2demo/deployment-prod.yaml @@ -0,0 +1,28 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: h2demo-deployment +spec: + replicas: 1 + template: + metadata: + labels: + app: h2demo + annotations: + container.seccomp.security.alpha.kubernetes.io/h2demo: docker/default + container.apparmor.security.beta.kubernetes.io/h2demo: runtime/default + spec: + containers: + - name: h2demo + image: gcr.io/symbolic-datum-552/h2demo:latest + imagePullPolicy: Always + command: ["/h2demo", "-prod"] + ports: + - containerPort: 80 + - containerPort: 443 + resources: + requests: + cpu: "1" + memory: "1Gi" + limits: + memory: "2Gi" diff --git a/vendor/golang.org/x/net/http2/h2demo/h2demo.go b/vendor/golang.org/x/net/http2/h2demo/h2demo.go index 9853107b9184db66da9b4e2e216346bb9324b915..ce842fd6b4dc012ff9aa35fb202eac0cee61d918 100644 --- a/vendor/golang.org/x/net/http2/h2demo/h2demo.go +++ b/vendor/golang.org/x/net/http2/h2demo/h2demo.go @@ -8,6 +8,7 @@ package main import ( "bytes" + "context" "crypto/tls" "flag" "fmt" @@ -19,7 +20,6 @@ import ( "log" "net" "net/http" - "os" "path" "regexp" "runtime" @@ -28,7 +28,9 @@ import ( "sync" "time" + "cloud.google.com/go/storage" "go4.org/syncutil/singleflight" + "golang.org/x/build/autocertcache" "golang.org/x/crypto/acme/autocert" "golang.org/x/net/http2" ) @@ -426,19 +428,10 @@ func httpHost() string { } } -func serveProdTLS() error { - const cacheDir = "/var/cache/autocert" - if err := os.MkdirAll(cacheDir, 0700); err != nil { - return err - } - m := autocert.Manager{ - Cache: autocert.DirCache(cacheDir), - Prompt: autocert.AcceptTOS, - HostPolicy: autocert.HostWhitelist("http2.golang.org"), - } +func serveProdTLS(autocertManager *autocert.Manager) error { srv := &http.Server{ TLSConfig: &tls.Config{ - GetCertificate: m.GetCertificate, + GetCertificate: autocertManager.GetCertificate, }, } http2.ConfigureServer(srv, &http2.Server{ @@ -468,9 +461,21 @@ func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) { } func serveProd() error { + log.Printf("running in production mode") + + storageClient, err := storage.NewClient(context.Background()) + if err != nil { + log.Fatalf("storage.NewClient: %v", err) + } + autocertManager := &autocert.Manager{ + Prompt: autocert.AcceptTOS, + HostPolicy: autocert.HostWhitelist("http2.golang.org"), + Cache: autocertcache.NewGoogleCloudStorageCache(storageClient, "golang-h2demo-autocert"), + } + errc := make(chan error, 2) - go func() { errc <- http.ListenAndServe(":80", nil) }() - go func() { errc <- serveProdTLS() }() + go func() { errc <- http.ListenAndServe(":80", autocertManager.HTTPHandler(http.DefaultServeMux)) }() + go func() { errc <- serveProdTLS(autocertManager) }() return <-errc } diff --git a/vendor/golang.org/x/net/http2/h2demo/service.yaml b/vendor/golang.org/x/net/http2/h2demo/service.yaml new file mode 100644 index 0000000000000000000000000000000000000000..8e7671e4a6fc2b406b6636e736c129d254464a83 --- /dev/null +++ b/vendor/golang.org/x/net/http2/h2demo/service.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Service +metadata: + name: h2demo +spec: + ports: + - port: 80 + targetPort: 80 + name: http + - port: 443 + targetPort: 443 + name: https + selector: + app: h2demo + type: LoadBalancer + loadBalancerIP: 130.211.116.44 diff --git a/vendor/golang.org/x/net/internal/iana/gen.go b/vendor/golang.org/x/net/internal/iana/gen.go index 86c78b3bb7dccf513630e23c5573e96d3479f8be..2a5c310c2f0d1c4212a60470568cb04d6b79abd9 100644 --- a/vendor/golang.org/x/net/internal/iana/gen.go +++ b/vendor/golang.org/x/net/internal/iana/gen.go @@ -28,15 +28,15 @@ var registries = []struct { parse func(io.Writer, io.Reader) error }{ { - "http://www.iana.org/assignments/dscp-registry/dscp-registry.xml", + "https://www.iana.org/assignments/dscp-registry/dscp-registry.xml", parseDSCPRegistry, }, { - "http://www.iana.org/assignments/ipv4-tos-byte/ipv4-tos-byte.xml", + "https://www.iana.org/assignments/ipv4-tos-byte/ipv4-tos-byte.xml", parseTOSTCByte, }, { - "http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml", + "https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml", parseProtocolNumbers, }, } diff --git a/vendor/golang.org/x/net/ipv4/gen.go b/vendor/golang.org/x/net/ipv4/gen.go index ffb44fe681fe4332bff2b0eb0e3f6205f605cb1c..9d490fac9db24814962cb7a56906d907b588fcb2 100644 --- a/vendor/golang.org/x/net/ipv4/gen.go +++ b/vendor/golang.org/x/net/ipv4/gen.go @@ -72,7 +72,7 @@ var registries = []struct { parse func(io.Writer, io.Reader) error }{ { - "http://www.iana.org/assignments/icmp-parameters/icmp-parameters.xml", + "https://www.iana.org/assignments/icmp-parameters/icmp-parameters.xml", parseICMPv4Parameters, }, } diff --git a/vendor/golang.org/x/net/ipv6/gen.go b/vendor/golang.org/x/net/ipv6/gen.go index 41886ec72189f3dff6f583bf7f817bdc0d6cfdc0..47b7e9f0a4748a5a0a2a144ce40909d5636aafe3 100644 --- a/vendor/golang.org/x/net/ipv6/gen.go +++ b/vendor/golang.org/x/net/ipv6/gen.go @@ -72,7 +72,7 @@ var registries = []struct { parse func(io.Writer, io.Reader) error }{ { - "http://www.iana.org/assignments/icmpv6-parameters/icmpv6-parameters.xml", + "https://www.iana.org/assignments/icmpv6-parameters/icmpv6-parameters.xml", parseICMPv6Parameters, }, } diff --git a/vendor/google.golang.org/genproto/.github/CODEOWNERS b/vendor/google.golang.org/genproto/.github/CODEOWNERS new file mode 100644 index 0000000000000000000000000000000000000000..7104b62ddb6fecd95055a8d8374f78a46beda621 --- /dev/null +++ b/vendor/google.golang.org/genproto/.github/CODEOWNERS @@ -0,0 +1 @@ +* @pongad @jba diff --git a/vendor/google.golang.org/genproto/googleapis/api/annotations/BUILD.bazel b/vendor/google.golang.org/genproto/googleapis/api/annotations/BUILD.bazel deleted file mode 100644 index 4c1349b0dbc716d2f823b4b6fb60e88cfe9f1165..0000000000000000000000000000000000000000 --- a/vendor/google.golang.org/genproto/googleapis/api/annotations/BUILD.bazel +++ /dev/null @@ -1,15 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "annotations.pb.go", - "http.pb.go", - ], - importpath = "google.golang.org/genproto/googleapis/api/annotations", - visibility = ["//visibility:public"], - deps = [ - "//vendor/github.com/golang/protobuf/proto:go_default_library", - "//vendor/github.com/golang/protobuf/protoc-gen-go/descriptor:go_default_library", - ], -) diff --git a/vendor/google.golang.org/genproto/googleapis/api/annotations/http.pb.go b/vendor/google.golang.org/genproto/googleapis/api/annotations/http.pb.go index f91c604620bc6732ad47ba90d679e63ea69db1e7..73f050f71df16224c2e3983afe81a2bd60ca014c 100644 --- a/vendor/google.golang.org/genproto/googleapis/api/annotations/http.pb.go +++ b/vendor/google.golang.org/genproto/googleapis/api/annotations/http.pb.go @@ -12,7 +12,7 @@ var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf -// Defines the HTTP configuration for a service. It contains a list of +// Defines the HTTP configuration for an API service. It contains a list of // [HttpRule][google.api.HttpRule], each specifying the mapping of an RPC method // to one or more HTTP REST API methods. type Http struct { @@ -20,6 +20,13 @@ type Http struct { // // **NOTE:** All service configuration rules follow "last one wins" order. Rules []*HttpRule `protobuf:"bytes,1,rep,name=rules" json:"rules,omitempty"` + // When set to true, URL path parmeters will be fully URI-decoded except in + // cases of single segment matches in reserved expansion, where "%2F" will be + // left encoded. + // + // The default behavior is to not decode RFC 6570 reserved characters in multi + // segment matches. + FullyDecodeReservedExpansion bool `protobuf:"varint,2,opt,name=fully_decode_reserved_expansion,json=fullyDecodeReservedExpansion" json:"fully_decode_reserved_expansion,omitempty"` } func (m *Http) Reset() { *m = Http{} } @@ -34,12 +41,19 @@ func (m *Http) GetRules() []*HttpRule { return nil } +func (m *Http) GetFullyDecodeReservedExpansion() bool { + if m != nil { + return m.FullyDecodeReservedExpansion + } + return false +} + // `HttpRule` defines the mapping of an RPC method to one or more HTTP -// REST APIs. The mapping determines what portions of the request -// message are populated from the path, query parameters, or body of -// the HTTP request. The mapping is typically specified as an -// `google.api.http` annotation, see "google/api/annotations.proto" -// for details. +// REST API methods. The mapping specifies how different portions of the RPC +// request message are mapped to URL path, URL query parameters, and +// HTTP request body. The mapping is typically specified as an +// `google.api.http` annotation on the RPC method, +// see "google/api/annotations.proto" for details. // // The mapping consists of a field specifying the path template and // method kind. The path template can refer to fields in the request @@ -87,6 +101,11 @@ func (m *Http) GetRules() []*HttpRule { // parameters. Assume the following definition of the request message: // // +// service Messaging { +// rpc GetMessage(GetMessageRequest) returns (Message) { +// option (google.api.http).get = "/v1/messages/{message_id}"; +// } +// } // message GetMessageRequest { // message SubMessage { // string subfield = 1; @@ -199,7 +218,7 @@ func (m *Http) GetRules() []*HttpRule { // to the request message are as follows: // // 1. The `body` field specifies either `*` or a field path, or is -// omitted. If omitted, it assumes there is no HTTP body. +// omitted. If omitted, it indicates there is no HTTP request body. // 2. Leaf fields (recursive expansion of nested messages in the // request) can be classified into three types: // (a) Matched in the URL template. @@ -218,28 +237,34 @@ func (m *Http) GetRules() []*HttpRule { // FieldPath = IDENT { "." IDENT } ; // Verb = ":" LITERAL ; // -// The syntax `*` matches a single path segment. It follows the semantics of -// [RFC 6570](https://tools.ietf.org/html/rfc6570) Section 3.2.2 Simple String -// Expansion. -// -// The syntax `**` matches zero or more path segments. It follows the semantics -// of [RFC 6570](https://tools.ietf.org/html/rfc6570) Section 3.2.3 Reserved -// Expansion. NOTE: it must be the last segment in the path except the Verb. +// The syntax `*` matches a single path segment. The syntax `**` matches zero +// or more path segments, which must be the last part of the path except the +// `Verb`. The syntax `LITERAL` matches literal text in the path. // -// The syntax `LITERAL` matches literal text in the URL path. -// -// The syntax `Variable` matches the entire path as specified by its template; -// this nested template must not contain further variables. If a variable +// The syntax `Variable` matches part of the URL path as specified by its +// template. A variable template must not contain other variables. If a variable // matches a single path segment, its template may be omitted, e.g. `{var}` // is equivalent to `{var=*}`. // +// If a variable contains exactly one path segment, such as `"{var}"` or +// `"{var=*}"`, when such a variable is expanded into a URL path, all characters +// except `[-_.~0-9a-zA-Z]` are percent-encoded. Such variables show up in the +// Discovery Document as `{var}`. +// +// If a variable contains one or more path segments, such as `"{var=foo/*}"` +// or `"{var=**}"`, when such a variable is expanded into a URL path, all +// characters except `[-_.~/0-9a-zA-Z]` are percent-encoded. Such variables +// show up in the Discovery Document as `{+var}`. +// +// NOTE: While the single segment variable matches the semantics of +// [RFC 6570](https://tools.ietf.org/html/rfc6570) Section 3.2.2 +// Simple String Expansion, the multi segment variable **does not** match +// RFC 6570 Reserved Expansion. The reason is that the Reserved Expansion +// does not expand special characters like `?` and `#`, which would lead +// to invalid URLs. +// // NOTE: the field paths in variables and in the `body` must not refer to // repeated fields or map fields. -// -// Use CustomHttpPattern to specify any HTTP method that is not included in the -// `pattern` field, such as HEAD, or "*" to leave the HTTP method unspecified for -// a given URL path rule. The wild-card rule is useful for services that provide -// content to Web (HTML) clients. type HttpRule struct { // Selects methods to which this rule applies. // @@ -539,28 +564,31 @@ func init() { func init() { proto.RegisterFile("google/api/http.proto", fileDescriptor1) } var fileDescriptor1 = []byte{ - // 359 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x92, 0xcf, 0x6a, 0xe3, 0x30, - 0x10, 0xc6, 0xd7, 0x89, 0xe3, 0x24, 0x13, 0x58, 0x58, 0x6d, 0x76, 0x11, 0x85, 0x42, 0xc8, 0x29, - 0xf4, 0x60, 0x43, 0x7a, 0xe8, 0x21, 0xa7, 0xb8, 0x94, 0xa6, 0xb7, 0xe0, 0x63, 0x2f, 0x45, 0xb1, - 0x85, 0xa2, 0xd6, 0x91, 0x84, 0x3d, 0x3e, 0xf4, 0x75, 0xfa, 0x0e, 0x7d, 0xb7, 0x1e, 0x8b, 0xfe, - 0xa4, 0x09, 0x14, 0x7a, 0x9b, 0xef, 0x37, 0x9f, 0x34, 0xa3, 0x19, 0xc1, 0x3f, 0xa1, 0xb5, 0xa8, - 0x79, 0xc6, 0x8c, 0xcc, 0xf6, 0x88, 0x26, 0x35, 0x8d, 0x46, 0x4d, 0xc0, 0xe3, 0x94, 0x19, 0x39, - 0x5f, 0x42, 0xbc, 0x41, 0x34, 0xe4, 0x0a, 0x06, 0x4d, 0x57, 0xf3, 0x96, 0x46, 0xb3, 0xfe, 0x62, - 0xb2, 0x9c, 0xa6, 0x27, 0x4f, 0x6a, 0x0d, 0x45, 0x57, 0xf3, 0xc2, 0x5b, 0xe6, 0xef, 0x3d, 0x18, - 0x1d, 0x19, 0xb9, 0x80, 0x51, 0xcb, 0x6b, 0x5e, 0xa2, 0x6e, 0x68, 0x34, 0x8b, 0x16, 0xe3, 0xe2, - 0x4b, 0x13, 0x02, 0x7d, 0xc1, 0x91, 0xf6, 0x2c, 0xde, 0xfc, 0x2a, 0xac, 0xb0, 0xcc, 0x74, 0x48, - 0xfb, 0x47, 0x66, 0x3a, 0x24, 0x53, 0x88, 0x8d, 0x6e, 0x91, 0xc6, 0x01, 0x3a, 0x45, 0x28, 0x24, - 0x15, 0xaf, 0x39, 0x72, 0x3a, 0x08, 0x3c, 0x68, 0xf2, 0x1f, 0x06, 0x86, 0x61, 0xb9, 0xa7, 0x49, - 0x48, 0x78, 0x49, 0x6e, 0x20, 0x29, 0xbb, 0x16, 0xf5, 0x81, 0x8e, 0x66, 0xd1, 0x62, 0xb2, 0xbc, - 0x3c, 0x7f, 0xc5, 0xad, 0xcb, 0xd8, 0xbe, 0xb7, 0x0c, 0x91, 0x37, 0xca, 0x5e, 0xe8, 0xed, 0x84, - 0x40, 0xbc, 0xd3, 0xd5, 0x2b, 0x1d, 0xba, 0x07, 0xb8, 0x98, 0xdc, 0xc1, 0x5f, 0x56, 0x55, 0x12, - 0xa5, 0x56, 0xac, 0x7e, 0xda, 0x49, 0x55, 0x49, 0x25, 0x5a, 0x3a, 0xf9, 0x61, 0x3e, 0xe4, 0x74, - 0x20, 0x0f, 0xfe, 0x7c, 0x0c, 0x43, 0xe3, 0xeb, 0xcd, 0x57, 0xf0, 0xe7, 0x5b, 0x13, 0xb6, 0xf4, - 0x8b, 0x54, 0x55, 0x98, 0x9d, 0x8b, 0x2d, 0x33, 0x0c, 0xf7, 0x7e, 0x70, 0x85, 0x8b, 0xf3, 0x67, - 0xf8, 0x5d, 0xea, 0xc3, 0x59, 0xd9, 0x7c, 0xec, 0xae, 0xb1, 0x1b, 0xdd, 0x46, 0x8f, 0xeb, 0x90, - 0x10, 0xba, 0x66, 0x4a, 0xa4, 0xba, 0x11, 0x99, 0xe0, 0xca, 0xed, 0x3b, 0xf3, 0x29, 0x66, 0x64, - 0xeb, 0x7e, 0x02, 0x53, 0x4a, 0x23, 0xb3, 0x6d, 0xb6, 0xab, 0xb3, 0xf8, 0x23, 0x8a, 0xde, 0x7a, - 0xf1, 0xfd, 0x7a, 0xfb, 0xb0, 0x4b, 0xdc, 0xb9, 0xeb, 0xcf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x68, - 0x15, 0x60, 0x5b, 0x40, 0x02, 0x00, 0x00, + // 401 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x92, 0x41, 0xab, 0x13, 0x31, + 0x10, 0xc7, 0xdd, 0x76, 0xdb, 0xd7, 0x4e, 0x41, 0x30, 0x3e, 0x25, 0x88, 0x62, 0xe9, 0xa9, 0x78, + 0xd8, 0xc2, 0xf3, 0xe0, 0xe1, 0x9d, 0x5e, 0xb5, 0xf8, 0xbc, 0x95, 0x3d, 0x7a, 0x29, 0xe9, 0x66, + 0x4c, 0xa3, 0x79, 0x49, 0xd8, 0xcc, 0x8a, 0xfd, 0x3a, 0x7e, 0x07, 0xbf, 0x9b, 0x47, 0x49, 0x36, + 0xb5, 0x05, 0xc1, 0xdb, 0xfc, 0xff, 0xf3, 0xcb, 0xcc, 0x64, 0x18, 0x78, 0xa6, 0x9c, 0x53, 0x06, + 0x57, 0xc2, 0xeb, 0xd5, 0x81, 0xc8, 0x57, 0xbe, 0x75, 0xe4, 0x18, 0xf4, 0x76, 0x25, 0xbc, 0x5e, + 0x1c, 0xa1, 0xbc, 0x27, 0xf2, 0xec, 0x0d, 0x8c, 0xda, 0xce, 0x60, 0xe0, 0xc5, 0x7c, 0xb8, 0x9c, + 0xdd, 0x5c, 0x57, 0x67, 0xa6, 0x8a, 0x40, 0xdd, 0x19, 0xac, 0x7b, 0x84, 0x6d, 0xe0, 0xf5, 0x97, + 0xce, 0x98, 0xe3, 0x4e, 0x62, 0xe3, 0x24, 0xee, 0x5a, 0x0c, 0xd8, 0x7e, 0x47, 0xb9, 0xc3, 0x1f, + 0x5e, 0xd8, 0xa0, 0x9d, 0xe5, 0x83, 0x79, 0xb1, 0x9c, 0xd4, 0x2f, 0x13, 0xf6, 0x21, 0x51, 0x75, + 0x86, 0x36, 0x27, 0x66, 0xf1, 0x6b, 0x00, 0x93, 0x53, 0x69, 0xf6, 0x02, 0x26, 0x01, 0x0d, 0x36, + 0xe4, 0x5a, 0x5e, 0xcc, 0x8b, 0xe5, 0xb4, 0xfe, 0xab, 0x19, 0x83, 0xa1, 0x42, 0x4a, 0x35, 0xa7, + 0xf7, 0x8f, 0xea, 0x28, 0xa2, 0xe7, 0x3b, 0xe2, 0xc3, 0x93, 0xe7, 0x3b, 0x62, 0xd7, 0x50, 0x7a, + 0x17, 0x88, 0x97, 0xd9, 0x4c, 0x8a, 0x71, 0x18, 0x4b, 0x34, 0x48, 0xc8, 0x47, 0xd9, 0xcf, 0x9a, + 0x3d, 0x87, 0x91, 0x17, 0xd4, 0x1c, 0xf8, 0x38, 0x27, 0x7a, 0xc9, 0xde, 0xc1, 0xb8, 0xe9, 0x02, + 0xb9, 0x07, 0x3e, 0x99, 0x17, 0xcb, 0xd9, 0xcd, 0xab, 0xcb, 0x65, 0xbc, 0x4f, 0x99, 0x38, 0xf7, + 0x56, 0x10, 0x61, 0x6b, 0x63, 0xc1, 0x1e, 0x67, 0x0c, 0xca, 0xbd, 0x93, 0x47, 0x7e, 0x95, 0x3e, + 0x90, 0x62, 0xb6, 0x81, 0xa7, 0x42, 0x4a, 0x4d, 0xda, 0x59, 0x61, 0x76, 0x7b, 0x6d, 0xa5, 0xb6, + 0x2a, 0xf0, 0xd9, 0x7f, 0xd6, 0xcc, 0xce, 0x0f, 0xd6, 0x99, 0x5f, 0x4f, 0xe1, 0xca, 0xf7, 0xfd, + 0x16, 0xb7, 0xf0, 0xe4, 0x9f, 0x21, 0x62, 0xeb, 0x6f, 0xda, 0xca, 0xbc, 0xbb, 0x14, 0x47, 0xcf, + 0x0b, 0x3a, 0xf4, 0x8b, 0xab, 0x53, 0xbc, 0xfe, 0x0a, 0x8f, 0x1b, 0xf7, 0x70, 0xd1, 0x76, 0x3d, + 0x4d, 0x65, 0xe2, 0x61, 0x6c, 0x8b, 0xcf, 0x77, 0x39, 0xa1, 0x9c, 0x11, 0x56, 0x55, 0xae, 0x55, + 0x2b, 0x85, 0x36, 0x9d, 0xcd, 0xaa, 0x4f, 0x09, 0xaf, 0x43, 0x3a, 0x28, 0x61, 0xad, 0x23, 0x11, + 0xc7, 0x0c, 0xb7, 0x17, 0xf1, 0xef, 0xa2, 0xf8, 0x39, 0x28, 0x3f, 0xde, 0x6d, 0x3f, 0xed, 0xc7, + 0xe9, 0xdd, 0xdb, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x73, 0x2c, 0xed, 0xfb, 0x87, 0x02, 0x00, + 0x00, } diff --git a/vendor/google.golang.org/genproto/googleapis/cloud/dialogflow/v2beta1/agent.pb.go b/vendor/google.golang.org/genproto/googleapis/cloud/dialogflow/v2beta1/agent.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..fae63a5b1be3537401849c5defeb287ea40216a1 --- /dev/null +++ b/vendor/google.golang.org/genproto/googleapis/cloud/dialogflow/v2beta1/agent.pb.go @@ -0,0 +1,1153 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: google/cloud/dialogflow/v2beta1/agent.proto + +/* +Package dialogflow is a generated protocol buffer package. + +It is generated from these files: + google/cloud/dialogflow/v2beta1/agent.proto + google/cloud/dialogflow/v2beta1/context.proto + google/cloud/dialogflow/v2beta1/entity_type.proto + google/cloud/dialogflow/v2beta1/intent.proto + google/cloud/dialogflow/v2beta1/session.proto + google/cloud/dialogflow/v2beta1/session_entity_type.proto + google/cloud/dialogflow/v2beta1/webhook.proto + +It has these top-level messages: + Agent + GetAgentRequest + SearchAgentsRequest + SearchAgentsResponse + TrainAgentRequest + ExportAgentRequest + ExportAgentResponse + ImportAgentRequest + RestoreAgentRequest + Context + ListContextsRequest + ListContextsResponse + GetContextRequest + CreateContextRequest + UpdateContextRequest + DeleteContextRequest + DeleteAllContextsRequest + EntityType + ListEntityTypesRequest + ListEntityTypesResponse + GetEntityTypeRequest + CreateEntityTypeRequest + UpdateEntityTypeRequest + DeleteEntityTypeRequest + BatchUpdateEntityTypesRequest + BatchUpdateEntityTypesResponse + BatchDeleteEntityTypesRequest + BatchCreateEntitiesRequest + BatchUpdateEntitiesRequest + BatchDeleteEntitiesRequest + EntityTypeBatch + Intent + ListIntentsRequest + ListIntentsResponse + GetIntentRequest + CreateIntentRequest + UpdateIntentRequest + DeleteIntentRequest + BatchUpdateIntentsRequest + BatchUpdateIntentsResponse + BatchDeleteIntentsRequest + IntentBatch + DetectIntentRequest + DetectIntentResponse + QueryParameters + QueryInput + QueryResult + StreamingDetectIntentRequest + StreamingDetectIntentResponse + StreamingRecognitionResult + InputAudioConfig + TextInput + EventInput + SessionEntityType + ListSessionEntityTypesRequest + ListSessionEntityTypesResponse + GetSessionEntityTypeRequest + CreateSessionEntityTypeRequest + UpdateSessionEntityTypeRequest + DeleteSessionEntityTypeRequest + WebhookRequest + WebhookResponse + OriginalDetectIntentRequest +*/ +package dialogflow + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import _ "google.golang.org/genproto/googleapis/api/annotations" +import google_longrunning "google.golang.org/genproto/googleapis/longrunning" +import _ "github.com/golang/protobuf/ptypes/empty" +import _ "google.golang.org/genproto/protobuf/field_mask" +import _ "github.com/golang/protobuf/ptypes/struct" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +// Match mode determines how intents are detected from user queries. +type Agent_MatchMode int32 + +const ( + // Not specified. + Agent_MATCH_MODE_UNSPECIFIED Agent_MatchMode = 0 + // Best for agents with a small number of examples in intents and/or wide + // use of templates syntax and composite entities. + Agent_MATCH_MODE_HYBRID Agent_MatchMode = 1 + // Can be used for agents with a large number of examples in intents, + // especially the ones using @sys.any or very large developer entities. + Agent_MATCH_MODE_ML_ONLY Agent_MatchMode = 2 +) + +var Agent_MatchMode_name = map[int32]string{ + 0: "MATCH_MODE_UNSPECIFIED", + 1: "MATCH_MODE_HYBRID", + 2: "MATCH_MODE_ML_ONLY", +} +var Agent_MatchMode_value = map[string]int32{ + "MATCH_MODE_UNSPECIFIED": 0, + "MATCH_MODE_HYBRID": 1, + "MATCH_MODE_ML_ONLY": 2, +} + +func (x Agent_MatchMode) String() string { + return proto.EnumName(Agent_MatchMode_name, int32(x)) +} +func (Agent_MatchMode) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0, 0} } + +// Represents a conversational agent. +type Agent struct { + // Required. The project of this agent. + // Format: `projects/`. + Parent string `protobuf:"bytes,1,opt,name=parent" json:"parent,omitempty"` + // Required. The name of this agent. + DisplayName string `protobuf:"bytes,2,opt,name=display_name,json=displayName" json:"display_name,omitempty"` + // Required. The default language of the agent as a language tag. See + // [Language Support](https://dialogflow.com/docs/reference/language) for a + // list of the currently supported language codes. + // This field cannot be set by the `Update` method. + DefaultLanguageCode string `protobuf:"bytes,3,opt,name=default_language_code,json=defaultLanguageCode" json:"default_language_code,omitempty"` + // Optional. The list of all languages supported by this agent (except for the + // `default_language_code`). + SupportedLanguageCodes []string `protobuf:"bytes,4,rep,name=supported_language_codes,json=supportedLanguageCodes" json:"supported_language_codes,omitempty"` + // Required. The time zone of this agent from the + // [time zone database](https://www.iana.org/time-zones), e.g., + // America/New_York, Europe/Paris. + TimeZone string `protobuf:"bytes,5,opt,name=time_zone,json=timeZone" json:"time_zone,omitempty"` + // Optional. The description of this agent. + // The maximum length is 500 characters. If exceeded, the request is rejected. + Description string `protobuf:"bytes,6,opt,name=description" json:"description,omitempty"` + // Optional. The URI of the agent's avatar. + // Avatars are used throughout API.AI console and in the self-hosted + // [Web Demo](https://dialogflow.com/docs/integrations/web-demo) integration. + AvatarUri string `protobuf:"bytes,7,opt,name=avatar_uri,json=avatarUri" json:"avatar_uri,omitempty"` + // Optional. Determines whether this agent should log conversation queries. + EnableLogging bool `protobuf:"varint,8,opt,name=enable_logging,json=enableLogging" json:"enable_logging,omitempty"` + // Optional. Determines how intents are detected from user queries. + MatchMode Agent_MatchMode `protobuf:"varint,9,opt,name=match_mode,json=matchMode,enum=google.cloud.dialogflow.v2beta1.Agent_MatchMode" json:"match_mode,omitempty"` + // Optional. To filter out false positive results and still get variety in + // matched natural language inputs for your agent, you can tune the machine + // learning classification threshold. If the returned score value is less than + // the threshold value, then a fallback intent is be triggered or, if there + // are no fallback intents defined, no intent will be triggered. The score + // values range from 0.0 (completely uncertain) to 1.0 (completely certain). + // If set to 0.0, the default of 0.3 is used. + ClassificationThreshold float32 `protobuf:"fixed32,10,opt,name=classification_threshold,json=classificationThreshold" json:"classification_threshold,omitempty"` +} + +func (m *Agent) Reset() { *m = Agent{} } +func (m *Agent) String() string { return proto.CompactTextString(m) } +func (*Agent) ProtoMessage() {} +func (*Agent) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +func (m *Agent) GetParent() string { + if m != nil { + return m.Parent + } + return "" +} + +func (m *Agent) GetDisplayName() string { + if m != nil { + return m.DisplayName + } + return "" +} + +func (m *Agent) GetDefaultLanguageCode() string { + if m != nil { + return m.DefaultLanguageCode + } + return "" +} + +func (m *Agent) GetSupportedLanguageCodes() []string { + if m != nil { + return m.SupportedLanguageCodes + } + return nil +} + +func (m *Agent) GetTimeZone() string { + if m != nil { + return m.TimeZone + } + return "" +} + +func (m *Agent) GetDescription() string { + if m != nil { + return m.Description + } + return "" +} + +func (m *Agent) GetAvatarUri() string { + if m != nil { + return m.AvatarUri + } + return "" +} + +func (m *Agent) GetEnableLogging() bool { + if m != nil { + return m.EnableLogging + } + return false +} + +func (m *Agent) GetMatchMode() Agent_MatchMode { + if m != nil { + return m.MatchMode + } + return Agent_MATCH_MODE_UNSPECIFIED +} + +func (m *Agent) GetClassificationThreshold() float32 { + if m != nil { + return m.ClassificationThreshold + } + return 0 +} + +// The request message for +// [Agents.GetAgent][google.cloud.dialogflow.v2beta1.Agents.GetAgent]. +type GetAgentRequest struct { + // Required. The project that the agent to fetch is associated with. + // Format: `projects/`. + Parent string `protobuf:"bytes,1,opt,name=parent" json:"parent,omitempty"` +} + +func (m *GetAgentRequest) Reset() { *m = GetAgentRequest{} } +func (m *GetAgentRequest) String() string { return proto.CompactTextString(m) } +func (*GetAgentRequest) ProtoMessage() {} +func (*GetAgentRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +func (m *GetAgentRequest) GetParent() string { + if m != nil { + return m.Parent + } + return "" +} + +// The request message for +// [Agents.SearchAgents][google.cloud.dialogflow.v2beta1.Agents.SearchAgents]. +type SearchAgentsRequest struct { + // Required. The project to list agents from. + // Format: `projects/`. + Parent string `protobuf:"bytes,1,opt,name=parent" json:"parent,omitempty"` + // Optional. The maximum number of items to return in a single page. By + // default 100 and at most 1000. + PageSize int32 `protobuf:"varint,2,opt,name=page_size,json=pageSize" json:"page_size,omitempty"` + // Optional. The next_page_token value returned from a previous list request. + PageToken string `protobuf:"bytes,3,opt,name=page_token,json=pageToken" json:"page_token,omitempty"` +} + +func (m *SearchAgentsRequest) Reset() { *m = SearchAgentsRequest{} } +func (m *SearchAgentsRequest) String() string { return proto.CompactTextString(m) } +func (*SearchAgentsRequest) ProtoMessage() {} +func (*SearchAgentsRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } + +func (m *SearchAgentsRequest) GetParent() string { + if m != nil { + return m.Parent + } + return "" +} + +func (m *SearchAgentsRequest) GetPageSize() int32 { + if m != nil { + return m.PageSize + } + return 0 +} + +func (m *SearchAgentsRequest) GetPageToken() string { + if m != nil { + return m.PageToken + } + return "" +} + +// The response message for +// [Agents.SearchAgents][google.cloud.dialogflow.v2beta1.Agents.SearchAgents]. +type SearchAgentsResponse struct { + // The list of agents. There will be a maximum number of items returned based + // on the page_size field in the request. + Agents []*Agent `protobuf:"bytes,1,rep,name=agents" json:"agents,omitempty"` + // Token to retrieve the next page of results, or empty if there are no + // more results in the list. + NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken" json:"next_page_token,omitempty"` +} + +func (m *SearchAgentsResponse) Reset() { *m = SearchAgentsResponse{} } +func (m *SearchAgentsResponse) String() string { return proto.CompactTextString(m) } +func (*SearchAgentsResponse) ProtoMessage() {} +func (*SearchAgentsResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } + +func (m *SearchAgentsResponse) GetAgents() []*Agent { + if m != nil { + return m.Agents + } + return nil +} + +func (m *SearchAgentsResponse) GetNextPageToken() string { + if m != nil { + return m.NextPageToken + } + return "" +} + +// The request message for +// [Agents.TrainAgent][google.cloud.dialogflow.v2beta1.Agents.TrainAgent]. +type TrainAgentRequest struct { + // Required. The project that the agent to train is associated with. + // Format: `projects/`. + Parent string `protobuf:"bytes,1,opt,name=parent" json:"parent,omitempty"` +} + +func (m *TrainAgentRequest) Reset() { *m = TrainAgentRequest{} } +func (m *TrainAgentRequest) String() string { return proto.CompactTextString(m) } +func (*TrainAgentRequest) ProtoMessage() {} +func (*TrainAgentRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } + +func (m *TrainAgentRequest) GetParent() string { + if m != nil { + return m.Parent + } + return "" +} + +// The request message for +// [Agents.ExportAgent][google.cloud.dialogflow.v2beta1.Agents.ExportAgent]. +type ExportAgentRequest struct { + // Required. The project that the agent to export is associated with. + // Format: `projects/`. + Parent string `protobuf:"bytes,1,opt,name=parent" json:"parent,omitempty"` + // Warning: Exporting agents to a URI is not implemented yet. + // This feature is coming soon. + // Optional. The Google Cloud Storage URI to export the agent to. + // Note: The URI must start with + // "gs://". If left unspecified, the serialized agent is returned inline. + AgentUri string `protobuf:"bytes,2,opt,name=agent_uri,json=agentUri" json:"agent_uri,omitempty"` +} + +func (m *ExportAgentRequest) Reset() { *m = ExportAgentRequest{} } +func (m *ExportAgentRequest) String() string { return proto.CompactTextString(m) } +func (*ExportAgentRequest) ProtoMessage() {} +func (*ExportAgentRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } + +func (m *ExportAgentRequest) GetParent() string { + if m != nil { + return m.Parent + } + return "" +} + +func (m *ExportAgentRequest) GetAgentUri() string { + if m != nil { + return m.AgentUri + } + return "" +} + +// The response message for +// [Agents.ExportAgent][google.cloud.dialogflow.v2beta1.Agents.ExportAgent]. +type ExportAgentResponse struct { + // Required. The exported agent. + // + // Types that are valid to be assigned to Agent: + // *ExportAgentResponse_AgentUri + // *ExportAgentResponse_AgentContent + Agent isExportAgentResponse_Agent `protobuf_oneof:"agent"` +} + +func (m *ExportAgentResponse) Reset() { *m = ExportAgentResponse{} } +func (m *ExportAgentResponse) String() string { return proto.CompactTextString(m) } +func (*ExportAgentResponse) ProtoMessage() {} +func (*ExportAgentResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } + +type isExportAgentResponse_Agent interface { + isExportAgentResponse_Agent() +} + +type ExportAgentResponse_AgentUri struct { + AgentUri string `protobuf:"bytes,1,opt,name=agent_uri,json=agentUri,oneof"` +} +type ExportAgentResponse_AgentContent struct { + AgentContent []byte `protobuf:"bytes,2,opt,name=agent_content,json=agentContent,proto3,oneof"` +} + +func (*ExportAgentResponse_AgentUri) isExportAgentResponse_Agent() {} +func (*ExportAgentResponse_AgentContent) isExportAgentResponse_Agent() {} + +func (m *ExportAgentResponse) GetAgent() isExportAgentResponse_Agent { + if m != nil { + return m.Agent + } + return nil +} + +func (m *ExportAgentResponse) GetAgentUri() string { + if x, ok := m.GetAgent().(*ExportAgentResponse_AgentUri); ok { + return x.AgentUri + } + return "" +} + +func (m *ExportAgentResponse) GetAgentContent() []byte { + if x, ok := m.GetAgent().(*ExportAgentResponse_AgentContent); ok { + return x.AgentContent + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*ExportAgentResponse) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _ExportAgentResponse_OneofMarshaler, _ExportAgentResponse_OneofUnmarshaler, _ExportAgentResponse_OneofSizer, []interface{}{ + (*ExportAgentResponse_AgentUri)(nil), + (*ExportAgentResponse_AgentContent)(nil), + } +} + +func _ExportAgentResponse_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*ExportAgentResponse) + // agent + switch x := m.Agent.(type) { + case *ExportAgentResponse_AgentUri: + b.EncodeVarint(1<<3 | proto.WireBytes) + b.EncodeStringBytes(x.AgentUri) + case *ExportAgentResponse_AgentContent: + b.EncodeVarint(2<<3 | proto.WireBytes) + b.EncodeRawBytes(x.AgentContent) + case nil: + default: + return fmt.Errorf("ExportAgentResponse.Agent has unexpected type %T", x) + } + return nil +} + +func _ExportAgentResponse_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*ExportAgentResponse) + switch tag { + case 1: // agent.agent_uri + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeStringBytes() + m.Agent = &ExportAgentResponse_AgentUri{x} + return true, err + case 2: // agent.agent_content + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeRawBytes(true) + m.Agent = &ExportAgentResponse_AgentContent{x} + return true, err + default: + return false, nil + } +} + +func _ExportAgentResponse_OneofSizer(msg proto.Message) (n int) { + m := msg.(*ExportAgentResponse) + // agent + switch x := m.Agent.(type) { + case *ExportAgentResponse_AgentUri: + n += proto.SizeVarint(1<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.AgentUri))) + n += len(x.AgentUri) + case *ExportAgentResponse_AgentContent: + n += proto.SizeVarint(2<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.AgentContent))) + n += len(x.AgentContent) + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +// The request message for +// [Agents.ImportAgent][google.cloud.dialogflow.v2beta1.Agents.ImportAgent]. +type ImportAgentRequest struct { + // Required. The project that the agent to import is associated with. + // Format: `projects/`. + Parent string `protobuf:"bytes,1,opt,name=parent" json:"parent,omitempty"` + // Required. The agent to import. + // + // Types that are valid to be assigned to Agent: + // *ImportAgentRequest_AgentUri + // *ImportAgentRequest_AgentContent + Agent isImportAgentRequest_Agent `protobuf_oneof:"agent"` +} + +func (m *ImportAgentRequest) Reset() { *m = ImportAgentRequest{} } +func (m *ImportAgentRequest) String() string { return proto.CompactTextString(m) } +func (*ImportAgentRequest) ProtoMessage() {} +func (*ImportAgentRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } + +type isImportAgentRequest_Agent interface { + isImportAgentRequest_Agent() +} + +type ImportAgentRequest_AgentUri struct { + AgentUri string `protobuf:"bytes,2,opt,name=agent_uri,json=agentUri,oneof"` +} +type ImportAgentRequest_AgentContent struct { + AgentContent []byte `protobuf:"bytes,3,opt,name=agent_content,json=agentContent,proto3,oneof"` +} + +func (*ImportAgentRequest_AgentUri) isImportAgentRequest_Agent() {} +func (*ImportAgentRequest_AgentContent) isImportAgentRequest_Agent() {} + +func (m *ImportAgentRequest) GetAgent() isImportAgentRequest_Agent { + if m != nil { + return m.Agent + } + return nil +} + +func (m *ImportAgentRequest) GetParent() string { + if m != nil { + return m.Parent + } + return "" +} + +func (m *ImportAgentRequest) GetAgentUri() string { + if x, ok := m.GetAgent().(*ImportAgentRequest_AgentUri); ok { + return x.AgentUri + } + return "" +} + +func (m *ImportAgentRequest) GetAgentContent() []byte { + if x, ok := m.GetAgent().(*ImportAgentRequest_AgentContent); ok { + return x.AgentContent + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*ImportAgentRequest) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _ImportAgentRequest_OneofMarshaler, _ImportAgentRequest_OneofUnmarshaler, _ImportAgentRequest_OneofSizer, []interface{}{ + (*ImportAgentRequest_AgentUri)(nil), + (*ImportAgentRequest_AgentContent)(nil), + } +} + +func _ImportAgentRequest_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*ImportAgentRequest) + // agent + switch x := m.Agent.(type) { + case *ImportAgentRequest_AgentUri: + b.EncodeVarint(2<<3 | proto.WireBytes) + b.EncodeStringBytes(x.AgentUri) + case *ImportAgentRequest_AgentContent: + b.EncodeVarint(3<<3 | proto.WireBytes) + b.EncodeRawBytes(x.AgentContent) + case nil: + default: + return fmt.Errorf("ImportAgentRequest.Agent has unexpected type %T", x) + } + return nil +} + +func _ImportAgentRequest_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*ImportAgentRequest) + switch tag { + case 2: // agent.agent_uri + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeStringBytes() + m.Agent = &ImportAgentRequest_AgentUri{x} + return true, err + case 3: // agent.agent_content + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeRawBytes(true) + m.Agent = &ImportAgentRequest_AgentContent{x} + return true, err + default: + return false, nil + } +} + +func _ImportAgentRequest_OneofSizer(msg proto.Message) (n int) { + m := msg.(*ImportAgentRequest) + // agent + switch x := m.Agent.(type) { + case *ImportAgentRequest_AgentUri: + n += proto.SizeVarint(2<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.AgentUri))) + n += len(x.AgentUri) + case *ImportAgentRequest_AgentContent: + n += proto.SizeVarint(3<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.AgentContent))) + n += len(x.AgentContent) + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +// The request message for +// [Agents.RestoreAgent][google.cloud.dialogflow.v2beta1.Agents.RestoreAgent]. +type RestoreAgentRequest struct { + // Required. The project that the agent to restore is associated with. + // Format: `projects/`. + Parent string `protobuf:"bytes,1,opt,name=parent" json:"parent,omitempty"` + // Required. The agent to restore. + // + // Types that are valid to be assigned to Agent: + // *RestoreAgentRequest_AgentUri + // *RestoreAgentRequest_AgentContent + Agent isRestoreAgentRequest_Agent `protobuf_oneof:"agent"` +} + +func (m *RestoreAgentRequest) Reset() { *m = RestoreAgentRequest{} } +func (m *RestoreAgentRequest) String() string { return proto.CompactTextString(m) } +func (*RestoreAgentRequest) ProtoMessage() {} +func (*RestoreAgentRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } + +type isRestoreAgentRequest_Agent interface { + isRestoreAgentRequest_Agent() +} + +type RestoreAgentRequest_AgentUri struct { + AgentUri string `protobuf:"bytes,2,opt,name=agent_uri,json=agentUri,oneof"` +} +type RestoreAgentRequest_AgentContent struct { + AgentContent []byte `protobuf:"bytes,3,opt,name=agent_content,json=agentContent,proto3,oneof"` +} + +func (*RestoreAgentRequest_AgentUri) isRestoreAgentRequest_Agent() {} +func (*RestoreAgentRequest_AgentContent) isRestoreAgentRequest_Agent() {} + +func (m *RestoreAgentRequest) GetAgent() isRestoreAgentRequest_Agent { + if m != nil { + return m.Agent + } + return nil +} + +func (m *RestoreAgentRequest) GetParent() string { + if m != nil { + return m.Parent + } + return "" +} + +func (m *RestoreAgentRequest) GetAgentUri() string { + if x, ok := m.GetAgent().(*RestoreAgentRequest_AgentUri); ok { + return x.AgentUri + } + return "" +} + +func (m *RestoreAgentRequest) GetAgentContent() []byte { + if x, ok := m.GetAgent().(*RestoreAgentRequest_AgentContent); ok { + return x.AgentContent + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*RestoreAgentRequest) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _RestoreAgentRequest_OneofMarshaler, _RestoreAgentRequest_OneofUnmarshaler, _RestoreAgentRequest_OneofSizer, []interface{}{ + (*RestoreAgentRequest_AgentUri)(nil), + (*RestoreAgentRequest_AgentContent)(nil), + } +} + +func _RestoreAgentRequest_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*RestoreAgentRequest) + // agent + switch x := m.Agent.(type) { + case *RestoreAgentRequest_AgentUri: + b.EncodeVarint(2<<3 | proto.WireBytes) + b.EncodeStringBytes(x.AgentUri) + case *RestoreAgentRequest_AgentContent: + b.EncodeVarint(3<<3 | proto.WireBytes) + b.EncodeRawBytes(x.AgentContent) + case nil: + default: + return fmt.Errorf("RestoreAgentRequest.Agent has unexpected type %T", x) + } + return nil +} + +func _RestoreAgentRequest_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*RestoreAgentRequest) + switch tag { + case 2: // agent.agent_uri + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeStringBytes() + m.Agent = &RestoreAgentRequest_AgentUri{x} + return true, err + case 3: // agent.agent_content + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeRawBytes(true) + m.Agent = &RestoreAgentRequest_AgentContent{x} + return true, err + default: + return false, nil + } +} + +func _RestoreAgentRequest_OneofSizer(msg proto.Message) (n int) { + m := msg.(*RestoreAgentRequest) + // agent + switch x := m.Agent.(type) { + case *RestoreAgentRequest_AgentUri: + n += proto.SizeVarint(2<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.AgentUri))) + n += len(x.AgentUri) + case *RestoreAgentRequest_AgentContent: + n += proto.SizeVarint(3<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.AgentContent))) + n += len(x.AgentContent) + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +func init() { + proto.RegisterType((*Agent)(nil), "google.cloud.dialogflow.v2beta1.Agent") + proto.RegisterType((*GetAgentRequest)(nil), "google.cloud.dialogflow.v2beta1.GetAgentRequest") + proto.RegisterType((*SearchAgentsRequest)(nil), "google.cloud.dialogflow.v2beta1.SearchAgentsRequest") + proto.RegisterType((*SearchAgentsResponse)(nil), "google.cloud.dialogflow.v2beta1.SearchAgentsResponse") + proto.RegisterType((*TrainAgentRequest)(nil), "google.cloud.dialogflow.v2beta1.TrainAgentRequest") + proto.RegisterType((*ExportAgentRequest)(nil), "google.cloud.dialogflow.v2beta1.ExportAgentRequest") + proto.RegisterType((*ExportAgentResponse)(nil), "google.cloud.dialogflow.v2beta1.ExportAgentResponse") + proto.RegisterType((*ImportAgentRequest)(nil), "google.cloud.dialogflow.v2beta1.ImportAgentRequest") + proto.RegisterType((*RestoreAgentRequest)(nil), "google.cloud.dialogflow.v2beta1.RestoreAgentRequest") + proto.RegisterEnum("google.cloud.dialogflow.v2beta1.Agent_MatchMode", Agent_MatchMode_name, Agent_MatchMode_value) +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// Client API for Agents service + +type AgentsClient interface { + // Retrieves the specified agent. + GetAgent(ctx context.Context, in *GetAgentRequest, opts ...grpc.CallOption) (*Agent, error) + // Returns the list of agents. + // + // Since there is at most one conversational agent per project, this method is + // useful primarily for listing all agents across projects the caller has + // access to. One can achieve that with a wildcard project collection id "-". + // Refer to [List + // Sub-Collections](https://cloud.google.com/apis/design/design_patterns#list_sub-collections). + SearchAgents(ctx context.Context, in *SearchAgentsRequest, opts ...grpc.CallOption) (*SearchAgentsResponse, error) + // Trains the specified agent. + // + // + // Operation + TrainAgent(ctx context.Context, in *TrainAgentRequest, opts ...grpc.CallOption) (*google_longrunning.Operation, error) + // Exports the specified agent to a ZIP file. + // + // + // Operation + ExportAgent(ctx context.Context, in *ExportAgentRequest, opts ...grpc.CallOption) (*google_longrunning.Operation, error) + // Imports the specified agent from a ZIP file. + // + // Uploads new intents and entity types without deleting the existing ones. + // Intents and entity types with the same name are replaced with the new + // versions from ImportAgentRequest. + // + // + // Operation + ImportAgent(ctx context.Context, in *ImportAgentRequest, opts ...grpc.CallOption) (*google_longrunning.Operation, error) + // Restores the specified agent from a ZIP file. + // + // Replaces the current agent version with a new one. All the intents and + // entity types in the older version are deleted. + // + // + // Operation + RestoreAgent(ctx context.Context, in *RestoreAgentRequest, opts ...grpc.CallOption) (*google_longrunning.Operation, error) +} + +type agentsClient struct { + cc *grpc.ClientConn +} + +func NewAgentsClient(cc *grpc.ClientConn) AgentsClient { + return &agentsClient{cc} +} + +func (c *agentsClient) GetAgent(ctx context.Context, in *GetAgentRequest, opts ...grpc.CallOption) (*Agent, error) { + out := new(Agent) + err := grpc.Invoke(ctx, "/google.cloud.dialogflow.v2beta1.Agents/GetAgent", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *agentsClient) SearchAgents(ctx context.Context, in *SearchAgentsRequest, opts ...grpc.CallOption) (*SearchAgentsResponse, error) { + out := new(SearchAgentsResponse) + err := grpc.Invoke(ctx, "/google.cloud.dialogflow.v2beta1.Agents/SearchAgents", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *agentsClient) TrainAgent(ctx context.Context, in *TrainAgentRequest, opts ...grpc.CallOption) (*google_longrunning.Operation, error) { + out := new(google_longrunning.Operation) + err := grpc.Invoke(ctx, "/google.cloud.dialogflow.v2beta1.Agents/TrainAgent", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *agentsClient) ExportAgent(ctx context.Context, in *ExportAgentRequest, opts ...grpc.CallOption) (*google_longrunning.Operation, error) { + out := new(google_longrunning.Operation) + err := grpc.Invoke(ctx, "/google.cloud.dialogflow.v2beta1.Agents/ExportAgent", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *agentsClient) ImportAgent(ctx context.Context, in *ImportAgentRequest, opts ...grpc.CallOption) (*google_longrunning.Operation, error) { + out := new(google_longrunning.Operation) + err := grpc.Invoke(ctx, "/google.cloud.dialogflow.v2beta1.Agents/ImportAgent", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *agentsClient) RestoreAgent(ctx context.Context, in *RestoreAgentRequest, opts ...grpc.CallOption) (*google_longrunning.Operation, error) { + out := new(google_longrunning.Operation) + err := grpc.Invoke(ctx, "/google.cloud.dialogflow.v2beta1.Agents/RestoreAgent", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for Agents service + +type AgentsServer interface { + // Retrieves the specified agent. + GetAgent(context.Context, *GetAgentRequest) (*Agent, error) + // Returns the list of agents. + // + // Since there is at most one conversational agent per project, this method is + // useful primarily for listing all agents across projects the caller has + // access to. One can achieve that with a wildcard project collection id "-". + // Refer to [List + // Sub-Collections](https://cloud.google.com/apis/design/design_patterns#list_sub-collections). + SearchAgents(context.Context, *SearchAgentsRequest) (*SearchAgentsResponse, error) + // Trains the specified agent. + // + // + // Operation + TrainAgent(context.Context, *TrainAgentRequest) (*google_longrunning.Operation, error) + // Exports the specified agent to a ZIP file. + // + // + // Operation + ExportAgent(context.Context, *ExportAgentRequest) (*google_longrunning.Operation, error) + // Imports the specified agent from a ZIP file. + // + // Uploads new intents and entity types without deleting the existing ones. + // Intents and entity types with the same name are replaced with the new + // versions from ImportAgentRequest. + // + // + // Operation + ImportAgent(context.Context, *ImportAgentRequest) (*google_longrunning.Operation, error) + // Restores the specified agent from a ZIP file. + // + // Replaces the current agent version with a new one. All the intents and + // entity types in the older version are deleted. + // + // + // Operation + RestoreAgent(context.Context, *RestoreAgentRequest) (*google_longrunning.Operation, error) +} + +func RegisterAgentsServer(s *grpc.Server, srv AgentsServer) { + s.RegisterService(&_Agents_serviceDesc, srv) +} + +func _Agents_GetAgent_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetAgentRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AgentsServer).GetAgent(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.dialogflow.v2beta1.Agents/GetAgent", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AgentsServer).GetAgent(ctx, req.(*GetAgentRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Agents_SearchAgents_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SearchAgentsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AgentsServer).SearchAgents(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.dialogflow.v2beta1.Agents/SearchAgents", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AgentsServer).SearchAgents(ctx, req.(*SearchAgentsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Agents_TrainAgent_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(TrainAgentRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AgentsServer).TrainAgent(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.dialogflow.v2beta1.Agents/TrainAgent", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AgentsServer).TrainAgent(ctx, req.(*TrainAgentRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Agents_ExportAgent_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ExportAgentRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AgentsServer).ExportAgent(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.dialogflow.v2beta1.Agents/ExportAgent", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AgentsServer).ExportAgent(ctx, req.(*ExportAgentRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Agents_ImportAgent_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ImportAgentRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AgentsServer).ImportAgent(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.dialogflow.v2beta1.Agents/ImportAgent", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AgentsServer).ImportAgent(ctx, req.(*ImportAgentRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Agents_RestoreAgent_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RestoreAgentRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AgentsServer).RestoreAgent(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.dialogflow.v2beta1.Agents/RestoreAgent", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AgentsServer).RestoreAgent(ctx, req.(*RestoreAgentRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Agents_serviceDesc = grpc.ServiceDesc{ + ServiceName: "google.cloud.dialogflow.v2beta1.Agents", + HandlerType: (*AgentsServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetAgent", + Handler: _Agents_GetAgent_Handler, + }, + { + MethodName: "SearchAgents", + Handler: _Agents_SearchAgents_Handler, + }, + { + MethodName: "TrainAgent", + Handler: _Agents_TrainAgent_Handler, + }, + { + MethodName: "ExportAgent", + Handler: _Agents_ExportAgent_Handler, + }, + { + MethodName: "ImportAgent", + Handler: _Agents_ImportAgent_Handler, + }, + { + MethodName: "RestoreAgent", + Handler: _Agents_RestoreAgent_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "google/cloud/dialogflow/v2beta1/agent.proto", +} + +func init() { proto.RegisterFile("google/cloud/dialogflow/v2beta1/agent.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 975 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x56, 0x41, 0x6f, 0xdc, 0x44, + 0x14, 0xae, 0x37, 0x4d, 0xb2, 0xfb, 0x92, 0xb4, 0xe9, 0x84, 0x06, 0x6b, 0xdb, 0xa8, 0x8b, 0x4b, + 0xab, 0xed, 0x46, 0xd8, 0x74, 0xd3, 0x4a, 0x10, 0x04, 0x52, 0xb3, 0x9b, 0x36, 0x2b, 0x65, 0x93, + 0xc8, 0x49, 0x2a, 0xb5, 0x17, 0x6b, 0x62, 0xcf, 0x3a, 0x43, 0xed, 0x19, 0xe3, 0x99, 0x2d, 0x6d, + 0x0a, 0x1c, 0xf8, 0x05, 0x48, 0x20, 0x21, 0x38, 0x72, 0x42, 0x1c, 0x38, 0xf1, 0x4f, 0xf8, 0x0b, + 0xfc, 0x08, 0x8e, 0xc8, 0x63, 0x6f, 0xd6, 0x9b, 0xb4, 0xb5, 0x91, 0x90, 0xb8, 0xd9, 0xdf, 0xfb, + 0xde, 0x7b, 0xdf, 0xcc, 0x7c, 0x4f, 0x33, 0xb0, 0xea, 0x73, 0xee, 0x07, 0xc4, 0x72, 0x03, 0x3e, + 0xf4, 0x2c, 0x8f, 0xe2, 0x80, 0xfb, 0x83, 0x80, 0x7f, 0x69, 0x3d, 0x6f, 0x1f, 0x11, 0x89, 0xef, + 0x5a, 0xd8, 0x27, 0x4c, 0x9a, 0x51, 0xcc, 0x25, 0x47, 0x37, 0x52, 0xb2, 0xa9, 0xc8, 0xe6, 0x98, + 0x6c, 0x66, 0xe4, 0xfa, 0xf5, 0xac, 0x1a, 0x8e, 0xa8, 0x85, 0x19, 0xe3, 0x12, 0x4b, 0xca, 0x99, + 0x48, 0xd3, 0xeb, 0x37, 0xb3, 0x68, 0xc0, 0x99, 0x1f, 0x0f, 0x19, 0xa3, 0xcc, 0xb7, 0x78, 0x44, + 0xe2, 0x09, 0xd2, 0xb5, 0x8c, 0xa4, 0xfe, 0x8e, 0x86, 0x03, 0x8b, 0x84, 0x91, 0x7c, 0x99, 0x05, + 0x1b, 0x67, 0x83, 0x03, 0x4a, 0x02, 0xcf, 0x09, 0xb1, 0x78, 0x96, 0x31, 0xae, 0x9f, 0x65, 0x08, + 0x19, 0x0f, 0xdd, 0x6c, 0x01, 0xc6, 0x4f, 0x17, 0x61, 0xfa, 0x41, 0xb2, 0x20, 0xb4, 0x0c, 0x33, + 0x11, 0x8e, 0x09, 0x93, 0xba, 0xd6, 0xd0, 0x9a, 0x35, 0x3b, 0xfb, 0x43, 0xef, 0xc1, 0xbc, 0x47, + 0x45, 0x14, 0xe0, 0x97, 0x0e, 0xc3, 0x21, 0xd1, 0x2b, 0x2a, 0x3a, 0x97, 0x61, 0x3b, 0x38, 0x24, + 0xa8, 0x0d, 0x57, 0x3d, 0x32, 0xc0, 0xc3, 0x40, 0x3a, 0x01, 0x66, 0xfe, 0x10, 0xfb, 0xc4, 0x71, + 0xb9, 0x47, 0xf4, 0x29, 0xc5, 0x5d, 0xca, 0x82, 0xdb, 0x59, 0xac, 0xc3, 0x3d, 0x82, 0x3e, 0x02, + 0x5d, 0x0c, 0xa3, 0x88, 0xc7, 0x92, 0x78, 0x93, 0x59, 0x42, 0xbf, 0xd8, 0x98, 0x6a, 0xd6, 0xec, + 0xe5, 0xd3, 0x78, 0x3e, 0x51, 0xa0, 0x6b, 0x50, 0x93, 0x34, 0x24, 0xce, 0x09, 0x67, 0x44, 0x9f, + 0x56, 0x1d, 0xaa, 0x09, 0xf0, 0x94, 0x33, 0x82, 0x1a, 0x30, 0xe7, 0x11, 0xe1, 0xc6, 0x34, 0x4a, + 0xb6, 0x50, 0x9f, 0xc9, 0xc4, 0x8e, 0x21, 0xb4, 0x02, 0x80, 0x9f, 0x63, 0x89, 0x63, 0x67, 0x18, + 0x53, 0x7d, 0x56, 0x11, 0x6a, 0x29, 0x72, 0x18, 0x53, 0x74, 0x0b, 0x2e, 0x11, 0x86, 0x8f, 0x02, + 0xe2, 0x04, 0xdc, 0xf7, 0x29, 0xf3, 0xf5, 0x6a, 0x43, 0x6b, 0x56, 0xed, 0x85, 0x14, 0xdd, 0x4e, + 0x41, 0xb4, 0x0b, 0x10, 0x62, 0xe9, 0x1e, 0x3b, 0x61, 0xb2, 0xce, 0x5a, 0x43, 0x6b, 0x5e, 0x6a, + 0x7f, 0x68, 0x16, 0xb8, 0xc1, 0x54, 0x3b, 0x6d, 0xf6, 0x93, 0xc4, 0x3e, 0xf7, 0x88, 0x5d, 0x0b, + 0x47, 0x9f, 0xe8, 0x63, 0xd0, 0xdd, 0x00, 0x0b, 0x41, 0x07, 0xd4, 0x55, 0xc7, 0xef, 0xc8, 0xe3, + 0x98, 0x88, 0x63, 0x1e, 0x78, 0x3a, 0x34, 0xb4, 0x66, 0xc5, 0x7e, 0x77, 0x32, 0x7e, 0x30, 0x0a, + 0x1b, 0x8f, 0xa1, 0x76, 0x5a, 0x12, 0xd5, 0x61, 0xb9, 0xff, 0xe0, 0xa0, 0xb3, 0xe5, 0xf4, 0x77, + 0xbb, 0x9b, 0xce, 0xe1, 0xce, 0xfe, 0xde, 0x66, 0xa7, 0xf7, 0xb0, 0xb7, 0xd9, 0x5d, 0xbc, 0x80, + 0xae, 0xc2, 0x95, 0x5c, 0x6c, 0xeb, 0xc9, 0x86, 0xdd, 0xeb, 0x2e, 0x6a, 0x68, 0x19, 0x50, 0x0e, + 0xee, 0x6f, 0x3b, 0xbb, 0x3b, 0xdb, 0x4f, 0x16, 0x2b, 0xc6, 0x1d, 0xb8, 0xfc, 0x88, 0x48, 0xa5, + 0xd9, 0x26, 0x5f, 0x0c, 0x89, 0x78, 0xa3, 0x49, 0x0c, 0x0a, 0x4b, 0xfb, 0x04, 0xc7, 0xee, 0xb1, + 0x62, 0x8b, 0x02, 0x7a, 0x72, 0x84, 0x51, 0x72, 0xdc, 0x82, 0x9e, 0xa4, 0x86, 0x9a, 0xb6, 0xab, + 0x09, 0xb0, 0x4f, 0x4f, 0x48, 0x72, 0x40, 0x2a, 0x28, 0xf9, 0x33, 0xc2, 0x32, 0x0b, 0x29, 0xfa, + 0x41, 0x02, 0x18, 0xdf, 0xc0, 0x3b, 0x93, 0xad, 0x44, 0xc4, 0x99, 0x20, 0xe8, 0x33, 0x98, 0x51, + 0x93, 0x29, 0x74, 0xad, 0x31, 0xd5, 0x9c, 0x6b, 0xdf, 0x2e, 0x77, 0x1a, 0x76, 0x96, 0x85, 0x6e, + 0xc3, 0x65, 0x46, 0x5e, 0x48, 0x27, 0xd7, 0x3b, 0xb5, 0xfa, 0x42, 0x02, 0xef, 0x9d, 0xf6, 0x5f, + 0x85, 0x2b, 0x07, 0x31, 0xa6, 0xac, 0xd4, 0xbe, 0xf4, 0x00, 0x6d, 0xbe, 0x48, 0x4c, 0x5c, 0x86, + 0x9d, 0x6c, 0x8b, 0x12, 0xa3, 0x9c, 0x99, 0x36, 0xaf, 0x2a, 0xe0, 0x30, 0xa6, 0x86, 0x07, 0x4b, + 0x13, 0xa5, 0xb2, 0x65, 0xaf, 0xe4, 0x73, 0x54, 0xb9, 0xad, 0x0b, 0xe3, 0x2c, 0x74, 0x0b, 0x16, + 0xd2, 0xb0, 0xcb, 0x99, 0x4c, 0x3a, 0x26, 0x65, 0xe7, 0xb7, 0x2e, 0xd8, 0xf3, 0x0a, 0xee, 0xa4, + 0xe8, 0xc6, 0x2c, 0x4c, 0xab, 0x7f, 0xe3, 0x15, 0xa0, 0x5e, 0x58, 0x5a, 0xf0, 0xca, 0x39, 0xc1, + 0x6f, 0x6f, 0x3e, 0xf5, 0xf6, 0xe6, 0x5f, 0xc1, 0x92, 0x4d, 0x84, 0xe4, 0x31, 0xf9, 0x1f, 0xba, + 0xb7, 0xff, 0x98, 0x85, 0x99, 0xd4, 0x53, 0xe8, 0x3b, 0x0d, 0xaa, 0x23, 0xeb, 0xa3, 0xe2, 0xb1, + 0x3e, 0x33, 0x25, 0xf5, 0x92, 0xd6, 0x33, 0x5a, 0xdf, 0xfe, 0xf9, 0xd7, 0xf7, 0x95, 0xf7, 0x91, + 0x71, 0x7a, 0xb7, 0xbc, 0x4a, 0x97, 0xf6, 0x69, 0x14, 0xf3, 0xcf, 0x89, 0x2b, 0x85, 0xd5, 0xfa, + 0x3a, 0xbd, 0x6f, 0xd0, 0xef, 0x1a, 0xcc, 0xe7, 0x7d, 0x8f, 0xee, 0x15, 0x36, 0x79, 0xcd, 0x44, + 0xd6, 0xef, 0xff, 0xcb, 0xac, 0xd4, 0x65, 0xc6, 0x5d, 0xa5, 0x74, 0x15, 0xdd, 0x29, 0x56, 0xba, + 0x2e, 0x54, 0x01, 0xf4, 0x83, 0x06, 0x30, 0x1e, 0x14, 0xd4, 0x2e, 0x6c, 0x7c, 0x6e, 0xaa, 0xea, + 0x2b, 0xa3, 0x9c, 0xdc, 0xfd, 0x68, 0xee, 0x8e, 0xee, 0x47, 0x63, 0x4d, 0x89, 0xfa, 0xc0, 0x68, + 0x96, 0x10, 0x25, 0x93, 0xe2, 0xeb, 0x5a, 0x0b, 0xfd, 0xa8, 0xc1, 0x5c, 0x6e, 0x8e, 0xd0, 0x5a, + 0xa1, 0xae, 0xf3, 0x03, 0x5c, 0x24, 0xec, 0x9e, 0x12, 0x66, 0x1a, 0x65, 0x76, 0x8b, 0xa8, 0xea, + 0x23, 0x65, 0xb9, 0xd9, 0x2b, 0xa1, 0xec, 0xfc, 0xa4, 0xfe, 0x97, 0xca, 0x68, 0x38, 0x52, 0xf6, + 0xb3, 0x06, 0xf3, 0xf9, 0xc1, 0x2c, 0xe1, 0xbd, 0xd7, 0xcc, 0x71, 0x91, 0xb6, 0xfb, 0x4a, 0x9b, + 0x65, 0xb4, 0x4a, 0x68, 0x8b, 0xd3, 0xf2, 0xeb, 0x5a, 0x6b, 0xe3, 0x57, 0x0d, 0x6e, 0xba, 0x3c, + 0x2c, 0x52, 0xb4, 0x01, 0x4a, 0xcb, 0x5e, 0xf2, 0xea, 0xd9, 0xd3, 0x9e, 0xf6, 0x32, 0xba, 0xcf, + 0x93, 0xb7, 0x87, 0xc9, 0x63, 0xdf, 0xf2, 0x09, 0x53, 0x6f, 0x22, 0x2b, 0x0d, 0xe1, 0x88, 0x8a, + 0x37, 0x3e, 0x02, 0x3f, 0x19, 0x43, 0x7f, 0x6b, 0xda, 0x2f, 0x95, 0x4a, 0xf7, 0xe1, 0x6f, 0x95, + 0x1b, 0x8f, 0xd2, 0x9a, 0x1d, 0x25, 0xa1, 0x3b, 0x96, 0xf0, 0x38, 0x4d, 0x3a, 0x9a, 0x51, 0xf5, + 0xd7, 0xfe, 0x09, 0x00, 0x00, 0xff, 0xff, 0x35, 0x4d, 0xe2, 0x83, 0x63, 0x0a, 0x00, 0x00, +} diff --git a/vendor/google.golang.org/genproto/googleapis/cloud/dialogflow/v2beta1/context.pb.go b/vendor/google.golang.org/genproto/googleapis/cloud/dialogflow/v2beta1/context.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..6fde89dad0ad40ded0a5fb47c46d1b0ddbb8e3ad --- /dev/null +++ b/vendor/google.golang.org/genproto/googleapis/cloud/dialogflow/v2beta1/context.pb.go @@ -0,0 +1,564 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: google/cloud/dialogflow/v2beta1/context.proto + +package dialogflow + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import _ "google.golang.org/genproto/googleapis/api/annotations" +import google_protobuf2 "github.com/golang/protobuf/ptypes/empty" +import google_protobuf3 "google.golang.org/genproto/protobuf/field_mask" +import google_protobuf4 "github.com/golang/protobuf/ptypes/struct" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// Represents a context. +type Context struct { + // Required. The unique identifier of the context. Format: + // `projects//agent/sessions//contexts/`. + // Note: The Context ID is always converted to lowercase. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // Optional. The number of conversational query requests after which the + // context expires. If set to `0` (the default) the context expires + // immediately. Contexts expire automatically after 10 minutes even if there + // are no matching queries. + LifespanCount int32 `protobuf:"varint,2,opt,name=lifespan_count,json=lifespanCount" json:"lifespan_count,omitempty"` + // Optional. The collection of parameters associated with this context. + // Refer to [this doc](https://dialogflow.com/docs/actions-and-parameters) for + // syntax. + Parameters *google_protobuf4.Struct `protobuf:"bytes,3,opt,name=parameters" json:"parameters,omitempty"` +} + +func (m *Context) Reset() { *m = Context{} } +func (m *Context) String() string { return proto.CompactTextString(m) } +func (*Context) ProtoMessage() {} +func (*Context) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} } + +func (m *Context) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *Context) GetLifespanCount() int32 { + if m != nil { + return m.LifespanCount + } + return 0 +} + +func (m *Context) GetParameters() *google_protobuf4.Struct { + if m != nil { + return m.Parameters + } + return nil +} + +// The request message for +// [Contexts.ListContexts][google.cloud.dialogflow.v2beta1.Contexts.ListContexts]. +type ListContextsRequest struct { + // Required. The session to list all contexts from. + // Format: `projects//agent/sessions/`. + Parent string `protobuf:"bytes,1,opt,name=parent" json:"parent,omitempty"` + // Optional. The maximum number of items to return in a single page. By + // default 100 and at most 1000. + PageSize int32 `protobuf:"varint,2,opt,name=page_size,json=pageSize" json:"page_size,omitempty"` + // Optional. The next_page_token value returned from a previous list request. + PageToken string `protobuf:"bytes,3,opt,name=page_token,json=pageToken" json:"page_token,omitempty"` +} + +func (m *ListContextsRequest) Reset() { *m = ListContextsRequest{} } +func (m *ListContextsRequest) String() string { return proto.CompactTextString(m) } +func (*ListContextsRequest) ProtoMessage() {} +func (*ListContextsRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{1} } + +func (m *ListContextsRequest) GetParent() string { + if m != nil { + return m.Parent + } + return "" +} + +func (m *ListContextsRequest) GetPageSize() int32 { + if m != nil { + return m.PageSize + } + return 0 +} + +func (m *ListContextsRequest) GetPageToken() string { + if m != nil { + return m.PageToken + } + return "" +} + +// The response message for +// [Contexts.ListContexts][google.cloud.dialogflow.v2beta1.Contexts.ListContexts]. +type ListContextsResponse struct { + // The list of contexts. There will be a maximum number of items + // returned based on the page_size field in the request. + Contexts []*Context `protobuf:"bytes,1,rep,name=contexts" json:"contexts,omitempty"` + // Token to retrieve the next page of results, or empty if there are no + // more results in the list. + NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken" json:"next_page_token,omitempty"` +} + +func (m *ListContextsResponse) Reset() { *m = ListContextsResponse{} } +func (m *ListContextsResponse) String() string { return proto.CompactTextString(m) } +func (*ListContextsResponse) ProtoMessage() {} +func (*ListContextsResponse) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{2} } + +func (m *ListContextsResponse) GetContexts() []*Context { + if m != nil { + return m.Contexts + } + return nil +} + +func (m *ListContextsResponse) GetNextPageToken() string { + if m != nil { + return m.NextPageToken + } + return "" +} + +// The request message for +// [Contexts.GetContext][google.cloud.dialogflow.v2beta1.Contexts.GetContext]. +type GetContextRequest struct { + // Required. The name of the context. Format: + // `projects//agent/sessions//contexts/`. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` +} + +func (m *GetContextRequest) Reset() { *m = GetContextRequest{} } +func (m *GetContextRequest) String() string { return proto.CompactTextString(m) } +func (*GetContextRequest) ProtoMessage() {} +func (*GetContextRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{3} } + +func (m *GetContextRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +// The request message for +// [Contexts.CreateContext][google.cloud.dialogflow.v2beta1.Contexts.CreateContext]. +type CreateContextRequest struct { + // Required. The session to create a context for. + // Format: `projects//agent/sessions/`. + Parent string `protobuf:"bytes,1,opt,name=parent" json:"parent,omitempty"` + // Required. The context to create. + Context *Context `protobuf:"bytes,2,opt,name=context" json:"context,omitempty"` +} + +func (m *CreateContextRequest) Reset() { *m = CreateContextRequest{} } +func (m *CreateContextRequest) String() string { return proto.CompactTextString(m) } +func (*CreateContextRequest) ProtoMessage() {} +func (*CreateContextRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{4} } + +func (m *CreateContextRequest) GetParent() string { + if m != nil { + return m.Parent + } + return "" +} + +func (m *CreateContextRequest) GetContext() *Context { + if m != nil { + return m.Context + } + return nil +} + +// The request message for +// [Contexts.UpdateContext][google.cloud.dialogflow.v2beta1.Contexts.UpdateContext]. +type UpdateContextRequest struct { + // Required. The context to update. Format: + // `projects//agent/sessions//contexts/`. + Context *Context `protobuf:"bytes,1,opt,name=context" json:"context,omitempty"` + // Optional. The mask to control which fields get updated. + UpdateMask *google_protobuf3.FieldMask `protobuf:"bytes,2,opt,name=update_mask,json=updateMask" json:"update_mask,omitempty"` +} + +func (m *UpdateContextRequest) Reset() { *m = UpdateContextRequest{} } +func (m *UpdateContextRequest) String() string { return proto.CompactTextString(m) } +func (*UpdateContextRequest) ProtoMessage() {} +func (*UpdateContextRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{5} } + +func (m *UpdateContextRequest) GetContext() *Context { + if m != nil { + return m.Context + } + return nil +} + +func (m *UpdateContextRequest) GetUpdateMask() *google_protobuf3.FieldMask { + if m != nil { + return m.UpdateMask + } + return nil +} + +// The request message for +// [Contexts.DeleteContext][google.cloud.dialogflow.v2beta1.Contexts.DeleteContext]. +type DeleteContextRequest struct { + // Required. The name of the context to delete. Format: + // `projects//agent/sessions//contexts/`. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` +} + +func (m *DeleteContextRequest) Reset() { *m = DeleteContextRequest{} } +func (m *DeleteContextRequest) String() string { return proto.CompactTextString(m) } +func (*DeleteContextRequest) ProtoMessage() {} +func (*DeleteContextRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{6} } + +func (m *DeleteContextRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +// The request message for +// [Contexts.DeleteAllContexts][google.cloud.dialogflow.v2beta1.Contexts.DeleteAllContexts]. +type DeleteAllContextsRequest struct { + // Required. The name of the session to delete all contexts from. Format: + // `projects//agent/sessions/`. + Parent string `protobuf:"bytes,1,opt,name=parent" json:"parent,omitempty"` +} + +func (m *DeleteAllContextsRequest) Reset() { *m = DeleteAllContextsRequest{} } +func (m *DeleteAllContextsRequest) String() string { return proto.CompactTextString(m) } +func (*DeleteAllContextsRequest) ProtoMessage() {} +func (*DeleteAllContextsRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{7} } + +func (m *DeleteAllContextsRequest) GetParent() string { + if m != nil { + return m.Parent + } + return "" +} + +func init() { + proto.RegisterType((*Context)(nil), "google.cloud.dialogflow.v2beta1.Context") + proto.RegisterType((*ListContextsRequest)(nil), "google.cloud.dialogflow.v2beta1.ListContextsRequest") + proto.RegisterType((*ListContextsResponse)(nil), "google.cloud.dialogflow.v2beta1.ListContextsResponse") + proto.RegisterType((*GetContextRequest)(nil), "google.cloud.dialogflow.v2beta1.GetContextRequest") + proto.RegisterType((*CreateContextRequest)(nil), "google.cloud.dialogflow.v2beta1.CreateContextRequest") + proto.RegisterType((*UpdateContextRequest)(nil), "google.cloud.dialogflow.v2beta1.UpdateContextRequest") + proto.RegisterType((*DeleteContextRequest)(nil), "google.cloud.dialogflow.v2beta1.DeleteContextRequest") + proto.RegisterType((*DeleteAllContextsRequest)(nil), "google.cloud.dialogflow.v2beta1.DeleteAllContextsRequest") +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// Client API for Contexts service + +type ContextsClient interface { + // Returns the list of all contexts in the specified session. + ListContexts(ctx context.Context, in *ListContextsRequest, opts ...grpc.CallOption) (*ListContextsResponse, error) + // Retrieves the specified context. + GetContext(ctx context.Context, in *GetContextRequest, opts ...grpc.CallOption) (*Context, error) + // Creates a context. + CreateContext(ctx context.Context, in *CreateContextRequest, opts ...grpc.CallOption) (*Context, error) + // Updates the specified context. + UpdateContext(ctx context.Context, in *UpdateContextRequest, opts ...grpc.CallOption) (*Context, error) + // Deletes the specified context. + DeleteContext(ctx context.Context, in *DeleteContextRequest, opts ...grpc.CallOption) (*google_protobuf2.Empty, error) + // Deletes all active contexts in the specified session. + DeleteAllContexts(ctx context.Context, in *DeleteAllContextsRequest, opts ...grpc.CallOption) (*google_protobuf2.Empty, error) +} + +type contextsClient struct { + cc *grpc.ClientConn +} + +func NewContextsClient(cc *grpc.ClientConn) ContextsClient { + return &contextsClient{cc} +} + +func (c *contextsClient) ListContexts(ctx context.Context, in *ListContextsRequest, opts ...grpc.CallOption) (*ListContextsResponse, error) { + out := new(ListContextsResponse) + err := grpc.Invoke(ctx, "/google.cloud.dialogflow.v2beta1.Contexts/ListContexts", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *contextsClient) GetContext(ctx context.Context, in *GetContextRequest, opts ...grpc.CallOption) (*Context, error) { + out := new(Context) + err := grpc.Invoke(ctx, "/google.cloud.dialogflow.v2beta1.Contexts/GetContext", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *contextsClient) CreateContext(ctx context.Context, in *CreateContextRequest, opts ...grpc.CallOption) (*Context, error) { + out := new(Context) + err := grpc.Invoke(ctx, "/google.cloud.dialogflow.v2beta1.Contexts/CreateContext", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *contextsClient) UpdateContext(ctx context.Context, in *UpdateContextRequest, opts ...grpc.CallOption) (*Context, error) { + out := new(Context) + err := grpc.Invoke(ctx, "/google.cloud.dialogflow.v2beta1.Contexts/UpdateContext", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *contextsClient) DeleteContext(ctx context.Context, in *DeleteContextRequest, opts ...grpc.CallOption) (*google_protobuf2.Empty, error) { + out := new(google_protobuf2.Empty) + err := grpc.Invoke(ctx, "/google.cloud.dialogflow.v2beta1.Contexts/DeleteContext", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *contextsClient) DeleteAllContexts(ctx context.Context, in *DeleteAllContextsRequest, opts ...grpc.CallOption) (*google_protobuf2.Empty, error) { + out := new(google_protobuf2.Empty) + err := grpc.Invoke(ctx, "/google.cloud.dialogflow.v2beta1.Contexts/DeleteAllContexts", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for Contexts service + +type ContextsServer interface { + // Returns the list of all contexts in the specified session. + ListContexts(context.Context, *ListContextsRequest) (*ListContextsResponse, error) + // Retrieves the specified context. + GetContext(context.Context, *GetContextRequest) (*Context, error) + // Creates a context. + CreateContext(context.Context, *CreateContextRequest) (*Context, error) + // Updates the specified context. + UpdateContext(context.Context, *UpdateContextRequest) (*Context, error) + // Deletes the specified context. + DeleteContext(context.Context, *DeleteContextRequest) (*google_protobuf2.Empty, error) + // Deletes all active contexts in the specified session. + DeleteAllContexts(context.Context, *DeleteAllContextsRequest) (*google_protobuf2.Empty, error) +} + +func RegisterContextsServer(s *grpc.Server, srv ContextsServer) { + s.RegisterService(&_Contexts_serviceDesc, srv) +} + +func _Contexts_ListContexts_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListContextsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ContextsServer).ListContexts(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.dialogflow.v2beta1.Contexts/ListContexts", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ContextsServer).ListContexts(ctx, req.(*ListContextsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Contexts_GetContext_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetContextRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ContextsServer).GetContext(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.dialogflow.v2beta1.Contexts/GetContext", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ContextsServer).GetContext(ctx, req.(*GetContextRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Contexts_CreateContext_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateContextRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ContextsServer).CreateContext(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.dialogflow.v2beta1.Contexts/CreateContext", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ContextsServer).CreateContext(ctx, req.(*CreateContextRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Contexts_UpdateContext_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdateContextRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ContextsServer).UpdateContext(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.dialogflow.v2beta1.Contexts/UpdateContext", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ContextsServer).UpdateContext(ctx, req.(*UpdateContextRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Contexts_DeleteContext_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteContextRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ContextsServer).DeleteContext(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.dialogflow.v2beta1.Contexts/DeleteContext", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ContextsServer).DeleteContext(ctx, req.(*DeleteContextRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Contexts_DeleteAllContexts_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteAllContextsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ContextsServer).DeleteAllContexts(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.dialogflow.v2beta1.Contexts/DeleteAllContexts", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ContextsServer).DeleteAllContexts(ctx, req.(*DeleteAllContextsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Contexts_serviceDesc = grpc.ServiceDesc{ + ServiceName: "google.cloud.dialogflow.v2beta1.Contexts", + HandlerType: (*ContextsServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "ListContexts", + Handler: _Contexts_ListContexts_Handler, + }, + { + MethodName: "GetContext", + Handler: _Contexts_GetContext_Handler, + }, + { + MethodName: "CreateContext", + Handler: _Contexts_CreateContext_Handler, + }, + { + MethodName: "UpdateContext", + Handler: _Contexts_UpdateContext_Handler, + }, + { + MethodName: "DeleteContext", + Handler: _Contexts_DeleteContext_Handler, + }, + { + MethodName: "DeleteAllContexts", + Handler: _Contexts_DeleteAllContexts_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "google/cloud/dialogflow/v2beta1/context.proto", +} + +func init() { proto.RegisterFile("google/cloud/dialogflow/v2beta1/context.proto", fileDescriptor1) } + +var fileDescriptor1 = []byte{ + // 731 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x96, 0xcd, 0x6e, 0xd3, 0x4a, + 0x14, 0xc7, 0x35, 0xe9, 0xbd, 0x6d, 0x7a, 0xda, 0xdc, 0xab, 0x0e, 0x51, 0x89, 0xd2, 0xa2, 0x46, + 0x46, 0x40, 0x14, 0x09, 0x5b, 0x84, 0x6f, 0x2a, 0x2a, 0xb5, 0x09, 0xad, 0x2a, 0x81, 0xa8, 0x52, + 0x60, 0xc1, 0x26, 0x9a, 0x26, 0x27, 0x96, 0xa9, 0xe3, 0x31, 0x9e, 0x09, 0x94, 0xa2, 0x6e, 0x10, + 0x6f, 0xc0, 0x82, 0x1d, 0x0b, 0x16, 0x2c, 0xfa, 0x06, 0x88, 0x05, 0xe2, 0x19, 0x78, 0x05, 0x1e, + 0x82, 0x25, 0xf2, 0x78, 0x9c, 0x8f, 0x26, 0x25, 0x71, 0x77, 0xf1, 0xcc, 0x7f, 0xce, 0xf9, 0x9d, + 0x33, 0xff, 0x63, 0x07, 0xae, 0xda, 0x9c, 0xdb, 0x2e, 0x5a, 0x0d, 0x97, 0x77, 0x9a, 0x56, 0xd3, + 0x61, 0x2e, 0xb7, 0x5b, 0x2e, 0x7f, 0x6d, 0xbd, 0x2a, 0xef, 0xa1, 0x64, 0xd7, 0xac, 0x06, 0xf7, + 0x24, 0x1e, 0x48, 0xd3, 0x0f, 0xb8, 0xe4, 0x74, 0x25, 0x92, 0x9b, 0x4a, 0x6e, 0xf6, 0xe4, 0xa6, + 0x96, 0xe7, 0x97, 0x75, 0x3c, 0xe6, 0x3b, 0x16, 0xf3, 0x3c, 0x2e, 0x99, 0x74, 0xb8, 0x27, 0xa2, + 0xe3, 0xf9, 0x25, 0xbd, 0xab, 0x9e, 0xf6, 0x3a, 0x2d, 0x0b, 0xdb, 0xbe, 0x7c, 0xa3, 0x37, 0x0b, + 0x27, 0x37, 0x5b, 0x0e, 0xba, 0xcd, 0x7a, 0x9b, 0x89, 0x7d, 0xad, 0x58, 0x3e, 0xa9, 0x10, 0x32, + 0xe8, 0x34, 0x34, 0x9b, 0x71, 0x04, 0x33, 0x95, 0x08, 0x96, 0x52, 0xf8, 0xc7, 0x63, 0x6d, 0xcc, + 0x91, 0x02, 0x29, 0xce, 0xd6, 0xd4, 0x6f, 0x7a, 0x09, 0xfe, 0x73, 0x9d, 0x16, 0x0a, 0x9f, 0x79, + 0xf5, 0x06, 0xef, 0x78, 0x32, 0x97, 0x2a, 0x90, 0xe2, 0xbf, 0xb5, 0x4c, 0xbc, 0x5a, 0x09, 0x17, + 0xe9, 0x6d, 0x00, 0x9f, 0x05, 0xac, 0x8d, 0x12, 0x03, 0x91, 0x9b, 0x2a, 0x90, 0xe2, 0x5c, 0xf9, + 0xbc, 0xa9, 0xcb, 0x8e, 0x13, 0x9b, 0xbb, 0x2a, 0x71, 0xad, 0x4f, 0x6a, 0x38, 0x70, 0xee, 0xa1, + 0x23, 0xa4, 0x46, 0x10, 0x35, 0x7c, 0xd9, 0x41, 0x21, 0xe9, 0x22, 0x4c, 0xfb, 0x2c, 0x40, 0x4f, + 0x6a, 0x18, 0xfd, 0x44, 0x97, 0x60, 0xd6, 0x67, 0x36, 0xd6, 0x85, 0x73, 0x88, 0x9a, 0x24, 0x1d, + 0x2e, 0xec, 0x3a, 0x87, 0x48, 0x2f, 0x84, 0x10, 0x36, 0xd6, 0x25, 0xdf, 0x47, 0x4f, 0x41, 0xcc, + 0xd6, 0x94, 0xfc, 0x49, 0xb8, 0x60, 0xbc, 0x27, 0x90, 0x1d, 0xcc, 0x25, 0x7c, 0xee, 0x09, 0xa4, + 0x55, 0x48, 0xeb, 0xfb, 0x12, 0x39, 0x52, 0x98, 0x2a, 0xce, 0x95, 0x8b, 0xe6, 0x98, 0x1b, 0x33, + 0x75, 0x90, 0x5a, 0xf7, 0x24, 0xbd, 0x0c, 0xff, 0x7b, 0x78, 0x20, 0xeb, 0x7d, 0x08, 0x29, 0x85, + 0x90, 0x09, 0x97, 0x77, 0xba, 0x18, 0x57, 0x60, 0x61, 0x0b, 0x63, 0x88, 0xb8, 0xde, 0x11, 0xad, + 0x37, 0x02, 0xc8, 0x56, 0x02, 0x64, 0x12, 0x4f, 0x68, 0x4f, 0xeb, 0xcd, 0x06, 0xcc, 0x68, 0x18, + 0x95, 0x38, 0x49, 0x15, 0xf1, 0x41, 0xe3, 0x23, 0x81, 0xec, 0x53, 0xbf, 0x39, 0x9c, 0xb4, 0x2f, + 0x38, 0x39, 0x63, 0x70, 0xba, 0x0a, 0x73, 0x1d, 0x15, 0x5b, 0xb9, 0x53, 0x43, 0xe6, 0x87, 0x5c, + 0xb2, 0x19, 0x1a, 0xf8, 0x11, 0x13, 0xfb, 0x35, 0x88, 0xe4, 0xe1, 0x6f, 0xa3, 0x04, 0xd9, 0x2a, + 0xba, 0x38, 0x04, 0x36, 0xaa, 0x73, 0x65, 0xc8, 0x45, 0xda, 0x75, 0xd7, 0x9d, 0xd0, 0x59, 0xe5, + 0xef, 0x69, 0x48, 0xc7, 0x5a, 0xfa, 0x8d, 0xc0, 0x7c, 0xbf, 0x55, 0xe8, 0x8d, 0xb1, 0xd5, 0x8e, + 0x70, 0x71, 0xfe, 0x66, 0xc2, 0x53, 0x91, 0x1f, 0x8d, 0xb5, 0x77, 0x3f, 0x7f, 0x7d, 0x48, 0xdd, + 0xa1, 0xb7, 0xba, 0xaf, 0x93, 0xb7, 0x11, 0xe4, 0x7d, 0x3f, 0xe0, 0x2f, 0xb0, 0x21, 0x85, 0x55, + 0xb2, 0x98, 0x8d, 0x9e, 0xb4, 0x04, 0x0a, 0x11, 0xbe, 0x29, 0xac, 0xd2, 0x91, 0xd5, 0x75, 0xe2, + 0x31, 0x01, 0xe8, 0x59, 0x8c, 0x96, 0xc7, 0x52, 0x0c, 0xf9, 0x31, 0x3f, 0xf1, 0xed, 0x8e, 0x82, + 0x0d, 0xef, 0xe0, 0x6f, 0xa8, 0x5d, 0x52, 0xab, 0x74, 0x44, 0xbf, 0x12, 0xc8, 0x0c, 0xd8, 0x9c, + 0x8e, 0xef, 0xda, 0xa8, 0xb1, 0x48, 0x80, 0xbc, 0xa5, 0x90, 0xd7, 0x8d, 0x33, 0xf6, 0xf7, 0x5e, + 0xd7, 0xd0, 0x3f, 0x08, 0x64, 0x06, 0xa6, 0x65, 0x02, 0xf6, 0x51, 0xd3, 0x95, 0x80, 0xfd, 0xb1, + 0x62, 0xdf, 0x2e, 0xaf, 0xf5, 0xd8, 0xe3, 0x6f, 0x4d, 0x92, 0xb6, 0xf7, 0x6a, 0xf8, 0x44, 0x20, + 0x33, 0x30, 0x58, 0x13, 0xd4, 0x30, 0x6a, 0x10, 0xf3, 0x8b, 0x43, 0x83, 0xfc, 0x20, 0xfc, 0x4c, + 0xc5, 0x06, 0x29, 0x9d, 0xd5, 0x20, 0x5f, 0x08, 0x2c, 0x0c, 0x4d, 0x33, 0xbd, 0x3b, 0x21, 0xe4, + 0xf0, 0x1b, 0x20, 0x09, 0x68, 0x12, 0x5b, 0x6c, 0x1c, 0x13, 0xb8, 0xd8, 0xe0, 0xed, 0x71, 0x60, + 0x1b, 0xf3, 0x1a, 0x68, 0x27, 0x4c, 0xbf, 0x43, 0x9e, 0x6f, 0xeb, 0x03, 0x36, 0x77, 0x99, 0x67, + 0x9b, 0x3c, 0xb0, 0x2d, 0x1b, 0x3d, 0x05, 0x67, 0x45, 0x5b, 0xcc, 0x77, 0xc4, 0xa9, 0xff, 0x35, + 0x56, 0x7b, 0x4b, 0xbf, 0x09, 0xf9, 0x9c, 0x4a, 0x55, 0x37, 0x8f, 0x53, 0x2b, 0x5b, 0x51, 0xcc, + 0x8a, 0x82, 0xa8, 0xf6, 0x20, 0x9e, 0x45, 0x87, 0xf6, 0xa6, 0x55, 0xfc, 0xeb, 0x7f, 0x02, 0x00, + 0x00, 0xff, 0xff, 0x69, 0x4e, 0x3f, 0xa2, 0xca, 0x08, 0x00, 0x00, +} diff --git a/vendor/google.golang.org/genproto/googleapis/cloud/dialogflow/v2beta1/entity_type.pb.go b/vendor/google.golang.org/genproto/googleapis/cloud/dialogflow/v2beta1/entity_type.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..31d44cbf8cd5357e7b86d408ca2a1cbca1cae315 --- /dev/null +++ b/vendor/google.golang.org/genproto/googleapis/cloud/dialogflow/v2beta1/entity_type.pb.go @@ -0,0 +1,1285 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: google/cloud/dialogflow/v2beta1/entity_type.proto + +package dialogflow + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import _ "google.golang.org/genproto/googleapis/api/annotations" +import google_longrunning "google.golang.org/genproto/googleapis/longrunning" +import google_protobuf2 "github.com/golang/protobuf/ptypes/empty" +import google_protobuf3 "google.golang.org/genproto/protobuf/field_mask" +import _ "github.com/golang/protobuf/ptypes/struct" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// Represents kinds of entities. +type EntityType_Kind int32 + +const ( + // Not specified. This value should be never used. + EntityType_KIND_UNSPECIFIED EntityType_Kind = 0 + // Map entity types allow mapping of a group of synonyms to a canonical + // value. + EntityType_KIND_MAP EntityType_Kind = 1 + // List entity types contain a set of entries that do not map to canonical + // values. However, list entity types can contain references to other entity + // types (with or without aliases). + EntityType_KIND_LIST EntityType_Kind = 2 +) + +var EntityType_Kind_name = map[int32]string{ + 0: "KIND_UNSPECIFIED", + 1: "KIND_MAP", + 2: "KIND_LIST", +} +var EntityType_Kind_value = map[string]int32{ + "KIND_UNSPECIFIED": 0, + "KIND_MAP": 1, + "KIND_LIST": 2, +} + +func (x EntityType_Kind) String() string { + return proto.EnumName(EntityType_Kind_name, int32(x)) +} +func (EntityType_Kind) EnumDescriptor() ([]byte, []int) { return fileDescriptor2, []int{0, 0} } + +// Represents different entity type expansion modes. Automated expansion +// allows an agent to recognize values that have not been explicitly listed in +// the entity (for example, new kinds of shopping list items). +type EntityType_AutoExpansionMode int32 + +const ( + // Auto expansion disabled for the entity. + EntityType_AUTO_EXPANSION_MODE_UNSPECIFIED EntityType_AutoExpansionMode = 0 + // Allows an agent to recognize values that have not been explicitly + // listed in the entity. + EntityType_AUTO_EXPANSION_MODE_DEFAULT EntityType_AutoExpansionMode = 1 +) + +var EntityType_AutoExpansionMode_name = map[int32]string{ + 0: "AUTO_EXPANSION_MODE_UNSPECIFIED", + 1: "AUTO_EXPANSION_MODE_DEFAULT", +} +var EntityType_AutoExpansionMode_value = map[string]int32{ + "AUTO_EXPANSION_MODE_UNSPECIFIED": 0, + "AUTO_EXPANSION_MODE_DEFAULT": 1, +} + +func (x EntityType_AutoExpansionMode) String() string { + return proto.EnumName(EntityType_AutoExpansionMode_name, int32(x)) +} +func (EntityType_AutoExpansionMode) EnumDescriptor() ([]byte, []int) { + return fileDescriptor2, []int{0, 1} +} + +// Represents an entity type. +// Entity types serve as a tool for extracting parameter values from natural +// language queries. +type EntityType struct { + // Required for all methods except `create` (`create` populates the name + // automatically. + // The unique identifier of the entity type. Format: + // `projects//agent/entityTypes/`. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // Required. The name of the entity. + DisplayName string `protobuf:"bytes,2,opt,name=display_name,json=displayName" json:"display_name,omitempty"` + // Required. Indicates the kind of entity type. + Kind EntityType_Kind `protobuf:"varint,3,opt,name=kind,enum=google.cloud.dialogflow.v2beta1.EntityType_Kind" json:"kind,omitempty"` + // Optional. Indicates whether the entity type can be automatically + // expanded. + AutoExpansionMode EntityType_AutoExpansionMode `protobuf:"varint,4,opt,name=auto_expansion_mode,json=autoExpansionMode,enum=google.cloud.dialogflow.v2beta1.EntityType_AutoExpansionMode" json:"auto_expansion_mode,omitempty"` + // Optional. The collection of entities associated with the entity type. + Entities []*EntityType_Entity `protobuf:"bytes,6,rep,name=entities" json:"entities,omitempty"` +} + +func (m *EntityType) Reset() { *m = EntityType{} } +func (m *EntityType) String() string { return proto.CompactTextString(m) } +func (*EntityType) ProtoMessage() {} +func (*EntityType) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{0} } + +func (m *EntityType) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *EntityType) GetDisplayName() string { + if m != nil { + return m.DisplayName + } + return "" +} + +func (m *EntityType) GetKind() EntityType_Kind { + if m != nil { + return m.Kind + } + return EntityType_KIND_UNSPECIFIED +} + +func (m *EntityType) GetAutoExpansionMode() EntityType_AutoExpansionMode { + if m != nil { + return m.AutoExpansionMode + } + return EntityType_AUTO_EXPANSION_MODE_UNSPECIFIED +} + +func (m *EntityType) GetEntities() []*EntityType_Entity { + if m != nil { + return m.Entities + } + return nil +} + +// Optional. Represents an entity. +type EntityType_Entity struct { + // Required. + // For `KIND_MAP` entity types: + // A canonical name to be used in place of synonyms. + // For `KIND_LIST` entity types: + // A string that can contain references to other entity types (with or + // without aliases). + Value string `protobuf:"bytes,1,opt,name=value" json:"value,omitempty"` + // Required. A collection of synonyms. For `KIND_LIST` entity types this + // must contain exactly one synonym equal to `value`. + Synonyms []string `protobuf:"bytes,2,rep,name=synonyms" json:"synonyms,omitempty"` +} + +func (m *EntityType_Entity) Reset() { *m = EntityType_Entity{} } +func (m *EntityType_Entity) String() string { return proto.CompactTextString(m) } +func (*EntityType_Entity) ProtoMessage() {} +func (*EntityType_Entity) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{0, 0} } + +func (m *EntityType_Entity) GetValue() string { + if m != nil { + return m.Value + } + return "" +} + +func (m *EntityType_Entity) GetSynonyms() []string { + if m != nil { + return m.Synonyms + } + return nil +} + +// The request message for +// [EntityTypes.ListEntityTypes][google.cloud.dialogflow.v2beta1.EntityTypes.ListEntityTypes]. +type ListEntityTypesRequest struct { + // Required. The agent to list all entity types from. + // Format: `projects//agent`. + Parent string `protobuf:"bytes,1,opt,name=parent" json:"parent,omitempty"` + // Optional. The language to list entity synonyms for. If not specified, + // the agent's default language is used. + // [More than a dozen + // languages](https://dialogflow.com/docs/reference/language) are supported. + // Note: languages must be enabled in the agent, before they can be used. + LanguageCode string `protobuf:"bytes,2,opt,name=language_code,json=languageCode" json:"language_code,omitempty"` + // Optional. The maximum number of items to return in a single page. By + // default 100 and at most 1000. + PageSize int32 `protobuf:"varint,3,opt,name=page_size,json=pageSize" json:"page_size,omitempty"` + // Optional. The next_page_token value returned from a previous list request. + PageToken string `protobuf:"bytes,4,opt,name=page_token,json=pageToken" json:"page_token,omitempty"` +} + +func (m *ListEntityTypesRequest) Reset() { *m = ListEntityTypesRequest{} } +func (m *ListEntityTypesRequest) String() string { return proto.CompactTextString(m) } +func (*ListEntityTypesRequest) ProtoMessage() {} +func (*ListEntityTypesRequest) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{1} } + +func (m *ListEntityTypesRequest) GetParent() string { + if m != nil { + return m.Parent + } + return "" +} + +func (m *ListEntityTypesRequest) GetLanguageCode() string { + if m != nil { + return m.LanguageCode + } + return "" +} + +func (m *ListEntityTypesRequest) GetPageSize() int32 { + if m != nil { + return m.PageSize + } + return 0 +} + +func (m *ListEntityTypesRequest) GetPageToken() string { + if m != nil { + return m.PageToken + } + return "" +} + +// The response message for +// [EntityTypes.ListEntityTypes][google.cloud.dialogflow.v2beta1.EntityTypes.ListEntityTypes]. +type ListEntityTypesResponse struct { + // The list of agent entity types. There will be a maximum number of items + // returned based on the page_size field in the request. + EntityTypes []*EntityType `protobuf:"bytes,1,rep,name=entity_types,json=entityTypes" json:"entity_types,omitempty"` + // Token to retrieve the next page of results, or empty if there are no + // more results in the list. + NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken" json:"next_page_token,omitempty"` +} + +func (m *ListEntityTypesResponse) Reset() { *m = ListEntityTypesResponse{} } +func (m *ListEntityTypesResponse) String() string { return proto.CompactTextString(m) } +func (*ListEntityTypesResponse) ProtoMessage() {} +func (*ListEntityTypesResponse) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{2} } + +func (m *ListEntityTypesResponse) GetEntityTypes() []*EntityType { + if m != nil { + return m.EntityTypes + } + return nil +} + +func (m *ListEntityTypesResponse) GetNextPageToken() string { + if m != nil { + return m.NextPageToken + } + return "" +} + +// The request message for +// [EntityTypes.GetEntityType][google.cloud.dialogflow.v2beta1.EntityTypes.GetEntityType]. +type GetEntityTypeRequest struct { + // Required. The name of the entity type. + // Format: `projects//agent/entityTypes/`. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // Optional. The language to retrieve entity synonyms for. If not specified, + // the agent's default language is used. + // [More than a dozen + // languages](https://dialogflow.com/docs/reference/language) are supported. + // Note: languages must be enabled in the agent, before they can be used. + LanguageCode string `protobuf:"bytes,2,opt,name=language_code,json=languageCode" json:"language_code,omitempty"` +} + +func (m *GetEntityTypeRequest) Reset() { *m = GetEntityTypeRequest{} } +func (m *GetEntityTypeRequest) String() string { return proto.CompactTextString(m) } +func (*GetEntityTypeRequest) ProtoMessage() {} +func (*GetEntityTypeRequest) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{3} } + +func (m *GetEntityTypeRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *GetEntityTypeRequest) GetLanguageCode() string { + if m != nil { + return m.LanguageCode + } + return "" +} + +// The request message for +// [EntityTypes.CreateEntityType][google.cloud.dialogflow.v2beta1.EntityTypes.CreateEntityType]. +type CreateEntityTypeRequest struct { + // Required. The agent to create a entity type for. + // Format: `projects//agent`. + Parent string `protobuf:"bytes,1,opt,name=parent" json:"parent,omitempty"` + // Required. The entity type to create. + EntityType *EntityType `protobuf:"bytes,2,opt,name=entity_type,json=entityType" json:"entity_type,omitempty"` + // Optional. The language of entity synonyms defined in `entity_type`. If not + // specified, the agent's default language is used. + // [More than a dozen + // languages](https://dialogflow.com/docs/reference/language) are supported. + // Note: languages must be enabled in the agent, before they can be used. + LanguageCode string `protobuf:"bytes,3,opt,name=language_code,json=languageCode" json:"language_code,omitempty"` +} + +func (m *CreateEntityTypeRequest) Reset() { *m = CreateEntityTypeRequest{} } +func (m *CreateEntityTypeRequest) String() string { return proto.CompactTextString(m) } +func (*CreateEntityTypeRequest) ProtoMessage() {} +func (*CreateEntityTypeRequest) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{4} } + +func (m *CreateEntityTypeRequest) GetParent() string { + if m != nil { + return m.Parent + } + return "" +} + +func (m *CreateEntityTypeRequest) GetEntityType() *EntityType { + if m != nil { + return m.EntityType + } + return nil +} + +func (m *CreateEntityTypeRequest) GetLanguageCode() string { + if m != nil { + return m.LanguageCode + } + return "" +} + +// The request message for +// [EntityTypes.UpdateEntityType][google.cloud.dialogflow.v2beta1.EntityTypes.UpdateEntityType]. +type UpdateEntityTypeRequest struct { + // Required. The entity type to update. + // Format: `projects//agent/entityTypes/`. + EntityType *EntityType `protobuf:"bytes,1,opt,name=entity_type,json=entityType" json:"entity_type,omitempty"` + // Optional. The language of entity synonyms defined in `entity_type`. If not + // specified, the agent's default language is used. + // [More than a dozen + // languages](https://dialogflow.com/docs/reference/language) are supported. + // Note: languages must be enabled in the agent, before they can be used. + LanguageCode string `protobuf:"bytes,2,opt,name=language_code,json=languageCode" json:"language_code,omitempty"` + // Optional. The mask to control which fields get updated. + UpdateMask *google_protobuf3.FieldMask `protobuf:"bytes,3,opt,name=update_mask,json=updateMask" json:"update_mask,omitempty"` +} + +func (m *UpdateEntityTypeRequest) Reset() { *m = UpdateEntityTypeRequest{} } +func (m *UpdateEntityTypeRequest) String() string { return proto.CompactTextString(m) } +func (*UpdateEntityTypeRequest) ProtoMessage() {} +func (*UpdateEntityTypeRequest) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{5} } + +func (m *UpdateEntityTypeRequest) GetEntityType() *EntityType { + if m != nil { + return m.EntityType + } + return nil +} + +func (m *UpdateEntityTypeRequest) GetLanguageCode() string { + if m != nil { + return m.LanguageCode + } + return "" +} + +func (m *UpdateEntityTypeRequest) GetUpdateMask() *google_protobuf3.FieldMask { + if m != nil { + return m.UpdateMask + } + return nil +} + +// The request message for +// [EntityTypes.DeleteEntityType][google.cloud.dialogflow.v2beta1.EntityTypes.DeleteEntityType]. +type DeleteEntityTypeRequest struct { + // Required. The name of the entity type to delete. + // Format: `projects//agent/entityTypes/`. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` +} + +func (m *DeleteEntityTypeRequest) Reset() { *m = DeleteEntityTypeRequest{} } +func (m *DeleteEntityTypeRequest) String() string { return proto.CompactTextString(m) } +func (*DeleteEntityTypeRequest) ProtoMessage() {} +func (*DeleteEntityTypeRequest) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{6} } + +func (m *DeleteEntityTypeRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +// The request message for +// [EntityTypes.BatchUpdateEntityTypes][google.cloud.dialogflow.v2beta1.EntityTypes.BatchUpdateEntityTypes]. +type BatchUpdateEntityTypesRequest struct { + // Required. The name of the agent to update or create entity types in. + // Format: `projects//agent`. + Parent string `protobuf:"bytes,1,opt,name=parent" json:"parent,omitempty"` + // Required. The source of the entity type batch. + // + // For each entity type in the batch: + // * If `name` is specified, we update an existing entity type. + // * If `name` is not specified, we create a new entity type. + // + // Types that are valid to be assigned to EntityTypeBatch: + // *BatchUpdateEntityTypesRequest_EntityTypeBatchUri + // *BatchUpdateEntityTypesRequest_EntityTypeBatchInline + EntityTypeBatch isBatchUpdateEntityTypesRequest_EntityTypeBatch `protobuf_oneof:"entity_type_batch"` + // Optional. The language of entity synonyms defined in `entity_types`. If not + // specified, the agent's default language is used. + // [More than a dozen + // languages](https://dialogflow.com/docs/reference/language) are supported. + // Note: languages must be enabled in the agent, before they can be used. + LanguageCode string `protobuf:"bytes,4,opt,name=language_code,json=languageCode" json:"language_code,omitempty"` + // Optional. The mask to control which fields get updated. + UpdateMask *google_protobuf3.FieldMask `protobuf:"bytes,5,opt,name=update_mask,json=updateMask" json:"update_mask,omitempty"` +} + +func (m *BatchUpdateEntityTypesRequest) Reset() { *m = BatchUpdateEntityTypesRequest{} } +func (m *BatchUpdateEntityTypesRequest) String() string { return proto.CompactTextString(m) } +func (*BatchUpdateEntityTypesRequest) ProtoMessage() {} +func (*BatchUpdateEntityTypesRequest) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{7} } + +type isBatchUpdateEntityTypesRequest_EntityTypeBatch interface { + isBatchUpdateEntityTypesRequest_EntityTypeBatch() +} + +type BatchUpdateEntityTypesRequest_EntityTypeBatchUri struct { + EntityTypeBatchUri string `protobuf:"bytes,2,opt,name=entity_type_batch_uri,json=entityTypeBatchUri,oneof"` +} +type BatchUpdateEntityTypesRequest_EntityTypeBatchInline struct { + EntityTypeBatchInline *EntityTypeBatch `protobuf:"bytes,3,opt,name=entity_type_batch_inline,json=entityTypeBatchInline,oneof"` +} + +func (*BatchUpdateEntityTypesRequest_EntityTypeBatchUri) isBatchUpdateEntityTypesRequest_EntityTypeBatch() { +} +func (*BatchUpdateEntityTypesRequest_EntityTypeBatchInline) isBatchUpdateEntityTypesRequest_EntityTypeBatch() { +} + +func (m *BatchUpdateEntityTypesRequest) GetEntityTypeBatch() isBatchUpdateEntityTypesRequest_EntityTypeBatch { + if m != nil { + return m.EntityTypeBatch + } + return nil +} + +func (m *BatchUpdateEntityTypesRequest) GetParent() string { + if m != nil { + return m.Parent + } + return "" +} + +func (m *BatchUpdateEntityTypesRequest) GetEntityTypeBatchUri() string { + if x, ok := m.GetEntityTypeBatch().(*BatchUpdateEntityTypesRequest_EntityTypeBatchUri); ok { + return x.EntityTypeBatchUri + } + return "" +} + +func (m *BatchUpdateEntityTypesRequest) GetEntityTypeBatchInline() *EntityTypeBatch { + if x, ok := m.GetEntityTypeBatch().(*BatchUpdateEntityTypesRequest_EntityTypeBatchInline); ok { + return x.EntityTypeBatchInline + } + return nil +} + +func (m *BatchUpdateEntityTypesRequest) GetLanguageCode() string { + if m != nil { + return m.LanguageCode + } + return "" +} + +func (m *BatchUpdateEntityTypesRequest) GetUpdateMask() *google_protobuf3.FieldMask { + if m != nil { + return m.UpdateMask + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*BatchUpdateEntityTypesRequest) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _BatchUpdateEntityTypesRequest_OneofMarshaler, _BatchUpdateEntityTypesRequest_OneofUnmarshaler, _BatchUpdateEntityTypesRequest_OneofSizer, []interface{}{ + (*BatchUpdateEntityTypesRequest_EntityTypeBatchUri)(nil), + (*BatchUpdateEntityTypesRequest_EntityTypeBatchInline)(nil), + } +} + +func _BatchUpdateEntityTypesRequest_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*BatchUpdateEntityTypesRequest) + // entity_type_batch + switch x := m.EntityTypeBatch.(type) { + case *BatchUpdateEntityTypesRequest_EntityTypeBatchUri: + b.EncodeVarint(2<<3 | proto.WireBytes) + b.EncodeStringBytes(x.EntityTypeBatchUri) + case *BatchUpdateEntityTypesRequest_EntityTypeBatchInline: + b.EncodeVarint(3<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.EntityTypeBatchInline); err != nil { + return err + } + case nil: + default: + return fmt.Errorf("BatchUpdateEntityTypesRequest.EntityTypeBatch has unexpected type %T", x) + } + return nil +} + +func _BatchUpdateEntityTypesRequest_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*BatchUpdateEntityTypesRequest) + switch tag { + case 2: // entity_type_batch.entity_type_batch_uri + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeStringBytes() + m.EntityTypeBatch = &BatchUpdateEntityTypesRequest_EntityTypeBatchUri{x} + return true, err + case 3: // entity_type_batch.entity_type_batch_inline + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(EntityTypeBatch) + err := b.DecodeMessage(msg) + m.EntityTypeBatch = &BatchUpdateEntityTypesRequest_EntityTypeBatchInline{msg} + return true, err + default: + return false, nil + } +} + +func _BatchUpdateEntityTypesRequest_OneofSizer(msg proto.Message) (n int) { + m := msg.(*BatchUpdateEntityTypesRequest) + // entity_type_batch + switch x := m.EntityTypeBatch.(type) { + case *BatchUpdateEntityTypesRequest_EntityTypeBatchUri: + n += proto.SizeVarint(2<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.EntityTypeBatchUri))) + n += len(x.EntityTypeBatchUri) + case *BatchUpdateEntityTypesRequest_EntityTypeBatchInline: + s := proto.Size(x.EntityTypeBatchInline) + n += proto.SizeVarint(3<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +// The response message for +// [EntityTypes.BatchUpdateEntityTypes][google.cloud.dialogflow.v2beta1.EntityTypes.BatchUpdateEntityTypes]. +type BatchUpdateEntityTypesResponse struct { + // The collection of updated or created entity types. + EntityTypes []*EntityType `protobuf:"bytes,1,rep,name=entity_types,json=entityTypes" json:"entity_types,omitempty"` +} + +func (m *BatchUpdateEntityTypesResponse) Reset() { *m = BatchUpdateEntityTypesResponse{} } +func (m *BatchUpdateEntityTypesResponse) String() string { return proto.CompactTextString(m) } +func (*BatchUpdateEntityTypesResponse) ProtoMessage() {} +func (*BatchUpdateEntityTypesResponse) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{8} } + +func (m *BatchUpdateEntityTypesResponse) GetEntityTypes() []*EntityType { + if m != nil { + return m.EntityTypes + } + return nil +} + +// The request message for +// [EntityTypes.BatchDeleteEntityTypes][google.cloud.dialogflow.v2beta1.EntityTypes.BatchDeleteEntityTypes]. +type BatchDeleteEntityTypesRequest struct { + // Required. The name of the agent to delete all entities types for. Format: + // `projects//agent`. + Parent string `protobuf:"bytes,1,opt,name=parent" json:"parent,omitempty"` + // Required. The names entity types to delete. All names must point to the + // same agent as `parent`. + EntityTypeNames []string `protobuf:"bytes,2,rep,name=entity_type_names,json=entityTypeNames" json:"entity_type_names,omitempty"` +} + +func (m *BatchDeleteEntityTypesRequest) Reset() { *m = BatchDeleteEntityTypesRequest{} } +func (m *BatchDeleteEntityTypesRequest) String() string { return proto.CompactTextString(m) } +func (*BatchDeleteEntityTypesRequest) ProtoMessage() {} +func (*BatchDeleteEntityTypesRequest) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{9} } + +func (m *BatchDeleteEntityTypesRequest) GetParent() string { + if m != nil { + return m.Parent + } + return "" +} + +func (m *BatchDeleteEntityTypesRequest) GetEntityTypeNames() []string { + if m != nil { + return m.EntityTypeNames + } + return nil +} + +// The request message for +// [EntityTypes.BatchCreateEntities][google.cloud.dialogflow.v2beta1.EntityTypes.BatchCreateEntities]. +type BatchCreateEntitiesRequest struct { + // Required. The name of the entity type to create entities in. Format: + // `projects//agent/entityTypes/`. + Parent string `protobuf:"bytes,1,opt,name=parent" json:"parent,omitempty"` + // Required. The collection of entities to create. + Entities []*EntityType_Entity `protobuf:"bytes,2,rep,name=entities" json:"entities,omitempty"` + // Optional. The language of entity synonyms defined in `entities`. If not + // specified, the agent's default language is used. + // [More than a dozen + // languages](https://dialogflow.com/docs/reference/language) are supported. + // Note: languages must be enabled in the agent, before they can be used. + LanguageCode string `protobuf:"bytes,3,opt,name=language_code,json=languageCode" json:"language_code,omitempty"` +} + +func (m *BatchCreateEntitiesRequest) Reset() { *m = BatchCreateEntitiesRequest{} } +func (m *BatchCreateEntitiesRequest) String() string { return proto.CompactTextString(m) } +func (*BatchCreateEntitiesRequest) ProtoMessage() {} +func (*BatchCreateEntitiesRequest) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{10} } + +func (m *BatchCreateEntitiesRequest) GetParent() string { + if m != nil { + return m.Parent + } + return "" +} + +func (m *BatchCreateEntitiesRequest) GetEntities() []*EntityType_Entity { + if m != nil { + return m.Entities + } + return nil +} + +func (m *BatchCreateEntitiesRequest) GetLanguageCode() string { + if m != nil { + return m.LanguageCode + } + return "" +} + +// The response message for +// [EntityTypes.BatchCreateEntities][google.cloud.dialogflow.v2beta1.EntityTypes.BatchCreateEntities]. +type BatchUpdateEntitiesRequest struct { + // Required. The name of the entity type to update the entities in. Format: + // `projects//agent/entityTypes/`. + Parent string `protobuf:"bytes,1,opt,name=parent" json:"parent,omitempty"` + // Required. The collection of new entities to replace the existing entities. + Entities []*EntityType_Entity `protobuf:"bytes,2,rep,name=entities" json:"entities,omitempty"` + // Optional. The language of entity synonyms defined in `entities`. If not + // specified, the agent's default language is used. + // [More than a dozen + // languages](https://dialogflow.com/docs/reference/language) are supported. + // Note: languages must be enabled in the agent, before they can be used. + LanguageCode string `protobuf:"bytes,3,opt,name=language_code,json=languageCode" json:"language_code,omitempty"` + // Optional. The mask to control which fields get updated. + UpdateMask *google_protobuf3.FieldMask `protobuf:"bytes,4,opt,name=update_mask,json=updateMask" json:"update_mask,omitempty"` +} + +func (m *BatchUpdateEntitiesRequest) Reset() { *m = BatchUpdateEntitiesRequest{} } +func (m *BatchUpdateEntitiesRequest) String() string { return proto.CompactTextString(m) } +func (*BatchUpdateEntitiesRequest) ProtoMessage() {} +func (*BatchUpdateEntitiesRequest) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{11} } + +func (m *BatchUpdateEntitiesRequest) GetParent() string { + if m != nil { + return m.Parent + } + return "" +} + +func (m *BatchUpdateEntitiesRequest) GetEntities() []*EntityType_Entity { + if m != nil { + return m.Entities + } + return nil +} + +func (m *BatchUpdateEntitiesRequest) GetLanguageCode() string { + if m != nil { + return m.LanguageCode + } + return "" +} + +func (m *BatchUpdateEntitiesRequest) GetUpdateMask() *google_protobuf3.FieldMask { + if m != nil { + return m.UpdateMask + } + return nil +} + +// The request message for +// [EntityTypes.BatchDeleteEntities][google.cloud.dialogflow.v2beta1.EntityTypes.BatchDeleteEntities]. +type BatchDeleteEntitiesRequest struct { + // Required. The name of the entity type to delete entries for. Format: + // `projects//agent/entityTypes/`. + Parent string `protobuf:"bytes,1,opt,name=parent" json:"parent,omitempty"` + // Required. The canonical `values` of the entities to delete. Note that + // these are not fully-qualified names, i.e. they don't start with + // `projects/`. + EntityValues []string `protobuf:"bytes,2,rep,name=entity_values,json=entityValues" json:"entity_values,omitempty"` + // Optional. The language of entity synonyms defined in `entities`. If not + // specified, the agent's default language is used. + // [More than a dozen + // languages](https://dialogflow.com/docs/reference/language) are supported. + // Note: languages must be enabled in the agent, before they can be used. + LanguageCode string `protobuf:"bytes,3,opt,name=language_code,json=languageCode" json:"language_code,omitempty"` +} + +func (m *BatchDeleteEntitiesRequest) Reset() { *m = BatchDeleteEntitiesRequest{} } +func (m *BatchDeleteEntitiesRequest) String() string { return proto.CompactTextString(m) } +func (*BatchDeleteEntitiesRequest) ProtoMessage() {} +func (*BatchDeleteEntitiesRequest) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{12} } + +func (m *BatchDeleteEntitiesRequest) GetParent() string { + if m != nil { + return m.Parent + } + return "" +} + +func (m *BatchDeleteEntitiesRequest) GetEntityValues() []string { + if m != nil { + return m.EntityValues + } + return nil +} + +func (m *BatchDeleteEntitiesRequest) GetLanguageCode() string { + if m != nil { + return m.LanguageCode + } + return "" +} + +// This message is a wrapper around a collection of entity types. +type EntityTypeBatch struct { + // A collection of entity types. + EntityTypes []*EntityType `protobuf:"bytes,1,rep,name=entity_types,json=entityTypes" json:"entity_types,omitempty"` +} + +func (m *EntityTypeBatch) Reset() { *m = EntityTypeBatch{} } +func (m *EntityTypeBatch) String() string { return proto.CompactTextString(m) } +func (*EntityTypeBatch) ProtoMessage() {} +func (*EntityTypeBatch) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{13} } + +func (m *EntityTypeBatch) GetEntityTypes() []*EntityType { + if m != nil { + return m.EntityTypes + } + return nil +} + +func init() { + proto.RegisterType((*EntityType)(nil), "google.cloud.dialogflow.v2beta1.EntityType") + proto.RegisterType((*EntityType_Entity)(nil), "google.cloud.dialogflow.v2beta1.EntityType.Entity") + proto.RegisterType((*ListEntityTypesRequest)(nil), "google.cloud.dialogflow.v2beta1.ListEntityTypesRequest") + proto.RegisterType((*ListEntityTypesResponse)(nil), "google.cloud.dialogflow.v2beta1.ListEntityTypesResponse") + proto.RegisterType((*GetEntityTypeRequest)(nil), "google.cloud.dialogflow.v2beta1.GetEntityTypeRequest") + proto.RegisterType((*CreateEntityTypeRequest)(nil), "google.cloud.dialogflow.v2beta1.CreateEntityTypeRequest") + proto.RegisterType((*UpdateEntityTypeRequest)(nil), "google.cloud.dialogflow.v2beta1.UpdateEntityTypeRequest") + proto.RegisterType((*DeleteEntityTypeRequest)(nil), "google.cloud.dialogflow.v2beta1.DeleteEntityTypeRequest") + proto.RegisterType((*BatchUpdateEntityTypesRequest)(nil), "google.cloud.dialogflow.v2beta1.BatchUpdateEntityTypesRequest") + proto.RegisterType((*BatchUpdateEntityTypesResponse)(nil), "google.cloud.dialogflow.v2beta1.BatchUpdateEntityTypesResponse") + proto.RegisterType((*BatchDeleteEntityTypesRequest)(nil), "google.cloud.dialogflow.v2beta1.BatchDeleteEntityTypesRequest") + proto.RegisterType((*BatchCreateEntitiesRequest)(nil), "google.cloud.dialogflow.v2beta1.BatchCreateEntitiesRequest") + proto.RegisterType((*BatchUpdateEntitiesRequest)(nil), "google.cloud.dialogflow.v2beta1.BatchUpdateEntitiesRequest") + proto.RegisterType((*BatchDeleteEntitiesRequest)(nil), "google.cloud.dialogflow.v2beta1.BatchDeleteEntitiesRequest") + proto.RegisterType((*EntityTypeBatch)(nil), "google.cloud.dialogflow.v2beta1.EntityTypeBatch") + proto.RegisterEnum("google.cloud.dialogflow.v2beta1.EntityType_Kind", EntityType_Kind_name, EntityType_Kind_value) + proto.RegisterEnum("google.cloud.dialogflow.v2beta1.EntityType_AutoExpansionMode", EntityType_AutoExpansionMode_name, EntityType_AutoExpansionMode_value) +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// Client API for EntityTypes service + +type EntityTypesClient interface { + // Returns the list of all entity types in the specified agent. + ListEntityTypes(ctx context.Context, in *ListEntityTypesRequest, opts ...grpc.CallOption) (*ListEntityTypesResponse, error) + // Retrieves the specified entity type. + GetEntityType(ctx context.Context, in *GetEntityTypeRequest, opts ...grpc.CallOption) (*EntityType, error) + // Creates an entity type in the specified agent. + CreateEntityType(ctx context.Context, in *CreateEntityTypeRequest, opts ...grpc.CallOption) (*EntityType, error) + // Updates the specified entity type. + UpdateEntityType(ctx context.Context, in *UpdateEntityTypeRequest, opts ...grpc.CallOption) (*EntityType, error) + // Deletes the specified entity type. + DeleteEntityType(ctx context.Context, in *DeleteEntityTypeRequest, opts ...grpc.CallOption) (*google_protobuf2.Empty, error) + // Updates/Creates multiple entity types in the specified agent. + // + // Operation + BatchUpdateEntityTypes(ctx context.Context, in *BatchUpdateEntityTypesRequest, opts ...grpc.CallOption) (*google_longrunning.Operation, error) + // Deletes entity types in the specified agent. + // + // Operation + BatchDeleteEntityTypes(ctx context.Context, in *BatchDeleteEntityTypesRequest, opts ...grpc.CallOption) (*google_longrunning.Operation, error) + // Creates multiple new entities in the specified entity type (extends the + // existing collection of entries). + // + // Operation + BatchCreateEntities(ctx context.Context, in *BatchCreateEntitiesRequest, opts ...grpc.CallOption) (*google_longrunning.Operation, error) + // Updates entities in the specified entity type (replaces the existing + // collection of entries). + // + // Operation + BatchUpdateEntities(ctx context.Context, in *BatchUpdateEntitiesRequest, opts ...grpc.CallOption) (*google_longrunning.Operation, error) + // Deletes entities in the specified entity type. + // + // Operation + BatchDeleteEntities(ctx context.Context, in *BatchDeleteEntitiesRequest, opts ...grpc.CallOption) (*google_longrunning.Operation, error) +} + +type entityTypesClient struct { + cc *grpc.ClientConn +} + +func NewEntityTypesClient(cc *grpc.ClientConn) EntityTypesClient { + return &entityTypesClient{cc} +} + +func (c *entityTypesClient) ListEntityTypes(ctx context.Context, in *ListEntityTypesRequest, opts ...grpc.CallOption) (*ListEntityTypesResponse, error) { + out := new(ListEntityTypesResponse) + err := grpc.Invoke(ctx, "/google.cloud.dialogflow.v2beta1.EntityTypes/ListEntityTypes", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *entityTypesClient) GetEntityType(ctx context.Context, in *GetEntityTypeRequest, opts ...grpc.CallOption) (*EntityType, error) { + out := new(EntityType) + err := grpc.Invoke(ctx, "/google.cloud.dialogflow.v2beta1.EntityTypes/GetEntityType", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *entityTypesClient) CreateEntityType(ctx context.Context, in *CreateEntityTypeRequest, opts ...grpc.CallOption) (*EntityType, error) { + out := new(EntityType) + err := grpc.Invoke(ctx, "/google.cloud.dialogflow.v2beta1.EntityTypes/CreateEntityType", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *entityTypesClient) UpdateEntityType(ctx context.Context, in *UpdateEntityTypeRequest, opts ...grpc.CallOption) (*EntityType, error) { + out := new(EntityType) + err := grpc.Invoke(ctx, "/google.cloud.dialogflow.v2beta1.EntityTypes/UpdateEntityType", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *entityTypesClient) DeleteEntityType(ctx context.Context, in *DeleteEntityTypeRequest, opts ...grpc.CallOption) (*google_protobuf2.Empty, error) { + out := new(google_protobuf2.Empty) + err := grpc.Invoke(ctx, "/google.cloud.dialogflow.v2beta1.EntityTypes/DeleteEntityType", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *entityTypesClient) BatchUpdateEntityTypes(ctx context.Context, in *BatchUpdateEntityTypesRequest, opts ...grpc.CallOption) (*google_longrunning.Operation, error) { + out := new(google_longrunning.Operation) + err := grpc.Invoke(ctx, "/google.cloud.dialogflow.v2beta1.EntityTypes/BatchUpdateEntityTypes", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *entityTypesClient) BatchDeleteEntityTypes(ctx context.Context, in *BatchDeleteEntityTypesRequest, opts ...grpc.CallOption) (*google_longrunning.Operation, error) { + out := new(google_longrunning.Operation) + err := grpc.Invoke(ctx, "/google.cloud.dialogflow.v2beta1.EntityTypes/BatchDeleteEntityTypes", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *entityTypesClient) BatchCreateEntities(ctx context.Context, in *BatchCreateEntitiesRequest, opts ...grpc.CallOption) (*google_longrunning.Operation, error) { + out := new(google_longrunning.Operation) + err := grpc.Invoke(ctx, "/google.cloud.dialogflow.v2beta1.EntityTypes/BatchCreateEntities", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *entityTypesClient) BatchUpdateEntities(ctx context.Context, in *BatchUpdateEntitiesRequest, opts ...grpc.CallOption) (*google_longrunning.Operation, error) { + out := new(google_longrunning.Operation) + err := grpc.Invoke(ctx, "/google.cloud.dialogflow.v2beta1.EntityTypes/BatchUpdateEntities", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *entityTypesClient) BatchDeleteEntities(ctx context.Context, in *BatchDeleteEntitiesRequest, opts ...grpc.CallOption) (*google_longrunning.Operation, error) { + out := new(google_longrunning.Operation) + err := grpc.Invoke(ctx, "/google.cloud.dialogflow.v2beta1.EntityTypes/BatchDeleteEntities", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for EntityTypes service + +type EntityTypesServer interface { + // Returns the list of all entity types in the specified agent. + ListEntityTypes(context.Context, *ListEntityTypesRequest) (*ListEntityTypesResponse, error) + // Retrieves the specified entity type. + GetEntityType(context.Context, *GetEntityTypeRequest) (*EntityType, error) + // Creates an entity type in the specified agent. + CreateEntityType(context.Context, *CreateEntityTypeRequest) (*EntityType, error) + // Updates the specified entity type. + UpdateEntityType(context.Context, *UpdateEntityTypeRequest) (*EntityType, error) + // Deletes the specified entity type. + DeleteEntityType(context.Context, *DeleteEntityTypeRequest) (*google_protobuf2.Empty, error) + // Updates/Creates multiple entity types in the specified agent. + // + // Operation + BatchUpdateEntityTypes(context.Context, *BatchUpdateEntityTypesRequest) (*google_longrunning.Operation, error) + // Deletes entity types in the specified agent. + // + // Operation + BatchDeleteEntityTypes(context.Context, *BatchDeleteEntityTypesRequest) (*google_longrunning.Operation, error) + // Creates multiple new entities in the specified entity type (extends the + // existing collection of entries). + // + // Operation + BatchCreateEntities(context.Context, *BatchCreateEntitiesRequest) (*google_longrunning.Operation, error) + // Updates entities in the specified entity type (replaces the existing + // collection of entries). + // + // Operation + BatchUpdateEntities(context.Context, *BatchUpdateEntitiesRequest) (*google_longrunning.Operation, error) + // Deletes entities in the specified entity type. + // + // Operation + BatchDeleteEntities(context.Context, *BatchDeleteEntitiesRequest) (*google_longrunning.Operation, error) +} + +func RegisterEntityTypesServer(s *grpc.Server, srv EntityTypesServer) { + s.RegisterService(&_EntityTypes_serviceDesc, srv) +} + +func _EntityTypes_ListEntityTypes_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListEntityTypesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EntityTypesServer).ListEntityTypes(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.dialogflow.v2beta1.EntityTypes/ListEntityTypes", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EntityTypesServer).ListEntityTypes(ctx, req.(*ListEntityTypesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _EntityTypes_GetEntityType_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetEntityTypeRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EntityTypesServer).GetEntityType(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.dialogflow.v2beta1.EntityTypes/GetEntityType", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EntityTypesServer).GetEntityType(ctx, req.(*GetEntityTypeRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _EntityTypes_CreateEntityType_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateEntityTypeRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EntityTypesServer).CreateEntityType(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.dialogflow.v2beta1.EntityTypes/CreateEntityType", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EntityTypesServer).CreateEntityType(ctx, req.(*CreateEntityTypeRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _EntityTypes_UpdateEntityType_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdateEntityTypeRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EntityTypesServer).UpdateEntityType(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.dialogflow.v2beta1.EntityTypes/UpdateEntityType", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EntityTypesServer).UpdateEntityType(ctx, req.(*UpdateEntityTypeRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _EntityTypes_DeleteEntityType_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteEntityTypeRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EntityTypesServer).DeleteEntityType(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.dialogflow.v2beta1.EntityTypes/DeleteEntityType", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EntityTypesServer).DeleteEntityType(ctx, req.(*DeleteEntityTypeRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _EntityTypes_BatchUpdateEntityTypes_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(BatchUpdateEntityTypesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EntityTypesServer).BatchUpdateEntityTypes(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.dialogflow.v2beta1.EntityTypes/BatchUpdateEntityTypes", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EntityTypesServer).BatchUpdateEntityTypes(ctx, req.(*BatchUpdateEntityTypesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _EntityTypes_BatchDeleteEntityTypes_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(BatchDeleteEntityTypesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EntityTypesServer).BatchDeleteEntityTypes(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.dialogflow.v2beta1.EntityTypes/BatchDeleteEntityTypes", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EntityTypesServer).BatchDeleteEntityTypes(ctx, req.(*BatchDeleteEntityTypesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _EntityTypes_BatchCreateEntities_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(BatchCreateEntitiesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EntityTypesServer).BatchCreateEntities(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.dialogflow.v2beta1.EntityTypes/BatchCreateEntities", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EntityTypesServer).BatchCreateEntities(ctx, req.(*BatchCreateEntitiesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _EntityTypes_BatchUpdateEntities_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(BatchUpdateEntitiesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EntityTypesServer).BatchUpdateEntities(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.dialogflow.v2beta1.EntityTypes/BatchUpdateEntities", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EntityTypesServer).BatchUpdateEntities(ctx, req.(*BatchUpdateEntitiesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _EntityTypes_BatchDeleteEntities_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(BatchDeleteEntitiesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EntityTypesServer).BatchDeleteEntities(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.dialogflow.v2beta1.EntityTypes/BatchDeleteEntities", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EntityTypesServer).BatchDeleteEntities(ctx, req.(*BatchDeleteEntitiesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _EntityTypes_serviceDesc = grpc.ServiceDesc{ + ServiceName: "google.cloud.dialogflow.v2beta1.EntityTypes", + HandlerType: (*EntityTypesServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "ListEntityTypes", + Handler: _EntityTypes_ListEntityTypes_Handler, + }, + { + MethodName: "GetEntityType", + Handler: _EntityTypes_GetEntityType_Handler, + }, + { + MethodName: "CreateEntityType", + Handler: _EntityTypes_CreateEntityType_Handler, + }, + { + MethodName: "UpdateEntityType", + Handler: _EntityTypes_UpdateEntityType_Handler, + }, + { + MethodName: "DeleteEntityType", + Handler: _EntityTypes_DeleteEntityType_Handler, + }, + { + MethodName: "BatchUpdateEntityTypes", + Handler: _EntityTypes_BatchUpdateEntityTypes_Handler, + }, + { + MethodName: "BatchDeleteEntityTypes", + Handler: _EntityTypes_BatchDeleteEntityTypes_Handler, + }, + { + MethodName: "BatchCreateEntities", + Handler: _EntityTypes_BatchCreateEntities_Handler, + }, + { + MethodName: "BatchUpdateEntities", + Handler: _EntityTypes_BatchUpdateEntities_Handler, + }, + { + MethodName: "BatchDeleteEntities", + Handler: _EntityTypes_BatchDeleteEntities_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "google/cloud/dialogflow/v2beta1/entity_type.proto", +} + +func init() { proto.RegisterFile("google/cloud/dialogflow/v2beta1/entity_type.proto", fileDescriptor2) } + +var fileDescriptor2 = []byte{ + // 1236 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x58, 0xcf, 0x6e, 0xe3, 0xd4, + 0x17, 0x9e, 0x9b, 0xa6, 0x55, 0x7b, 0xd2, 0x4e, 0xd3, 0xdb, 0x4e, 0x1b, 0xa5, 0xd3, 0x5f, 0xfb, + 0x73, 0x25, 0x54, 0x15, 0x11, 0xcf, 0x64, 0xc4, 0xbf, 0x56, 0x05, 0xb5, 0x4d, 0x3a, 0x13, 0xa6, + 0x4d, 0x22, 0xb7, 0x1d, 0x01, 0x1b, 0xcb, 0x4d, 0x6e, 0x83, 0xa9, 0x73, 0xaf, 0x89, 0xed, 0x61, + 0x32, 0x68, 0x58, 0xf0, 0x06, 0x88, 0x1d, 0x62, 0x85, 0xd8, 0x00, 0xe2, 0x0d, 0x10, 0x1b, 0x56, + 0xb0, 0x42, 0xe2, 0x15, 0x10, 0xcf, 0x80, 0xc4, 0x06, 0xf9, 0xda, 0x8e, 0x1d, 0xc7, 0xc1, 0x36, + 0xcc, 0x8c, 0xd8, 0xe5, 0xfe, 0x39, 0xe7, 0x7c, 0xdf, 0x39, 0xe7, 0xde, 0xef, 0x3a, 0x70, 0xbb, + 0xc3, 0x58, 0x47, 0x23, 0x62, 0x4b, 0x63, 0x56, 0x5b, 0x6c, 0xab, 0x8a, 0xc6, 0x3a, 0x97, 0x1a, + 0xfb, 0x50, 0x7c, 0x58, 0xbe, 0x20, 0xa6, 0x72, 0x5b, 0x24, 0xd4, 0x54, 0xcd, 0xbe, 0x6c, 0xf6, + 0x75, 0x52, 0xd2, 0x7b, 0xcc, 0x64, 0x78, 0xdd, 0x31, 0x29, 0x71, 0x93, 0x92, 0x6f, 0x52, 0x72, + 0x4d, 0x8a, 0x37, 0x5d, 0x9f, 0x8a, 0xae, 0x8a, 0x0a, 0xa5, 0xcc, 0x54, 0x4c, 0x95, 0x51, 0xc3, + 0x31, 0x2f, 0x6e, 0xba, 0xab, 0x1a, 0xa3, 0x9d, 0x9e, 0x45, 0xa9, 0x4a, 0x3b, 0x22, 0xd3, 0x49, + 0x6f, 0x68, 0xd3, 0xaa, 0xbb, 0x89, 0x8f, 0x2e, 0xac, 0x4b, 0x91, 0x74, 0x75, 0xb3, 0xef, 0x2e, + 0x6e, 0x84, 0x17, 0x2f, 0x55, 0xa2, 0xb5, 0xe5, 0xae, 0x62, 0x5c, 0xb9, 0x3b, 0x6e, 0x86, 0x77, + 0x18, 0x66, 0xcf, 0x6a, 0x99, 0xce, 0xaa, 0xf0, 0x79, 0x16, 0xa0, 0xca, 0x69, 0x9d, 0xf5, 0x75, + 0x82, 0x31, 0x64, 0xa9, 0xd2, 0x25, 0x05, 0xb4, 0x81, 0xb6, 0x66, 0x24, 0xfe, 0x1b, 0xff, 0x1f, + 0x66, 0xdb, 0xaa, 0xa1, 0x6b, 0x4a, 0x5f, 0xe6, 0x6b, 0x19, 0xbe, 0x96, 0x73, 0xe7, 0xea, 0xf6, + 0x96, 0x0a, 0x64, 0xaf, 0x54, 0xda, 0x2e, 0x4c, 0x6c, 0xa0, 0xad, 0xeb, 0xe5, 0x5b, 0xa5, 0x98, + 0xac, 0x94, 0xfc, 0x88, 0xa5, 0xfb, 0x2a, 0x6d, 0x4b, 0xdc, 0x1a, 0x77, 0x61, 0x51, 0xb1, 0x4c, + 0x26, 0x93, 0x47, 0xba, 0x42, 0x0d, 0x95, 0x51, 0xb9, 0xcb, 0xda, 0xa4, 0x90, 0xe5, 0x4e, 0xf7, + 0xd2, 0x38, 0xdd, 0xb7, 0x4c, 0x56, 0xf5, 0xbc, 0x9c, 0xb0, 0x36, 0x91, 0x16, 0x94, 0xf0, 0x14, + 0xae, 0xc3, 0x34, 0x2f, 0xa8, 0x4a, 0x8c, 0xc2, 0xd4, 0xc6, 0xc4, 0x56, 0xae, 0x5c, 0x4e, 0x13, + 0xc3, 0xf9, 0x29, 0x0d, 0x7c, 0x14, 0x77, 0x60, 0xca, 0x99, 0xc3, 0x4b, 0x30, 0xf9, 0x50, 0xd1, + 0x2c, 0x2f, 0x8d, 0xce, 0x00, 0x17, 0x61, 0xda, 0xe8, 0x53, 0x46, 0xfb, 0x5d, 0xa3, 0x90, 0xd9, + 0x98, 0xd8, 0x9a, 0x91, 0x06, 0x63, 0xe1, 0x75, 0xc8, 0xda, 0x89, 0xc0, 0x4b, 0x90, 0xbf, 0x5f, + 0xab, 0x57, 0xe4, 0xf3, 0xfa, 0x69, 0xb3, 0x7a, 0x58, 0x3b, 0xaa, 0x55, 0x2b, 0xf9, 0x6b, 0x78, + 0x16, 0xa6, 0xf9, 0xec, 0xc9, 0x7e, 0x33, 0x8f, 0xf0, 0x1c, 0xcc, 0xf0, 0xd1, 0x71, 0xed, 0xf4, + 0x2c, 0x9f, 0x11, 0xde, 0x81, 0x85, 0x11, 0xba, 0x78, 0x13, 0xd6, 0xf7, 0xcf, 0xcf, 0x1a, 0x72, + 0xf5, 0xed, 0xe6, 0x7e, 0xfd, 0xb4, 0xd6, 0xa8, 0xcb, 0x27, 0x8d, 0x4a, 0x35, 0xe4, 0x76, 0x1d, + 0x56, 0xa3, 0x36, 0x55, 0xaa, 0x47, 0xfb, 0xe7, 0xc7, 0x67, 0x79, 0x24, 0x7c, 0x8a, 0x60, 0xf9, + 0x58, 0x35, 0x4c, 0x9f, 0xb5, 0x21, 0x91, 0x0f, 0x2c, 0x62, 0x98, 0x78, 0x19, 0xa6, 0x74, 0xa5, + 0x47, 0xa8, 0xe9, 0x72, 0x74, 0x47, 0x78, 0x13, 0xe6, 0x34, 0x85, 0x76, 0x2c, 0xa5, 0x43, 0xe4, + 0x96, 0x5d, 0x3d, 0xa7, 0x5b, 0x66, 0xbd, 0xc9, 0x43, 0x1b, 0xdd, 0x2a, 0xcc, 0xe8, 0xf6, 0x06, + 0x43, 0x7d, 0x4c, 0x78, 0xcf, 0x4c, 0x4a, 0xd3, 0xf6, 0xc4, 0xa9, 0xfa, 0x98, 0xe0, 0x35, 0x00, + 0xbe, 0x68, 0xb2, 0x2b, 0x42, 0x79, 0xf1, 0x67, 0x24, 0xbe, 0xfd, 0xcc, 0x9e, 0xb0, 0x31, 0xad, + 0x8c, 0x60, 0x32, 0x74, 0x46, 0x0d, 0xbb, 0xa2, 0xb3, 0x81, 0x23, 0x6a, 0x14, 0x10, 0xaf, 0xea, + 0x8b, 0x29, 0xaa, 0x2a, 0xe5, 0x88, 0xef, 0x17, 0xbf, 0x00, 0xf3, 0x94, 0x3c, 0x32, 0xe5, 0x00, + 0x1e, 0x87, 0xce, 0x9c, 0x3d, 0xdd, 0x1c, 0x60, 0x6a, 0xc0, 0xd2, 0x5d, 0x12, 0x40, 0xe4, 0x25, + 0x29, 0xea, 0x34, 0x25, 0x49, 0x90, 0xf0, 0x15, 0x82, 0x95, 0xc3, 0x1e, 0x51, 0x4c, 0x32, 0xea, + 0x74, 0x5c, 0xe6, 0x8f, 0x21, 0x17, 0x20, 0xcf, 0xdd, 0xa6, 0xe4, 0x0e, 0x3e, 0xf7, 0x51, 0x98, + 0x13, 0x11, 0x30, 0x7f, 0x42, 0xb0, 0x72, 0xae, 0xb7, 0x23, 0x61, 0x86, 0xe0, 0xa0, 0xa7, 0x0c, + 0x27, 0xaa, 0xad, 0x76, 0x21, 0x67, 0x71, 0x34, 0xfc, 0xfa, 0xe3, 0x88, 0x73, 0xe5, 0xa2, 0x17, + 0xd2, 0xbb, 0xff, 0x4a, 0x47, 0xf6, 0x0d, 0x79, 0xa2, 0x18, 0x57, 0x12, 0x38, 0xdb, 0xed, 0xdf, + 0xc2, 0x4b, 0xb0, 0x52, 0x21, 0x1a, 0x89, 0xa2, 0x12, 0x51, 0x46, 0xe1, 0x97, 0x0c, 0xac, 0x1d, + 0x28, 0x66, 0xeb, 0xbd, 0x30, 0xff, 0xd8, 0x13, 0x72, 0x07, 0x6e, 0x04, 0x12, 0x23, 0x5f, 0xd8, + 0x4e, 0x64, 0xab, 0xa7, 0x3a, 0x94, 0xee, 0x5d, 0x93, 0xb0, 0xcf, 0xdb, 0x89, 0xd0, 0x53, 0xf1, + 0x15, 0x14, 0x46, 0x8d, 0x54, 0xaa, 0xa9, 0x94, 0xb8, 0x3c, 0xd3, 0x5c, 0xba, 0xdc, 0xed, 0xbd, + 0x6b, 0xd2, 0x8d, 0x50, 0xa4, 0x1a, 0x77, 0x38, 0x9a, 0xec, 0x6c, 0x7c, 0xb2, 0x27, 0xd3, 0x24, + 0xfb, 0x60, 0x11, 0x16, 0x46, 0xe8, 0x08, 0x3a, 0xfc, 0x6f, 0x5c, 0x46, 0x9f, 0xcd, 0xf9, 0x16, + 0x5a, 0x6e, 0x0d, 0xc3, 0x85, 0x8f, 0xad, 0xe1, 0xf6, 0x30, 0x7e, 0xbb, 0x23, 0xbc, 0x3b, 0x7d, + 0xde, 0x0f, 0x60, 0x4b, 0xa3, 0x21, 0x7c, 0x8d, 0xa0, 0xc8, 0xa3, 0x04, 0x0e, 0xb4, 0x1a, 0x1f, + 0x22, 0xa8, 0x4e, 0x99, 0x7f, 0xaf, 0x4e, 0xc9, 0x0e, 0xf4, 0xef, 0x1e, 0xd6, 0x40, 0x0d, 0xfe, + 0xa3, 0x58, 0xc3, 0x0d, 0x98, 0x4d, 0x75, 0xda, 0x3f, 0x76, 0x79, 0x06, 0x2a, 0xaf, 0x26, 0x12, + 0x37, 0xb7, 0xec, 0x5c, 0xd1, 0xbd, 0x92, 0xbb, 0x4d, 0xf9, 0x80, 0xcf, 0x25, 0x4b, 0xb4, 0x02, + 0xf3, 0xa1, 0xe3, 0xf8, 0xb4, 0x9b, 0xbb, 0xfc, 0xe7, 0x75, 0xc8, 0x05, 0x5a, 0x1a, 0x7f, 0x8f, + 0x60, 0x3e, 0x24, 0x9c, 0xf8, 0xd5, 0x58, 0xef, 0xd1, 0xf2, 0x5f, 0x7c, 0x2d, 0xbd, 0xa1, 0x73, + 0x86, 0x85, 0x57, 0x3e, 0xf9, 0xf5, 0xb7, 0xcf, 0x32, 0xb7, 0x70, 0x69, 0xf0, 0xaa, 0xfe, 0xc8, + 0xc9, 0xee, 0x9e, 0xde, 0x63, 0xef, 0x93, 0x96, 0x69, 0x88, 0xdb, 0xa2, 0xd2, 0x21, 0xd4, 0x7c, + 0x22, 0x06, 0xb5, 0xf8, 0x5b, 0x04, 0x73, 0x43, 0x22, 0x8b, 0x5f, 0x8e, 0xc5, 0x10, 0x25, 0xca, + 0xc5, 0x34, 0x19, 0x8d, 0x42, 0x6b, 0x1f, 0xf6, 0x11, 0xac, 0x41, 0xa8, 0xe2, 0xf6, 0x13, 0xfc, + 0x03, 0x82, 0x7c, 0x58, 0xc0, 0x71, 0x7c, 0xd2, 0xc6, 0x68, 0x7e, 0x3a, 0xcc, 0x87, 0x1c, 0xf3, + 0x9e, 0x90, 0x32, 0xc3, 0x3b, 0x41, 0xbd, 0xc6, 0x3f, 0x23, 0xc8, 0x87, 0x2f, 0xe2, 0x04, 0x04, + 0xc6, 0xbc, 0x06, 0xd2, 0x11, 0x68, 0x70, 0x02, 0xb5, 0xf2, 0x8e, 0x4f, 0x20, 0xf8, 0xe5, 0x95, + 0xa4, 0x00, 0xc3, 0x64, 0xbe, 0x40, 0x90, 0x0f, 0xdf, 0xf1, 0x09, 0xc8, 0x8c, 0x79, 0x0f, 0x14, + 0x97, 0x47, 0x2e, 0x99, 0xaa, 0xfd, 0x45, 0xe6, 0x35, 0xcb, 0xf6, 0x3f, 0x68, 0x96, 0xe5, 0x68, + 0xe5, 0xc3, 0x6f, 0xc4, 0x82, 0xfc, 0xdb, 0x47, 0x48, 0x71, 0xcd, 0xb3, 0x0f, 0x7c, 0x61, 0x96, + 0x1a, 0xde, 0x17, 0xa6, 0x50, 0xe5, 0x88, 0xdf, 0x14, 0x76, 0x52, 0xb6, 0xca, 0x85, 0x1f, 0x74, + 0x07, 0x6d, 0xfb, 0x04, 0x46, 0x84, 0x34, 0x29, 0x81, 0x71, 0x0a, 0xfc, 0x4c, 0x09, 0x38, 0x41, + 0x6d, 0x02, 0x3f, 0x22, 0x58, 0x8c, 0xd0, 0x68, 0xbc, 0x9b, 0x0c, 0x7d, 0xa4, 0xb2, 0xc7, 0x41, + 0x6f, 0x72, 0xe8, 0x6f, 0x09, 0xd5, 0x58, 0xe8, 0xa1, 0x7e, 0x11, 0x3d, 0x9d, 0x74, 0x58, 0x38, + 0xc1, 0x87, 0x58, 0x0c, 0xab, 0x77, 0x52, 0x16, 0x91, 0x9a, 0xff, 0xbc, 0x58, 0xf8, 0xcd, 0x34, + 0x60, 0x31, 0xac, 0xcd, 0x49, 0x59, 0x44, 0x2a, 0xfa, 0xf3, 0x62, 0x31, 0xe8, 0xa8, 0x83, 0xef, + 0x10, 0x6c, 0xb6, 0x58, 0x37, 0x0e, 0xf3, 0x41, 0xe0, 0x19, 0xd0, 0xb4, 0x6f, 0x93, 0x26, 0x7a, + 0xb7, 0xe6, 0xda, 0x74, 0x98, 0xfd, 0x64, 0x28, 0xb1, 0x5e, 0x47, 0xec, 0x10, 0xca, 0xef, 0x1a, + 0xd1, 0x59, 0x52, 0x74, 0xd5, 0x18, 0xfb, 0x2f, 0xd5, 0xae, 0x3f, 0xf5, 0x07, 0x42, 0x5f, 0x66, + 0x32, 0x95, 0xa3, 0x6f, 0x32, 0xeb, 0x77, 0x1d, 0x9f, 0x87, 0x1c, 0x47, 0xc5, 0xc7, 0xf1, 0xc0, + 0x31, 0xba, 0x98, 0xe2, 0xfe, 0xef, 0xfc, 0x15, 0x00, 0x00, 0xff, 0xff, 0x7d, 0x5f, 0x36, 0x09, + 0x04, 0x13, 0x00, 0x00, +} diff --git a/vendor/google.golang.org/genproto/googleapis/cloud/dialogflow/v2beta1/intent.pb.go b/vendor/google.golang.org/genproto/googleapis/cloud/dialogflow/v2beta1/intent.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..533a24c9a29c309f0df245bb9ae9b019723db2c6 --- /dev/null +++ b/vendor/google.golang.org/genproto/googleapis/cloud/dialogflow/v2beta1/intent.pb.go @@ -0,0 +1,2540 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: google/cloud/dialogflow/v2beta1/intent.proto + +package dialogflow + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import _ "google.golang.org/genproto/googleapis/api/annotations" +import google_longrunning "google.golang.org/genproto/googleapis/longrunning" +import google_protobuf2 "github.com/golang/protobuf/ptypes/empty" +import google_protobuf3 "google.golang.org/genproto/protobuf/field_mask" +import google_protobuf4 "github.com/golang/protobuf/ptypes/struct" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// Represents the options for views of an intent. +// An intent can be a sizable object. Therefore, we provide a resource view that +// does not return training phrases in the response by default. +type IntentView int32 + +const ( + // Training phrases field is not populated in the response. + IntentView_INTENT_VIEW_UNSPECIFIED IntentView = 0 + // All fields are populated. + IntentView_INTENT_VIEW_FULL IntentView = 1 +) + +var IntentView_name = map[int32]string{ + 0: "INTENT_VIEW_UNSPECIFIED", + 1: "INTENT_VIEW_FULL", +} +var IntentView_value = map[string]int32{ + "INTENT_VIEW_UNSPECIFIED": 0, + "INTENT_VIEW_FULL": 1, +} + +func (x IntentView) String() string { + return proto.EnumName(IntentView_name, int32(x)) +} +func (IntentView) EnumDescriptor() ([]byte, []int) { return fileDescriptor3, []int{0} } + +// Represents the different states that webhooks can be in. +type Intent_WebhookState int32 + +const ( + // Webhook is disabled in the agent and in the intent. + Intent_WEBHOOK_STATE_UNSPECIFIED Intent_WebhookState = 0 + // Webhook is enabled in the agent and in the intent. + Intent_WEBHOOK_STATE_ENABLED Intent_WebhookState = 1 + // Webhook is enabled in the agent and in the intent. Also, each slot + // filling prompt is forwarded to the webhook. + Intent_WEBHOOK_STATE_ENABLED_FOR_SLOT_FILLING Intent_WebhookState = 2 +) + +var Intent_WebhookState_name = map[int32]string{ + 0: "WEBHOOK_STATE_UNSPECIFIED", + 1: "WEBHOOK_STATE_ENABLED", + 2: "WEBHOOK_STATE_ENABLED_FOR_SLOT_FILLING", +} +var Intent_WebhookState_value = map[string]int32{ + "WEBHOOK_STATE_UNSPECIFIED": 0, + "WEBHOOK_STATE_ENABLED": 1, + "WEBHOOK_STATE_ENABLED_FOR_SLOT_FILLING": 2, +} + +func (x Intent_WebhookState) String() string { + return proto.EnumName(Intent_WebhookState_name, int32(x)) +} +func (Intent_WebhookState) EnumDescriptor() ([]byte, []int) { return fileDescriptor3, []int{0, 0} } + +// Represents different types of training phrases. +type Intent_TrainingPhrase_Type int32 + +const ( + // Not specified. This value should never be used. + Intent_TrainingPhrase_TYPE_UNSPECIFIED Intent_TrainingPhrase_Type = 0 + // Examples do not contain @-prefixed entity type names, but example parts + // can be annotated with entity types. + Intent_TrainingPhrase_EXAMPLE Intent_TrainingPhrase_Type = 1 + // Templates are not annotated with entity types, but they can contain + // @-prefixed entity type names as substrings. + Intent_TrainingPhrase_TEMPLATE Intent_TrainingPhrase_Type = 2 +) + +var Intent_TrainingPhrase_Type_name = map[int32]string{ + 0: "TYPE_UNSPECIFIED", + 1: "EXAMPLE", + 2: "TEMPLATE", +} +var Intent_TrainingPhrase_Type_value = map[string]int32{ + "TYPE_UNSPECIFIED": 0, + "EXAMPLE": 1, + "TEMPLATE": 2, +} + +func (x Intent_TrainingPhrase_Type) String() string { + return proto.EnumName(Intent_TrainingPhrase_Type_name, int32(x)) +} +func (Intent_TrainingPhrase_Type) EnumDescriptor() ([]byte, []int) { + return fileDescriptor3, []int{0, 0, 0} +} + +// Represents different platforms that a rich message can be intended for. +type Intent_Message_Platform int32 + +const ( + // Not specified. + Intent_Message_PLATFORM_UNSPECIFIED Intent_Message_Platform = 0 + // Facebook. + Intent_Message_FACEBOOK Intent_Message_Platform = 1 + // Slack. + Intent_Message_SLACK Intent_Message_Platform = 2 + // Telegram. + Intent_Message_TELEGRAM Intent_Message_Platform = 3 + // Kik. + Intent_Message_KIK Intent_Message_Platform = 4 + // Skype. + Intent_Message_SKYPE Intent_Message_Platform = 5 + // Line. + Intent_Message_LINE Intent_Message_Platform = 6 + // Viber. + Intent_Message_VIBER Intent_Message_Platform = 7 + // Actions on Google. + Intent_Message_ACTIONS_ON_GOOGLE Intent_Message_Platform = 8 +) + +var Intent_Message_Platform_name = map[int32]string{ + 0: "PLATFORM_UNSPECIFIED", + 1: "FACEBOOK", + 2: "SLACK", + 3: "TELEGRAM", + 4: "KIK", + 5: "SKYPE", + 6: "LINE", + 7: "VIBER", + 8: "ACTIONS_ON_GOOGLE", +} +var Intent_Message_Platform_value = map[string]int32{ + "PLATFORM_UNSPECIFIED": 0, + "FACEBOOK": 1, + "SLACK": 2, + "TELEGRAM": 3, + "KIK": 4, + "SKYPE": 5, + "LINE": 6, + "VIBER": 7, + "ACTIONS_ON_GOOGLE": 8, +} + +func (x Intent_Message_Platform) String() string { + return proto.EnumName(Intent_Message_Platform_name, int32(x)) +} +func (Intent_Message_Platform) EnumDescriptor() ([]byte, []int) { + return fileDescriptor3, []int{0, 2, 0} +} + +// Represents an intent. +// Intents convert a number of user expressions or patterns into an action. An +// action is an extraction of a user command or sentence semantics. +type Intent struct { + // Required for all methods except `create` (`create` populates the name + // automatically. + // The unique identifier of this intent. + // Format: `projects//agent/intents/`. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // Required. The name of this intent. + DisplayName string `protobuf:"bytes,2,opt,name=display_name,json=displayName" json:"display_name,omitempty"` + // Required. Indicates whether webhooks are enabled for the intent. + WebhookState Intent_WebhookState `protobuf:"varint,6,opt,name=webhook_state,json=webhookState,enum=google.cloud.dialogflow.v2beta1.Intent_WebhookState" json:"webhook_state,omitempty"` + // Optional. The priority of this intent. Higher numbers represent higher + // priorities. Zero or negative numbers mean that the intent is disabled. + Priority int32 `protobuf:"varint,3,opt,name=priority" json:"priority,omitempty"` + // Optional. Indicates whether this is a fallback intent. + IsFallback bool `protobuf:"varint,4,opt,name=is_fallback,json=isFallback" json:"is_fallback,omitempty"` + // Optional. Indicates whether Machine Learning is enabled for the intent. + // Note: If `ml_enabled` setting is set to false, then this intent is not + // taken into account during inference in `ML ONLY` match mode. Also, + // auto-markup in the UI is turned off. + MlEnabled bool `protobuf:"varint,5,opt,name=ml_enabled,json=mlEnabled" json:"ml_enabled,omitempty"` + // Optional. The list of context names required for this intent to be + // triggered. + // Format: `projects//agent/sessions/-/contexts/`. + InputContextNames []string `protobuf:"bytes,7,rep,name=input_context_names,json=inputContextNames" json:"input_context_names,omitempty"` + // Optional. The collection of event names that trigger the intent. + // If the collection of input contexts is not empty, all of the contexts must + // be present in the active user session for an event to trigger this intent. + Events []string `protobuf:"bytes,8,rep,name=events" json:"events,omitempty"` + // Optional. The collection of examples/templates that the agent is + // trained on. + TrainingPhrases []*Intent_TrainingPhrase `protobuf:"bytes,9,rep,name=training_phrases,json=trainingPhrases" json:"training_phrases,omitempty"` + // Optional. The name of the action associated with the intent. + Action string `protobuf:"bytes,10,opt,name=action" json:"action,omitempty"` + // Optional. The collection of contexts that are activated when the intent + // is matched. Context messages in this collection should not set the + // parameters field. Setting the `lifespan_count` to 0 will reset the context + // when the intent is matched. + // Format: `projects//agent/sessions/-/contexts/`. + OutputContexts []*Context `protobuf:"bytes,11,rep,name=output_contexts,json=outputContexts" json:"output_contexts,omitempty"` + // Optional. Indicates whether to delete all contexts in the current + // session when this intent is matched. + ResetContexts bool `protobuf:"varint,12,opt,name=reset_contexts,json=resetContexts" json:"reset_contexts,omitempty"` + // Optional. The collection of parameters associated with the intent. + Parameters []*Intent_Parameter `protobuf:"bytes,13,rep,name=parameters" json:"parameters,omitempty"` + // Optional. The collection of rich messages corresponding to the + // `Response` field in API.AI console. + Messages []*Intent_Message `protobuf:"bytes,14,rep,name=messages" json:"messages,omitempty"` + // Optional. The list of platforms for which the first response will be + // taken from among the messages assigned to the DEFAULT_PLATFORM. + DefaultResponsePlatforms []Intent_Message_Platform `protobuf:"varint,15,rep,packed,name=default_response_platforms,json=defaultResponsePlatforms,enum=google.cloud.dialogflow.v2beta1.Intent_Message_Platform" json:"default_response_platforms,omitempty"` + // The unique identifier of the root intent in the chain of followup intents. + // It identifies the correct followup intents chain for this intent. + // Format: `projects//agent/intents/`. + RootFollowupIntentName string `protobuf:"bytes,16,opt,name=root_followup_intent_name,json=rootFollowupIntentName" json:"root_followup_intent_name,omitempty"` + // The unique identifier of the parent intent in the chain of followup + // intents. + // It identifies the parent followup intent. + // Format: `projects//agent/intents/`. + ParentFollowupIntentName string `protobuf:"bytes,17,opt,name=parent_followup_intent_name,json=parentFollowupIntentName" json:"parent_followup_intent_name,omitempty"` + // Optional. Collection of information about all followup intents that have + // name of this intent as a root_name. + FollowupIntentInfo []*Intent_FollowupIntentInfo `protobuf:"bytes,18,rep,name=followup_intent_info,json=followupIntentInfo" json:"followup_intent_info,omitempty"` +} + +func (m *Intent) Reset() { *m = Intent{} } +func (m *Intent) String() string { return proto.CompactTextString(m) } +func (*Intent) ProtoMessage() {} +func (*Intent) Descriptor() ([]byte, []int) { return fileDescriptor3, []int{0} } + +func (m *Intent) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *Intent) GetDisplayName() string { + if m != nil { + return m.DisplayName + } + return "" +} + +func (m *Intent) GetWebhookState() Intent_WebhookState { + if m != nil { + return m.WebhookState + } + return Intent_WEBHOOK_STATE_UNSPECIFIED +} + +func (m *Intent) GetPriority() int32 { + if m != nil { + return m.Priority + } + return 0 +} + +func (m *Intent) GetIsFallback() bool { + if m != nil { + return m.IsFallback + } + return false +} + +func (m *Intent) GetMlEnabled() bool { + if m != nil { + return m.MlEnabled + } + return false +} + +func (m *Intent) GetInputContextNames() []string { + if m != nil { + return m.InputContextNames + } + return nil +} + +func (m *Intent) GetEvents() []string { + if m != nil { + return m.Events + } + return nil +} + +func (m *Intent) GetTrainingPhrases() []*Intent_TrainingPhrase { + if m != nil { + return m.TrainingPhrases + } + return nil +} + +func (m *Intent) GetAction() string { + if m != nil { + return m.Action + } + return "" +} + +func (m *Intent) GetOutputContexts() []*Context { + if m != nil { + return m.OutputContexts + } + return nil +} + +func (m *Intent) GetResetContexts() bool { + if m != nil { + return m.ResetContexts + } + return false +} + +func (m *Intent) GetParameters() []*Intent_Parameter { + if m != nil { + return m.Parameters + } + return nil +} + +func (m *Intent) GetMessages() []*Intent_Message { + if m != nil { + return m.Messages + } + return nil +} + +func (m *Intent) GetDefaultResponsePlatforms() []Intent_Message_Platform { + if m != nil { + return m.DefaultResponsePlatforms + } + return nil +} + +func (m *Intent) GetRootFollowupIntentName() string { + if m != nil { + return m.RootFollowupIntentName + } + return "" +} + +func (m *Intent) GetParentFollowupIntentName() string { + if m != nil { + return m.ParentFollowupIntentName + } + return "" +} + +func (m *Intent) GetFollowupIntentInfo() []*Intent_FollowupIntentInfo { + if m != nil { + return m.FollowupIntentInfo + } + return nil +} + +// Represents an example or template that the agent is trained on. +type Intent_TrainingPhrase struct { + // Required. The unique identifier of this training phrase. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // Required. The type of the training phrase. + Type Intent_TrainingPhrase_Type `protobuf:"varint,2,opt,name=type,enum=google.cloud.dialogflow.v2beta1.Intent_TrainingPhrase_Type" json:"type,omitempty"` + // Required. The collection of training phrase parts (can be annotated). + // Fields: `entity_type`, `alias` and `user_defined` should be populated + // only for the annotated parts of the training phrase. + Parts []*Intent_TrainingPhrase_Part `protobuf:"bytes,3,rep,name=parts" json:"parts,omitempty"` + // Optional. Indicates how many times this example or template was added to + // the intent. Each time a developer adds an existing sample by editing an + // intent or training, this counter is increased. + TimesAddedCount int32 `protobuf:"varint,4,opt,name=times_added_count,json=timesAddedCount" json:"times_added_count,omitempty"` +} + +func (m *Intent_TrainingPhrase) Reset() { *m = Intent_TrainingPhrase{} } +func (m *Intent_TrainingPhrase) String() string { return proto.CompactTextString(m) } +func (*Intent_TrainingPhrase) ProtoMessage() {} +func (*Intent_TrainingPhrase) Descriptor() ([]byte, []int) { return fileDescriptor3, []int{0, 0} } + +func (m *Intent_TrainingPhrase) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *Intent_TrainingPhrase) GetType() Intent_TrainingPhrase_Type { + if m != nil { + return m.Type + } + return Intent_TrainingPhrase_TYPE_UNSPECIFIED +} + +func (m *Intent_TrainingPhrase) GetParts() []*Intent_TrainingPhrase_Part { + if m != nil { + return m.Parts + } + return nil +} + +func (m *Intent_TrainingPhrase) GetTimesAddedCount() int32 { + if m != nil { + return m.TimesAddedCount + } + return 0 +} + +// Represents a part of a training phrase. +type Intent_TrainingPhrase_Part struct { + // Required. The text corresponding to the example or template, + // if there are no annotations. For + // annotated examples, it is the text for one of the example's parts. + Text string `protobuf:"bytes,1,opt,name=text" json:"text,omitempty"` + // Optional. The entity type name prefixed with `@`. This field is + // required for the annotated part of the text and applies only to + // examples. + EntityType string `protobuf:"bytes,2,opt,name=entity_type,json=entityType" json:"entity_type,omitempty"` + // Optional. The parameter name for the value extracted from the + // annotated part of the example. + Alias string `protobuf:"bytes,3,opt,name=alias" json:"alias,omitempty"` + // Optional. Indicates whether the text was manually annotated by the + // developer. + UserDefined bool `protobuf:"varint,4,opt,name=user_defined,json=userDefined" json:"user_defined,omitempty"` +} + +func (m *Intent_TrainingPhrase_Part) Reset() { *m = Intent_TrainingPhrase_Part{} } +func (m *Intent_TrainingPhrase_Part) String() string { return proto.CompactTextString(m) } +func (*Intent_TrainingPhrase_Part) ProtoMessage() {} +func (*Intent_TrainingPhrase_Part) Descriptor() ([]byte, []int) { + return fileDescriptor3, []int{0, 0, 0} +} + +func (m *Intent_TrainingPhrase_Part) GetText() string { + if m != nil { + return m.Text + } + return "" +} + +func (m *Intent_TrainingPhrase_Part) GetEntityType() string { + if m != nil { + return m.EntityType + } + return "" +} + +func (m *Intent_TrainingPhrase_Part) GetAlias() string { + if m != nil { + return m.Alias + } + return "" +} + +func (m *Intent_TrainingPhrase_Part) GetUserDefined() bool { + if m != nil { + return m.UserDefined + } + return false +} + +// Represents intent parameters. +type Intent_Parameter struct { + // The unique identifier of this parameter. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // Required. The name of the parameter. + DisplayName string `protobuf:"bytes,2,opt,name=display_name,json=displayName" json:"display_name,omitempty"` + // Optional. The definition of the parameter value. It can be: + // - a constant string, + // - a parameter value defined as `$parameter_name`, + // - an original parameter value defined as `$parameter_name.original`, + // - a parameter value from some context defined as + // `#context_name.parameter_name`. + Value string `protobuf:"bytes,3,opt,name=value" json:"value,omitempty"` + // Optional. The default value to use when the `value` yields an empty + // result. + // Default values can be extracted from contexts by using the following + // syntax: `#context_name.parameter_name`. + DefaultValue string `protobuf:"bytes,4,opt,name=default_value,json=defaultValue" json:"default_value,omitempty"` + // Optional. The name of the entity type, prefixed with `@`, that + // describes values of the parameter. If the parameter is + // required, this must be provided. + EntityTypeDisplayName string `protobuf:"bytes,5,opt,name=entity_type_display_name,json=entityTypeDisplayName" json:"entity_type_display_name,omitempty"` + // Optional. Indicates whether the parameter is required. That is, + // whether the intent cannot be completed without collecting the parameter + // value. + Mandatory bool `protobuf:"varint,6,opt,name=mandatory" json:"mandatory,omitempty"` + // Optional. The collection of prompts that the agent can present to the + // user in order to collect value for the parameter. + Prompts []string `protobuf:"bytes,7,rep,name=prompts" json:"prompts,omitempty"` + // Optional. Indicates whether the parameter represents a list of values. + IsList bool `protobuf:"varint,8,opt,name=is_list,json=isList" json:"is_list,omitempty"` +} + +func (m *Intent_Parameter) Reset() { *m = Intent_Parameter{} } +func (m *Intent_Parameter) String() string { return proto.CompactTextString(m) } +func (*Intent_Parameter) ProtoMessage() {} +func (*Intent_Parameter) Descriptor() ([]byte, []int) { return fileDescriptor3, []int{0, 1} } + +func (m *Intent_Parameter) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *Intent_Parameter) GetDisplayName() string { + if m != nil { + return m.DisplayName + } + return "" +} + +func (m *Intent_Parameter) GetValue() string { + if m != nil { + return m.Value + } + return "" +} + +func (m *Intent_Parameter) GetDefaultValue() string { + if m != nil { + return m.DefaultValue + } + return "" +} + +func (m *Intent_Parameter) GetEntityTypeDisplayName() string { + if m != nil { + return m.EntityTypeDisplayName + } + return "" +} + +func (m *Intent_Parameter) GetMandatory() bool { + if m != nil { + return m.Mandatory + } + return false +} + +func (m *Intent_Parameter) GetPrompts() []string { + if m != nil { + return m.Prompts + } + return nil +} + +func (m *Intent_Parameter) GetIsList() bool { + if m != nil { + return m.IsList + } + return false +} + +// Corresponds to the `Response` field in API.AI console. +type Intent_Message struct { + // Required. The rich response message. + // + // Types that are valid to be assigned to Message: + // *Intent_Message_Text_ + // *Intent_Message_Image_ + // *Intent_Message_QuickReplies_ + // *Intent_Message_Card_ + // *Intent_Message_Payload + // *Intent_Message_SimpleResponses_ + // *Intent_Message_BasicCard_ + // *Intent_Message_Suggestions_ + // *Intent_Message_LinkOutSuggestion_ + // *Intent_Message_ListSelect_ + // *Intent_Message_CarouselSelect_ + Message isIntent_Message_Message `protobuf_oneof:"message"` + // Optional. The platform that this message is intended for. + Platform Intent_Message_Platform `protobuf:"varint,6,opt,name=platform,enum=google.cloud.dialogflow.v2beta1.Intent_Message_Platform" json:"platform,omitempty"` +} + +func (m *Intent_Message) Reset() { *m = Intent_Message{} } +func (m *Intent_Message) String() string { return proto.CompactTextString(m) } +func (*Intent_Message) ProtoMessage() {} +func (*Intent_Message) Descriptor() ([]byte, []int) { return fileDescriptor3, []int{0, 2} } + +type isIntent_Message_Message interface { + isIntent_Message_Message() +} + +type Intent_Message_Text_ struct { + Text *Intent_Message_Text `protobuf:"bytes,1,opt,name=text,oneof"` +} +type Intent_Message_Image_ struct { + Image *Intent_Message_Image `protobuf:"bytes,2,opt,name=image,oneof"` +} +type Intent_Message_QuickReplies_ struct { + QuickReplies *Intent_Message_QuickReplies `protobuf:"bytes,3,opt,name=quick_replies,json=quickReplies,oneof"` +} +type Intent_Message_Card_ struct { + Card *Intent_Message_Card `protobuf:"bytes,4,opt,name=card,oneof"` +} +type Intent_Message_Payload struct { + Payload *google_protobuf4.Struct `protobuf:"bytes,5,opt,name=payload,oneof"` +} +type Intent_Message_SimpleResponses_ struct { + SimpleResponses *Intent_Message_SimpleResponses `protobuf:"bytes,7,opt,name=simple_responses,json=simpleResponses,oneof"` +} +type Intent_Message_BasicCard_ struct { + BasicCard *Intent_Message_BasicCard `protobuf:"bytes,8,opt,name=basic_card,json=basicCard,oneof"` +} +type Intent_Message_Suggestions_ struct { + Suggestions *Intent_Message_Suggestions `protobuf:"bytes,9,opt,name=suggestions,oneof"` +} +type Intent_Message_LinkOutSuggestion_ struct { + LinkOutSuggestion *Intent_Message_LinkOutSuggestion `protobuf:"bytes,10,opt,name=link_out_suggestion,json=linkOutSuggestion,oneof"` +} +type Intent_Message_ListSelect_ struct { + ListSelect *Intent_Message_ListSelect `protobuf:"bytes,11,opt,name=list_select,json=listSelect,oneof"` +} +type Intent_Message_CarouselSelect_ struct { + CarouselSelect *Intent_Message_CarouselSelect `protobuf:"bytes,12,opt,name=carousel_select,json=carouselSelect,oneof"` +} + +func (*Intent_Message_Text_) isIntent_Message_Message() {} +func (*Intent_Message_Image_) isIntent_Message_Message() {} +func (*Intent_Message_QuickReplies_) isIntent_Message_Message() {} +func (*Intent_Message_Card_) isIntent_Message_Message() {} +func (*Intent_Message_Payload) isIntent_Message_Message() {} +func (*Intent_Message_SimpleResponses_) isIntent_Message_Message() {} +func (*Intent_Message_BasicCard_) isIntent_Message_Message() {} +func (*Intent_Message_Suggestions_) isIntent_Message_Message() {} +func (*Intent_Message_LinkOutSuggestion_) isIntent_Message_Message() {} +func (*Intent_Message_ListSelect_) isIntent_Message_Message() {} +func (*Intent_Message_CarouselSelect_) isIntent_Message_Message() {} + +func (m *Intent_Message) GetMessage() isIntent_Message_Message { + if m != nil { + return m.Message + } + return nil +} + +func (m *Intent_Message) GetText() *Intent_Message_Text { + if x, ok := m.GetMessage().(*Intent_Message_Text_); ok { + return x.Text + } + return nil +} + +func (m *Intent_Message) GetImage() *Intent_Message_Image { + if x, ok := m.GetMessage().(*Intent_Message_Image_); ok { + return x.Image + } + return nil +} + +func (m *Intent_Message) GetQuickReplies() *Intent_Message_QuickReplies { + if x, ok := m.GetMessage().(*Intent_Message_QuickReplies_); ok { + return x.QuickReplies + } + return nil +} + +func (m *Intent_Message) GetCard() *Intent_Message_Card { + if x, ok := m.GetMessage().(*Intent_Message_Card_); ok { + return x.Card + } + return nil +} + +func (m *Intent_Message) GetPayload() *google_protobuf4.Struct { + if x, ok := m.GetMessage().(*Intent_Message_Payload); ok { + return x.Payload + } + return nil +} + +func (m *Intent_Message) GetSimpleResponses() *Intent_Message_SimpleResponses { + if x, ok := m.GetMessage().(*Intent_Message_SimpleResponses_); ok { + return x.SimpleResponses + } + return nil +} + +func (m *Intent_Message) GetBasicCard() *Intent_Message_BasicCard { + if x, ok := m.GetMessage().(*Intent_Message_BasicCard_); ok { + return x.BasicCard + } + return nil +} + +func (m *Intent_Message) GetSuggestions() *Intent_Message_Suggestions { + if x, ok := m.GetMessage().(*Intent_Message_Suggestions_); ok { + return x.Suggestions + } + return nil +} + +func (m *Intent_Message) GetLinkOutSuggestion() *Intent_Message_LinkOutSuggestion { + if x, ok := m.GetMessage().(*Intent_Message_LinkOutSuggestion_); ok { + return x.LinkOutSuggestion + } + return nil +} + +func (m *Intent_Message) GetListSelect() *Intent_Message_ListSelect { + if x, ok := m.GetMessage().(*Intent_Message_ListSelect_); ok { + return x.ListSelect + } + return nil +} + +func (m *Intent_Message) GetCarouselSelect() *Intent_Message_CarouselSelect { + if x, ok := m.GetMessage().(*Intent_Message_CarouselSelect_); ok { + return x.CarouselSelect + } + return nil +} + +func (m *Intent_Message) GetPlatform() Intent_Message_Platform { + if m != nil { + return m.Platform + } + return Intent_Message_PLATFORM_UNSPECIFIED +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*Intent_Message) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _Intent_Message_OneofMarshaler, _Intent_Message_OneofUnmarshaler, _Intent_Message_OneofSizer, []interface{}{ + (*Intent_Message_Text_)(nil), + (*Intent_Message_Image_)(nil), + (*Intent_Message_QuickReplies_)(nil), + (*Intent_Message_Card_)(nil), + (*Intent_Message_Payload)(nil), + (*Intent_Message_SimpleResponses_)(nil), + (*Intent_Message_BasicCard_)(nil), + (*Intent_Message_Suggestions_)(nil), + (*Intent_Message_LinkOutSuggestion_)(nil), + (*Intent_Message_ListSelect_)(nil), + (*Intent_Message_CarouselSelect_)(nil), + } +} + +func _Intent_Message_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*Intent_Message) + // message + switch x := m.Message.(type) { + case *Intent_Message_Text_: + b.EncodeVarint(1<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Text); err != nil { + return err + } + case *Intent_Message_Image_: + b.EncodeVarint(2<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Image); err != nil { + return err + } + case *Intent_Message_QuickReplies_: + b.EncodeVarint(3<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.QuickReplies); err != nil { + return err + } + case *Intent_Message_Card_: + b.EncodeVarint(4<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Card); err != nil { + return err + } + case *Intent_Message_Payload: + b.EncodeVarint(5<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Payload); err != nil { + return err + } + case *Intent_Message_SimpleResponses_: + b.EncodeVarint(7<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.SimpleResponses); err != nil { + return err + } + case *Intent_Message_BasicCard_: + b.EncodeVarint(8<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.BasicCard); err != nil { + return err + } + case *Intent_Message_Suggestions_: + b.EncodeVarint(9<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Suggestions); err != nil { + return err + } + case *Intent_Message_LinkOutSuggestion_: + b.EncodeVarint(10<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.LinkOutSuggestion); err != nil { + return err + } + case *Intent_Message_ListSelect_: + b.EncodeVarint(11<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.ListSelect); err != nil { + return err + } + case *Intent_Message_CarouselSelect_: + b.EncodeVarint(12<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.CarouselSelect); err != nil { + return err + } + case nil: + default: + return fmt.Errorf("Intent_Message.Message has unexpected type %T", x) + } + return nil +} + +func _Intent_Message_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*Intent_Message) + switch tag { + case 1: // message.text + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(Intent_Message_Text) + err := b.DecodeMessage(msg) + m.Message = &Intent_Message_Text_{msg} + return true, err + case 2: // message.image + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(Intent_Message_Image) + err := b.DecodeMessage(msg) + m.Message = &Intent_Message_Image_{msg} + return true, err + case 3: // message.quick_replies + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(Intent_Message_QuickReplies) + err := b.DecodeMessage(msg) + m.Message = &Intent_Message_QuickReplies_{msg} + return true, err + case 4: // message.card + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(Intent_Message_Card) + err := b.DecodeMessage(msg) + m.Message = &Intent_Message_Card_{msg} + return true, err + case 5: // message.payload + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(google_protobuf4.Struct) + err := b.DecodeMessage(msg) + m.Message = &Intent_Message_Payload{msg} + return true, err + case 7: // message.simple_responses + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(Intent_Message_SimpleResponses) + err := b.DecodeMessage(msg) + m.Message = &Intent_Message_SimpleResponses_{msg} + return true, err + case 8: // message.basic_card + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(Intent_Message_BasicCard) + err := b.DecodeMessage(msg) + m.Message = &Intent_Message_BasicCard_{msg} + return true, err + case 9: // message.suggestions + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(Intent_Message_Suggestions) + err := b.DecodeMessage(msg) + m.Message = &Intent_Message_Suggestions_{msg} + return true, err + case 10: // message.link_out_suggestion + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(Intent_Message_LinkOutSuggestion) + err := b.DecodeMessage(msg) + m.Message = &Intent_Message_LinkOutSuggestion_{msg} + return true, err + case 11: // message.list_select + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(Intent_Message_ListSelect) + err := b.DecodeMessage(msg) + m.Message = &Intent_Message_ListSelect_{msg} + return true, err + case 12: // message.carousel_select + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(Intent_Message_CarouselSelect) + err := b.DecodeMessage(msg) + m.Message = &Intent_Message_CarouselSelect_{msg} + return true, err + default: + return false, nil + } +} + +func _Intent_Message_OneofSizer(msg proto.Message) (n int) { + m := msg.(*Intent_Message) + // message + switch x := m.Message.(type) { + case *Intent_Message_Text_: + s := proto.Size(x.Text) + n += proto.SizeVarint(1<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Intent_Message_Image_: + s := proto.Size(x.Image) + n += proto.SizeVarint(2<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Intent_Message_QuickReplies_: + s := proto.Size(x.QuickReplies) + n += proto.SizeVarint(3<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Intent_Message_Card_: + s := proto.Size(x.Card) + n += proto.SizeVarint(4<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Intent_Message_Payload: + s := proto.Size(x.Payload) + n += proto.SizeVarint(5<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Intent_Message_SimpleResponses_: + s := proto.Size(x.SimpleResponses) + n += proto.SizeVarint(7<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Intent_Message_BasicCard_: + s := proto.Size(x.BasicCard) + n += proto.SizeVarint(8<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Intent_Message_Suggestions_: + s := proto.Size(x.Suggestions) + n += proto.SizeVarint(9<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Intent_Message_LinkOutSuggestion_: + s := proto.Size(x.LinkOutSuggestion) + n += proto.SizeVarint(10<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Intent_Message_ListSelect_: + s := proto.Size(x.ListSelect) + n += proto.SizeVarint(11<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Intent_Message_CarouselSelect_: + s := proto.Size(x.CarouselSelect) + n += proto.SizeVarint(12<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +// The text response message. +type Intent_Message_Text struct { + // Optional. The collection of the agent's responses. + Text []string `protobuf:"bytes,1,rep,name=text" json:"text,omitempty"` +} + +func (m *Intent_Message_Text) Reset() { *m = Intent_Message_Text{} } +func (m *Intent_Message_Text) String() string { return proto.CompactTextString(m) } +func (*Intent_Message_Text) ProtoMessage() {} +func (*Intent_Message_Text) Descriptor() ([]byte, []int) { return fileDescriptor3, []int{0, 2, 0} } + +func (m *Intent_Message_Text) GetText() []string { + if m != nil { + return m.Text + } + return nil +} + +// The image response message. +type Intent_Message_Image struct { + // Optional. The public URI to an image file. + ImageUri string `protobuf:"bytes,1,opt,name=image_uri,json=imageUri" json:"image_uri,omitempty"` +} + +func (m *Intent_Message_Image) Reset() { *m = Intent_Message_Image{} } +func (m *Intent_Message_Image) String() string { return proto.CompactTextString(m) } +func (*Intent_Message_Image) ProtoMessage() {} +func (*Intent_Message_Image) Descriptor() ([]byte, []int) { return fileDescriptor3, []int{0, 2, 1} } + +func (m *Intent_Message_Image) GetImageUri() string { + if m != nil { + return m.ImageUri + } + return "" +} + +// The quick replies response message. +type Intent_Message_QuickReplies struct { + // Optional. The title of the collection of quick replies. + Title string `protobuf:"bytes,1,opt,name=title" json:"title,omitempty"` + // Optional. The collection of quick replies. + QuickReplies []string `protobuf:"bytes,2,rep,name=quick_replies,json=quickReplies" json:"quick_replies,omitempty"` +} + +func (m *Intent_Message_QuickReplies) Reset() { *m = Intent_Message_QuickReplies{} } +func (m *Intent_Message_QuickReplies) String() string { return proto.CompactTextString(m) } +func (*Intent_Message_QuickReplies) ProtoMessage() {} +func (*Intent_Message_QuickReplies) Descriptor() ([]byte, []int) { + return fileDescriptor3, []int{0, 2, 2} +} + +func (m *Intent_Message_QuickReplies) GetTitle() string { + if m != nil { + return m.Title + } + return "" +} + +func (m *Intent_Message_QuickReplies) GetQuickReplies() []string { + if m != nil { + return m.QuickReplies + } + return nil +} + +// The card response message. +type Intent_Message_Card struct { + // Optional. The title of the card. + Title string `protobuf:"bytes,1,opt,name=title" json:"title,omitempty"` + // Optional. The subtitle of the card. + Subtitle string `protobuf:"bytes,2,opt,name=subtitle" json:"subtitle,omitempty"` + // Optional. The public URI to an image file for the card. + ImageUri string `protobuf:"bytes,3,opt,name=image_uri,json=imageUri" json:"image_uri,omitempty"` + // Optional. The collection of card buttons. + Buttons []*Intent_Message_Card_Button `protobuf:"bytes,4,rep,name=buttons" json:"buttons,omitempty"` +} + +func (m *Intent_Message_Card) Reset() { *m = Intent_Message_Card{} } +func (m *Intent_Message_Card) String() string { return proto.CompactTextString(m) } +func (*Intent_Message_Card) ProtoMessage() {} +func (*Intent_Message_Card) Descriptor() ([]byte, []int) { return fileDescriptor3, []int{0, 2, 3} } + +func (m *Intent_Message_Card) GetTitle() string { + if m != nil { + return m.Title + } + return "" +} + +func (m *Intent_Message_Card) GetSubtitle() string { + if m != nil { + return m.Subtitle + } + return "" +} + +func (m *Intent_Message_Card) GetImageUri() string { + if m != nil { + return m.ImageUri + } + return "" +} + +func (m *Intent_Message_Card) GetButtons() []*Intent_Message_Card_Button { + if m != nil { + return m.Buttons + } + return nil +} + +// Optional. Contains information about a button. +type Intent_Message_Card_Button struct { + // Optional. The text to show on the button. + Text string `protobuf:"bytes,1,opt,name=text" json:"text,omitempty"` + // Optional. The text to send back to the Dialogflow API or a URI to + // open. + Postback string `protobuf:"bytes,2,opt,name=postback" json:"postback,omitempty"` +} + +func (m *Intent_Message_Card_Button) Reset() { *m = Intent_Message_Card_Button{} } +func (m *Intent_Message_Card_Button) String() string { return proto.CompactTextString(m) } +func (*Intent_Message_Card_Button) ProtoMessage() {} +func (*Intent_Message_Card_Button) Descriptor() ([]byte, []int) { + return fileDescriptor3, []int{0, 2, 3, 0} +} + +func (m *Intent_Message_Card_Button) GetText() string { + if m != nil { + return m.Text + } + return "" +} + +func (m *Intent_Message_Card_Button) GetPostback() string { + if m != nil { + return m.Postback + } + return "" +} + +// The simple response message containing speech or text. +type Intent_Message_SimpleResponse struct { + // One of text_to_speech or ssml must be provided. The plain text of the + // speech output. Mutually exclusive with ssml. + TextToSpeech string `protobuf:"bytes,1,opt,name=text_to_speech,json=textToSpeech" json:"text_to_speech,omitempty"` + // One of text_to_speech or ssml must be provided. Structured spoken + // response to the user in the SSML format. Mutually exclusive with + // text_to_speech. + Ssml string `protobuf:"bytes,2,opt,name=ssml" json:"ssml,omitempty"` + // Optional. The text to display. + DisplayText string `protobuf:"bytes,3,opt,name=display_text,json=displayText" json:"display_text,omitempty"` +} + +func (m *Intent_Message_SimpleResponse) Reset() { *m = Intent_Message_SimpleResponse{} } +func (m *Intent_Message_SimpleResponse) String() string { return proto.CompactTextString(m) } +func (*Intent_Message_SimpleResponse) ProtoMessage() {} +func (*Intent_Message_SimpleResponse) Descriptor() ([]byte, []int) { + return fileDescriptor3, []int{0, 2, 4} +} + +func (m *Intent_Message_SimpleResponse) GetTextToSpeech() string { + if m != nil { + return m.TextToSpeech + } + return "" +} + +func (m *Intent_Message_SimpleResponse) GetSsml() string { + if m != nil { + return m.Ssml + } + return "" +} + +func (m *Intent_Message_SimpleResponse) GetDisplayText() string { + if m != nil { + return m.DisplayText + } + return "" +} + +// The collection of simple response candidates. +// This message in `QueryResult.fulfillment_messages` and +// `WebhookResponse.fulfillment_messages` should contain only one +// `SimpleResponse`. +type Intent_Message_SimpleResponses struct { + // Required. The list of simple responses. + SimpleResponses []*Intent_Message_SimpleResponse `protobuf:"bytes,1,rep,name=simple_responses,json=simpleResponses" json:"simple_responses,omitempty"` +} + +func (m *Intent_Message_SimpleResponses) Reset() { *m = Intent_Message_SimpleResponses{} } +func (m *Intent_Message_SimpleResponses) String() string { return proto.CompactTextString(m) } +func (*Intent_Message_SimpleResponses) ProtoMessage() {} +func (*Intent_Message_SimpleResponses) Descriptor() ([]byte, []int) { + return fileDescriptor3, []int{0, 2, 5} +} + +func (m *Intent_Message_SimpleResponses) GetSimpleResponses() []*Intent_Message_SimpleResponse { + if m != nil { + return m.SimpleResponses + } + return nil +} + +// The basic card message. Useful for displaying information. +type Intent_Message_BasicCard struct { + // Optional. The title of the card. + Title string `protobuf:"bytes,1,opt,name=title" json:"title,omitempty"` + // Optional. The subtitle of the card. + Subtitle string `protobuf:"bytes,2,opt,name=subtitle" json:"subtitle,omitempty"` + // Required, unless image is present. The body text of the card. + FormattedText string `protobuf:"bytes,3,opt,name=formatted_text,json=formattedText" json:"formatted_text,omitempty"` + // Optional. The image for the card. + Image *Intent_Message_Image `protobuf:"bytes,4,opt,name=image" json:"image,omitempty"` + // Optional. The collection of card buttons. + Buttons []*Intent_Message_BasicCard_Button `protobuf:"bytes,5,rep,name=buttons" json:"buttons,omitempty"` +} + +func (m *Intent_Message_BasicCard) Reset() { *m = Intent_Message_BasicCard{} } +func (m *Intent_Message_BasicCard) String() string { return proto.CompactTextString(m) } +func (*Intent_Message_BasicCard) ProtoMessage() {} +func (*Intent_Message_BasicCard) Descriptor() ([]byte, []int) { return fileDescriptor3, []int{0, 2, 6} } + +func (m *Intent_Message_BasicCard) GetTitle() string { + if m != nil { + return m.Title + } + return "" +} + +func (m *Intent_Message_BasicCard) GetSubtitle() string { + if m != nil { + return m.Subtitle + } + return "" +} + +func (m *Intent_Message_BasicCard) GetFormattedText() string { + if m != nil { + return m.FormattedText + } + return "" +} + +func (m *Intent_Message_BasicCard) GetImage() *Intent_Message_Image { + if m != nil { + return m.Image + } + return nil +} + +func (m *Intent_Message_BasicCard) GetButtons() []*Intent_Message_BasicCard_Button { + if m != nil { + return m.Buttons + } + return nil +} + +// The button object that appears at the bottom of a card. +type Intent_Message_BasicCard_Button struct { + // Required. The title of the button. + Title string `protobuf:"bytes,1,opt,name=title" json:"title,omitempty"` + // Required. Action to take when a user taps on the button. + OpenUriAction *Intent_Message_BasicCard_Button_OpenUriAction `protobuf:"bytes,2,opt,name=open_uri_action,json=openUriAction" json:"open_uri_action,omitempty"` +} + +func (m *Intent_Message_BasicCard_Button) Reset() { *m = Intent_Message_BasicCard_Button{} } +func (m *Intent_Message_BasicCard_Button) String() string { return proto.CompactTextString(m) } +func (*Intent_Message_BasicCard_Button) ProtoMessage() {} +func (*Intent_Message_BasicCard_Button) Descriptor() ([]byte, []int) { + return fileDescriptor3, []int{0, 2, 6, 0} +} + +func (m *Intent_Message_BasicCard_Button) GetTitle() string { + if m != nil { + return m.Title + } + return "" +} + +func (m *Intent_Message_BasicCard_Button) GetOpenUriAction() *Intent_Message_BasicCard_Button_OpenUriAction { + if m != nil { + return m.OpenUriAction + } + return nil +} + +// Opens the given URI. +type Intent_Message_BasicCard_Button_OpenUriAction struct { + // Required. The HTTP or HTTPS scheme URI. + Uri string `protobuf:"bytes,1,opt,name=uri" json:"uri,omitempty"` +} + +func (m *Intent_Message_BasicCard_Button_OpenUriAction) Reset() { + *m = Intent_Message_BasicCard_Button_OpenUriAction{} +} +func (m *Intent_Message_BasicCard_Button_OpenUriAction) String() string { + return proto.CompactTextString(m) +} +func (*Intent_Message_BasicCard_Button_OpenUriAction) ProtoMessage() {} +func (*Intent_Message_BasicCard_Button_OpenUriAction) Descriptor() ([]byte, []int) { + return fileDescriptor3, []int{0, 2, 6, 0, 0} +} + +func (m *Intent_Message_BasicCard_Button_OpenUriAction) GetUri() string { + if m != nil { + return m.Uri + } + return "" +} + +// The suggestion chip message that the user can tap to quickly post a reply +// to the conversation. +type Intent_Message_Suggestion struct { + // Required. The text shown the in the suggestion chip. + Title string `protobuf:"bytes,1,opt,name=title" json:"title,omitempty"` +} + +func (m *Intent_Message_Suggestion) Reset() { *m = Intent_Message_Suggestion{} } +func (m *Intent_Message_Suggestion) String() string { return proto.CompactTextString(m) } +func (*Intent_Message_Suggestion) ProtoMessage() {} +func (*Intent_Message_Suggestion) Descriptor() ([]byte, []int) { return fileDescriptor3, []int{0, 2, 7} } + +func (m *Intent_Message_Suggestion) GetTitle() string { + if m != nil { + return m.Title + } + return "" +} + +// The collection of suggestions. +type Intent_Message_Suggestions struct { + // Required. The list of suggested replies. + Suggestions []*Intent_Message_Suggestion `protobuf:"bytes,1,rep,name=suggestions" json:"suggestions,omitempty"` +} + +func (m *Intent_Message_Suggestions) Reset() { *m = Intent_Message_Suggestions{} } +func (m *Intent_Message_Suggestions) String() string { return proto.CompactTextString(m) } +func (*Intent_Message_Suggestions) ProtoMessage() {} +func (*Intent_Message_Suggestions) Descriptor() ([]byte, []int) { + return fileDescriptor3, []int{0, 2, 8} +} + +func (m *Intent_Message_Suggestions) GetSuggestions() []*Intent_Message_Suggestion { + if m != nil { + return m.Suggestions + } + return nil +} + +// The suggestion chip message that allows the user to jump out to the app +// or website associated with this agent. +type Intent_Message_LinkOutSuggestion struct { + // Required. The name of the app or site this chip is linking to. + DestinationName string `protobuf:"bytes,1,opt,name=destination_name,json=destinationName" json:"destination_name,omitempty"` + // Required. The URI of the app or site to open when the user taps the + // suggestion chip. + Uri string `protobuf:"bytes,2,opt,name=uri" json:"uri,omitempty"` +} + +func (m *Intent_Message_LinkOutSuggestion) Reset() { *m = Intent_Message_LinkOutSuggestion{} } +func (m *Intent_Message_LinkOutSuggestion) String() string { return proto.CompactTextString(m) } +func (*Intent_Message_LinkOutSuggestion) ProtoMessage() {} +func (*Intent_Message_LinkOutSuggestion) Descriptor() ([]byte, []int) { + return fileDescriptor3, []int{0, 2, 9} +} + +func (m *Intent_Message_LinkOutSuggestion) GetDestinationName() string { + if m != nil { + return m.DestinationName + } + return "" +} + +func (m *Intent_Message_LinkOutSuggestion) GetUri() string { + if m != nil { + return m.Uri + } + return "" +} + +// The card for presenting a list of options to select from. +type Intent_Message_ListSelect struct { + // Optional. The overall title of the list. + Title string `protobuf:"bytes,1,opt,name=title" json:"title,omitempty"` + // Required. List items. + Items []*Intent_Message_ListSelect_Item `protobuf:"bytes,2,rep,name=items" json:"items,omitempty"` +} + +func (m *Intent_Message_ListSelect) Reset() { *m = Intent_Message_ListSelect{} } +func (m *Intent_Message_ListSelect) String() string { return proto.CompactTextString(m) } +func (*Intent_Message_ListSelect) ProtoMessage() {} +func (*Intent_Message_ListSelect) Descriptor() ([]byte, []int) { + return fileDescriptor3, []int{0, 2, 10} +} + +func (m *Intent_Message_ListSelect) GetTitle() string { + if m != nil { + return m.Title + } + return "" +} + +func (m *Intent_Message_ListSelect) GetItems() []*Intent_Message_ListSelect_Item { + if m != nil { + return m.Items + } + return nil +} + +// An item in the list. +type Intent_Message_ListSelect_Item struct { + // Required. Additional information about this option. + Info *Intent_Message_SelectItemInfo `protobuf:"bytes,1,opt,name=info" json:"info,omitempty"` + // Required. The title of the list item. + Title string `protobuf:"bytes,2,opt,name=title" json:"title,omitempty"` + // Optional. The main text describing the item. + Description string `protobuf:"bytes,3,opt,name=description" json:"description,omitempty"` + // Optional. The image to display. + Image *Intent_Message_Image `protobuf:"bytes,4,opt,name=image" json:"image,omitempty"` +} + +func (m *Intent_Message_ListSelect_Item) Reset() { *m = Intent_Message_ListSelect_Item{} } +func (m *Intent_Message_ListSelect_Item) String() string { return proto.CompactTextString(m) } +func (*Intent_Message_ListSelect_Item) ProtoMessage() {} +func (*Intent_Message_ListSelect_Item) Descriptor() ([]byte, []int) { + return fileDescriptor3, []int{0, 2, 10, 0} +} + +func (m *Intent_Message_ListSelect_Item) GetInfo() *Intent_Message_SelectItemInfo { + if m != nil { + return m.Info + } + return nil +} + +func (m *Intent_Message_ListSelect_Item) GetTitle() string { + if m != nil { + return m.Title + } + return "" +} + +func (m *Intent_Message_ListSelect_Item) GetDescription() string { + if m != nil { + return m.Description + } + return "" +} + +func (m *Intent_Message_ListSelect_Item) GetImage() *Intent_Message_Image { + if m != nil { + return m.Image + } + return nil +} + +// The card for presenting a carousel of options to select from. +type Intent_Message_CarouselSelect struct { + // Required. Carousel items. + Items []*Intent_Message_CarouselSelect_Item `protobuf:"bytes,1,rep,name=items" json:"items,omitempty"` +} + +func (m *Intent_Message_CarouselSelect) Reset() { *m = Intent_Message_CarouselSelect{} } +func (m *Intent_Message_CarouselSelect) String() string { return proto.CompactTextString(m) } +func (*Intent_Message_CarouselSelect) ProtoMessage() {} +func (*Intent_Message_CarouselSelect) Descriptor() ([]byte, []int) { + return fileDescriptor3, []int{0, 2, 11} +} + +func (m *Intent_Message_CarouselSelect) GetItems() []*Intent_Message_CarouselSelect_Item { + if m != nil { + return m.Items + } + return nil +} + +// An item in the carousel. +type Intent_Message_CarouselSelect_Item struct { + // Required. Additional info about the option item. + Info *Intent_Message_SelectItemInfo `protobuf:"bytes,1,opt,name=info" json:"info,omitempty"` + // Required. Title of the carousel item. + Title string `protobuf:"bytes,2,opt,name=title" json:"title,omitempty"` + // Optional. The body text of the card. + Description string `protobuf:"bytes,3,opt,name=description" json:"description,omitempty"` + // Optional. The image to display. + Image *Intent_Message_Image `protobuf:"bytes,4,opt,name=image" json:"image,omitempty"` +} + +func (m *Intent_Message_CarouselSelect_Item) Reset() { *m = Intent_Message_CarouselSelect_Item{} } +func (m *Intent_Message_CarouselSelect_Item) String() string { return proto.CompactTextString(m) } +func (*Intent_Message_CarouselSelect_Item) ProtoMessage() {} +func (*Intent_Message_CarouselSelect_Item) Descriptor() ([]byte, []int) { + return fileDescriptor3, []int{0, 2, 11, 0} +} + +func (m *Intent_Message_CarouselSelect_Item) GetInfo() *Intent_Message_SelectItemInfo { + if m != nil { + return m.Info + } + return nil +} + +func (m *Intent_Message_CarouselSelect_Item) GetTitle() string { + if m != nil { + return m.Title + } + return "" +} + +func (m *Intent_Message_CarouselSelect_Item) GetDescription() string { + if m != nil { + return m.Description + } + return "" +} + +func (m *Intent_Message_CarouselSelect_Item) GetImage() *Intent_Message_Image { + if m != nil { + return m.Image + } + return nil +} + +// Additional info about the select item for when it is triggered in a +// dialog. +type Intent_Message_SelectItemInfo struct { + // Required. A unique key that will be sent back to the agent if this + // response is given. + Key string `protobuf:"bytes,1,opt,name=key" json:"key,omitempty"` + // Optional. A list of synonyms that can also be used to trigger this + // item in dialog. + Synonyms []string `protobuf:"bytes,2,rep,name=synonyms" json:"synonyms,omitempty"` +} + +func (m *Intent_Message_SelectItemInfo) Reset() { *m = Intent_Message_SelectItemInfo{} } +func (m *Intent_Message_SelectItemInfo) String() string { return proto.CompactTextString(m) } +func (*Intent_Message_SelectItemInfo) ProtoMessage() {} +func (*Intent_Message_SelectItemInfo) Descriptor() ([]byte, []int) { + return fileDescriptor3, []int{0, 2, 12} +} + +func (m *Intent_Message_SelectItemInfo) GetKey() string { + if m != nil { + return m.Key + } + return "" +} + +func (m *Intent_Message_SelectItemInfo) GetSynonyms() []string { + if m != nil { + return m.Synonyms + } + return nil +} + +// Represents a single followup intent in the chain. +type Intent_FollowupIntentInfo struct { + // The unique identifier of the followup intent. + // Format: `projects//agent/intents/`. + FollowupIntentName string `protobuf:"bytes,1,opt,name=followup_intent_name,json=followupIntentName" json:"followup_intent_name,omitempty"` + // The unique identifier of the followup intent parent. + // Format: `projects//agent/intents/`. + ParentFollowupIntentName string `protobuf:"bytes,2,opt,name=parent_followup_intent_name,json=parentFollowupIntentName" json:"parent_followup_intent_name,omitempty"` +} + +func (m *Intent_FollowupIntentInfo) Reset() { *m = Intent_FollowupIntentInfo{} } +func (m *Intent_FollowupIntentInfo) String() string { return proto.CompactTextString(m) } +func (*Intent_FollowupIntentInfo) ProtoMessage() {} +func (*Intent_FollowupIntentInfo) Descriptor() ([]byte, []int) { return fileDescriptor3, []int{0, 3} } + +func (m *Intent_FollowupIntentInfo) GetFollowupIntentName() string { + if m != nil { + return m.FollowupIntentName + } + return "" +} + +func (m *Intent_FollowupIntentInfo) GetParentFollowupIntentName() string { + if m != nil { + return m.ParentFollowupIntentName + } + return "" +} + +// The request message for +// [Intents.ListIntents][google.cloud.dialogflow.v2beta1.Intents.ListIntents]. +type ListIntentsRequest struct { + // Required. The agent to list all intents from. + // Format: `projects//agent`. + Parent string `protobuf:"bytes,1,opt,name=parent" json:"parent,omitempty"` + // Optional. The language to list training phrases, parameters and rich + // messages for. If not specified, the agent's default language is used. + // [More than a dozen + // languages](https://dialogflow.com/docs/reference/language) are supported. + // Note: languages must be enabled in the agent before they can be used. + LanguageCode string `protobuf:"bytes,2,opt,name=language_code,json=languageCode" json:"language_code,omitempty"` + // Optional. The resource view to apply to the returned intent. + IntentView IntentView `protobuf:"varint,3,opt,name=intent_view,json=intentView,enum=google.cloud.dialogflow.v2beta1.IntentView" json:"intent_view,omitempty"` + // Optional. The maximum number of items to return in a single page. By + // default 100 and at most 1000. + PageSize int32 `protobuf:"varint,4,opt,name=page_size,json=pageSize" json:"page_size,omitempty"` + // Optional. The next_page_token value returned from a previous list request. + PageToken string `protobuf:"bytes,5,opt,name=page_token,json=pageToken" json:"page_token,omitempty"` +} + +func (m *ListIntentsRequest) Reset() { *m = ListIntentsRequest{} } +func (m *ListIntentsRequest) String() string { return proto.CompactTextString(m) } +func (*ListIntentsRequest) ProtoMessage() {} +func (*ListIntentsRequest) Descriptor() ([]byte, []int) { return fileDescriptor3, []int{1} } + +func (m *ListIntentsRequest) GetParent() string { + if m != nil { + return m.Parent + } + return "" +} + +func (m *ListIntentsRequest) GetLanguageCode() string { + if m != nil { + return m.LanguageCode + } + return "" +} + +func (m *ListIntentsRequest) GetIntentView() IntentView { + if m != nil { + return m.IntentView + } + return IntentView_INTENT_VIEW_UNSPECIFIED +} + +func (m *ListIntentsRequest) GetPageSize() int32 { + if m != nil { + return m.PageSize + } + return 0 +} + +func (m *ListIntentsRequest) GetPageToken() string { + if m != nil { + return m.PageToken + } + return "" +} + +// The response message for +// [Intents.ListIntents][google.cloud.dialogflow.v2beta1.Intents.ListIntents]. +type ListIntentsResponse struct { + // The list of agent intents. There will be a maximum number of items + // returned based on the page_size field in the request. + Intents []*Intent `protobuf:"bytes,1,rep,name=intents" json:"intents,omitempty"` + // Token to retrieve the next page of results, or empty if there are no + // more results in the list. + NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken" json:"next_page_token,omitempty"` +} + +func (m *ListIntentsResponse) Reset() { *m = ListIntentsResponse{} } +func (m *ListIntentsResponse) String() string { return proto.CompactTextString(m) } +func (*ListIntentsResponse) ProtoMessage() {} +func (*ListIntentsResponse) Descriptor() ([]byte, []int) { return fileDescriptor3, []int{2} } + +func (m *ListIntentsResponse) GetIntents() []*Intent { + if m != nil { + return m.Intents + } + return nil +} + +func (m *ListIntentsResponse) GetNextPageToken() string { + if m != nil { + return m.NextPageToken + } + return "" +} + +// The request message for +// [Intents.GetIntent][google.cloud.dialogflow.v2beta1.Intents.GetIntent]. +type GetIntentRequest struct { + // Required. The name of the intent. + // Format: `projects//agent/intents/`. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // Optional. The language to retrieve training phrases, parameters and rich + // messages for. If not specified, the agent's default language is used. + // [More than a dozen + // languages](https://dialogflow.com/docs/reference/language) are supported. + // Note: languages must be enabled in the agent, before they can be used. + LanguageCode string `protobuf:"bytes,2,opt,name=language_code,json=languageCode" json:"language_code,omitempty"` + // Optional. The resource view to apply to the returned intent. + IntentView IntentView `protobuf:"varint,3,opt,name=intent_view,json=intentView,enum=google.cloud.dialogflow.v2beta1.IntentView" json:"intent_view,omitempty"` +} + +func (m *GetIntentRequest) Reset() { *m = GetIntentRequest{} } +func (m *GetIntentRequest) String() string { return proto.CompactTextString(m) } +func (*GetIntentRequest) ProtoMessage() {} +func (*GetIntentRequest) Descriptor() ([]byte, []int) { return fileDescriptor3, []int{3} } + +func (m *GetIntentRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *GetIntentRequest) GetLanguageCode() string { + if m != nil { + return m.LanguageCode + } + return "" +} + +func (m *GetIntentRequest) GetIntentView() IntentView { + if m != nil { + return m.IntentView + } + return IntentView_INTENT_VIEW_UNSPECIFIED +} + +// The request message for +// [Intents.CreateIntent][google.cloud.dialogflow.v2beta1.Intents.CreateIntent]. +type CreateIntentRequest struct { + // Required. The agent to create a intent for. + // Format: `projects//agent`. + Parent string `protobuf:"bytes,1,opt,name=parent" json:"parent,omitempty"` + // Required. The intent to create. + Intent *Intent `protobuf:"bytes,2,opt,name=intent" json:"intent,omitempty"` + // Optional. The language of training phrases, parameters and rich messages + // defined in `intent`. If not specified, the agent's default language is + // used. [More than a dozen + // languages](https://dialogflow.com/docs/reference/language) are supported. + // Note: languages must be enabled in the agent, before they can be used. + LanguageCode string `protobuf:"bytes,3,opt,name=language_code,json=languageCode" json:"language_code,omitempty"` + // Optional. The resource view to apply to the returned intent. + IntentView IntentView `protobuf:"varint,4,opt,name=intent_view,json=intentView,enum=google.cloud.dialogflow.v2beta1.IntentView" json:"intent_view,omitempty"` +} + +func (m *CreateIntentRequest) Reset() { *m = CreateIntentRequest{} } +func (m *CreateIntentRequest) String() string { return proto.CompactTextString(m) } +func (*CreateIntentRequest) ProtoMessage() {} +func (*CreateIntentRequest) Descriptor() ([]byte, []int) { return fileDescriptor3, []int{4} } + +func (m *CreateIntentRequest) GetParent() string { + if m != nil { + return m.Parent + } + return "" +} + +func (m *CreateIntentRequest) GetIntent() *Intent { + if m != nil { + return m.Intent + } + return nil +} + +func (m *CreateIntentRequest) GetLanguageCode() string { + if m != nil { + return m.LanguageCode + } + return "" +} + +func (m *CreateIntentRequest) GetIntentView() IntentView { + if m != nil { + return m.IntentView + } + return IntentView_INTENT_VIEW_UNSPECIFIED +} + +// The request message for +// [Intents.UpdateIntent][google.cloud.dialogflow.v2beta1.Intents.UpdateIntent]. +type UpdateIntentRequest struct { + // Required. The intent to update. + // Format: `projects//agent/intents/`. + Intent *Intent `protobuf:"bytes,1,opt,name=intent" json:"intent,omitempty"` + // Optional. The language of training phrases, parameters and rich messages + // defined in `intent`. If not specified, the agent's default language is + // used. [More than a dozen + // languages](https://dialogflow.com/docs/reference/language) are supported. + // Note: languages must be enabled in the agent, before they can be used. + LanguageCode string `protobuf:"bytes,2,opt,name=language_code,json=languageCode" json:"language_code,omitempty"` + // Optional. The mask to control which fields get updated. + UpdateMask *google_protobuf3.FieldMask `protobuf:"bytes,3,opt,name=update_mask,json=updateMask" json:"update_mask,omitempty"` + // Optional. The resource view to apply to the returned intent. + IntentView IntentView `protobuf:"varint,4,opt,name=intent_view,json=intentView,enum=google.cloud.dialogflow.v2beta1.IntentView" json:"intent_view,omitempty"` +} + +func (m *UpdateIntentRequest) Reset() { *m = UpdateIntentRequest{} } +func (m *UpdateIntentRequest) String() string { return proto.CompactTextString(m) } +func (*UpdateIntentRequest) ProtoMessage() {} +func (*UpdateIntentRequest) Descriptor() ([]byte, []int) { return fileDescriptor3, []int{5} } + +func (m *UpdateIntentRequest) GetIntent() *Intent { + if m != nil { + return m.Intent + } + return nil +} + +func (m *UpdateIntentRequest) GetLanguageCode() string { + if m != nil { + return m.LanguageCode + } + return "" +} + +func (m *UpdateIntentRequest) GetUpdateMask() *google_protobuf3.FieldMask { + if m != nil { + return m.UpdateMask + } + return nil +} + +func (m *UpdateIntentRequest) GetIntentView() IntentView { + if m != nil { + return m.IntentView + } + return IntentView_INTENT_VIEW_UNSPECIFIED +} + +// The request message for +// [Intents.DeleteIntent][google.cloud.dialogflow.v2beta1.Intents.DeleteIntent]. +type DeleteIntentRequest struct { + // Required. The name of the intent to delete. + // Format: `projects//agent/intents/`. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` +} + +func (m *DeleteIntentRequest) Reset() { *m = DeleteIntentRequest{} } +func (m *DeleteIntentRequest) String() string { return proto.CompactTextString(m) } +func (*DeleteIntentRequest) ProtoMessage() {} +func (*DeleteIntentRequest) Descriptor() ([]byte, []int) { return fileDescriptor3, []int{6} } + +func (m *DeleteIntentRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +// The request message for +// [Intents.BatchUpdateIntents][google.cloud.dialogflow.v2beta1.Intents.BatchUpdateIntents]. +type BatchUpdateIntentsRequest struct { + // Required. The name of the agent to update or create intents in. + // Format: `projects//agent`. + Parent string `protobuf:"bytes,1,opt,name=parent" json:"parent,omitempty"` + // Required. The source of the intent batch. + // + // Types that are valid to be assigned to IntentBatch: + // *BatchUpdateIntentsRequest_IntentBatchUri + // *BatchUpdateIntentsRequest_IntentBatchInline + IntentBatch isBatchUpdateIntentsRequest_IntentBatch `protobuf_oneof:"intent_batch"` + // Optional. The language of training phrases, parameters and rich messages + // defined in `intents`. If not specified, the agent's default language is + // used. [More than a dozen + // languages](https://dialogflow.com/docs/reference/language) are supported. + // Note: languages must be enabled in the agent, before they can be used. + LanguageCode string `protobuf:"bytes,4,opt,name=language_code,json=languageCode" json:"language_code,omitempty"` + // Optional. The mask to control which fields get updated. + UpdateMask *google_protobuf3.FieldMask `protobuf:"bytes,5,opt,name=update_mask,json=updateMask" json:"update_mask,omitempty"` + // Optional. The resource view to apply to the returned intent. + IntentView IntentView `protobuf:"varint,6,opt,name=intent_view,json=intentView,enum=google.cloud.dialogflow.v2beta1.IntentView" json:"intent_view,omitempty"` +} + +func (m *BatchUpdateIntentsRequest) Reset() { *m = BatchUpdateIntentsRequest{} } +func (m *BatchUpdateIntentsRequest) String() string { return proto.CompactTextString(m) } +func (*BatchUpdateIntentsRequest) ProtoMessage() {} +func (*BatchUpdateIntentsRequest) Descriptor() ([]byte, []int) { return fileDescriptor3, []int{7} } + +type isBatchUpdateIntentsRequest_IntentBatch interface { + isBatchUpdateIntentsRequest_IntentBatch() +} + +type BatchUpdateIntentsRequest_IntentBatchUri struct { + IntentBatchUri string `protobuf:"bytes,2,opt,name=intent_batch_uri,json=intentBatchUri,oneof"` +} +type BatchUpdateIntentsRequest_IntentBatchInline struct { + IntentBatchInline *IntentBatch `protobuf:"bytes,3,opt,name=intent_batch_inline,json=intentBatchInline,oneof"` +} + +func (*BatchUpdateIntentsRequest_IntentBatchUri) isBatchUpdateIntentsRequest_IntentBatch() {} +func (*BatchUpdateIntentsRequest_IntentBatchInline) isBatchUpdateIntentsRequest_IntentBatch() {} + +func (m *BatchUpdateIntentsRequest) GetIntentBatch() isBatchUpdateIntentsRequest_IntentBatch { + if m != nil { + return m.IntentBatch + } + return nil +} + +func (m *BatchUpdateIntentsRequest) GetParent() string { + if m != nil { + return m.Parent + } + return "" +} + +func (m *BatchUpdateIntentsRequest) GetIntentBatchUri() string { + if x, ok := m.GetIntentBatch().(*BatchUpdateIntentsRequest_IntentBatchUri); ok { + return x.IntentBatchUri + } + return "" +} + +func (m *BatchUpdateIntentsRequest) GetIntentBatchInline() *IntentBatch { + if x, ok := m.GetIntentBatch().(*BatchUpdateIntentsRequest_IntentBatchInline); ok { + return x.IntentBatchInline + } + return nil +} + +func (m *BatchUpdateIntentsRequest) GetLanguageCode() string { + if m != nil { + return m.LanguageCode + } + return "" +} + +func (m *BatchUpdateIntentsRequest) GetUpdateMask() *google_protobuf3.FieldMask { + if m != nil { + return m.UpdateMask + } + return nil +} + +func (m *BatchUpdateIntentsRequest) GetIntentView() IntentView { + if m != nil { + return m.IntentView + } + return IntentView_INTENT_VIEW_UNSPECIFIED +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*BatchUpdateIntentsRequest) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _BatchUpdateIntentsRequest_OneofMarshaler, _BatchUpdateIntentsRequest_OneofUnmarshaler, _BatchUpdateIntentsRequest_OneofSizer, []interface{}{ + (*BatchUpdateIntentsRequest_IntentBatchUri)(nil), + (*BatchUpdateIntentsRequest_IntentBatchInline)(nil), + } +} + +func _BatchUpdateIntentsRequest_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*BatchUpdateIntentsRequest) + // intent_batch + switch x := m.IntentBatch.(type) { + case *BatchUpdateIntentsRequest_IntentBatchUri: + b.EncodeVarint(2<<3 | proto.WireBytes) + b.EncodeStringBytes(x.IntentBatchUri) + case *BatchUpdateIntentsRequest_IntentBatchInline: + b.EncodeVarint(3<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.IntentBatchInline); err != nil { + return err + } + case nil: + default: + return fmt.Errorf("BatchUpdateIntentsRequest.IntentBatch has unexpected type %T", x) + } + return nil +} + +func _BatchUpdateIntentsRequest_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*BatchUpdateIntentsRequest) + switch tag { + case 2: // intent_batch.intent_batch_uri + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeStringBytes() + m.IntentBatch = &BatchUpdateIntentsRequest_IntentBatchUri{x} + return true, err + case 3: // intent_batch.intent_batch_inline + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(IntentBatch) + err := b.DecodeMessage(msg) + m.IntentBatch = &BatchUpdateIntentsRequest_IntentBatchInline{msg} + return true, err + default: + return false, nil + } +} + +func _BatchUpdateIntentsRequest_OneofSizer(msg proto.Message) (n int) { + m := msg.(*BatchUpdateIntentsRequest) + // intent_batch + switch x := m.IntentBatch.(type) { + case *BatchUpdateIntentsRequest_IntentBatchUri: + n += proto.SizeVarint(2<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.IntentBatchUri))) + n += len(x.IntentBatchUri) + case *BatchUpdateIntentsRequest_IntentBatchInline: + s := proto.Size(x.IntentBatchInline) + n += proto.SizeVarint(3<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +// The response message for +// [Intents.BatchUpdateIntents][google.cloud.dialogflow.v2beta1.Intents.BatchUpdateIntents]. +type BatchUpdateIntentsResponse struct { + // The collection of updated or created intents. + Intents []*Intent `protobuf:"bytes,1,rep,name=intents" json:"intents,omitempty"` +} + +func (m *BatchUpdateIntentsResponse) Reset() { *m = BatchUpdateIntentsResponse{} } +func (m *BatchUpdateIntentsResponse) String() string { return proto.CompactTextString(m) } +func (*BatchUpdateIntentsResponse) ProtoMessage() {} +func (*BatchUpdateIntentsResponse) Descriptor() ([]byte, []int) { return fileDescriptor3, []int{8} } + +func (m *BatchUpdateIntentsResponse) GetIntents() []*Intent { + if m != nil { + return m.Intents + } + return nil +} + +// The request message for +// [Intents.BatchDeleteIntents][google.cloud.dialogflow.v2beta1.Intents.BatchDeleteIntents]. +type BatchDeleteIntentsRequest struct { + // Required. The name of the agent to delete all entities types for. Format: + // `projects//agent`. + Parent string `protobuf:"bytes,1,opt,name=parent" json:"parent,omitempty"` + // Required. The collection of intents to delete. Only intent `name` must be + // filled in. + Intents []*Intent `protobuf:"bytes,2,rep,name=intents" json:"intents,omitempty"` +} + +func (m *BatchDeleteIntentsRequest) Reset() { *m = BatchDeleteIntentsRequest{} } +func (m *BatchDeleteIntentsRequest) String() string { return proto.CompactTextString(m) } +func (*BatchDeleteIntentsRequest) ProtoMessage() {} +func (*BatchDeleteIntentsRequest) Descriptor() ([]byte, []int) { return fileDescriptor3, []int{9} } + +func (m *BatchDeleteIntentsRequest) GetParent() string { + if m != nil { + return m.Parent + } + return "" +} + +func (m *BatchDeleteIntentsRequest) GetIntents() []*Intent { + if m != nil { + return m.Intents + } + return nil +} + +// This message is a wrapper around a collection of intents. +type IntentBatch struct { + // A collection of intents. + Intents []*Intent `protobuf:"bytes,1,rep,name=intents" json:"intents,omitempty"` +} + +func (m *IntentBatch) Reset() { *m = IntentBatch{} } +func (m *IntentBatch) String() string { return proto.CompactTextString(m) } +func (*IntentBatch) ProtoMessage() {} +func (*IntentBatch) Descriptor() ([]byte, []int) { return fileDescriptor3, []int{10} } + +func (m *IntentBatch) GetIntents() []*Intent { + if m != nil { + return m.Intents + } + return nil +} + +func init() { + proto.RegisterType((*Intent)(nil), "google.cloud.dialogflow.v2beta1.Intent") + proto.RegisterType((*Intent_TrainingPhrase)(nil), "google.cloud.dialogflow.v2beta1.Intent.TrainingPhrase") + proto.RegisterType((*Intent_TrainingPhrase_Part)(nil), "google.cloud.dialogflow.v2beta1.Intent.TrainingPhrase.Part") + proto.RegisterType((*Intent_Parameter)(nil), "google.cloud.dialogflow.v2beta1.Intent.Parameter") + proto.RegisterType((*Intent_Message)(nil), "google.cloud.dialogflow.v2beta1.Intent.Message") + proto.RegisterType((*Intent_Message_Text)(nil), "google.cloud.dialogflow.v2beta1.Intent.Message.Text") + proto.RegisterType((*Intent_Message_Image)(nil), "google.cloud.dialogflow.v2beta1.Intent.Message.Image") + proto.RegisterType((*Intent_Message_QuickReplies)(nil), "google.cloud.dialogflow.v2beta1.Intent.Message.QuickReplies") + proto.RegisterType((*Intent_Message_Card)(nil), "google.cloud.dialogflow.v2beta1.Intent.Message.Card") + proto.RegisterType((*Intent_Message_Card_Button)(nil), "google.cloud.dialogflow.v2beta1.Intent.Message.Card.Button") + proto.RegisterType((*Intent_Message_SimpleResponse)(nil), "google.cloud.dialogflow.v2beta1.Intent.Message.SimpleResponse") + proto.RegisterType((*Intent_Message_SimpleResponses)(nil), "google.cloud.dialogflow.v2beta1.Intent.Message.SimpleResponses") + proto.RegisterType((*Intent_Message_BasicCard)(nil), "google.cloud.dialogflow.v2beta1.Intent.Message.BasicCard") + proto.RegisterType((*Intent_Message_BasicCard_Button)(nil), "google.cloud.dialogflow.v2beta1.Intent.Message.BasicCard.Button") + proto.RegisterType((*Intent_Message_BasicCard_Button_OpenUriAction)(nil), "google.cloud.dialogflow.v2beta1.Intent.Message.BasicCard.Button.OpenUriAction") + proto.RegisterType((*Intent_Message_Suggestion)(nil), "google.cloud.dialogflow.v2beta1.Intent.Message.Suggestion") + proto.RegisterType((*Intent_Message_Suggestions)(nil), "google.cloud.dialogflow.v2beta1.Intent.Message.Suggestions") + proto.RegisterType((*Intent_Message_LinkOutSuggestion)(nil), "google.cloud.dialogflow.v2beta1.Intent.Message.LinkOutSuggestion") + proto.RegisterType((*Intent_Message_ListSelect)(nil), "google.cloud.dialogflow.v2beta1.Intent.Message.ListSelect") + proto.RegisterType((*Intent_Message_ListSelect_Item)(nil), "google.cloud.dialogflow.v2beta1.Intent.Message.ListSelect.Item") + proto.RegisterType((*Intent_Message_CarouselSelect)(nil), "google.cloud.dialogflow.v2beta1.Intent.Message.CarouselSelect") + proto.RegisterType((*Intent_Message_CarouselSelect_Item)(nil), "google.cloud.dialogflow.v2beta1.Intent.Message.CarouselSelect.Item") + proto.RegisterType((*Intent_Message_SelectItemInfo)(nil), "google.cloud.dialogflow.v2beta1.Intent.Message.SelectItemInfo") + proto.RegisterType((*Intent_FollowupIntentInfo)(nil), "google.cloud.dialogflow.v2beta1.Intent.FollowupIntentInfo") + proto.RegisterType((*ListIntentsRequest)(nil), "google.cloud.dialogflow.v2beta1.ListIntentsRequest") + proto.RegisterType((*ListIntentsResponse)(nil), "google.cloud.dialogflow.v2beta1.ListIntentsResponse") + proto.RegisterType((*GetIntentRequest)(nil), "google.cloud.dialogflow.v2beta1.GetIntentRequest") + proto.RegisterType((*CreateIntentRequest)(nil), "google.cloud.dialogflow.v2beta1.CreateIntentRequest") + proto.RegisterType((*UpdateIntentRequest)(nil), "google.cloud.dialogflow.v2beta1.UpdateIntentRequest") + proto.RegisterType((*DeleteIntentRequest)(nil), "google.cloud.dialogflow.v2beta1.DeleteIntentRequest") + proto.RegisterType((*BatchUpdateIntentsRequest)(nil), "google.cloud.dialogflow.v2beta1.BatchUpdateIntentsRequest") + proto.RegisterType((*BatchUpdateIntentsResponse)(nil), "google.cloud.dialogflow.v2beta1.BatchUpdateIntentsResponse") + proto.RegisterType((*BatchDeleteIntentsRequest)(nil), "google.cloud.dialogflow.v2beta1.BatchDeleteIntentsRequest") + proto.RegisterType((*IntentBatch)(nil), "google.cloud.dialogflow.v2beta1.IntentBatch") + proto.RegisterEnum("google.cloud.dialogflow.v2beta1.IntentView", IntentView_name, IntentView_value) + proto.RegisterEnum("google.cloud.dialogflow.v2beta1.Intent_WebhookState", Intent_WebhookState_name, Intent_WebhookState_value) + proto.RegisterEnum("google.cloud.dialogflow.v2beta1.Intent_TrainingPhrase_Type", Intent_TrainingPhrase_Type_name, Intent_TrainingPhrase_Type_value) + proto.RegisterEnum("google.cloud.dialogflow.v2beta1.Intent_Message_Platform", Intent_Message_Platform_name, Intent_Message_Platform_value) +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// Client API for Intents service + +type IntentsClient interface { + // Returns the list of all intents in the specified agent. + ListIntents(ctx context.Context, in *ListIntentsRequest, opts ...grpc.CallOption) (*ListIntentsResponse, error) + // Retrieves the specified intent. + GetIntent(ctx context.Context, in *GetIntentRequest, opts ...grpc.CallOption) (*Intent, error) + // Creates an intent in the specified agent. + CreateIntent(ctx context.Context, in *CreateIntentRequest, opts ...grpc.CallOption) (*Intent, error) + // Updates the specified intent. + UpdateIntent(ctx context.Context, in *UpdateIntentRequest, opts ...grpc.CallOption) (*Intent, error) + // Deletes the specified intent. + DeleteIntent(ctx context.Context, in *DeleteIntentRequest, opts ...grpc.CallOption) (*google_protobuf2.Empty, error) + // Updates/Creates multiple intents in the specified agent. + // + // Operation + BatchUpdateIntents(ctx context.Context, in *BatchUpdateIntentsRequest, opts ...grpc.CallOption) (*google_longrunning.Operation, error) + // Deletes intents in the specified agent. + // + // Operation + BatchDeleteIntents(ctx context.Context, in *BatchDeleteIntentsRequest, opts ...grpc.CallOption) (*google_longrunning.Operation, error) +} + +type intentsClient struct { + cc *grpc.ClientConn +} + +func NewIntentsClient(cc *grpc.ClientConn) IntentsClient { + return &intentsClient{cc} +} + +func (c *intentsClient) ListIntents(ctx context.Context, in *ListIntentsRequest, opts ...grpc.CallOption) (*ListIntentsResponse, error) { + out := new(ListIntentsResponse) + err := grpc.Invoke(ctx, "/google.cloud.dialogflow.v2beta1.Intents/ListIntents", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *intentsClient) GetIntent(ctx context.Context, in *GetIntentRequest, opts ...grpc.CallOption) (*Intent, error) { + out := new(Intent) + err := grpc.Invoke(ctx, "/google.cloud.dialogflow.v2beta1.Intents/GetIntent", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *intentsClient) CreateIntent(ctx context.Context, in *CreateIntentRequest, opts ...grpc.CallOption) (*Intent, error) { + out := new(Intent) + err := grpc.Invoke(ctx, "/google.cloud.dialogflow.v2beta1.Intents/CreateIntent", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *intentsClient) UpdateIntent(ctx context.Context, in *UpdateIntentRequest, opts ...grpc.CallOption) (*Intent, error) { + out := new(Intent) + err := grpc.Invoke(ctx, "/google.cloud.dialogflow.v2beta1.Intents/UpdateIntent", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *intentsClient) DeleteIntent(ctx context.Context, in *DeleteIntentRequest, opts ...grpc.CallOption) (*google_protobuf2.Empty, error) { + out := new(google_protobuf2.Empty) + err := grpc.Invoke(ctx, "/google.cloud.dialogflow.v2beta1.Intents/DeleteIntent", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *intentsClient) BatchUpdateIntents(ctx context.Context, in *BatchUpdateIntentsRequest, opts ...grpc.CallOption) (*google_longrunning.Operation, error) { + out := new(google_longrunning.Operation) + err := grpc.Invoke(ctx, "/google.cloud.dialogflow.v2beta1.Intents/BatchUpdateIntents", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *intentsClient) BatchDeleteIntents(ctx context.Context, in *BatchDeleteIntentsRequest, opts ...grpc.CallOption) (*google_longrunning.Operation, error) { + out := new(google_longrunning.Operation) + err := grpc.Invoke(ctx, "/google.cloud.dialogflow.v2beta1.Intents/BatchDeleteIntents", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for Intents service + +type IntentsServer interface { + // Returns the list of all intents in the specified agent. + ListIntents(context.Context, *ListIntentsRequest) (*ListIntentsResponse, error) + // Retrieves the specified intent. + GetIntent(context.Context, *GetIntentRequest) (*Intent, error) + // Creates an intent in the specified agent. + CreateIntent(context.Context, *CreateIntentRequest) (*Intent, error) + // Updates the specified intent. + UpdateIntent(context.Context, *UpdateIntentRequest) (*Intent, error) + // Deletes the specified intent. + DeleteIntent(context.Context, *DeleteIntentRequest) (*google_protobuf2.Empty, error) + // Updates/Creates multiple intents in the specified agent. + // + // Operation + BatchUpdateIntents(context.Context, *BatchUpdateIntentsRequest) (*google_longrunning.Operation, error) + // Deletes intents in the specified agent. + // + // Operation + BatchDeleteIntents(context.Context, *BatchDeleteIntentsRequest) (*google_longrunning.Operation, error) +} + +func RegisterIntentsServer(s *grpc.Server, srv IntentsServer) { + s.RegisterService(&_Intents_serviceDesc, srv) +} + +func _Intents_ListIntents_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListIntentsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(IntentsServer).ListIntents(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.dialogflow.v2beta1.Intents/ListIntents", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(IntentsServer).ListIntents(ctx, req.(*ListIntentsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Intents_GetIntent_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetIntentRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(IntentsServer).GetIntent(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.dialogflow.v2beta1.Intents/GetIntent", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(IntentsServer).GetIntent(ctx, req.(*GetIntentRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Intents_CreateIntent_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateIntentRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(IntentsServer).CreateIntent(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.dialogflow.v2beta1.Intents/CreateIntent", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(IntentsServer).CreateIntent(ctx, req.(*CreateIntentRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Intents_UpdateIntent_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdateIntentRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(IntentsServer).UpdateIntent(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.dialogflow.v2beta1.Intents/UpdateIntent", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(IntentsServer).UpdateIntent(ctx, req.(*UpdateIntentRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Intents_DeleteIntent_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteIntentRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(IntentsServer).DeleteIntent(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.dialogflow.v2beta1.Intents/DeleteIntent", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(IntentsServer).DeleteIntent(ctx, req.(*DeleteIntentRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Intents_BatchUpdateIntents_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(BatchUpdateIntentsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(IntentsServer).BatchUpdateIntents(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.dialogflow.v2beta1.Intents/BatchUpdateIntents", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(IntentsServer).BatchUpdateIntents(ctx, req.(*BatchUpdateIntentsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Intents_BatchDeleteIntents_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(BatchDeleteIntentsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(IntentsServer).BatchDeleteIntents(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.dialogflow.v2beta1.Intents/BatchDeleteIntents", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(IntentsServer).BatchDeleteIntents(ctx, req.(*BatchDeleteIntentsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Intents_serviceDesc = grpc.ServiceDesc{ + ServiceName: "google.cloud.dialogflow.v2beta1.Intents", + HandlerType: (*IntentsServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "ListIntents", + Handler: _Intents_ListIntents_Handler, + }, + { + MethodName: "GetIntent", + Handler: _Intents_GetIntent_Handler, + }, + { + MethodName: "CreateIntent", + Handler: _Intents_CreateIntent_Handler, + }, + { + MethodName: "UpdateIntent", + Handler: _Intents_UpdateIntent_Handler, + }, + { + MethodName: "DeleteIntent", + Handler: _Intents_DeleteIntent_Handler, + }, + { + MethodName: "BatchUpdateIntents", + Handler: _Intents_BatchUpdateIntents_Handler, + }, + { + MethodName: "BatchDeleteIntents", + Handler: _Intents_BatchDeleteIntents_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "google/cloud/dialogflow/v2beta1/intent.proto", +} + +func init() { proto.RegisterFile("google/cloud/dialogflow/v2beta1/intent.proto", fileDescriptor3) } + +var fileDescriptor3 = []byte{ + // 2555 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x5a, 0x4d, 0x73, 0x23, 0x47, + 0xf9, 0xf7, 0xe8, 0xc5, 0x92, 0x1e, 0xc9, 0xb2, 0xdc, 0xde, 0x6c, 0xb4, 0x93, 0xa4, 0xe2, 0x28, + 0x2f, 0x7f, 0xc7, 0xff, 0x20, 0x11, 0x25, 0xe4, 0xc5, 0x4b, 0x76, 0x91, 0x6d, 0xd9, 0x16, 0x96, + 0x2d, 0xed, 0x58, 0xde, 0x65, 0xb7, 0x80, 0xa9, 0x91, 0xd4, 0xd6, 0x0e, 0x1e, 0xcd, 0xcc, 0x4e, + 0xb7, 0xec, 0x28, 0x90, 0x2a, 0x8a, 0x2a, 0xe0, 0xc0, 0x85, 0x2a, 0x4e, 0x14, 0x37, 0x38, 0x85, + 0xe2, 0x40, 0xe5, 0xc6, 0x27, 0xa0, 0x38, 0x70, 0xe2, 0x98, 0x03, 0x45, 0x41, 0xf1, 0x19, 0xb8, + 0x41, 0xf5, 0xcb, 0x48, 0x23, 0x4b, 0x8b, 0x24, 0x7b, 0xe1, 0xc2, 0x6d, 0xfa, 0xe9, 0xee, 0xdf, + 0xf3, 0xd6, 0xfd, 0x7b, 0xba, 0x5b, 0x82, 0xb7, 0x3a, 0x8e, 0xd3, 0xb1, 0x70, 0xa1, 0x65, 0x39, + 0xbd, 0x76, 0xa1, 0x6d, 0x1a, 0x96, 0xd3, 0x39, 0xb5, 0x9c, 0x8b, 0xc2, 0x79, 0xb1, 0x89, 0xa9, + 0xf1, 0x76, 0xc1, 0xb4, 0x29, 0xb6, 0x69, 0xde, 0xf5, 0x1c, 0xea, 0xa0, 0x97, 0xc5, 0xe8, 0x3c, + 0x1f, 0x9d, 0x1f, 0x8e, 0xce, 0xcb, 0xd1, 0xea, 0x8b, 0x12, 0xce, 0x70, 0xcd, 0x82, 0x61, 0xdb, + 0x0e, 0x35, 0xa8, 0xe9, 0xd8, 0x44, 0x4c, 0x57, 0xbf, 0x34, 0x4d, 0x59, 0xcb, 0xb1, 0x29, 0xfe, + 0x58, 0x6a, 0x53, 0x5f, 0x95, 0xc3, 0x2d, 0xc7, 0xee, 0x78, 0x3d, 0xdb, 0x36, 0xed, 0x4e, 0xc1, + 0x71, 0xb1, 0x37, 0x82, 0xf9, 0x82, 0x1c, 0xc4, 0x5b, 0xcd, 0xde, 0x69, 0x01, 0x77, 0x5d, 0xda, + 0x97, 0x9d, 0x6b, 0x97, 0x3b, 0x4f, 0x4d, 0x6c, 0xb5, 0xf5, 0xae, 0x41, 0xce, 0xe4, 0x88, 0x17, + 0x2f, 0x8f, 0x20, 0xd4, 0xeb, 0xb5, 0xa4, 0x05, 0xb9, 0xdf, 0xbf, 0x09, 0x8b, 0x15, 0x1e, 0x00, + 0x84, 0x20, 0x62, 0x1b, 0x5d, 0x9c, 0x55, 0xd6, 0x94, 0xf5, 0x84, 0xc6, 0xbf, 0xd1, 0x2b, 0x90, + 0x6a, 0x9b, 0xc4, 0xb5, 0x8c, 0xbe, 0xce, 0xfb, 0x42, 0xbc, 0x2f, 0x29, 0x65, 0x47, 0x6c, 0xc8, + 0x43, 0x58, 0xba, 0xc0, 0xcd, 0xc7, 0x8e, 0x73, 0xa6, 0x13, 0x6a, 0x50, 0x9c, 0x5d, 0x5c, 0x53, + 0xd6, 0xd3, 0xc5, 0x77, 0xf3, 0x53, 0x22, 0x99, 0x17, 0x6a, 0xf3, 0x0f, 0xc4, 0xe4, 0x63, 0x36, + 0x57, 0x4b, 0x5d, 0x04, 0x5a, 0x48, 0x85, 0xb8, 0xeb, 0x99, 0x8e, 0x67, 0xd2, 0x7e, 0x36, 0xbc, + 0xa6, 0xac, 0x47, 0xb5, 0x41, 0x1b, 0xbd, 0x0c, 0x49, 0x93, 0xe8, 0xa7, 0x86, 0x65, 0x35, 0x8d, + 0xd6, 0x59, 0x36, 0xb2, 0xa6, 0xac, 0xc7, 0x35, 0x30, 0xc9, 0xae, 0x94, 0xa0, 0x97, 0x00, 0xba, + 0x96, 0x8e, 0x6d, 0xa3, 0x69, 0xe1, 0x76, 0x36, 0xca, 0xfb, 0x13, 0x5d, 0xab, 0x2c, 0x04, 0x28, + 0x0f, 0xab, 0xa6, 0xed, 0xf6, 0xa8, 0x2e, 0x33, 0xc2, 0xfd, 0x23, 0xd9, 0xd8, 0x5a, 0x78, 0x3d, + 0xa1, 0xad, 0xf0, 0xae, 0x6d, 0xd1, 0xc3, 0xbc, 0x24, 0xe8, 0x26, 0x2c, 0xe2, 0x73, 0x6c, 0x53, + 0x92, 0x8d, 0xf3, 0x21, 0xb2, 0x85, 0x0c, 0xc8, 0x50, 0xcf, 0x30, 0x59, 0xea, 0x74, 0xf7, 0xb1, + 0x67, 0x10, 0x4c, 0xb2, 0x89, 0xb5, 0xf0, 0x7a, 0xb2, 0xf8, 0xde, 0xac, 0x11, 0x68, 0xc8, 0xf9, + 0x75, 0x3e, 0x5d, 0x5b, 0xa6, 0x23, 0x6d, 0xae, 0xda, 0x68, 0xb1, 0x15, 0x91, 0x05, 0x1e, 0x7e, + 0xd9, 0x42, 0xf7, 0x60, 0xd9, 0xe9, 0xd1, 0x80, 0x0f, 0x24, 0x9b, 0xe4, 0x9a, 0xd7, 0xa7, 0x6a, + 0x96, 0xae, 0x69, 0x69, 0x01, 0x20, 0x9b, 0x04, 0xbd, 0x0e, 0x69, 0x0f, 0x13, 0x1c, 0x40, 0x4c, + 0xf1, 0xc0, 0x2d, 0x71, 0xe9, 0x60, 0xd8, 0x3d, 0x00, 0xd7, 0xf0, 0x8c, 0x2e, 0xa6, 0xd8, 0x23, + 0xd9, 0x25, 0xae, 0xf4, 0xed, 0x59, 0xdd, 0xad, 0xfb, 0x33, 0xb5, 0x00, 0x08, 0x3a, 0x80, 0x78, + 0x17, 0x13, 0x62, 0x74, 0x30, 0xc9, 0xa6, 0x39, 0x60, 0x61, 0x56, 0xc0, 0x43, 0x31, 0x4f, 0x1b, + 0x00, 0xa0, 0x73, 0x50, 0xdb, 0xf8, 0xd4, 0xe8, 0x59, 0x54, 0xf7, 0x30, 0x71, 0x1d, 0x9b, 0x60, + 0xdd, 0xb5, 0x0c, 0x7a, 0xea, 0x78, 0x5d, 0x92, 0x5d, 0x5e, 0x0b, 0xaf, 0xa7, 0x8b, 0x1f, 0xcc, + 0x09, 0x9f, 0xaf, 0x4b, 0x00, 0x2d, 0x2b, 0xb1, 0x35, 0x09, 0xed, 0x77, 0x10, 0xf4, 0x21, 0xdc, + 0xf2, 0x1c, 0x87, 0xea, 0xa7, 0x8e, 0x65, 0x39, 0x17, 0x3d, 0x57, 0x17, 0xdc, 0x22, 0xf6, 0x4e, + 0x86, 0x27, 0xef, 0x26, 0x1b, 0xb0, 0x2b, 0xfb, 0x85, 0x06, 0xbe, 0x8d, 0x3e, 0x82, 0x17, 0x5c, + 0xc3, 0x63, 0x83, 0x27, 0x4e, 0x5e, 0xe1, 0x93, 0xb3, 0x62, 0xc8, 0x84, 0xe9, 0x16, 0xdc, 0xb8, + 0x3c, 0xcf, 0xb4, 0x4f, 0x9d, 0x2c, 0xe2, 0xa1, 0xdc, 0x9c, 0xd5, 0xd7, 0x51, 0xe4, 0x8a, 0x7d, + 0xea, 0x68, 0xe8, 0x74, 0x4c, 0xa6, 0xfe, 0x2a, 0x0c, 0xe9, 0xd1, 0x55, 0x3b, 0x91, 0x3d, 0x6a, + 0x10, 0xa1, 0x7d, 0x57, 0xb0, 0x46, 0xba, 0x78, 0xfb, 0x6a, 0xfb, 0x21, 0xdf, 0xe8, 0xbb, 0x58, + 0xe3, 0x40, 0xe8, 0x1e, 0x44, 0x5d, 0xc3, 0xa3, 0x24, 0x1b, 0xe6, 0x6e, 0x5d, 0x15, 0xb1, 0x6e, + 0x78, 0x54, 0x13, 0x48, 0x68, 0x03, 0x56, 0xa8, 0xd9, 0xc5, 0x44, 0x37, 0xda, 0x6d, 0xdc, 0xd6, + 0x5b, 0x4e, 0xcf, 0xa6, 0x9c, 0x4d, 0xa2, 0xda, 0x32, 0xef, 0x28, 0x31, 0xf9, 0x36, 0x13, 0xab, + 0x14, 0x22, 0x6c, 0x2a, 0xf3, 0x95, 0xed, 0x03, 0xdf, 0x57, 0xf6, 0xcd, 0xf8, 0x08, 0xdb, 0xd4, + 0xa4, 0x7d, 0x7d, 0xe0, 0x72, 0x42, 0x03, 0x21, 0x62, 0x1e, 0xa0, 0x1b, 0x10, 0x35, 0x2c, 0xd3, + 0x20, 0x9c, 0xc9, 0x12, 0x9a, 0x68, 0x30, 0x82, 0xed, 0x11, 0xec, 0xe9, 0x6d, 0x7c, 0x6a, 0xda, + 0xb8, 0x2d, 0x79, 0x2c, 0xc9, 0x64, 0x3b, 0x42, 0x94, 0x7b, 0x1f, 0x22, 0x12, 0x20, 0xd3, 0x78, + 0x58, 0x2f, 0xeb, 0x27, 0x47, 0xc7, 0xf5, 0xf2, 0x76, 0x65, 0xb7, 0x52, 0xde, 0xc9, 0x2c, 0xa0, + 0x24, 0xc4, 0xca, 0xdf, 0x28, 0x1d, 0xd6, 0xab, 0xe5, 0x8c, 0x82, 0x52, 0x10, 0x6f, 0x94, 0x0f, + 0xeb, 0xd5, 0x52, 0xa3, 0x9c, 0x09, 0xa9, 0x3f, 0x0e, 0x41, 0x62, 0xb0, 0xd9, 0xae, 0x4a, 0xef, + 0x37, 0x20, 0x7a, 0x6e, 0x58, 0x3d, 0xec, 0x9b, 0xcd, 0x1b, 0xe8, 0x55, 0x58, 0xf2, 0x37, 0x98, + 0xe8, 0x8d, 0xf0, 0xde, 0x94, 0x14, 0xde, 0xe7, 0x83, 0xde, 0x87, 0x6c, 0x20, 0x24, 0xfa, 0x88, + 0xa6, 0x28, 0x1f, 0xff, 0xdc, 0x30, 0x3e, 0x3b, 0x01, 0x9d, 0x2f, 0x42, 0xa2, 0x6b, 0xd8, 0x6d, + 0x83, 0x3a, 0x5e, 0x9f, 0x97, 0x13, 0xc6, 0xdc, 0xbe, 0x00, 0x65, 0x21, 0xe6, 0x7a, 0x4e, 0xd7, + 0xa5, 0x3e, 0x5b, 0xfb, 0x4d, 0xf4, 0x3c, 0xc4, 0x4c, 0xa2, 0x5b, 0x26, 0xa1, 0xd9, 0x38, 0x9f, + 0xb5, 0x68, 0x92, 0xaa, 0x49, 0xa8, 0xfa, 0xd7, 0x5b, 0x10, 0x93, 0xdb, 0x18, 0x7d, 0x3d, 0x90, + 0xbc, 0xe4, 0xec, 0x65, 0xca, 0x67, 0x81, 0x06, 0xfe, 0x98, 0xee, 0x2f, 0xc8, 0xa4, 0x1f, 0x42, + 0xd4, 0xec, 0x1a, 0x1d, 0x11, 0xb8, 0x64, 0xf1, 0x2b, 0xf3, 0x82, 0x55, 0xd8, 0xe4, 0xfd, 0x05, + 0x4d, 0xa0, 0xa0, 0x16, 0x2c, 0x3d, 0xe9, 0x99, 0xad, 0x33, 0xdd, 0xc3, 0xae, 0x65, 0x62, 0xb1, + 0x54, 0x92, 0xc5, 0xaf, 0xce, 0x0b, 0x7b, 0x8f, 0x81, 0x68, 0x02, 0x63, 0x7f, 0x41, 0x4b, 0x3d, + 0x09, 0xb4, 0x99, 0xff, 0x2d, 0xc3, 0x13, 0x2b, 0xed, 0x0a, 0xfe, 0x6f, 0x1b, 0x5e, 0x9b, 0xf9, + 0xcf, 0x30, 0xd0, 0x3b, 0x10, 0x73, 0x8d, 0xbe, 0xe5, 0x18, 0xa2, 0xc0, 0x26, 0x8b, 0xcf, 0xfb, + 0x70, 0xfe, 0x69, 0x23, 0x7f, 0xcc, 0x4f, 0x1b, 0xfb, 0x0b, 0x9a, 0x3f, 0x12, 0x59, 0x90, 0x21, + 0x66, 0xd7, 0xb5, 0xf0, 0x80, 0x9b, 0x59, 0x22, 0xd9, 0xec, 0xbb, 0xf3, 0x1a, 0x73, 0xcc, 0x71, + 0x7c, 0x1e, 0x66, 0xbe, 0x2e, 0x93, 0x51, 0x11, 0x7a, 0x04, 0xd0, 0x34, 0x88, 0xd9, 0xd2, 0xb9, + 0xd3, 0x71, 0xae, 0xe7, 0xc3, 0x79, 0xf5, 0x6c, 0x31, 0x04, 0xe9, 0x79, 0xa2, 0xe9, 0x37, 0x90, + 0x0e, 0x49, 0xd2, 0xeb, 0x74, 0x30, 0xe1, 0xc7, 0xb5, 0x6c, 0x82, 0x83, 0xdf, 0x9e, 0xdb, 0x89, + 0x21, 0xc4, 0xfe, 0x82, 0x16, 0x44, 0x44, 0x04, 0x56, 0x2d, 0xd3, 0x3e, 0xd3, 0x9d, 0x1e, 0xd5, + 0x87, 0x72, 0x7e, 0x0c, 0x48, 0x16, 0x4b, 0xf3, 0x2a, 0xaa, 0x9a, 0xf6, 0x59, 0xad, 0x47, 0x87, + 0xfa, 0xf6, 0x17, 0xb4, 0x15, 0xeb, 0xb2, 0x10, 0x7d, 0x0b, 0x92, 0x6c, 0x0b, 0xe9, 0x04, 0x5b, + 0xb8, 0x45, 0xb3, 0x49, 0xae, 0x6c, 0x73, 0x7e, 0x65, 0x84, 0x1e, 0x73, 0x84, 0xfd, 0x05, 0x0d, + 0xac, 0x41, 0x0b, 0x99, 0xb0, 0xdc, 0x32, 0x3c, 0xa7, 0x47, 0xb0, 0xe5, 0xab, 0x48, 0x71, 0x15, + 0x77, 0xae, 0xb0, 0x14, 0x39, 0xcc, 0x40, 0x4d, 0xba, 0x35, 0x22, 0x41, 0x0d, 0x88, 0xfb, 0x55, + 0x5f, 0x9e, 0x4a, 0xaf, 0x5e, 0xf4, 0x07, 0x48, 0xaa, 0x0a, 0x11, 0x46, 0x02, 0x81, 0x2a, 0x10, + 0xf6, 0xab, 0x80, 0xfa, 0x1a, 0x44, 0xf9, 0x9e, 0x46, 0x2f, 0x40, 0x82, 0xef, 0x69, 0xbd, 0xe7, + 0x99, 0x92, 0x72, 0xe3, 0x5c, 0x70, 0xe2, 0x99, 0x6a, 0x05, 0x52, 0xc1, 0x2d, 0xca, 0x38, 0x96, + 0x9a, 0xd4, 0xf2, 0xb9, 0x59, 0x34, 0x18, 0xc7, 0x8e, 0xb2, 0x41, 0x88, 0x2b, 0x1a, 0xd9, 0xcd, + 0xea, 0xdf, 0x15, 0x88, 0xf0, 0xb5, 0x38, 0x19, 0x43, 0x85, 0x38, 0xe9, 0x35, 0x45, 0x87, 0x20, + 0xf7, 0x41, 0x7b, 0xd4, 0xc4, 0xf0, 0xa8, 0x89, 0xe8, 0x04, 0x62, 0xcd, 0x1e, 0xa5, 0x6c, 0x59, + 0x47, 0xe6, 0xab, 0xb5, 0x41, 0xa2, 0xc8, 0x6f, 0x71, 0x0c, 0xcd, 0xc7, 0x52, 0x3f, 0x80, 0x45, + 0x21, 0x9a, 0x58, 0x43, 0xd9, 0x79, 0xdf, 0x21, 0x94, 0x1f, 0xe8, 0xa5, 0xb5, 0x7e, 0x5b, 0xed, + 0x42, 0x7a, 0x74, 0xb7, 0xa3, 0xd7, 0x20, 0xcd, 0x0f, 0xee, 0xd4, 0xd1, 0x89, 0x8b, 0x71, 0xeb, + 0xb1, 0xc4, 0x4a, 0x31, 0x69, 0xc3, 0x39, 0xe6, 0x32, 0xa6, 0x87, 0x90, 0xae, 0x25, 0xf1, 0xf8, + 0x77, 0xb0, 0xec, 0x71, 0x1b, 0xc2, 0x23, 0x65, 0x8f, 0x25, 0x57, 0xfd, 0x1e, 0x2c, 0x5f, 0x22, + 0x17, 0x64, 0x4e, 0xe0, 0x2d, 0x85, 0xc7, 0xe6, 0xce, 0xf5, 0x78, 0x6b, 0x8c, 0xb4, 0xd4, 0x3f, + 0x84, 0x21, 0x31, 0xe0, 0x9c, 0x2b, 0xa4, 0xf6, 0x75, 0x48, 0xb3, 0xa5, 0x6a, 0x50, 0x8a, 0xdb, + 0x41, 0x17, 0x97, 0x06, 0x52, 0xbe, 0x82, 0x0f, 0xfc, 0xf2, 0x15, 0xb9, 0x46, 0xf9, 0xf2, 0x8b, + 0xd7, 0xa3, 0xe1, 0x8a, 0x89, 0xf2, 0xa8, 0x7c, 0xed, 0xca, 0x2c, 0x3b, 0xb6, 0x6c, 0x7e, 0xa7, + 0x0c, 0xd6, 0xcd, 0xe4, 0x60, 0x9c, 0xc3, 0xb2, 0xe3, 0x62, 0x9b, 0x2d, 0x65, 0x5d, 0xde, 0x95, + 0x44, 0x49, 0x3e, 0xba, 0xae, 0x11, 0xf9, 0x9a, 0x8b, 0xed, 0x13, 0xcf, 0x2c, 0x71, 0x54, 0x6d, + 0xc9, 0x09, 0x36, 0xd5, 0x57, 0x60, 0x69, 0xa4, 0x1f, 0x65, 0x20, 0x3c, 0xdc, 0xf1, 0xec, 0x53, + 0xcd, 0x01, 0x04, 0xc8, 0x75, 0xa2, 0xf9, 0xea, 0x19, 0x24, 0x03, 0x55, 0x00, 0x7d, 0x73, 0xb4, + 0xae, 0x28, 0xf3, 0x9d, 0xe1, 0xc7, 0xeb, 0xca, 0x48, 0x51, 0x51, 0xeb, 0xb0, 0x32, 0x56, 0x09, + 0xd0, 0x9b, 0x90, 0x69, 0xb3, 0x4f, 0x9b, 0x3f, 0x3d, 0xe8, 0x81, 0x93, 0xe2, 0x72, 0x40, 0xce, + 0x4f, 0x67, 0xd2, 0xc5, 0xd0, 0xd0, 0xc5, 0x2f, 0x42, 0x00, 0x43, 0xbe, 0x7f, 0x4a, 0x8a, 0x4e, + 0x20, 0x6a, 0x52, 0xdc, 0x15, 0x34, 0x76, 0x85, 0x5a, 0x3f, 0x54, 0x90, 0xaf, 0x50, 0xdc, 0xd5, + 0x04, 0x9a, 0xfa, 0x67, 0x05, 0x22, 0xac, 0x8d, 0x34, 0x88, 0xf0, 0x1b, 0x8f, 0x72, 0xb5, 0x62, + 0x22, 0xa0, 0x19, 0x12, 0xbf, 0xf5, 0x70, 0xac, 0xa1, 0x27, 0xa1, 0xa0, 0x27, 0x6b, 0x90, 0x6c, + 0x63, 0xd2, 0xf2, 0x4c, 0x97, 0x2f, 0x34, 0x9f, 0x3d, 0x86, 0xa2, 0x67, 0xba, 0xb1, 0xd4, 0x3f, + 0x86, 0x20, 0x3d, 0x5a, 0xea, 0xd0, 0x43, 0x3f, 0x96, 0x62, 0x69, 0x6c, 0x5f, 0xaf, 0x72, 0xfe, + 0x8f, 0xc5, 0xf3, 0x0e, 0xa4, 0x47, 0x8d, 0x63, 0x2b, 0xfa, 0x0c, 0xf7, 0xfd, 0x4d, 0x7b, 0x86, + 0xfb, 0x9c, 0x5c, 0xfb, 0xb6, 0x63, 0xf7, 0xbb, 0x7e, 0xd9, 0x1d, 0xb4, 0x73, 0x3f, 0x51, 0x20, + 0xee, 0x1f, 0x0b, 0x50, 0x16, 0x6e, 0xb0, 0xeb, 0xd6, 0x6e, 0x4d, 0x3b, 0xbc, 0x74, 0x31, 0x4b, + 0x41, 0x7c, 0xb7, 0xb4, 0x5d, 0xde, 0xaa, 0xd5, 0x0e, 0x32, 0x0a, 0x4a, 0x40, 0xf4, 0xb8, 0x5a, + 0xda, 0x3e, 0xc8, 0x84, 0xc4, 0x25, 0xad, 0x5a, 0xde, 0xd3, 0x4a, 0x87, 0x99, 0x30, 0x8a, 0x41, + 0xf8, 0xa0, 0x72, 0x90, 0x89, 0xf0, 0x11, 0x07, 0x0f, 0xeb, 0xe5, 0x4c, 0x14, 0xc5, 0x21, 0x52, + 0xad, 0x1c, 0x95, 0x33, 0x8b, 0x4c, 0x78, 0xbf, 0xb2, 0x55, 0xd6, 0x32, 0x31, 0xf4, 0x1c, 0xac, + 0x94, 0xb6, 0x1b, 0x95, 0xda, 0xd1, 0xb1, 0x5e, 0x3b, 0xd2, 0xf7, 0x6a, 0xb5, 0xbd, 0x6a, 0x39, + 0x13, 0xdf, 0x4a, 0x40, 0x4c, 0x3e, 0x7b, 0xa8, 0x3f, 0x54, 0x00, 0x8d, 0x5f, 0xe0, 0xd1, 0x97, + 0xc7, 0x9f, 0x06, 0x02, 0xdb, 0xfb, 0xd2, 0xf5, 0x7e, 0x96, 0xb7, 0x88, 0xd0, 0xbf, 0x7f, 0x8b, + 0xc8, 0x51, 0x48, 0x05, 0x1f, 0xf5, 0xd0, 0x4b, 0x70, 0xeb, 0x41, 0x79, 0x6b, 0xbf, 0x56, 0x3b, + 0xd0, 0x8f, 0x1b, 0xa5, 0xc6, 0xe5, 0x1b, 0xec, 0x2d, 0x78, 0x6e, 0xb4, 0xbb, 0x7c, 0x54, 0xda, + 0xaa, 0x96, 0x77, 0x32, 0x0a, 0xda, 0x80, 0x37, 0x26, 0x76, 0xe9, 0xbb, 0x35, 0x4d, 0x3f, 0xae, + 0xd6, 0x1a, 0xfa, 0x6e, 0xa5, 0x5a, 0xad, 0x1c, 0xed, 0x65, 0x42, 0xb9, 0x2f, 0x14, 0x40, 0x8c, + 0x23, 0x84, 0x21, 0x44, 0xc3, 0x4f, 0x7a, 0x98, 0x50, 0x74, 0x13, 0x16, 0x85, 0xa1, 0xd2, 0x5f, + 0xd9, 0x62, 0xa7, 0x2b, 0xcb, 0xb0, 0x3b, 0x3d, 0x76, 0x00, 0x6a, 0x39, 0x6d, 0xdf, 0xab, 0x94, + 0x2f, 0xdc, 0x76, 0xda, 0x18, 0x55, 0x21, 0x29, 0x1d, 0x3f, 0x37, 0xf1, 0x05, 0x5f, 0x99, 0xe9, + 0xe2, 0xff, 0xcf, 0xb8, 0xfa, 0xee, 0x9b, 0xf8, 0x42, 0x03, 0x73, 0xf0, 0xcd, 0x0e, 0x5c, 0x2e, + 0x53, 0x47, 0xcc, 0x4f, 0xb0, 0x7c, 0x62, 0x88, 0x33, 0xc1, 0xb1, 0xf9, 0x09, 0x0b, 0x12, 0xf0, + 0x4e, 0xea, 0x9c, 0x61, 0x5b, 0x5e, 0x8f, 0xf9, 0xf0, 0x06, 0x13, 0xe4, 0xbe, 0xaf, 0xc0, 0xea, + 0x88, 0x77, 0xf2, 0x10, 0x54, 0x82, 0x98, 0xd0, 0xe0, 0x73, 0xc1, 0xff, 0xcd, 0x68, 0x9d, 0xe6, + 0xcf, 0x43, 0x6f, 0xc0, 0xb2, 0xcd, 0xce, 0x51, 0x01, 0xf5, 0x22, 0x16, 0x4b, 0x4c, 0x5c, 0x1f, + 0x98, 0xf0, 0x73, 0x05, 0x32, 0x7b, 0x58, 0x5a, 0xe0, 0x87, 0x77, 0xd2, 0xab, 0xc2, 0x7f, 0x3f, + 0xb4, 0xb9, 0xbf, 0x28, 0xb0, 0xba, 0xed, 0x61, 0x83, 0xe2, 0x51, 0xf3, 0x9e, 0x96, 0xfd, 0xbb, + 0xb0, 0x28, 0x66, 0xcb, 0x63, 0xc2, 0xcc, 0x51, 0x93, 0xd3, 0xc6, 0x7d, 0x0c, 0x4f, 0xf7, 0x31, + 0x72, 0x3d, 0x1f, 0x7f, 0x14, 0x82, 0xd5, 0x13, 0xb7, 0x3d, 0xe6, 0xe3, 0xd0, 0x17, 0xe5, 0x19, + 0xf9, 0x32, 0x29, 0x5f, 0xb7, 0x21, 0xd9, 0xe3, 0xca, 0xf9, 0x6f, 0x0b, 0xf2, 0x65, 0x42, 0x1d, + 0xbb, 0xee, 0xef, 0x9a, 0xd8, 0x6a, 0x1f, 0x1a, 0xe4, 0x4c, 0x03, 0x31, 0x9c, 0x7d, 0x3f, 0xe3, + 0x40, 0xbc, 0x09, 0xab, 0x3b, 0xd8, 0xc2, 0x97, 0xe3, 0x30, 0x61, 0x29, 0xe6, 0xfe, 0x19, 0x82, + 0x5b, 0x5b, 0x06, 0x6d, 0x3d, 0x0e, 0x06, 0x6e, 0x2a, 0x37, 0x6c, 0x40, 0x46, 0x9a, 0xdb, 0x64, + 0x73, 0xf5, 0xc1, 0x71, 0x87, 0xdd, 0x31, 0x45, 0x8f, 0x00, 0xf5, 0x4c, 0xf4, 0x6d, 0x58, 0x1d, + 0x19, 0x6b, 0xda, 0x96, 0x69, 0x63, 0x19, 0x9f, 0xb7, 0x66, 0x74, 0x91, 0xa3, 0xb1, 0xdb, 0x78, + 0x00, 0xbc, 0xc2, 0x81, 0xc6, 0x93, 0x13, 0x99, 0x9e, 0x9c, 0xe8, 0x75, 0x92, 0xb3, 0x78, 0xad, + 0xe4, 0x6c, 0xa5, 0x21, 0x15, 0x8c, 0x47, 0x4e, 0x07, 0x75, 0x52, 0x02, 0x9e, 0x19, 0x7d, 0xe5, + 0xce, 0x65, 0x86, 0x83, 0x4b, 0x62, 0x6a, 0x86, 0x03, 0x7a, 0x43, 0x57, 0xd4, 0x5b, 0x87, 0x64, + 0x20, 0x79, 0xcf, 0xc0, 0x93, 0x8d, 0xbb, 0x00, 0x95, 0x60, 0xb5, 0x78, 0xbe, 0x72, 0xd4, 0x28, + 0x1f, 0x35, 0xf4, 0xfb, 0x95, 0xf2, 0x83, 0x4b, 0x35, 0xf3, 0x06, 0x64, 0x82, 0x9d, 0xbb, 0x27, + 0xd5, 0x6a, 0x46, 0x29, 0x7e, 0x9e, 0x80, 0x98, 0x0c, 0x00, 0xfa, 0x8d, 0x02, 0xc9, 0x40, 0xc1, + 0x40, 0xef, 0x4c, 0x35, 0x67, 0xbc, 0x78, 0xaa, 0xef, 0xce, 0x37, 0x49, 0x24, 0x35, 0x57, 0xfc, + 0xc1, 0x9f, 0xfe, 0xf6, 0xb3, 0xd0, 0x5b, 0x68, 0x63, 0xf0, 0xab, 0xe7, 0x77, 0x45, 0xd8, 0x3f, + 0x72, 0x3d, 0xe7, 0x3b, 0xb8, 0x45, 0x49, 0x61, 0xa3, 0x60, 0x74, 0xb0, 0x4d, 0x3f, 0x2d, 0xf8, + 0x45, 0xe8, 0x17, 0x0a, 0x24, 0x06, 0xc5, 0x05, 0x4d, 0xff, 0x2d, 0xe9, 0x72, 0x21, 0x52, 0x67, + 0x0d, 0xf7, 0x24, 0xeb, 0x18, 0x55, 0x8c, 0xd9, 0xe6, 0x9b, 0x56, 0xd8, 0xf8, 0x14, 0x7d, 0xa6, + 0x40, 0x2a, 0x58, 0x5e, 0xd0, 0xf4, 0xc0, 0x4c, 0xa8, 0x46, 0xb3, 0xdb, 0xb8, 0xc9, 0x6d, 0x7c, + 0x37, 0x37, 0x47, 0x04, 0x37, 0x7d, 0x36, 0xff, 0xad, 0x02, 0xa9, 0xe0, 0x66, 0x9b, 0xc1, 0xd6, + 0x09, 0x55, 0x65, 0x76, 0x5b, 0x4b, 0xdc, 0xd6, 0xdb, 0xc5, 0xb7, 0x87, 0xb6, 0xca, 0x5f, 0xd4, + 0xa7, 0x85, 0x75, 0x60, 0xf2, 0x4f, 0x15, 0x48, 0x05, 0xb7, 0xef, 0x0c, 0x26, 0x4f, 0x28, 0x00, + 0xea, 0xcd, 0x31, 0xc2, 0x2b, 0x77, 0x5d, 0xda, 0xf7, 0x33, 0xbe, 0x31, 0x4f, 0xc6, 0x3f, 0x57, + 0x00, 0x8d, 0xf3, 0x16, 0x9a, 0x7e, 0x09, 0x7f, 0x6a, 0xb5, 0x51, 0x5f, 0xf2, 0xe7, 0x06, 0x7e, + 0xed, 0xcf, 0xd7, 0xfc, 0x5f, 0xfb, 0xfd, 0x38, 0xe6, 0xde, 0x9b, 0x23, 0xe7, 0xcd, 0xa1, 0xb2, + 0x4d, 0x65, 0x63, 0x68, 0xf4, 0x08, 0x17, 0xce, 0x6a, 0xf4, 0x24, 0x02, 0xfd, 0x8f, 0x19, 0x2d, + 0x94, 0x6d, 0x2a, 0x1b, 0x5b, 0x9f, 0x29, 0xf0, 0x6a, 0xcb, 0xe9, 0x4e, 0xb3, 0x71, 0x4b, 0xb2, + 0x6d, 0x9d, 0xe5, 0xb6, 0xae, 0x3c, 0xaa, 0xc8, 0xf1, 0x1d, 0x87, 0x55, 0xc2, 0xbc, 0xe3, 0x75, + 0x0a, 0x1d, 0x6c, 0xf3, 0xcc, 0x17, 0x44, 0x97, 0xe1, 0x9a, 0xe4, 0xa9, 0x7f, 0xc4, 0xb8, 0x3d, + 0x14, 0xfd, 0x43, 0x51, 0x7e, 0x19, 0x0a, 0xed, 0xec, 0xfe, 0x3a, 0xf4, 0xf2, 0x9e, 0xc0, 0xdc, + 0xe6, 0x36, 0xec, 0x0c, 0x6d, 0xb8, 0x2f, 0x26, 0x35, 0x17, 0x39, 0xfe, 0x3b, 0xff, 0x0a, 0x00, + 0x00, 0xff, 0xff, 0xb5, 0x89, 0xf2, 0x83, 0x54, 0x22, 0x00, 0x00, +} diff --git a/vendor/google.golang.org/genproto/googleapis/cloud/dialogflow/v2beta1/session.pb.go b/vendor/google.golang.org/genproto/googleapis/cloud/dialogflow/v2beta1/session.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..81ba15e49f5aa7ff959ddcf7ec1b4ec6ca6e9126 --- /dev/null +++ b/vendor/google.golang.org/genproto/googleapis/cloud/dialogflow/v2beta1/session.pb.go @@ -0,0 +1,1227 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: google/cloud/dialogflow/v2beta1/session.proto + +package dialogflow + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import _ "google.golang.org/genproto/googleapis/api/annotations" +import google_protobuf4 "github.com/golang/protobuf/ptypes/struct" +import google_rpc "google.golang.org/genproto/googleapis/rpc/status" +import google_type "google.golang.org/genproto/googleapis/type/latlng" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// Audio encoding of the audio content sent in the conversational query request. +// Refer to the [Cloud Speech API documentation](/speech/docs/basics) for more +// details. +type AudioEncoding int32 + +const ( + // Not specified. + AudioEncoding_AUDIO_ENCODING_UNSPECIFIED AudioEncoding = 0 + // Uncompressed 16-bit signed little-endian samples (Linear PCM). + AudioEncoding_AUDIO_ENCODING_LINEAR_16 AudioEncoding = 1 + // [`FLAC`](https://xiph.org/flac/documentation.html) (Free Lossless Audio + // Codec) is the recommended encoding because it is lossless (therefore + // recognition is not compromised) and requires only about half the + // bandwidth of `LINEAR16`. `FLAC` stream encoding supports 16-bit and + // 24-bit samples, however, not all fields in `STREAMINFO` are supported. + AudioEncoding_AUDIO_ENCODING_FLAC AudioEncoding = 2 + // 8-bit samples that compand 14-bit audio samples using G.711 PCMU/mu-law. + AudioEncoding_AUDIO_ENCODING_MULAW AudioEncoding = 3 + // Adaptive Multi-Rate Narrowband codec. `sample_rate_hertz` must be 8000. + AudioEncoding_AUDIO_ENCODING_AMR AudioEncoding = 4 + // Adaptive Multi-Rate Wideband codec. `sample_rate_hertz` must be 16000. + AudioEncoding_AUDIO_ENCODING_AMR_WB AudioEncoding = 5 + // Opus encoded audio frames in Ogg container + // ([OggOpus](https://wiki.xiph.org/OggOpus)). + // `sample_rate_hertz` must be 16000. + AudioEncoding_AUDIO_ENCODING_OGG_OPUS AudioEncoding = 6 + // Although the use of lossy encodings is not recommended, if a very low + // bitrate encoding is required, `OGG_OPUS` is highly preferred over + // Speex encoding. The [Speex](https://speex.org/) encoding supported by + // Dialogflow API has a header byte in each block, as in MIME type + // `audio/x-speex-with-header-byte`. + // It is a variant of the RTP Speex encoding defined in + // [RFC 5574](https://tools.ietf.org/html/rfc5574). + // The stream is a sequence of blocks, one block per RTP packet. Each block + // starts with a byte containing the length of the block, in bytes, followed + // by one or more frames of Speex data, padded to an integral number of + // bytes (octets) as specified in RFC 5574. In other words, each RTP header + // is replaced with a single byte containing the block length. Only Speex + // wideband is supported. `sample_rate_hertz` must be 16000. + AudioEncoding_AUDIO_ENCODING_SPEEX_WITH_HEADER_BYTE AudioEncoding = 7 +) + +var AudioEncoding_name = map[int32]string{ + 0: "AUDIO_ENCODING_UNSPECIFIED", + 1: "AUDIO_ENCODING_LINEAR_16", + 2: "AUDIO_ENCODING_FLAC", + 3: "AUDIO_ENCODING_MULAW", + 4: "AUDIO_ENCODING_AMR", + 5: "AUDIO_ENCODING_AMR_WB", + 6: "AUDIO_ENCODING_OGG_OPUS", + 7: "AUDIO_ENCODING_SPEEX_WITH_HEADER_BYTE", +} +var AudioEncoding_value = map[string]int32{ + "AUDIO_ENCODING_UNSPECIFIED": 0, + "AUDIO_ENCODING_LINEAR_16": 1, + "AUDIO_ENCODING_FLAC": 2, + "AUDIO_ENCODING_MULAW": 3, + "AUDIO_ENCODING_AMR": 4, + "AUDIO_ENCODING_AMR_WB": 5, + "AUDIO_ENCODING_OGG_OPUS": 6, + "AUDIO_ENCODING_SPEEX_WITH_HEADER_BYTE": 7, +} + +func (x AudioEncoding) String() string { + return proto.EnumName(AudioEncoding_name, int32(x)) +} +func (AudioEncoding) EnumDescriptor() ([]byte, []int) { return fileDescriptor4, []int{0} } + +// Type of the response message. +type StreamingRecognitionResult_MessageType int32 + +const ( + // Not specified. Should never be used. + StreamingRecognitionResult_MESSAGE_TYPE_UNSPECIFIED StreamingRecognitionResult_MessageType = 0 + // Message contains a (possibly partial) transcript. + StreamingRecognitionResult_TRANSCRIPT StreamingRecognitionResult_MessageType = 1 + // Event indicates that the server has detected the end of the user's speech + // utterance and expects no additional speech. Therefore, the server will + // not process additional audio (although it may subsequently return + // additional results). The client should stop sending additional audio + // data, half-close the gRPC connection, and wait for any additional results + // until the server closes the gRPC connection. This message is only sent if + // `single_utterance` was set to `true`, and is not used otherwise. + StreamingRecognitionResult_END_OF_SINGLE_UTTERANCE StreamingRecognitionResult_MessageType = 2 +) + +var StreamingRecognitionResult_MessageType_name = map[int32]string{ + 0: "MESSAGE_TYPE_UNSPECIFIED", + 1: "TRANSCRIPT", + 2: "END_OF_SINGLE_UTTERANCE", +} +var StreamingRecognitionResult_MessageType_value = map[string]int32{ + "MESSAGE_TYPE_UNSPECIFIED": 0, + "TRANSCRIPT": 1, + "END_OF_SINGLE_UTTERANCE": 2, +} + +func (x StreamingRecognitionResult_MessageType) String() string { + return proto.EnumName(StreamingRecognitionResult_MessageType_name, int32(x)) +} +func (StreamingRecognitionResult_MessageType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor4, []int{7, 0} +} + +// The request to detect user's intent. +type DetectIntentRequest struct { + // Required. The name of the session this query is sent to. Format: + // `projects//agent/sessions/`. + // It's up to the API caller to choose an appropriate session ID. It can be + // a random number or some type of user identifier (preferably hashed). + // The length of the session ID must not exceed 36 bytes. + Session string `protobuf:"bytes,1,opt,name=session" json:"session,omitempty"` + // Optional. The parameters of this query. + QueryParams *QueryParameters `protobuf:"bytes,2,opt,name=query_params,json=queryParams" json:"query_params,omitempty"` + // Required. The input specification. It can be set to: + // + // 1. an audio config + // which instructs the speech recognizer how to process the speech audio, + // + // 2. a conversational query in the form of text, or + // + // 3. an event that specifies which intent to trigger. + QueryInput *QueryInput `protobuf:"bytes,3,opt,name=query_input,json=queryInput" json:"query_input,omitempty"` + // Optional. The natural language speech audio to be processed. This field + // should be populated iff `query_input` is set to an input audio config. + // A single request can contain up to 1 minute of speech audio data. + InputAudio []byte `protobuf:"bytes,5,opt,name=input_audio,json=inputAudio,proto3" json:"input_audio,omitempty"` +} + +func (m *DetectIntentRequest) Reset() { *m = DetectIntentRequest{} } +func (m *DetectIntentRequest) String() string { return proto.CompactTextString(m) } +func (*DetectIntentRequest) ProtoMessage() {} +func (*DetectIntentRequest) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{0} } + +func (m *DetectIntentRequest) GetSession() string { + if m != nil { + return m.Session + } + return "" +} + +func (m *DetectIntentRequest) GetQueryParams() *QueryParameters { + if m != nil { + return m.QueryParams + } + return nil +} + +func (m *DetectIntentRequest) GetQueryInput() *QueryInput { + if m != nil { + return m.QueryInput + } + return nil +} + +func (m *DetectIntentRequest) GetInputAudio() []byte { + if m != nil { + return m.InputAudio + } + return nil +} + +// The message returned from the DetectIntent method. +type DetectIntentResponse struct { + // The unique identifier of the response. It can be used to + // locate a response in the training example set or for reporting issues. + ResponseId string `protobuf:"bytes,1,opt,name=response_id,json=responseId" json:"response_id,omitempty"` + // The results of the conversational query or event processing. + QueryResult *QueryResult `protobuf:"bytes,2,opt,name=query_result,json=queryResult" json:"query_result,omitempty"` + // Specifies the status of the webhook request. `webhook_status` + // is never populated in webhook requests. + WebhookStatus *google_rpc.Status `protobuf:"bytes,3,opt,name=webhook_status,json=webhookStatus" json:"webhook_status,omitempty"` +} + +func (m *DetectIntentResponse) Reset() { *m = DetectIntentResponse{} } +func (m *DetectIntentResponse) String() string { return proto.CompactTextString(m) } +func (*DetectIntentResponse) ProtoMessage() {} +func (*DetectIntentResponse) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{1} } + +func (m *DetectIntentResponse) GetResponseId() string { + if m != nil { + return m.ResponseId + } + return "" +} + +func (m *DetectIntentResponse) GetQueryResult() *QueryResult { + if m != nil { + return m.QueryResult + } + return nil +} + +func (m *DetectIntentResponse) GetWebhookStatus() *google_rpc.Status { + if m != nil { + return m.WebhookStatus + } + return nil +} + +// Represents the parameters of the conversational query. +type QueryParameters struct { + // Optional. The time zone of this conversational query from the + // [time zone database](https://www.iana.org/time-zones), e.g., + // America/New_York, Europe/Paris. If not provided, the time zone specified in + // agent settings is used. + TimeZone string `protobuf:"bytes,1,opt,name=time_zone,json=timeZone" json:"time_zone,omitempty"` + // Optional. The geo location of this conversational query. + GeoLocation *google_type.LatLng `protobuf:"bytes,2,opt,name=geo_location,json=geoLocation" json:"geo_location,omitempty"` + // Optional. The collection of contexts to be activated before this query is + // executed. + Contexts []*Context `protobuf:"bytes,3,rep,name=contexts" json:"contexts,omitempty"` + // Optional. Specifies whether to delete all contexts in the current session + // before the new ones are activated. + ResetContexts bool `protobuf:"varint,4,opt,name=reset_contexts,json=resetContexts" json:"reset_contexts,omitempty"` + // Optional. The collection of session entity types to replace or extend + // developer entities with for this query only. The entity synonyms apply + // to all languages. + SessionEntityTypes []*SessionEntityType `protobuf:"bytes,5,rep,name=session_entity_types,json=sessionEntityTypes" json:"session_entity_types,omitempty"` + // Optional. This field can be used to pass custom data into the webhook + // associated with the agent. Arbitrary JSON objects are supported. + Payload *google_protobuf4.Struct `protobuf:"bytes,6,opt,name=payload" json:"payload,omitempty"` +} + +func (m *QueryParameters) Reset() { *m = QueryParameters{} } +func (m *QueryParameters) String() string { return proto.CompactTextString(m) } +func (*QueryParameters) ProtoMessage() {} +func (*QueryParameters) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{2} } + +func (m *QueryParameters) GetTimeZone() string { + if m != nil { + return m.TimeZone + } + return "" +} + +func (m *QueryParameters) GetGeoLocation() *google_type.LatLng { + if m != nil { + return m.GeoLocation + } + return nil +} + +func (m *QueryParameters) GetContexts() []*Context { + if m != nil { + return m.Contexts + } + return nil +} + +func (m *QueryParameters) GetResetContexts() bool { + if m != nil { + return m.ResetContexts + } + return false +} + +func (m *QueryParameters) GetSessionEntityTypes() []*SessionEntityType { + if m != nil { + return m.SessionEntityTypes + } + return nil +} + +func (m *QueryParameters) GetPayload() *google_protobuf4.Struct { + if m != nil { + return m.Payload + } + return nil +} + +// Represents the query input. It can contain either: +// +// 1. An audio config which +// instructs the speech recognizer how to process the speech audio. +// +// 2. A conversational query in the form of text,. +// +// 3. An event that specifies which intent to trigger. +type QueryInput struct { + // Required. The input specification. + // + // Types that are valid to be assigned to Input: + // *QueryInput_AudioConfig + // *QueryInput_Text + // *QueryInput_Event + Input isQueryInput_Input `protobuf_oneof:"input"` +} + +func (m *QueryInput) Reset() { *m = QueryInput{} } +func (m *QueryInput) String() string { return proto.CompactTextString(m) } +func (*QueryInput) ProtoMessage() {} +func (*QueryInput) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{3} } + +type isQueryInput_Input interface { + isQueryInput_Input() +} + +type QueryInput_AudioConfig struct { + AudioConfig *InputAudioConfig `protobuf:"bytes,1,opt,name=audio_config,json=audioConfig,oneof"` +} +type QueryInput_Text struct { + Text *TextInput `protobuf:"bytes,2,opt,name=text,oneof"` +} +type QueryInput_Event struct { + Event *EventInput `protobuf:"bytes,3,opt,name=event,oneof"` +} + +func (*QueryInput_AudioConfig) isQueryInput_Input() {} +func (*QueryInput_Text) isQueryInput_Input() {} +func (*QueryInput_Event) isQueryInput_Input() {} + +func (m *QueryInput) GetInput() isQueryInput_Input { + if m != nil { + return m.Input + } + return nil +} + +func (m *QueryInput) GetAudioConfig() *InputAudioConfig { + if x, ok := m.GetInput().(*QueryInput_AudioConfig); ok { + return x.AudioConfig + } + return nil +} + +func (m *QueryInput) GetText() *TextInput { + if x, ok := m.GetInput().(*QueryInput_Text); ok { + return x.Text + } + return nil +} + +func (m *QueryInput) GetEvent() *EventInput { + if x, ok := m.GetInput().(*QueryInput_Event); ok { + return x.Event + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*QueryInput) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _QueryInput_OneofMarshaler, _QueryInput_OneofUnmarshaler, _QueryInput_OneofSizer, []interface{}{ + (*QueryInput_AudioConfig)(nil), + (*QueryInput_Text)(nil), + (*QueryInput_Event)(nil), + } +} + +func _QueryInput_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*QueryInput) + // input + switch x := m.Input.(type) { + case *QueryInput_AudioConfig: + b.EncodeVarint(1<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.AudioConfig); err != nil { + return err + } + case *QueryInput_Text: + b.EncodeVarint(2<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Text); err != nil { + return err + } + case *QueryInput_Event: + b.EncodeVarint(3<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Event); err != nil { + return err + } + case nil: + default: + return fmt.Errorf("QueryInput.Input has unexpected type %T", x) + } + return nil +} + +func _QueryInput_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*QueryInput) + switch tag { + case 1: // input.audio_config + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(InputAudioConfig) + err := b.DecodeMessage(msg) + m.Input = &QueryInput_AudioConfig{msg} + return true, err + case 2: // input.text + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(TextInput) + err := b.DecodeMessage(msg) + m.Input = &QueryInput_Text{msg} + return true, err + case 3: // input.event + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(EventInput) + err := b.DecodeMessage(msg) + m.Input = &QueryInput_Event{msg} + return true, err + default: + return false, nil + } +} + +func _QueryInput_OneofSizer(msg proto.Message) (n int) { + m := msg.(*QueryInput) + // input + switch x := m.Input.(type) { + case *QueryInput_AudioConfig: + s := proto.Size(x.AudioConfig) + n += proto.SizeVarint(1<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *QueryInput_Text: + s := proto.Size(x.Text) + n += proto.SizeVarint(2<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *QueryInput_Event: + s := proto.Size(x.Event) + n += proto.SizeVarint(3<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +// Represents the result of conversational query or event processing. +type QueryResult struct { + // The original conversational query text: + // - If natural language text was provided as input, `query_text` contains + // a copy of the input. + // - If natural language speech audio was provided as input, `query_text` + // contains the speech recognition result. If speech recognizer produced + // multiple alternatives, a particular one is picked. + // - If an event was provided as input, `query_text` is not set. + QueryText string `protobuf:"bytes,1,opt,name=query_text,json=queryText" json:"query_text,omitempty"` + // The language that was triggered during intent detection. + // See [Language Support](https://dialogflow.com/docs/reference/language) + // for a list of the currently supported language codes. + LanguageCode string `protobuf:"bytes,15,opt,name=language_code,json=languageCode" json:"language_code,omitempty"` + // The confidence estimate between 0.0 and 1.0. A higher number + // indicates an estimated greater likelihood that the recognized words are + // correct. The default of 0.0 is a sentinel value indicating that confidence + // was not set. This field is populated if natural speech audio was provided + // as input. + SpeechRecognitionConfidence float32 `protobuf:"fixed32,2,opt,name=speech_recognition_confidence,json=speechRecognitionConfidence" json:"speech_recognition_confidence,omitempty"` + // The action name from the matched intent. + Action string `protobuf:"bytes,3,opt,name=action" json:"action,omitempty"` + // The collection of extracted parameters. + Parameters *google_protobuf4.Struct `protobuf:"bytes,4,opt,name=parameters" json:"parameters,omitempty"` + // This field is set to: + // - `false` if the matched intent has required parameters and not all of + // the required parameter values have been collected. + // - `true` if all required parameter values have been collected, or if the + // matched intent doesn't contain any required parameters. + AllRequiredParamsPresent bool `protobuf:"varint,5,opt,name=all_required_params_present,json=allRequiredParamsPresent" json:"all_required_params_present,omitempty"` + // The text to be pronounced to the user or shown on the screen. + FulfillmentText string `protobuf:"bytes,6,opt,name=fulfillment_text,json=fulfillmentText" json:"fulfillment_text,omitempty"` + // The collection of rich messages to present to the user. + FulfillmentMessages []*Intent_Message `protobuf:"bytes,7,rep,name=fulfillment_messages,json=fulfillmentMessages" json:"fulfillment_messages,omitempty"` + // If the query was fulfilled by a webhook call, this field is set to the + // value of the `source` field returned in the webhook response. + WebhookSource string `protobuf:"bytes,8,opt,name=webhook_source,json=webhookSource" json:"webhook_source,omitempty"` + // If the query was fulfilled by a webhook call, this field is set to the + // value of the `payload` field returned in the webhook response. + WebhookPayload *google_protobuf4.Struct `protobuf:"bytes,9,opt,name=webhook_payload,json=webhookPayload" json:"webhook_payload,omitempty"` + // The collection of output contexts. If applicable, + // `output_contexts.parameters` contains entries with name + // `.original` containing the original parameter values + // before the query. + OutputContexts []*Context `protobuf:"bytes,10,rep,name=output_contexts,json=outputContexts" json:"output_contexts,omitempty"` + // The intent that matched the conversational query. Some, not + // all fields are filled in this message, including but not limited to: + // `name`, `display_name` and `webhook_state`. + Intent *Intent `protobuf:"bytes,11,opt,name=intent" json:"intent,omitempty"` + // The intent detection confidence. Values range from 0.0 + // (completely uncertain) to 1.0 (completely certain). + IntentDetectionConfidence float32 `protobuf:"fixed32,12,opt,name=intent_detection_confidence,json=intentDetectionConfidence" json:"intent_detection_confidence,omitempty"` + // The free-form diagnostic info. For example, this field + // could contain webhook call latency. + DiagnosticInfo *google_protobuf4.Struct `protobuf:"bytes,14,opt,name=diagnostic_info,json=diagnosticInfo" json:"diagnostic_info,omitempty"` +} + +func (m *QueryResult) Reset() { *m = QueryResult{} } +func (m *QueryResult) String() string { return proto.CompactTextString(m) } +func (*QueryResult) ProtoMessage() {} +func (*QueryResult) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{4} } + +func (m *QueryResult) GetQueryText() string { + if m != nil { + return m.QueryText + } + return "" +} + +func (m *QueryResult) GetLanguageCode() string { + if m != nil { + return m.LanguageCode + } + return "" +} + +func (m *QueryResult) GetSpeechRecognitionConfidence() float32 { + if m != nil { + return m.SpeechRecognitionConfidence + } + return 0 +} + +func (m *QueryResult) GetAction() string { + if m != nil { + return m.Action + } + return "" +} + +func (m *QueryResult) GetParameters() *google_protobuf4.Struct { + if m != nil { + return m.Parameters + } + return nil +} + +func (m *QueryResult) GetAllRequiredParamsPresent() bool { + if m != nil { + return m.AllRequiredParamsPresent + } + return false +} + +func (m *QueryResult) GetFulfillmentText() string { + if m != nil { + return m.FulfillmentText + } + return "" +} + +func (m *QueryResult) GetFulfillmentMessages() []*Intent_Message { + if m != nil { + return m.FulfillmentMessages + } + return nil +} + +func (m *QueryResult) GetWebhookSource() string { + if m != nil { + return m.WebhookSource + } + return "" +} + +func (m *QueryResult) GetWebhookPayload() *google_protobuf4.Struct { + if m != nil { + return m.WebhookPayload + } + return nil +} + +func (m *QueryResult) GetOutputContexts() []*Context { + if m != nil { + return m.OutputContexts + } + return nil +} + +func (m *QueryResult) GetIntent() *Intent { + if m != nil { + return m.Intent + } + return nil +} + +func (m *QueryResult) GetIntentDetectionConfidence() float32 { + if m != nil { + return m.IntentDetectionConfidence + } + return 0 +} + +func (m *QueryResult) GetDiagnosticInfo() *google_protobuf4.Struct { + if m != nil { + return m.DiagnosticInfo + } + return nil +} + +// The top-level message sent by the client to the +// `StreamingDetectIntent` method. +// +// Multiple request messages should be sent in order: +// +// 1. The first message must contain `session`, `query_input` plus optionally +// `query_params` and/or `single_utterance`. The message must not contain +// `input_audio`. +// +// 2. If `query_input` was set to a streaming input audio config, +// all subsequent messages must contain only `input_audio`. +// Otherwise, finish the request stream. +type StreamingDetectIntentRequest struct { + // Required. The name of the session the query is sent to. + // Format of the session name: + // `projects//agent/sessions/`. + // It’s up to the API caller to choose an appropriate . It can be + // a random number or some type of user identifier (preferably hashed). + // The length of the session ID must not exceed 36 characters. + Session string `protobuf:"bytes,1,opt,name=session" json:"session,omitempty"` + // Optional. The parameters of this query. + QueryParams *QueryParameters `protobuf:"bytes,2,opt,name=query_params,json=queryParams" json:"query_params,omitempty"` + // Required. The input specification. It can be set to: + // + // 1. an audio config which instructs the speech recognizer how to process + // the speech audio, + // + // 2. a conversational query in the form of text, or + // + // 3. an event that specifies which intent to trigger. + QueryInput *QueryInput `protobuf:"bytes,3,opt,name=query_input,json=queryInput" json:"query_input,omitempty"` + // Optional. If `true`, the recognizer will detect a single spoken utterance + // in input audio. When it detects that the user has paused or stopped + // speaking, it will cease recognition. This setting is ignored when + // `query_input` is a piece of text or an event. + SingleUtterance bool `protobuf:"varint,4,opt,name=single_utterance,json=singleUtterance" json:"single_utterance,omitempty"` + // Optional. The input audio content to be recognized. Must be sent if + // `query_input` was set to a streaming input audio config. The complete audio + // over all streaming messages must not exceed 1 minute. + InputAudio []byte `protobuf:"bytes,6,opt,name=input_audio,json=inputAudio,proto3" json:"input_audio,omitempty"` +} + +func (m *StreamingDetectIntentRequest) Reset() { *m = StreamingDetectIntentRequest{} } +func (m *StreamingDetectIntentRequest) String() string { return proto.CompactTextString(m) } +func (*StreamingDetectIntentRequest) ProtoMessage() {} +func (*StreamingDetectIntentRequest) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{5} } + +func (m *StreamingDetectIntentRequest) GetSession() string { + if m != nil { + return m.Session + } + return "" +} + +func (m *StreamingDetectIntentRequest) GetQueryParams() *QueryParameters { + if m != nil { + return m.QueryParams + } + return nil +} + +func (m *StreamingDetectIntentRequest) GetQueryInput() *QueryInput { + if m != nil { + return m.QueryInput + } + return nil +} + +func (m *StreamingDetectIntentRequest) GetSingleUtterance() bool { + if m != nil { + return m.SingleUtterance + } + return false +} + +func (m *StreamingDetectIntentRequest) GetInputAudio() []byte { + if m != nil { + return m.InputAudio + } + return nil +} + +// The top-level message returned from the +// `StreamingDetectIntent` method. +// +// Multiple response messages can be returned in order: +// +// 1. If the input was set to streaming audio, the first one or more messages +// contain `recognition_result`. Each `recognition_result` represents a more +// complete transcript of what the user said. The last `recognition_result` +// has `is_final` set to `true`. +// +// 2. The next message contains `response_id`, `query_result` +// and optionally `webhook_status` if a WebHook was called. +type StreamingDetectIntentResponse struct { + // The unique identifier of the response. It can be used to + // locate a response in the training example set or for reporting issues. + ResponseId string `protobuf:"bytes,1,opt,name=response_id,json=responseId" json:"response_id,omitempty"` + // The result of speech recognition. + RecognitionResult *StreamingRecognitionResult `protobuf:"bytes,2,opt,name=recognition_result,json=recognitionResult" json:"recognition_result,omitempty"` + // The result of the conversational query or event processing. + QueryResult *QueryResult `protobuf:"bytes,3,opt,name=query_result,json=queryResult" json:"query_result,omitempty"` + // Specifies the status of the webhook request. + WebhookStatus *google_rpc.Status `protobuf:"bytes,4,opt,name=webhook_status,json=webhookStatus" json:"webhook_status,omitempty"` +} + +func (m *StreamingDetectIntentResponse) Reset() { *m = StreamingDetectIntentResponse{} } +func (m *StreamingDetectIntentResponse) String() string { return proto.CompactTextString(m) } +func (*StreamingDetectIntentResponse) ProtoMessage() {} +func (*StreamingDetectIntentResponse) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{6} } + +func (m *StreamingDetectIntentResponse) GetResponseId() string { + if m != nil { + return m.ResponseId + } + return "" +} + +func (m *StreamingDetectIntentResponse) GetRecognitionResult() *StreamingRecognitionResult { + if m != nil { + return m.RecognitionResult + } + return nil +} + +func (m *StreamingDetectIntentResponse) GetQueryResult() *QueryResult { + if m != nil { + return m.QueryResult + } + return nil +} + +func (m *StreamingDetectIntentResponse) GetWebhookStatus() *google_rpc.Status { + if m != nil { + return m.WebhookStatus + } + return nil +} + +// Contains a speech recognition result corresponding to a portion of the audio +// that is currently being processed or an indication that this is the end +// of the single requested utterance. +// +// Example: +// +// 1. transcript: "tube" +// +// 2. transcript: "to be a" +// +// 3. transcript: "to be" +// +// 4. transcript: "to be or not to be" +// is_final: true +// +// 5. transcript: " that's" +// +// 6. transcript: " that is" +// +// 7. recognition_event_type: `RECOGNITION_EVENT_END_OF_SINGLE_UTTERANCE` +// +// 8. transcript: " that is the question" +// is_final: true +// +// Only two of the responses contain final results (#4 and #8 indicated by +// `is_final: true`). Concatenating these generates the full transcript: "to be +// or not to be that is the question". +// +// In each response we populate: +// +// * for `MESSAGE_TYPE_TRANSCRIPT`: `transcript` and possibly `is_final`. +// +// * for `MESSAGE_TYPE_END_OF_SINGLE_UTTERANCE`: only `event_type`. +type StreamingRecognitionResult struct { + // Type of the result message. + MessageType StreamingRecognitionResult_MessageType `protobuf:"varint,1,opt,name=message_type,json=messageType,enum=google.cloud.dialogflow.v2beta1.StreamingRecognitionResult_MessageType" json:"message_type,omitempty"` + // Transcript text representing the words that the user spoke. + // Populated if and only if `event_type` = `RECOGNITION_EVENT_TRANSCRIPT`. + Transcript string `protobuf:"bytes,2,opt,name=transcript" json:"transcript,omitempty"` + // If `false`, the `StreamingRecognitionResult` represents an + // interim result that may change. If `true`, the recognizer will not return + // any further hypotheses about this piece of the audio. May only be populated + // for `event_type` = `RECOGNITION_EVENT_TRANSCRIPT`. + IsFinal bool `protobuf:"varint,3,opt,name=is_final,json=isFinal" json:"is_final,omitempty"` +} + +func (m *StreamingRecognitionResult) Reset() { *m = StreamingRecognitionResult{} } +func (m *StreamingRecognitionResult) String() string { return proto.CompactTextString(m) } +func (*StreamingRecognitionResult) ProtoMessage() {} +func (*StreamingRecognitionResult) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{7} } + +func (m *StreamingRecognitionResult) GetMessageType() StreamingRecognitionResult_MessageType { + if m != nil { + return m.MessageType + } + return StreamingRecognitionResult_MESSAGE_TYPE_UNSPECIFIED +} + +func (m *StreamingRecognitionResult) GetTranscript() string { + if m != nil { + return m.Transcript + } + return "" +} + +func (m *StreamingRecognitionResult) GetIsFinal() bool { + if m != nil { + return m.IsFinal + } + return false +} + +// Instructs the speech recognizer how to process the audio content. +type InputAudioConfig struct { + // Required. Audio encoding of the audio content to process. + AudioEncoding AudioEncoding `protobuf:"varint,1,opt,name=audio_encoding,json=audioEncoding,enum=google.cloud.dialogflow.v2beta1.AudioEncoding" json:"audio_encoding,omitempty"` + // Required. Sample rate (in Hertz) of the audio content sent in the query. + // Refer to [Cloud Speech API documentation](/speech/docs/basics) for more + // details. + SampleRateHertz int32 `protobuf:"varint,2,opt,name=sample_rate_hertz,json=sampleRateHertz" json:"sample_rate_hertz,omitempty"` + // Required. The language of the supplied audio. Dialogflow does not do + // translations. See [Language + // Support](https://dialogflow.com/docs/languages) for a list of the + // currently supported language codes. Note that queries in the same session + // do not necessarily need to specify the same language. + LanguageCode string `protobuf:"bytes,3,opt,name=language_code,json=languageCode" json:"language_code,omitempty"` + // Optional. The collection of phrase hints which are used to boost accuracy + // of speech recognition. + // Refer to [Cloud Speech API documentation](/speech/docs/basics#phrase-hints) + // for more details. + PhraseHints []string `protobuf:"bytes,4,rep,name=phrase_hints,json=phraseHints" json:"phrase_hints,omitempty"` +} + +func (m *InputAudioConfig) Reset() { *m = InputAudioConfig{} } +func (m *InputAudioConfig) String() string { return proto.CompactTextString(m) } +func (*InputAudioConfig) ProtoMessage() {} +func (*InputAudioConfig) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{8} } + +func (m *InputAudioConfig) GetAudioEncoding() AudioEncoding { + if m != nil { + return m.AudioEncoding + } + return AudioEncoding_AUDIO_ENCODING_UNSPECIFIED +} + +func (m *InputAudioConfig) GetSampleRateHertz() int32 { + if m != nil { + return m.SampleRateHertz + } + return 0 +} + +func (m *InputAudioConfig) GetLanguageCode() string { + if m != nil { + return m.LanguageCode + } + return "" +} + +func (m *InputAudioConfig) GetPhraseHints() []string { + if m != nil { + return m.PhraseHints + } + return nil +} + +// Represents the natural language text to be processed. +type TextInput struct { + // Required. The UTF-8 encoded natural language text to be processed. + // Text length must not exceed 256 bytes. + Text string `protobuf:"bytes,1,opt,name=text" json:"text,omitempty"` + // Required. The language of this conversational query. See [Language + // Support](https://dialogflow.com/docs/languages) for a list of the + // currently supported language codes. Note that queries in the same session + // do not necessarily need to specify the same language. + LanguageCode string `protobuf:"bytes,2,opt,name=language_code,json=languageCode" json:"language_code,omitempty"` +} + +func (m *TextInput) Reset() { *m = TextInput{} } +func (m *TextInput) String() string { return proto.CompactTextString(m) } +func (*TextInput) ProtoMessage() {} +func (*TextInput) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{9} } + +func (m *TextInput) GetText() string { + if m != nil { + return m.Text + } + return "" +} + +func (m *TextInput) GetLanguageCode() string { + if m != nil { + return m.LanguageCode + } + return "" +} + +// Events allow for matching intents by event name instead of the natural +// language input. For instance, input `` can trigger a personalized welcome response. +// The parameter `name` may be used by the agent in the response: +// `“Hello #welcome_event.name! What can I do for you today?â€`. +type EventInput struct { + // Required. The unique identifier of the event. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // Optional. The collection of parameters associated with the event. + Parameters *google_protobuf4.Struct `protobuf:"bytes,2,opt,name=parameters" json:"parameters,omitempty"` + // Required. The language of this query. See [Language + // Support](https://dialogflow.com/docs/languages) for a list of the + // currently supported language codes. Note that queries in the same session + // do not necessarily need to specify the same language. + LanguageCode string `protobuf:"bytes,3,opt,name=language_code,json=languageCode" json:"language_code,omitempty"` +} + +func (m *EventInput) Reset() { *m = EventInput{} } +func (m *EventInput) String() string { return proto.CompactTextString(m) } +func (*EventInput) ProtoMessage() {} +func (*EventInput) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{10} } + +func (m *EventInput) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *EventInput) GetParameters() *google_protobuf4.Struct { + if m != nil { + return m.Parameters + } + return nil +} + +func (m *EventInput) GetLanguageCode() string { + if m != nil { + return m.LanguageCode + } + return "" +} + +func init() { + proto.RegisterType((*DetectIntentRequest)(nil), "google.cloud.dialogflow.v2beta1.DetectIntentRequest") + proto.RegisterType((*DetectIntentResponse)(nil), "google.cloud.dialogflow.v2beta1.DetectIntentResponse") + proto.RegisterType((*QueryParameters)(nil), "google.cloud.dialogflow.v2beta1.QueryParameters") + proto.RegisterType((*QueryInput)(nil), "google.cloud.dialogflow.v2beta1.QueryInput") + proto.RegisterType((*QueryResult)(nil), "google.cloud.dialogflow.v2beta1.QueryResult") + proto.RegisterType((*StreamingDetectIntentRequest)(nil), "google.cloud.dialogflow.v2beta1.StreamingDetectIntentRequest") + proto.RegisterType((*StreamingDetectIntentResponse)(nil), "google.cloud.dialogflow.v2beta1.StreamingDetectIntentResponse") + proto.RegisterType((*StreamingRecognitionResult)(nil), "google.cloud.dialogflow.v2beta1.StreamingRecognitionResult") + proto.RegisterType((*InputAudioConfig)(nil), "google.cloud.dialogflow.v2beta1.InputAudioConfig") + proto.RegisterType((*TextInput)(nil), "google.cloud.dialogflow.v2beta1.TextInput") + proto.RegisterType((*EventInput)(nil), "google.cloud.dialogflow.v2beta1.EventInput") + proto.RegisterEnum("google.cloud.dialogflow.v2beta1.AudioEncoding", AudioEncoding_name, AudioEncoding_value) + proto.RegisterEnum("google.cloud.dialogflow.v2beta1.StreamingRecognitionResult_MessageType", StreamingRecognitionResult_MessageType_name, StreamingRecognitionResult_MessageType_value) +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// Client API for Sessions service + +type SessionsClient interface { + // Processes a natural language query and returns structured, actionable data + // as a result. This method is not idempotent, because it may cause contexts + // and session entity types to be updated, which in turn might affect + // results of future queries. + DetectIntent(ctx context.Context, in *DetectIntentRequest, opts ...grpc.CallOption) (*DetectIntentResponse, error) + // Processes a natural language query in audio format in a streaming fashion + // and returns structured, actionable data as a result. This method is only + // available via the gRPC API (not REST). + StreamingDetectIntent(ctx context.Context, opts ...grpc.CallOption) (Sessions_StreamingDetectIntentClient, error) +} + +type sessionsClient struct { + cc *grpc.ClientConn +} + +func NewSessionsClient(cc *grpc.ClientConn) SessionsClient { + return &sessionsClient{cc} +} + +func (c *sessionsClient) DetectIntent(ctx context.Context, in *DetectIntentRequest, opts ...grpc.CallOption) (*DetectIntentResponse, error) { + out := new(DetectIntentResponse) + err := grpc.Invoke(ctx, "/google.cloud.dialogflow.v2beta1.Sessions/DetectIntent", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *sessionsClient) StreamingDetectIntent(ctx context.Context, opts ...grpc.CallOption) (Sessions_StreamingDetectIntentClient, error) { + stream, err := grpc.NewClientStream(ctx, &_Sessions_serviceDesc.Streams[0], c.cc, "/google.cloud.dialogflow.v2beta1.Sessions/StreamingDetectIntent", opts...) + if err != nil { + return nil, err + } + x := &sessionsStreamingDetectIntentClient{stream} + return x, nil +} + +type Sessions_StreamingDetectIntentClient interface { + Send(*StreamingDetectIntentRequest) error + Recv() (*StreamingDetectIntentResponse, error) + grpc.ClientStream +} + +type sessionsStreamingDetectIntentClient struct { + grpc.ClientStream +} + +func (x *sessionsStreamingDetectIntentClient) Send(m *StreamingDetectIntentRequest) error { + return x.ClientStream.SendMsg(m) +} + +func (x *sessionsStreamingDetectIntentClient) Recv() (*StreamingDetectIntentResponse, error) { + m := new(StreamingDetectIntentResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// Server API for Sessions service + +type SessionsServer interface { + // Processes a natural language query and returns structured, actionable data + // as a result. This method is not idempotent, because it may cause contexts + // and session entity types to be updated, which in turn might affect + // results of future queries. + DetectIntent(context.Context, *DetectIntentRequest) (*DetectIntentResponse, error) + // Processes a natural language query in audio format in a streaming fashion + // and returns structured, actionable data as a result. This method is only + // available via the gRPC API (not REST). + StreamingDetectIntent(Sessions_StreamingDetectIntentServer) error +} + +func RegisterSessionsServer(s *grpc.Server, srv SessionsServer) { + s.RegisterService(&_Sessions_serviceDesc, srv) +} + +func _Sessions_DetectIntent_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DetectIntentRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SessionsServer).DetectIntent(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.dialogflow.v2beta1.Sessions/DetectIntent", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SessionsServer).DetectIntent(ctx, req.(*DetectIntentRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Sessions_StreamingDetectIntent_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(SessionsServer).StreamingDetectIntent(&sessionsStreamingDetectIntentServer{stream}) +} + +type Sessions_StreamingDetectIntentServer interface { + Send(*StreamingDetectIntentResponse) error + Recv() (*StreamingDetectIntentRequest, error) + grpc.ServerStream +} + +type sessionsStreamingDetectIntentServer struct { + grpc.ServerStream +} + +func (x *sessionsStreamingDetectIntentServer) Send(m *StreamingDetectIntentResponse) error { + return x.ServerStream.SendMsg(m) +} + +func (x *sessionsStreamingDetectIntentServer) Recv() (*StreamingDetectIntentRequest, error) { + m := new(StreamingDetectIntentRequest) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +var _Sessions_serviceDesc = grpc.ServiceDesc{ + ServiceName: "google.cloud.dialogflow.v2beta1.Sessions", + HandlerType: (*SessionsServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "DetectIntent", + Handler: _Sessions_DetectIntent_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "StreamingDetectIntent", + Handler: _Sessions_StreamingDetectIntent_Handler, + ServerStreams: true, + ClientStreams: true, + }, + }, + Metadata: "google/cloud/dialogflow/v2beta1/session.proto", +} + +func init() { proto.RegisterFile("google/cloud/dialogflow/v2beta1/session.proto", fileDescriptor4) } + +var fileDescriptor4 = []byte{ + // 1572 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x57, 0x4f, 0x73, 0x1b, 0xb7, + 0x15, 0xf7, 0x52, 0xd6, 0xbf, 0x47, 0x4a, 0x62, 0x60, 0x27, 0x5e, 0x4b, 0x76, 0xec, 0x32, 0x93, + 0x29, 0xad, 0xa6, 0x64, 0xac, 0xb6, 0xe9, 0x24, 0x1e, 0xa7, 0xa6, 0xc8, 0x95, 0xc4, 0x19, 0x9a, + 0x62, 0x40, 0x2a, 0x4e, 0x72, 0xc1, 0x40, 0x4b, 0x70, 0xb5, 0xee, 0x12, 0x58, 0x2d, 0xc0, 0x24, + 0x4a, 0xa7, 0x3d, 0xf4, 0x2b, 0xf4, 0xd6, 0x99, 0x5e, 0x7a, 0xe9, 0x4c, 0xae, 0xbd, 0xf4, 0x9e, + 0x8f, 0xd0, 0x73, 0x6f, 0x3d, 0xb6, 0xa7, 0xf6, 0xd0, 0x99, 0x5e, 0x3a, 0x0b, 0x60, 0x49, 0x9a, + 0x92, 0x43, 0xba, 0xed, 0x29, 0xb7, 0xc5, 0x7b, 0xbf, 0xf7, 0xf0, 0xde, 0xc3, 0x0f, 0xef, 0x61, + 0xe1, 0x87, 0x81, 0x10, 0x41, 0xc4, 0xaa, 0x7e, 0x24, 0x46, 0xfd, 0x6a, 0x3f, 0xa4, 0x91, 0x08, + 0x06, 0x91, 0xf8, 0xa2, 0xfa, 0xf9, 0xde, 0x29, 0x53, 0xf4, 0x61, 0x55, 0x32, 0x29, 0x43, 0xc1, + 0x2b, 0x71, 0x22, 0x94, 0x40, 0xf7, 0x0c, 0xbc, 0xa2, 0xe1, 0x95, 0x09, 0xbc, 0x62, 0xe1, 0xdb, + 0x77, 0xac, 0x3f, 0x1a, 0x87, 0x55, 0xca, 0xb9, 0x50, 0x54, 0x85, 0x82, 0x4b, 0x63, 0xbe, 0x3d, + 0x77, 0x37, 0x5f, 0x70, 0xc5, 0xbe, 0x54, 0x16, 0xfe, 0xce, 0x3c, 0x78, 0xc8, 0x15, 0xe3, 0x19, + 0xfa, 0xfd, 0x05, 0x53, 0x21, 0x8c, 0xab, 0x50, 0x5d, 0x10, 0x75, 0x11, 0x33, 0x6b, 0x9a, 0x45, + 0xad, 0x57, 0xa7, 0xa3, 0x41, 0x55, 0xaa, 0x64, 0xe4, 0x67, 0x8e, 0x6f, 0x59, 0x6d, 0x12, 0xfb, + 0x55, 0xa9, 0xa8, 0x1a, 0x65, 0xe9, 0xb8, 0x56, 0x91, 0x7a, 0xaa, 0x46, 0x54, 0x45, 0x3c, 0x30, + 0x9a, 0xd2, 0x3f, 0x1c, 0xb8, 0xd1, 0x60, 0x8a, 0xf9, 0xaa, 0xa9, 0x43, 0xc4, 0xec, 0x7c, 0xc4, + 0xa4, 0x42, 0x2e, 0xac, 0xda, 0x28, 0x5c, 0xe7, 0xbe, 0x53, 0x5e, 0xc7, 0xd9, 0x12, 0x75, 0xa1, + 0x70, 0x3e, 0x62, 0xc9, 0x05, 0x89, 0x69, 0x42, 0x87, 0xd2, 0xcd, 0xdd, 0x77, 0xca, 0xf9, 0xbd, + 0x77, 0x2b, 0x73, 0x0a, 0x5e, 0xf9, 0x28, 0x35, 0xea, 0xa4, 0x36, 0x4c, 0xb1, 0x44, 0xe2, 0xfc, + 0xf9, 0x58, 0x20, 0x51, 0x0b, 0xcc, 0x92, 0x84, 0x3c, 0x1e, 0x29, 0x77, 0x49, 0xfb, 0xfc, 0xc1, + 0x62, 0x3e, 0x9b, 0xa9, 0x09, 0x86, 0xf3, 0xf1, 0x37, 0xba, 0x07, 0x79, 0xed, 0x87, 0xd0, 0x51, + 0x3f, 0x14, 0xee, 0xf2, 0x7d, 0xa7, 0x5c, 0xc0, 0xa0, 0x45, 0xb5, 0x54, 0x52, 0xfa, 0xc6, 0x81, + 0x9b, 0x2f, 0x66, 0x2d, 0x63, 0xc1, 0x25, 0x4b, 0x2d, 0x13, 0xfb, 0x4d, 0xc2, 0xbe, 0x4d, 0x1d, + 0x32, 0x51, 0xb3, 0x8f, 0x8e, 0xb3, 0xec, 0x13, 0x26, 0x47, 0x91, 0xb2, 0xd9, 0xbf, 0xb3, 0x58, + 0xa4, 0x58, 0xdb, 0xd8, 0xcc, 0xcd, 0x02, 0xbd, 0x0f, 0x9b, 0x5f, 0xb0, 0xd3, 0x33, 0x21, 0x7e, + 0x4e, 0xcc, 0x91, 0xd9, 0xe4, 0x51, 0xe6, 0x32, 0x89, 0xfd, 0x4a, 0x57, 0x6b, 0xf0, 0x86, 0x45, + 0x9a, 0x65, 0xe9, 0x6f, 0x39, 0xd8, 0x9a, 0xa9, 0x2a, 0xda, 0x81, 0x75, 0x15, 0x0e, 0x19, 0xf9, + 0x4a, 0x70, 0x66, 0xc3, 0x5f, 0x4b, 0x05, 0x9f, 0x09, 0xce, 0xd0, 0x7b, 0x50, 0x08, 0x98, 0x20, + 0x91, 0xf0, 0x35, 0xd9, 0x6d, 0xf0, 0x37, 0xb2, 0x9d, 0x34, 0xcf, 0x5a, 0x54, 0xb5, 0x78, 0x80, + 0xf3, 0x01, 0x13, 0x2d, 0x8b, 0x43, 0x0d, 0x58, 0xb3, 0x7c, 0x4f, 0xa3, 0x5b, 0x2a, 0xe7, 0xf7, + 0xca, 0x73, 0x13, 0xae, 0x1b, 0x03, 0x3c, 0xb6, 0x44, 0x6f, 0xc3, 0x66, 0xc2, 0x24, 0x53, 0x64, + 0xec, 0xeb, 0xfa, 0x7d, 0xa7, 0xbc, 0x86, 0x37, 0xb4, 0xb4, 0x9e, 0xc1, 0xfa, 0x70, 0xf3, 0x0a, + 0xfe, 0x4b, 0x77, 0x59, 0x6f, 0xbc, 0x37, 0x77, 0xe3, 0xae, 0x31, 0xf6, 0xb4, 0x6d, 0xef, 0x22, + 0x66, 0x18, 0xc9, 0x59, 0x91, 0x44, 0x0f, 0x61, 0x35, 0xa6, 0x17, 0x91, 0xa0, 0x7d, 0x77, 0x45, + 0x57, 0xe1, 0x56, 0xe6, 0x38, 0xbb, 0x5a, 0x95, 0xae, 0xbe, 0x5a, 0x38, 0xc3, 0x95, 0xfe, 0xe9, + 0x00, 0x4c, 0x08, 0x87, 0x3e, 0x86, 0x82, 0xa6, 0x57, 0x9a, 0xce, 0x20, 0x0c, 0x74, 0xb1, 0xf3, + 0x7b, 0x0f, 0xe7, 0xc6, 0xd7, 0x1c, 0xd3, 0xb0, 0xae, 0x0d, 0x8f, 0xae, 0xe1, 0x3c, 0x9d, 0x2c, + 0xd1, 0x13, 0xb8, 0x9e, 0x16, 0xc2, 0x1e, 0xce, 0xee, 0x5c, 0x7f, 0x3d, 0xf6, 0xa5, 0xd2, 0x3e, + 0x8f, 0xae, 0x61, 0x6d, 0x89, 0xea, 0xb0, 0xcc, 0x3e, 0x67, 0x7c, 0xf1, 0x6b, 0xe4, 0xa5, 0xe8, + 0xcc, 0x87, 0xb1, 0xdd, 0x5f, 0x85, 0x65, 0x7d, 0x61, 0x4a, 0x7f, 0x5c, 0x81, 0xfc, 0x14, 0x7b, + 0xd1, 0x5d, 0x30, 0x57, 0x8d, 0xe8, 0x28, 0x0d, 0xc5, 0xd6, 0xb5, 0x24, 0x8d, 0x04, 0xbd, 0x05, + 0x1b, 0x11, 0xe5, 0xc1, 0x88, 0x06, 0x8c, 0xf8, 0xa2, 0xcf, 0xdc, 0x2d, 0x8d, 0x28, 0x64, 0xc2, + 0xba, 0xe8, 0x33, 0xb4, 0x0f, 0x77, 0x65, 0xcc, 0x98, 0x7f, 0x46, 0x12, 0xe6, 0x8b, 0x80, 0x87, + 0x29, 0xcd, 0x4c, 0x21, 0xfb, 0x8c, 0xfb, 0x4c, 0x27, 0x9f, 0xc3, 0x3b, 0x06, 0x84, 0x27, 0x98, + 0xfa, 0x18, 0x82, 0xde, 0x80, 0x15, 0xea, 0x6b, 0x1a, 0x2f, 0xe9, 0x1d, 0xec, 0x0a, 0xfd, 0x14, + 0x20, 0x1e, 0xdf, 0x07, 0x4d, 0xb1, 0x6f, 0x39, 0xdc, 0x29, 0x28, 0x7a, 0x0c, 0x3b, 0x34, 0x8a, + 0x48, 0xc2, 0xce, 0x47, 0x61, 0xc2, 0xfa, 0xb6, 0xbf, 0x91, 0x38, 0xa5, 0x27, 0x57, 0xba, 0x8b, + 0xac, 0x61, 0x97, 0x46, 0x11, 0xb6, 0x08, 0xd3, 0xbb, 0x3a, 0x46, 0x8f, 0x1e, 0x40, 0x71, 0x30, + 0x8a, 0x06, 0x61, 0x14, 0x0d, 0x19, 0x57, 0xa6, 0x3a, 0x2b, 0x3a, 0xb2, 0xad, 0x29, 0xb9, 0xae, + 0xd1, 0x29, 0xdc, 0x9c, 0x86, 0x0e, 0x99, 0x94, 0x34, 0x60, 0xd2, 0x5d, 0xd5, 0x14, 0xaf, 0x2e, + 0x40, 0x21, 0x3d, 0x4d, 0x9e, 0x1a, 0x3b, 0x7c, 0x63, 0xca, 0x99, 0x95, 0xe9, 0xdb, 0x36, 0xee, + 0x2b, 0x62, 0x94, 0xf8, 0xcc, 0x5d, 0xd3, 0xc1, 0x8c, 0x7b, 0x88, 0x16, 0xa2, 0x27, 0xb0, 0x95, + 0xc1, 0xb2, 0xfb, 0xb0, 0xfe, 0xed, 0x25, 0xcb, 0xdc, 0x76, 0x0c, 0x1c, 0x7d, 0x04, 0x5b, 0x62, + 0xa4, 0xd2, 0x6e, 0x3b, 0xbe, 0xd7, 0xf0, 0x8a, 0x3d, 0x62, 0xd3, 0x38, 0x18, 0xb7, 0x80, 0x9f, + 0xc1, 0x8a, 0x19, 0x98, 0x6e, 0x5e, 0xc7, 0xf2, 0xfd, 0x05, 0x2b, 0x82, 0xad, 0x19, 0xfa, 0x10, + 0x76, 0xcc, 0x17, 0xe9, 0xeb, 0x2e, 0x3f, 0xc3, 0xae, 0x82, 0x66, 0xd7, 0x6d, 0x03, 0x69, 0x64, + 0x88, 0x29, 0x6e, 0x3d, 0x81, 0xad, 0x7e, 0x48, 0x03, 0x2e, 0xa4, 0x0a, 0x7d, 0x12, 0xf2, 0x81, + 0x70, 0x37, 0xe7, 0x54, 0x65, 0x82, 0x6f, 0xf2, 0x81, 0x28, 0xfd, 0x21, 0x07, 0x77, 0xba, 0x2a, + 0x61, 0x74, 0x18, 0xf2, 0xe0, 0x3b, 0x37, 0x60, 0x1f, 0x40, 0x51, 0x86, 0x3c, 0x88, 0x18, 0x19, + 0x29, 0xc5, 0x12, 0x9a, 0x16, 0xd5, 0x34, 0xf3, 0x2d, 0x23, 0x3f, 0xc9, 0xc4, 0xb3, 0xb3, 0x78, + 0xe5, 0xd2, 0x2c, 0xfe, 0x53, 0x0e, 0xee, 0xbe, 0xa4, 0x52, 0x8b, 0x0e, 0xe5, 0xe7, 0x80, 0xa6, + 0xfb, 0xc8, 0x0b, 0xa3, 0xf9, 0xd1, 0xfc, 0x81, 0x91, 0x6d, 0x3e, 0xd5, 0x67, 0xec, 0xa4, 0x7e, + 0x2d, 0x99, 0x15, 0x5d, 0x7a, 0x00, 0x2c, 0xfd, 0xff, 0x1f, 0x00, 0xd7, 0x17, 0x7d, 0x00, 0xfc, + 0x2e, 0x07, 0xdb, 0x2f, 0x8f, 0x1e, 0x3d, 0x87, 0x82, 0x6d, 0x2d, 0x7a, 0x84, 0xea, 0xc2, 0x6d, + 0xee, 0x1d, 0xfe, 0x0f, 0x05, 0xc9, 0x5a, 0x8e, 0x1e, 0xab, 0xf9, 0xe1, 0x64, 0x81, 0xde, 0x04, + 0x50, 0x09, 0xe5, 0xd2, 0x4f, 0xc2, 0xd8, 0x94, 0x7e, 0x1d, 0x4f, 0x49, 0xd0, 0x6d, 0x58, 0x0b, + 0x25, 0x19, 0x84, 0x9c, 0x46, 0xba, 0x64, 0x6b, 0x78, 0x35, 0x94, 0x07, 0xe9, 0xb2, 0xf4, 0x09, + 0xe4, 0xa7, 0xdc, 0xa2, 0x3b, 0xe0, 0x3e, 0xf5, 0xba, 0xdd, 0xda, 0xa1, 0x47, 0x7a, 0x9f, 0x76, + 0x3c, 0x72, 0xd2, 0xee, 0x76, 0xbc, 0x7a, 0xf3, 0xa0, 0xe9, 0x35, 0x8a, 0xd7, 0xd0, 0x26, 0x40, + 0x0f, 0xd7, 0xda, 0xdd, 0x3a, 0x6e, 0x76, 0x7a, 0x45, 0x07, 0xed, 0xc0, 0x2d, 0xaf, 0xdd, 0x20, + 0xc7, 0x07, 0xa4, 0xdb, 0x6c, 0x1f, 0xb6, 0x3c, 0x72, 0xd2, 0xeb, 0x79, 0xb8, 0xd6, 0xae, 0x7b, + 0xc5, 0x5c, 0xe9, 0x2f, 0x0e, 0x14, 0x67, 0xc7, 0x2d, 0x3a, 0x81, 0x4d, 0x33, 0xb7, 0x19, 0xf7, + 0x45, 0x3f, 0xe4, 0x81, 0xad, 0x4b, 0x65, 0x6e, 0x5d, 0xb4, 0x17, 0xcf, 0x5a, 0xe1, 0x0d, 0x3a, + 0xbd, 0x44, 0xbb, 0xf0, 0x9a, 0xa4, 0xc3, 0x38, 0x62, 0x24, 0xa1, 0x8a, 0x91, 0x33, 0x96, 0xa8, + 0xaf, 0x74, 0x1d, 0x96, 0xf1, 0x96, 0x51, 0x60, 0xaa, 0xd8, 0x51, 0x2a, 0xbe, 0x3c, 0x23, 0x97, + 0xae, 0x98, 0x91, 0xdf, 0x83, 0x42, 0x7c, 0x96, 0x50, 0xc9, 0xc8, 0x59, 0xc8, 0xf5, 0x63, 0x69, + 0xa9, 0xbc, 0x8e, 0xf3, 0x46, 0x76, 0x94, 0x8a, 0x4a, 0x0d, 0x58, 0x1f, 0x4f, 0x7f, 0x84, 0xec, + 0xbb, 0xc1, 0x5c, 0x0f, 0xf3, 0x12, 0xb8, 0xb4, 0x51, 0xee, 0xf2, 0x46, 0xa5, 0x5f, 0x01, 0x4c, + 0x1e, 0x00, 0xa9, 0x1b, 0x4e, 0x87, 0xd9, 0xdb, 0x51, 0x7f, 0xcf, 0x8c, 0xd4, 0xdc, 0xe2, 0x23, + 0x75, 0x91, 0x44, 0x77, 0xff, 0xed, 0xc0, 0xc6, 0x0b, 0xa5, 0x45, 0x6f, 0xc2, 0x76, 0xed, 0xa4, + 0xd1, 0x3c, 0x26, 0x5e, 0xbb, 0x7e, 0xdc, 0x68, 0xb6, 0x0f, 0x67, 0x48, 0x70, 0x07, 0xdc, 0x19, + 0x7d, 0xab, 0xd9, 0xf6, 0x6a, 0x98, 0x3c, 0x7c, 0xaf, 0xe8, 0xa0, 0x5b, 0x70, 0x63, 0x46, 0x7b, + 0xd0, 0xaa, 0xd5, 0x8b, 0x39, 0xe4, 0xc2, 0xcd, 0x19, 0xc5, 0xd3, 0x93, 0x56, 0xed, 0x59, 0x71, + 0x09, 0xbd, 0x01, 0x68, 0x46, 0x53, 0x7b, 0x8a, 0x8b, 0xd7, 0xd1, 0x6d, 0x78, 0xfd, 0xb2, 0x9c, + 0x3c, 0xdb, 0x2f, 0x2e, 0xa7, 0xc4, 0x9b, 0x51, 0x1d, 0x1f, 0x1e, 0x92, 0xe3, 0xce, 0x49, 0xb7, + 0xb8, 0x82, 0x1e, 0xc0, 0xdb, 0x33, 0xca, 0x6e, 0xc7, 0xf3, 0x3e, 0x21, 0xcf, 0x9a, 0xbd, 0x23, + 0x72, 0xe4, 0xd5, 0x1a, 0x1e, 0x26, 0xfb, 0x9f, 0xf6, 0xbc, 0xe2, 0xea, 0xde, 0xdf, 0x73, 0xb0, + 0x66, 0x9f, 0xac, 0x12, 0x7d, 0xe3, 0x40, 0x61, 0xba, 0x05, 0xa2, 0x1f, 0xcf, 0x25, 0xe5, 0x15, + 0xb3, 0x65, 0xfb, 0x27, 0xaf, 0x68, 0x65, 0x1a, 0x69, 0xe9, 0xe0, 0xd7, 0x7f, 0xfe, 0xeb, 0x6f, + 0x72, 0x4f, 0x4a, 0x8f, 0xc6, 0x3f, 0xa2, 0xbf, 0xb0, 0x33, 0xe9, 0x71, 0x9c, 0x88, 0xe7, 0xcc, + 0x57, 0xb2, 0xba, 0x5b, 0xa5, 0x01, 0xe3, 0x2a, 0xfb, 0x45, 0x95, 0xd5, 0xdd, 0x5f, 0x7e, 0xd0, + 0x9f, 0x72, 0xf6, 0x81, 0xb3, 0x8b, 0x7e, 0xeb, 0xc0, 0xeb, 0x57, 0x76, 0x74, 0xf4, 0x78, 0xf1, + 0xde, 0x73, 0x55, 0x5e, 0x1f, 0xfe, 0xb7, 0xe6, 0x26, 0xc1, 0xb2, 0xf3, 0xae, 0xb3, 0xff, 0xb5, + 0x03, 0x6f, 0xf9, 0x62, 0x38, 0xcf, 0xd3, 0x7e, 0xc1, 0x1e, 0x4a, 0x27, 0xa5, 0x77, 0xc7, 0xf9, + 0xac, 0x69, 0x0d, 0x02, 0x91, 0x92, 0xb7, 0x22, 0x92, 0xa0, 0x1a, 0x30, 0xae, 0xc9, 0x5f, 0x35, + 0x2a, 0x1a, 0x87, 0xf2, 0xa5, 0xff, 0xf4, 0x8f, 0x26, 0xa2, 0x7f, 0x39, 0xce, 0xef, 0x73, 0xb9, + 0xc6, 0xc1, 0xd7, 0xb9, 0x7b, 0x87, 0xc6, 0x67, 0x5d, 0x07, 0xd1, 0x98, 0x04, 0xf1, 0xb1, 0x31, + 0x3a, 0x5d, 0xd1, 0xfe, 0x7f, 0xf4, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7c, 0x60, 0x03, 0xc7, + 0xfd, 0x10, 0x00, 0x00, +} diff --git a/vendor/google.golang.org/genproto/googleapis/cloud/dialogflow/v2beta1/session_entity_type.pb.go b/vendor/google.golang.org/genproto/googleapis/cloud/dialogflow/v2beta1/session_entity_type.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..da14f2643902e26f7929d05be6f8aca4d2908ffe --- /dev/null +++ b/vendor/google.golang.org/genproto/googleapis/cloud/dialogflow/v2beta1/session_entity_type.pb.go @@ -0,0 +1,557 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: google/cloud/dialogflow/v2beta1/session_entity_type.proto + +package dialogflow + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import _ "google.golang.org/genproto/googleapis/api/annotations" +import google_protobuf2 "github.com/golang/protobuf/ptypes/empty" +import google_protobuf3 "google.golang.org/genproto/protobuf/field_mask" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// The types of modifications for a session entity type. +type SessionEntityType_EntityOverrideMode int32 + +const ( + // Not specified. This value should be never used. + SessionEntityType_ENTITY_OVERRIDE_MODE_UNSPECIFIED SessionEntityType_EntityOverrideMode = 0 + // The collection of session entities overrides the collection of entities + // in the corresponding developer entity type. + SessionEntityType_ENTITY_OVERRIDE_MODE_OVERRIDE SessionEntityType_EntityOverrideMode = 1 + // The collection of session entities extends the collection of entities in + // the corresponding developer entity type. + // Calls to `ListSessionEntityTypes`, `GetSessionEntityType`, + // `CreateSessionEntityType` and `UpdateSessionEntityType` return the full + // collection of entities from the developer entity type in the agent's + // default language and the session entity type. + SessionEntityType_ENTITY_OVERRIDE_MODE_SUPPLEMENT SessionEntityType_EntityOverrideMode = 2 +) + +var SessionEntityType_EntityOverrideMode_name = map[int32]string{ + 0: "ENTITY_OVERRIDE_MODE_UNSPECIFIED", + 1: "ENTITY_OVERRIDE_MODE_OVERRIDE", + 2: "ENTITY_OVERRIDE_MODE_SUPPLEMENT", +} +var SessionEntityType_EntityOverrideMode_value = map[string]int32{ + "ENTITY_OVERRIDE_MODE_UNSPECIFIED": 0, + "ENTITY_OVERRIDE_MODE_OVERRIDE": 1, + "ENTITY_OVERRIDE_MODE_SUPPLEMENT": 2, +} + +func (x SessionEntityType_EntityOverrideMode) String() string { + return proto.EnumName(SessionEntityType_EntityOverrideMode_name, int32(x)) +} +func (SessionEntityType_EntityOverrideMode) EnumDescriptor() ([]byte, []int) { + return fileDescriptor5, []int{0, 0} +} + +// Represents a session entity type. +// +// Extends or replaces a developer entity type at the user session level (we +// refer to the entity types defined at the agent level as "developer entity +// types"). +// +// Note: session entity types apply to all queries, regardless of the language. +type SessionEntityType struct { + // Required. The unique identifier of this session entity type. Format: + // `projects//agent/sessions//entityTypes/`. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // Required. Indicates whether the additional data should override or + // supplement the developer entity type definition. + EntityOverrideMode SessionEntityType_EntityOverrideMode `protobuf:"varint,2,opt,name=entity_override_mode,json=entityOverrideMode,enum=google.cloud.dialogflow.v2beta1.SessionEntityType_EntityOverrideMode" json:"entity_override_mode,omitempty"` + // Required. The collection of entities associated with this session entity + // type. + Entities []*EntityType_Entity `protobuf:"bytes,3,rep,name=entities" json:"entities,omitempty"` +} + +func (m *SessionEntityType) Reset() { *m = SessionEntityType{} } +func (m *SessionEntityType) String() string { return proto.CompactTextString(m) } +func (*SessionEntityType) ProtoMessage() {} +func (*SessionEntityType) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{0} } + +func (m *SessionEntityType) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *SessionEntityType) GetEntityOverrideMode() SessionEntityType_EntityOverrideMode { + if m != nil { + return m.EntityOverrideMode + } + return SessionEntityType_ENTITY_OVERRIDE_MODE_UNSPECIFIED +} + +func (m *SessionEntityType) GetEntities() []*EntityType_Entity { + if m != nil { + return m.Entities + } + return nil +} + +// The request message for +// [SessionEntityTypes.ListSessionEntityTypes][google.cloud.dialogflow.v2beta1.SessionEntityTypes.ListSessionEntityTypes]. +type ListSessionEntityTypesRequest struct { + // Required. The session to list all session entity types from. + // Format: `projects//agent/sessions/`. + Parent string `protobuf:"bytes,1,opt,name=parent" json:"parent,omitempty"` + // Optional. The maximum number of items to return in a single page. By + // default 100 and at most 1000. + PageSize int32 `protobuf:"varint,2,opt,name=page_size,json=pageSize" json:"page_size,omitempty"` + // Optional. The next_page_token value returned from a previous list request. + PageToken string `protobuf:"bytes,3,opt,name=page_token,json=pageToken" json:"page_token,omitempty"` +} + +func (m *ListSessionEntityTypesRequest) Reset() { *m = ListSessionEntityTypesRequest{} } +func (m *ListSessionEntityTypesRequest) String() string { return proto.CompactTextString(m) } +func (*ListSessionEntityTypesRequest) ProtoMessage() {} +func (*ListSessionEntityTypesRequest) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{1} } + +func (m *ListSessionEntityTypesRequest) GetParent() string { + if m != nil { + return m.Parent + } + return "" +} + +func (m *ListSessionEntityTypesRequest) GetPageSize() int32 { + if m != nil { + return m.PageSize + } + return 0 +} + +func (m *ListSessionEntityTypesRequest) GetPageToken() string { + if m != nil { + return m.PageToken + } + return "" +} + +// The response message for +// [SessionEntityTypes.ListSessionEntityTypes][google.cloud.dialogflow.v2beta1.SessionEntityTypes.ListSessionEntityTypes]. +type ListSessionEntityTypesResponse struct { + // The list of session entity types. There will be a maximum number of items + // returned based on the page_size field in the request. + SessionEntityTypes []*SessionEntityType `protobuf:"bytes,1,rep,name=session_entity_types,json=sessionEntityTypes" json:"session_entity_types,omitempty"` + // Token to retrieve the next page of results, or empty if there are no + // more results in the list. + NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken" json:"next_page_token,omitempty"` +} + +func (m *ListSessionEntityTypesResponse) Reset() { *m = ListSessionEntityTypesResponse{} } +func (m *ListSessionEntityTypesResponse) String() string { return proto.CompactTextString(m) } +func (*ListSessionEntityTypesResponse) ProtoMessage() {} +func (*ListSessionEntityTypesResponse) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{2} } + +func (m *ListSessionEntityTypesResponse) GetSessionEntityTypes() []*SessionEntityType { + if m != nil { + return m.SessionEntityTypes + } + return nil +} + +func (m *ListSessionEntityTypesResponse) GetNextPageToken() string { + if m != nil { + return m.NextPageToken + } + return "" +} + +// The request message for +// [SessionEntityTypes.GetSessionEntityType][google.cloud.dialogflow.v2beta1.SessionEntityTypes.GetSessionEntityType]. +type GetSessionEntityTypeRequest struct { + // Required. The name of the session entity type. Format: + // `projects//agent/sessions//entityTypes/`. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` +} + +func (m *GetSessionEntityTypeRequest) Reset() { *m = GetSessionEntityTypeRequest{} } +func (m *GetSessionEntityTypeRequest) String() string { return proto.CompactTextString(m) } +func (*GetSessionEntityTypeRequest) ProtoMessage() {} +func (*GetSessionEntityTypeRequest) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{3} } + +func (m *GetSessionEntityTypeRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +// The request message for +// [SessionEntityTypes.CreateSessionEntityType][google.cloud.dialogflow.v2beta1.SessionEntityTypes.CreateSessionEntityType]. +type CreateSessionEntityTypeRequest struct { + // Required. The session to create a session entity type for. + // Format: `projects//agent/sessions/`. + Parent string `protobuf:"bytes,1,opt,name=parent" json:"parent,omitempty"` + // Required. The session entity type to create. + SessionEntityType *SessionEntityType `protobuf:"bytes,2,opt,name=session_entity_type,json=sessionEntityType" json:"session_entity_type,omitempty"` +} + +func (m *CreateSessionEntityTypeRequest) Reset() { *m = CreateSessionEntityTypeRequest{} } +func (m *CreateSessionEntityTypeRequest) String() string { return proto.CompactTextString(m) } +func (*CreateSessionEntityTypeRequest) ProtoMessage() {} +func (*CreateSessionEntityTypeRequest) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{4} } + +func (m *CreateSessionEntityTypeRequest) GetParent() string { + if m != nil { + return m.Parent + } + return "" +} + +func (m *CreateSessionEntityTypeRequest) GetSessionEntityType() *SessionEntityType { + if m != nil { + return m.SessionEntityType + } + return nil +} + +// The request message for +// [SessionEntityTypes.UpdateSessionEntityType][google.cloud.dialogflow.v2beta1.SessionEntityTypes.UpdateSessionEntityType]. +type UpdateSessionEntityTypeRequest struct { + // Required. The entity type to update. Format: + // `projects//agent/sessions//entityTypes/`. + SessionEntityType *SessionEntityType `protobuf:"bytes,1,opt,name=session_entity_type,json=sessionEntityType" json:"session_entity_type,omitempty"` + // Optional. The mask to control which fields get updated. + UpdateMask *google_protobuf3.FieldMask `protobuf:"bytes,2,opt,name=update_mask,json=updateMask" json:"update_mask,omitempty"` +} + +func (m *UpdateSessionEntityTypeRequest) Reset() { *m = UpdateSessionEntityTypeRequest{} } +func (m *UpdateSessionEntityTypeRequest) String() string { return proto.CompactTextString(m) } +func (*UpdateSessionEntityTypeRequest) ProtoMessage() {} +func (*UpdateSessionEntityTypeRequest) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{5} } + +func (m *UpdateSessionEntityTypeRequest) GetSessionEntityType() *SessionEntityType { + if m != nil { + return m.SessionEntityType + } + return nil +} + +func (m *UpdateSessionEntityTypeRequest) GetUpdateMask() *google_protobuf3.FieldMask { + if m != nil { + return m.UpdateMask + } + return nil +} + +// The request message for +// [SessionEntityTypes.DeleteSessionEntityType][google.cloud.dialogflow.v2beta1.SessionEntityTypes.DeleteSessionEntityType]. +type DeleteSessionEntityTypeRequest struct { + // Required. The name of the entity type to delete. Format: + // `projects//agent/sessions//entityTypes/`. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` +} + +func (m *DeleteSessionEntityTypeRequest) Reset() { *m = DeleteSessionEntityTypeRequest{} } +func (m *DeleteSessionEntityTypeRequest) String() string { return proto.CompactTextString(m) } +func (*DeleteSessionEntityTypeRequest) ProtoMessage() {} +func (*DeleteSessionEntityTypeRequest) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{6} } + +func (m *DeleteSessionEntityTypeRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func init() { + proto.RegisterType((*SessionEntityType)(nil), "google.cloud.dialogflow.v2beta1.SessionEntityType") + proto.RegisterType((*ListSessionEntityTypesRequest)(nil), "google.cloud.dialogflow.v2beta1.ListSessionEntityTypesRequest") + proto.RegisterType((*ListSessionEntityTypesResponse)(nil), "google.cloud.dialogflow.v2beta1.ListSessionEntityTypesResponse") + proto.RegisterType((*GetSessionEntityTypeRequest)(nil), "google.cloud.dialogflow.v2beta1.GetSessionEntityTypeRequest") + proto.RegisterType((*CreateSessionEntityTypeRequest)(nil), "google.cloud.dialogflow.v2beta1.CreateSessionEntityTypeRequest") + proto.RegisterType((*UpdateSessionEntityTypeRequest)(nil), "google.cloud.dialogflow.v2beta1.UpdateSessionEntityTypeRequest") + proto.RegisterType((*DeleteSessionEntityTypeRequest)(nil), "google.cloud.dialogflow.v2beta1.DeleteSessionEntityTypeRequest") + proto.RegisterEnum("google.cloud.dialogflow.v2beta1.SessionEntityType_EntityOverrideMode", SessionEntityType_EntityOverrideMode_name, SessionEntityType_EntityOverrideMode_value) +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// Client API for SessionEntityTypes service + +type SessionEntityTypesClient interface { + // Returns the list of all session entity types in the specified session. + ListSessionEntityTypes(ctx context.Context, in *ListSessionEntityTypesRequest, opts ...grpc.CallOption) (*ListSessionEntityTypesResponse, error) + // Retrieves the specified session entity type. + GetSessionEntityType(ctx context.Context, in *GetSessionEntityTypeRequest, opts ...grpc.CallOption) (*SessionEntityType, error) + // Creates a session entity type. + CreateSessionEntityType(ctx context.Context, in *CreateSessionEntityTypeRequest, opts ...grpc.CallOption) (*SessionEntityType, error) + // Updates the specified session entity type. + UpdateSessionEntityType(ctx context.Context, in *UpdateSessionEntityTypeRequest, opts ...grpc.CallOption) (*SessionEntityType, error) + // Deletes the specified session entity type. + DeleteSessionEntityType(ctx context.Context, in *DeleteSessionEntityTypeRequest, opts ...grpc.CallOption) (*google_protobuf2.Empty, error) +} + +type sessionEntityTypesClient struct { + cc *grpc.ClientConn +} + +func NewSessionEntityTypesClient(cc *grpc.ClientConn) SessionEntityTypesClient { + return &sessionEntityTypesClient{cc} +} + +func (c *sessionEntityTypesClient) ListSessionEntityTypes(ctx context.Context, in *ListSessionEntityTypesRequest, opts ...grpc.CallOption) (*ListSessionEntityTypesResponse, error) { + out := new(ListSessionEntityTypesResponse) + err := grpc.Invoke(ctx, "/google.cloud.dialogflow.v2beta1.SessionEntityTypes/ListSessionEntityTypes", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *sessionEntityTypesClient) GetSessionEntityType(ctx context.Context, in *GetSessionEntityTypeRequest, opts ...grpc.CallOption) (*SessionEntityType, error) { + out := new(SessionEntityType) + err := grpc.Invoke(ctx, "/google.cloud.dialogflow.v2beta1.SessionEntityTypes/GetSessionEntityType", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *sessionEntityTypesClient) CreateSessionEntityType(ctx context.Context, in *CreateSessionEntityTypeRequest, opts ...grpc.CallOption) (*SessionEntityType, error) { + out := new(SessionEntityType) + err := grpc.Invoke(ctx, "/google.cloud.dialogflow.v2beta1.SessionEntityTypes/CreateSessionEntityType", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *sessionEntityTypesClient) UpdateSessionEntityType(ctx context.Context, in *UpdateSessionEntityTypeRequest, opts ...grpc.CallOption) (*SessionEntityType, error) { + out := new(SessionEntityType) + err := grpc.Invoke(ctx, "/google.cloud.dialogflow.v2beta1.SessionEntityTypes/UpdateSessionEntityType", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *sessionEntityTypesClient) DeleteSessionEntityType(ctx context.Context, in *DeleteSessionEntityTypeRequest, opts ...grpc.CallOption) (*google_protobuf2.Empty, error) { + out := new(google_protobuf2.Empty) + err := grpc.Invoke(ctx, "/google.cloud.dialogflow.v2beta1.SessionEntityTypes/DeleteSessionEntityType", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for SessionEntityTypes service + +type SessionEntityTypesServer interface { + // Returns the list of all session entity types in the specified session. + ListSessionEntityTypes(context.Context, *ListSessionEntityTypesRequest) (*ListSessionEntityTypesResponse, error) + // Retrieves the specified session entity type. + GetSessionEntityType(context.Context, *GetSessionEntityTypeRequest) (*SessionEntityType, error) + // Creates a session entity type. + CreateSessionEntityType(context.Context, *CreateSessionEntityTypeRequest) (*SessionEntityType, error) + // Updates the specified session entity type. + UpdateSessionEntityType(context.Context, *UpdateSessionEntityTypeRequest) (*SessionEntityType, error) + // Deletes the specified session entity type. + DeleteSessionEntityType(context.Context, *DeleteSessionEntityTypeRequest) (*google_protobuf2.Empty, error) +} + +func RegisterSessionEntityTypesServer(s *grpc.Server, srv SessionEntityTypesServer) { + s.RegisterService(&_SessionEntityTypes_serviceDesc, srv) +} + +func _SessionEntityTypes_ListSessionEntityTypes_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListSessionEntityTypesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SessionEntityTypesServer).ListSessionEntityTypes(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.dialogflow.v2beta1.SessionEntityTypes/ListSessionEntityTypes", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SessionEntityTypesServer).ListSessionEntityTypes(ctx, req.(*ListSessionEntityTypesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _SessionEntityTypes_GetSessionEntityType_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetSessionEntityTypeRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SessionEntityTypesServer).GetSessionEntityType(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.dialogflow.v2beta1.SessionEntityTypes/GetSessionEntityType", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SessionEntityTypesServer).GetSessionEntityType(ctx, req.(*GetSessionEntityTypeRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _SessionEntityTypes_CreateSessionEntityType_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateSessionEntityTypeRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SessionEntityTypesServer).CreateSessionEntityType(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.dialogflow.v2beta1.SessionEntityTypes/CreateSessionEntityType", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SessionEntityTypesServer).CreateSessionEntityType(ctx, req.(*CreateSessionEntityTypeRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _SessionEntityTypes_UpdateSessionEntityType_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdateSessionEntityTypeRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SessionEntityTypesServer).UpdateSessionEntityType(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.dialogflow.v2beta1.SessionEntityTypes/UpdateSessionEntityType", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SessionEntityTypesServer).UpdateSessionEntityType(ctx, req.(*UpdateSessionEntityTypeRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _SessionEntityTypes_DeleteSessionEntityType_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteSessionEntityTypeRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SessionEntityTypesServer).DeleteSessionEntityType(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.dialogflow.v2beta1.SessionEntityTypes/DeleteSessionEntityType", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SessionEntityTypesServer).DeleteSessionEntityType(ctx, req.(*DeleteSessionEntityTypeRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _SessionEntityTypes_serviceDesc = grpc.ServiceDesc{ + ServiceName: "google.cloud.dialogflow.v2beta1.SessionEntityTypes", + HandlerType: (*SessionEntityTypesServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "ListSessionEntityTypes", + Handler: _SessionEntityTypes_ListSessionEntityTypes_Handler, + }, + { + MethodName: "GetSessionEntityType", + Handler: _SessionEntityTypes_GetSessionEntityType_Handler, + }, + { + MethodName: "CreateSessionEntityType", + Handler: _SessionEntityTypes_CreateSessionEntityType_Handler, + }, + { + MethodName: "UpdateSessionEntityType", + Handler: _SessionEntityTypes_UpdateSessionEntityType_Handler, + }, + { + MethodName: "DeleteSessionEntityType", + Handler: _SessionEntityTypes_DeleteSessionEntityType_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "google/cloud/dialogflow/v2beta1/session_entity_type.proto", +} + +func init() { + proto.RegisterFile("google/cloud/dialogflow/v2beta1/session_entity_type.proto", fileDescriptor5) +} + +var fileDescriptor5 = []byte{ + // 804 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0x4f, 0x4f, 0xdb, 0x48, + 0x14, 0xdf, 0x31, 0xbb, 0x08, 0x06, 0xed, 0x2e, 0xcc, 0xa2, 0x10, 0x85, 0x25, 0x64, 0xcd, 0x6a, + 0x85, 0x72, 0xb0, 0x45, 0x76, 0x2f, 0x2c, 0xfd, 0xa3, 0x42, 0x0c, 0x8a, 0x44, 0x42, 0xe4, 0x04, + 0xa4, 0xf6, 0x62, 0x39, 0xf8, 0x61, 0x19, 0x12, 0x8f, 0x9b, 0x99, 0x40, 0x43, 0xc5, 0x85, 0xaf, + 0xd0, 0x6b, 0x4f, 0x3d, 0xf6, 0xd0, 0x53, 0xfb, 0x01, 0x7a, 0xee, 0xb1, 0xd7, 0x4a, 0xbd, 0x54, + 0xfd, 0x06, 0x95, 0xaa, 0x9e, 0x2a, 0x8f, 0x1d, 0x82, 0xea, 0x3f, 0xa1, 0x51, 0x6f, 0x9e, 0x37, + 0xf3, 0x7b, 0xef, 0xf7, 0x7b, 0xf3, 0xde, 0xf3, 0xe0, 0x75, 0x9b, 0x52, 0xbb, 0x0d, 0xea, 0x61, + 0x9b, 0xf6, 0x2c, 0xd5, 0x72, 0xcc, 0x36, 0xb5, 0x8f, 0xda, 0xf4, 0x4c, 0x3d, 0x2d, 0xb5, 0x80, + 0x9b, 0x6b, 0x2a, 0x03, 0xc6, 0x1c, 0xea, 0x1a, 0xe0, 0x72, 0x87, 0xf7, 0x0d, 0xde, 0xf7, 0x40, + 0xf1, 0xba, 0x94, 0x53, 0xb2, 0x1c, 0x40, 0x15, 0x01, 0x55, 0x86, 0x50, 0x25, 0x84, 0xe6, 0xfe, + 0x0c, 0x7d, 0x9b, 0x9e, 0xa3, 0x9a, 0xae, 0x4b, 0xb9, 0xc9, 0x1d, 0xea, 0xb2, 0x00, 0x9e, 0x5b, + 0x1b, 0x15, 0x39, 0x12, 0x31, 0xb7, 0x18, 0x42, 0xc4, 0xaa, 0xd5, 0x3b, 0x52, 0xa1, 0xe3, 0xf1, + 0x7e, 0xb8, 0x59, 0xf8, 0x76, 0xf3, 0xc8, 0x81, 0xb6, 0x65, 0x74, 0x4c, 0x76, 0x12, 0x9c, 0x90, + 0x3f, 0x49, 0x78, 0xae, 0x11, 0xc8, 0xd1, 0x84, 0xef, 0x66, 0xdf, 0x03, 0x42, 0xf0, 0xcf, 0xae, + 0xd9, 0x81, 0x2c, 0x2a, 0xa0, 0xd5, 0x69, 0x5d, 0x7c, 0x93, 0x33, 0x3c, 0x1f, 0x46, 0xa7, 0xa7, + 0xd0, 0xed, 0x3a, 0x16, 0x18, 0x1d, 0x6a, 0x41, 0x56, 0x2a, 0xa0, 0xd5, 0xdf, 0x4a, 0x9a, 0x32, + 0x42, 0xb9, 0x12, 0x89, 0xa2, 0x04, 0x9f, 0x7b, 0xa1, 0xb7, 0x2a, 0xb5, 0x40, 0x27, 0x10, 0xb1, + 0x91, 0x1a, 0x9e, 0x12, 0x56, 0x07, 0x58, 0x76, 0xa2, 0x30, 0xb1, 0x3a, 0x53, 0x2a, 0x8d, 0x0c, + 0x16, 0x89, 0xa2, 0x5f, 0xf9, 0x90, 0x2f, 0x11, 0x26, 0xd1, 0xd0, 0xe4, 0x6f, 0x5c, 0xd0, 0x6a, + 0xcd, 0x4a, 0xf3, 0xbe, 0xb1, 0x77, 0xa0, 0xe9, 0x7a, 0xa5, 0xac, 0x19, 0xd5, 0xbd, 0xb2, 0x66, + 0xec, 0xd7, 0x1a, 0x75, 0x6d, 0xab, 0xb2, 0x5d, 0xd1, 0xca, 0xb3, 0x3f, 0x91, 0xbf, 0xf0, 0x52, + 0xec, 0xa9, 0xc1, 0x6a, 0x16, 0x91, 0x15, 0xbc, 0x1c, 0x7b, 0xa4, 0xb1, 0x5f, 0xaf, 0xef, 0x6a, + 0x55, 0xad, 0xd6, 0x9c, 0x95, 0x64, 0x86, 0x97, 0x76, 0x1d, 0xc6, 0x23, 0x49, 0x61, 0x3a, 0x3c, + 0xec, 0x01, 0xe3, 0x24, 0x83, 0x27, 0x3d, 0xb3, 0x0b, 0x2e, 0x0f, 0x2f, 0x21, 0x5c, 0x91, 0x45, + 0x3c, 0xed, 0x99, 0x36, 0x18, 0xcc, 0x39, 0x0f, 0x72, 0xff, 0x8b, 0x3e, 0xe5, 0x1b, 0x1a, 0xce, + 0x39, 0x90, 0x25, 0x8c, 0xc5, 0x26, 0xa7, 0x27, 0xe0, 0x66, 0x27, 0x04, 0x50, 0x1c, 0x6f, 0xfa, + 0x06, 0xf9, 0x05, 0xc2, 0xf9, 0xa4, 0xa8, 0xcc, 0xa3, 0x2e, 0x03, 0x62, 0xe1, 0xf9, 0x98, 0xea, + 0x66, 0x59, 0x74, 0xc3, 0xc4, 0x47, 0x5c, 0xeb, 0x84, 0x45, 0xa2, 0x91, 0x7f, 0xf0, 0xef, 0x2e, + 0x3c, 0xe2, 0xc6, 0x35, 0xb2, 0x92, 0x20, 0xfb, 0xab, 0x6f, 0xae, 0x5f, 0x11, 0x5e, 0xc3, 0x8b, + 0x3b, 0x10, 0xa5, 0x3b, 0xc8, 0x51, 0x4c, 0x99, 0xca, 0x4f, 0x11, 0xce, 0x6f, 0x75, 0xc1, 0xe4, + 0x90, 0x08, 0x4b, 0x4a, 0x6d, 0x0b, 0xff, 0x11, 0xa3, 0x5d, 0x30, 0x1b, 0x4f, 0xfa, 0x5c, 0x44, + 0xba, 0xfc, 0x1a, 0xe1, 0xfc, 0xbe, 0x67, 0xa5, 0xd1, 0x4b, 0xa0, 0x81, 0x7e, 0x20, 0x0d, 0xb2, + 0x81, 0x67, 0x7a, 0x82, 0x85, 0x98, 0x05, 0xa1, 0xc4, 0xdc, 0xc0, 0xf7, 0x60, 0x5c, 0x28, 0xdb, + 0xfe, 0xb8, 0xa8, 0x9a, 0xec, 0x44, 0xc7, 0xc1, 0x71, 0xff, 0x5b, 0xfe, 0x0f, 0xe7, 0xcb, 0xd0, + 0x86, 0x14, 0x09, 0x31, 0x17, 0x53, 0x7a, 0x3f, 0x85, 0x49, 0xb4, 0xf0, 0xc8, 0x3b, 0x84, 0x33, + 0xf1, 0x35, 0x49, 0xee, 0x8c, 0xd4, 0x9a, 0xda, 0x42, 0xb9, 0xbb, 0x63, 0xe3, 0x83, 0x66, 0x90, + 0xef, 0x5d, 0xbe, 0xfd, 0xf0, 0x44, 0xda, 0x20, 0xeb, 0x57, 0xf3, 0xf7, 0x71, 0x50, 0x2a, 0xb7, + 0xbd, 0x2e, 0x3d, 0x86, 0x43, 0xce, 0xd4, 0xa2, 0x6a, 0xda, 0xe0, 0xf2, 0xc1, 0x2f, 0x81, 0xa9, + 0xc5, 0x8b, 0x70, 0x48, 0x07, 0x1a, 0xde, 0x20, 0x3c, 0x1f, 0x57, 0xc2, 0xe4, 0xd6, 0x48, 0x72, + 0x29, 0x95, 0x9f, 0x1b, 0xa3, 0x0c, 0xe2, 0xd4, 0xf8, 0x17, 0x93, 0xa6, 0xe5, 0xba, 0x14, 0xb5, + 0x78, 0x41, 0x3e, 0x22, 0xbc, 0x90, 0xd0, 0x5c, 0x64, 0x74, 0xb6, 0xd3, 0xdb, 0x72, 0x2c, 0x4d, + 0x07, 0x42, 0x53, 0x5d, 0x1e, 0xff, 0x86, 0xfe, 0x8f, 0x6b, 0x36, 0xf2, 0x05, 0xe1, 0x85, 0x84, + 0x36, 0xbd, 0x81, 0xd0, 0xf4, 0x06, 0x1f, 0x4b, 0xe8, 0xb1, 0x10, 0x6a, 0x95, 0xaa, 0x43, 0xa1, + 0x71, 0xaf, 0x90, 0xef, 0xbc, 0xd0, 0x78, 0xf1, 0xaf, 0x10, 0x5e, 0x48, 0x68, 0xf0, 0x1b, 0x88, + 0x4f, 0x1f, 0x0d, 0xb9, 0x4c, 0x64, 0xc8, 0x68, 0xfe, 0x83, 0x65, 0x50, 0x9d, 0xc5, 0xf1, 0xab, + 0x73, 0xf3, 0x25, 0xc2, 0x2b, 0x87, 0xb4, 0x33, 0x8a, 0xe1, 0x66, 0x26, 0x42, 0xae, 0xee, 0x73, + 0xa9, 0xa3, 0x07, 0x95, 0x10, 0x6a, 0xd3, 0xb6, 0xe9, 0xda, 0x0a, 0xed, 0xda, 0xaa, 0x0d, 0xae, + 0x60, 0xaa, 0x06, 0x5b, 0xa6, 0xe7, 0xb0, 0xc4, 0xe7, 0xd9, 0xc6, 0xd0, 0xf4, 0x19, 0xa1, 0x67, + 0x92, 0x54, 0xde, 0x7e, 0x2e, 0x2d, 0xef, 0x04, 0x3e, 0xb7, 0x04, 0x9d, 0xf2, 0x90, 0xce, 0x41, + 0x00, 0x6a, 0x4d, 0x0a, 0xff, 0xff, 0x7e, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xaf, 0x87, 0xb0, 0xb6, + 0x77, 0x0a, 0x00, 0x00, +} diff --git a/vendor/google.golang.org/genproto/googleapis/cloud/dialogflow/v2beta1/webhook.pb.go b/vendor/google.golang.org/genproto/googleapis/cloud/dialogflow/v2beta1/webhook.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..80e59ea30a9299d1d8bbaf7322cc5f4c84f16415 --- /dev/null +++ b/vendor/google.golang.org/genproto/googleapis/cloud/dialogflow/v2beta1/webhook.pb.go @@ -0,0 +1,209 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: google/cloud/dialogflow/v2beta1/webhook.proto + +package dialogflow + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import _ "google.golang.org/genproto/googleapis/api/annotations" +import google_protobuf4 "github.com/golang/protobuf/ptypes/struct" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// The request message for a webhook call. +type WebhookRequest struct { + // The unique identifier of detectIntent request session. + // Can be used to identify end-user inside webhook implementation. + // Format: `projects//agent/sessions/`. + Session string `protobuf:"bytes,4,opt,name=session" json:"session,omitempty"` + // The unique identifier of the response. Contains the same value as + // `[Streaming]DetectIntentResponse.response_id`. + ResponseId string `protobuf:"bytes,1,opt,name=response_id,json=responseId" json:"response_id,omitempty"` + // The result of the conversational query or event processing. Contains the + // same value as `[Streaming]DetectIntentResponse.query_result`. + QueryResult *QueryResult `protobuf:"bytes,2,opt,name=query_result,json=queryResult" json:"query_result,omitempty"` + // Optional. The contents of the original request that was passed to + // `[Streaming]DetectIntent` call. + OriginalDetectIntentRequest *OriginalDetectIntentRequest `protobuf:"bytes,3,opt,name=original_detect_intent_request,json=originalDetectIntentRequest" json:"original_detect_intent_request,omitempty"` +} + +func (m *WebhookRequest) Reset() { *m = WebhookRequest{} } +func (m *WebhookRequest) String() string { return proto.CompactTextString(m) } +func (*WebhookRequest) ProtoMessage() {} +func (*WebhookRequest) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{0} } + +func (m *WebhookRequest) GetSession() string { + if m != nil { + return m.Session + } + return "" +} + +func (m *WebhookRequest) GetResponseId() string { + if m != nil { + return m.ResponseId + } + return "" +} + +func (m *WebhookRequest) GetQueryResult() *QueryResult { + if m != nil { + return m.QueryResult + } + return nil +} + +func (m *WebhookRequest) GetOriginalDetectIntentRequest() *OriginalDetectIntentRequest { + if m != nil { + return m.OriginalDetectIntentRequest + } + return nil +} + +// The response message for a webhook call. +type WebhookResponse struct { + // Optional. The text to be shown on the screen. This value is passed directly + // to `QueryResult.fulfillment_text`. + FulfillmentText string `protobuf:"bytes,1,opt,name=fulfillment_text,json=fulfillmentText" json:"fulfillment_text,omitempty"` + // Optional. The collection of rich messages to present to the user. This + // value is passed directly to `QueryResult.fulfillment_messages`. + FulfillmentMessages []*Intent_Message `protobuf:"bytes,2,rep,name=fulfillment_messages,json=fulfillmentMessages" json:"fulfillment_messages,omitempty"` + // Optional. This value is passed directly to `QueryResult.webhook_source`. + Source string `protobuf:"bytes,3,opt,name=source" json:"source,omitempty"` + // Optional. This value is passed directly to `QueryResult.webhook_payload`. + Payload *google_protobuf4.Struct `protobuf:"bytes,4,opt,name=payload" json:"payload,omitempty"` + // Optional. The collection of output contexts. This value is passed directly + // to `QueryResult.output_contexts`. + OutputContexts []*Context `protobuf:"bytes,5,rep,name=output_contexts,json=outputContexts" json:"output_contexts,omitempty"` + // Optional. Makes the platform immediately invoke another `DetectIntent` call + // internally with the specified event as input. + FollowupEventInput *EventInput `protobuf:"bytes,6,opt,name=followup_event_input,json=followupEventInput" json:"followup_event_input,omitempty"` +} + +func (m *WebhookResponse) Reset() { *m = WebhookResponse{} } +func (m *WebhookResponse) String() string { return proto.CompactTextString(m) } +func (*WebhookResponse) ProtoMessage() {} +func (*WebhookResponse) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{1} } + +func (m *WebhookResponse) GetFulfillmentText() string { + if m != nil { + return m.FulfillmentText + } + return "" +} + +func (m *WebhookResponse) GetFulfillmentMessages() []*Intent_Message { + if m != nil { + return m.FulfillmentMessages + } + return nil +} + +func (m *WebhookResponse) GetSource() string { + if m != nil { + return m.Source + } + return "" +} + +func (m *WebhookResponse) GetPayload() *google_protobuf4.Struct { + if m != nil { + return m.Payload + } + return nil +} + +func (m *WebhookResponse) GetOutputContexts() []*Context { + if m != nil { + return m.OutputContexts + } + return nil +} + +func (m *WebhookResponse) GetFollowupEventInput() *EventInput { + if m != nil { + return m.FollowupEventInput + } + return nil +} + +// Represents the contents of the original request that was passed to +// the `[Streaming]DetectIntent` call. +type OriginalDetectIntentRequest struct { + // The source of this request, e.g., `google`, `facebook`, `slack`. It is set + // by Dialogflow-owned servers. Possible values of this field correspond to + // [Intent.Message.Platform][google.cloud.dialogflow.v2beta1.Intent.Message.Platform]. + Source string `protobuf:"bytes,1,opt,name=source" json:"source,omitempty"` + // Optional. This field is set to the value of `QueryParameters.payload` field + // passed in the request. + Payload *google_protobuf4.Struct `protobuf:"bytes,3,opt,name=payload" json:"payload,omitempty"` +} + +func (m *OriginalDetectIntentRequest) Reset() { *m = OriginalDetectIntentRequest{} } +func (m *OriginalDetectIntentRequest) String() string { return proto.CompactTextString(m) } +func (*OriginalDetectIntentRequest) ProtoMessage() {} +func (*OriginalDetectIntentRequest) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{2} } + +func (m *OriginalDetectIntentRequest) GetSource() string { + if m != nil { + return m.Source + } + return "" +} + +func (m *OriginalDetectIntentRequest) GetPayload() *google_protobuf4.Struct { + if m != nil { + return m.Payload + } + return nil +} + +func init() { + proto.RegisterType((*WebhookRequest)(nil), "google.cloud.dialogflow.v2beta1.WebhookRequest") + proto.RegisterType((*WebhookResponse)(nil), "google.cloud.dialogflow.v2beta1.WebhookResponse") + proto.RegisterType((*OriginalDetectIntentRequest)(nil), "google.cloud.dialogflow.v2beta1.OriginalDetectIntentRequest") +} + +func init() { proto.RegisterFile("google/cloud/dialogflow/v2beta1/webhook.proto", fileDescriptor6) } + +var fileDescriptor6 = []byte{ + // 538 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x53, 0x41, 0x6f, 0xd3, 0x30, + 0x14, 0x56, 0x52, 0xd8, 0x34, 0x77, 0x5a, 0x91, 0x99, 0x20, 0xda, 0x10, 0xad, 0xca, 0xa5, 0x88, + 0x91, 0x68, 0xe5, 0x08, 0xa7, 0xad, 0x80, 0x7a, 0x40, 0xdb, 0x02, 0x02, 0x09, 0x09, 0x45, 0x6e, + 0xe2, 0x66, 0x16, 0xae, 0x5f, 0x1a, 0xdb, 0xeb, 0x76, 0xe4, 0x87, 0x20, 0x21, 0x8e, 0xfb, 0x85, + 0x1c, 0x51, 0x6c, 0x87, 0xf4, 0x52, 0xb2, 0xe3, 0x7b, 0xfe, 0xbe, 0xef, 0x7d, 0xfe, 0xfc, 0x8c, + 0x5e, 0xe6, 0x00, 0x39, 0xa7, 0x51, 0xca, 0x41, 0x67, 0x51, 0xc6, 0x08, 0x87, 0x7c, 0xce, 0x61, + 0x15, 0x5d, 0x8d, 0x67, 0x54, 0x91, 0xe3, 0x68, 0x45, 0x67, 0x97, 0x00, 0xdf, 0xc3, 0xa2, 0x04, + 0x05, 0xb8, 0x6f, 0xe1, 0xa1, 0x81, 0x87, 0x0d, 0x3c, 0x74, 0xf0, 0x83, 0x27, 0x4e, 0x8f, 0x14, + 0x2c, 0x22, 0x42, 0x80, 0x22, 0x8a, 0x81, 0x90, 0x96, 0x7e, 0xd0, 0x3a, 0x2d, 0x05, 0xa1, 0xe8, + 0xb5, 0x72, 0xf0, 0xa3, 0x36, 0x38, 0x13, 0x8a, 0x0a, 0x75, 0x57, 0x71, 0x49, 0xa5, 0x64, 0x20, + 0x1c, 0xbc, 0x76, 0x6a, 0xaa, 0x99, 0x9e, 0x47, 0x52, 0x95, 0x3a, 0x75, 0x62, 0xc3, 0x5f, 0x3e, + 0xda, 0xfb, 0x62, 0xaf, 0x1e, 0xd3, 0xa5, 0xa6, 0x52, 0xe1, 0x00, 0x6d, 0x3b, 0x85, 0xe0, 0xde, + 0xc0, 0x1b, 0xed, 0xc4, 0x75, 0x89, 0xfb, 0xa8, 0x5b, 0x52, 0x59, 0x80, 0x90, 0x34, 0x61, 0x59, + 0xe0, 0x99, 0x53, 0x54, 0xb7, 0xa6, 0x19, 0x3e, 0x43, 0xbb, 0x4b, 0x4d, 0xcb, 0x9b, 0xa4, 0xa4, + 0x52, 0x73, 0x15, 0xf8, 0x03, 0x6f, 0xd4, 0x1d, 0x1f, 0x85, 0x2d, 0x69, 0x86, 0x17, 0x15, 0x29, + 0x36, 0x9c, 0xb8, 0xbb, 0x6c, 0x0a, 0xfc, 0xc3, 0x43, 0x4f, 0xa1, 0x64, 0x39, 0x13, 0x84, 0x27, + 0x19, 0x55, 0x34, 0x55, 0x89, 0x0d, 0x23, 0x29, 0xad, 0xdd, 0xa0, 0x63, 0x66, 0xbc, 0x69, 0x9d, + 0x71, 0xe6, 0x64, 0x26, 0x46, 0x65, 0x6a, 0x44, 0xdc, 0x95, 0xe3, 0x43, 0xd8, 0x7c, 0x38, 0xfc, + 0xd9, 0x41, 0xbd, 0x7f, 0x11, 0xd9, 0xab, 0xe2, 0xe7, 0xe8, 0xc1, 0x5c, 0xf3, 0x39, 0xe3, 0x7c, + 0x51, 0x79, 0xa9, 0xde, 0xd2, 0xc5, 0xd1, 0x5b, 0xeb, 0x7f, 0xa2, 0xd7, 0x0a, 0xcf, 0xd0, 0xfe, + 0x3a, 0x74, 0x41, 0xa5, 0x24, 0x39, 0x95, 0x81, 0x3f, 0xe8, 0x8c, 0xba, 0xe3, 0xa8, 0xd5, 0xb7, + 0x35, 0x13, 0x7e, 0xb0, 0xbc, 0xf8, 0xe1, 0x9a, 0x98, 0xeb, 0x49, 0xfc, 0x08, 0x6d, 0x49, 0xd0, + 0x65, 0x4a, 0x4d, 0x1a, 0x3b, 0xb1, 0xab, 0xf0, 0x31, 0xda, 0x2e, 0xc8, 0x0d, 0x07, 0x92, 0x99, + 0xa7, 0xec, 0x8e, 0x1f, 0xd7, 0xe3, 0xea, 0x6d, 0x08, 0x3f, 0x9a, 0x6d, 0x88, 0x6b, 0x1c, 0xbe, + 0x40, 0x3d, 0xd0, 0xaa, 0xd0, 0x2a, 0x71, 0x3b, 0x2a, 0x83, 0xfb, 0xc6, 0xe9, 0xa8, 0xd5, 0xe9, + 0xa9, 0x25, 0xc4, 0x7b, 0x56, 0xc0, 0x95, 0x12, 0x7f, 0x43, 0xfb, 0x73, 0xe0, 0x1c, 0x56, 0xba, + 0x48, 0xe8, 0x55, 0x15, 0x02, 0x13, 0x85, 0x56, 0xc1, 0x96, 0xb1, 0xf4, 0xa2, 0x55, 0xf7, 0x6d, + 0xc5, 0x99, 0x56, 0x94, 0x18, 0xd7, 0x42, 0x4d, 0x6f, 0x78, 0x89, 0x0e, 0xff, 0xf3, 0xb6, 0x6b, + 0xd9, 0x78, 0x9b, 0xb2, 0xe9, 0xdc, 0x2d, 0x9b, 0x93, 0x5b, 0x0f, 0x3d, 0x4b, 0x61, 0xd1, 0x66, + 0xf8, 0x64, 0xd7, 0xad, 0xcb, 0x79, 0x25, 0x74, 0xee, 0x7d, 0x9d, 0x3a, 0x42, 0x0e, 0x9c, 0x88, + 0x3c, 0x84, 0x32, 0x8f, 0x72, 0x2a, 0xcc, 0x98, 0xc8, 0x1e, 0x91, 0x82, 0xc9, 0x8d, 0x1f, 0xfa, + 0x75, 0xd3, 0xfa, 0xe3, 0x79, 0xbf, 0x7d, 0x7f, 0xf2, 0xee, 0xd6, 0xef, 0xbf, 0xb7, 0x9a, 0xa7, + 0xc6, 0xc4, 0xa4, 0x31, 0xf1, 0xd9, 0x92, 0x66, 0x5b, 0x46, 0xff, 0xd5, 0xdf, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x52, 0x6e, 0x3d, 0x85, 0xfa, 0x04, 0x00, 0x00, +} diff --git a/vendor/google.golang.org/genproto/googleapis/cloud/oslogin/common/common.pb.go b/vendor/google.golang.org/genproto/googleapis/cloud/oslogin/common/common.pb.go index 6d8c6380c6346df1973412a0908555653b13e2ab..28d69481602741c36cef5995e015589b10f3b278 100644 --- a/vendor/google.golang.org/genproto/googleapis/cloud/oslogin/common/common.pb.go +++ b/vendor/google.golang.org/genproto/googleapis/cloud/oslogin/common/common.pb.go @@ -1,11 +1,11 @@ // Code generated by protoc-gen-go. DO NOT EDIT. -// source: google/cloud/oslogin/common.proto +// source: google/cloud/oslogin/common/common.proto /* Package common is a generated protocol buffer package. It is generated from these files: - google/cloud/oslogin/common.proto + google/cloud/oslogin/common/common.proto It has these top-level messages: PosixAccount @@ -163,32 +163,34 @@ func init() { proto.RegisterType((*SshPublicKey)(nil), "google.cloud.oslogin.common.SshPublicKey") } -func init() { proto.RegisterFile("google/cloud/oslogin/common.proto", fileDescriptor0) } +func init() { proto.RegisterFile("google/cloud/oslogin/common/common.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 373 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x92, 0xcf, 0x6b, 0x14, 0x31, - 0x14, 0xc7, 0x19, 0xd7, 0xb6, 0x3b, 0x71, 0x15, 0x09, 0x3d, 0x84, 0x56, 0x71, 0x2d, 0x08, 0x7b, - 0x9a, 0x11, 0x3c, 0x7a, 0x6a, 0xf1, 0x52, 0x14, 0x5c, 0x46, 0xbd, 0x78, 0x19, 0xd2, 0xe4, 0x99, - 0x7d, 0x38, 0xc9, 0x1b, 0x92, 0x0c, 0x74, 0xfe, 0x72, 0xaf, 0x92, 0x64, 0x56, 0x3d, 0x48, 0x4f, - 0x93, 0xef, 0xe7, 0xfb, 0xcd, 0xf0, 0x7e, 0x84, 0xbd, 0x36, 0x44, 0x66, 0x80, 0x56, 0x0d, 0x34, - 0xe9, 0x96, 0xc2, 0x40, 0x06, 0x5d, 0xab, 0xc8, 0x5a, 0x72, 0xcd, 0xe8, 0x29, 0x12, 0xbf, 0x2c, - 0x91, 0x26, 0x47, 0x9a, 0x25, 0xd2, 0x94, 0xc8, 0xc5, 0x8b, 0xe5, 0xbe, 0x1c, 0xb1, 0x95, 0xce, - 0x51, 0x94, 0x11, 0xc9, 0x85, 0x72, 0xf5, 0xea, 0x57, 0xc5, 0x36, 0x7b, 0x0a, 0x78, 0x7f, 0xad, - 0x14, 0x4d, 0x2e, 0x72, 0xc1, 0xce, 0x46, 0x8f, 0x56, 0xfa, 0x59, 0x54, 0xdb, 0x6a, 0xb7, 0xee, - 0x8e, 0x92, 0x5f, 0xb0, 0xf5, 0x14, 0xc0, 0x3b, 0x69, 0x41, 0x3c, 0xda, 0x56, 0xbb, 0xba, 0xfb, - 0xa3, 0xf9, 0x73, 0xb6, 0x9a, 0x50, 0x8b, 0xd5, 0xb6, 0xda, 0xad, 0xba, 0x74, 0x4c, 0xc4, 0xa0, - 0x16, 0x8f, 0x0b, 0x31, 0xa8, 0xf9, 0x1b, 0xf6, 0xec, 0x40, 0x16, 0x7a, 0x8d, 0x1e, 0x54, 0x24, - 0x3f, 0x8b, 0x93, 0xfc, 0x97, 0xa7, 0x89, 0x7e, 0x38, 0x42, 0x7e, 0xce, 0x4e, 0xc2, 0x01, 0x86, - 0x41, 0x9c, 0x66, 0xb7, 0x88, 0x44, 0x0d, 0x28, 0x0a, 0xe2, 0xac, 0xd0, 0x2c, 0xf8, 0x25, 0xab, - 0xc3, 0x1c, 0x22, 0xd8, 0x1e, 0xb5, 0x58, 0x97, 0x9a, 0x0a, 0xb8, 0xd5, 0xfc, 0x25, 0x63, 0xb2, - 0x34, 0x95, 0xdc, 0x3a, 0xbb, 0xf5, 0x42, 0x6e, 0xf5, 0x55, 0x64, 0x9b, 0x2f, 0xe1, 0xb0, 0x9f, - 0xee, 0x06, 0x54, 0x1f, 0x61, 0x4e, 0x05, 0xff, 0x84, 0xd2, 0x74, 0xdd, 0xa5, 0x23, 0x7f, 0xcb, - 0xce, 0xe1, 0x7e, 0x44, 0x9f, 0x07, 0xd6, 0x47, 0xb4, 0xd0, 0x4f, 0x01, 0x54, 0x6e, 0x7e, 0xd5, - 0xf1, 0xbf, 0xde, 0x57, 0xb4, 0xf0, 0x2d, 0x80, 0xe2, 0x5b, 0xf6, 0xe4, 0x07, 0x3a, 0x03, 0x7e, - 0xf4, 0xe8, 0x62, 0x1e, 0x47, 0xdd, 0xfd, 0x8b, 0x6e, 0x3c, 0x7b, 0xa5, 0xc8, 0x36, 0x0f, 0x2c, - 0xec, 0x66, 0xf3, 0x39, 0x7c, 0x4a, 0x7a, 0x9f, 0x16, 0xf4, 0xfd, 0x7a, 0x89, 0x1a, 0x1a, 0xa4, - 0x33, 0x0d, 0x79, 0xd3, 0x1a, 0x70, 0x79, 0x79, 0x6d, 0xb1, 0xe4, 0x88, 0xe1, 0xbf, 0xaf, 0xe3, - 0x7d, 0xf9, 0xdc, 0x9d, 0xe6, 0xf4, 0xbb, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x0a, 0xe8, 0xeb, - 0xaa, 0x4a, 0x02, 0x00, 0x00, + // 406 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x92, 0x41, 0x6b, 0x14, 0x31, + 0x14, 0xc7, 0x99, 0xae, 0x6d, 0x77, 0xe2, 0x2a, 0x12, 0x7a, 0x08, 0x5d, 0xc5, 0xa5, 0x20, 0xec, + 0x69, 0x46, 0xf0, 0xe8, 0xa9, 0xad, 0x20, 0x45, 0xc1, 0x65, 0xd4, 0x8b, 0x2c, 0x2c, 0xd3, 0xe4, + 0x99, 0x7d, 0x38, 0xc9, 0x1b, 0x92, 0x0c, 0x74, 0xbf, 0x92, 0x07, 0x3f, 0x88, 0x5f, 0xc8, 0xab, + 0x24, 0x99, 0x51, 0x0f, 0xd2, 0x53, 0xf2, 0xff, 0xff, 0xfe, 0xf3, 0x92, 0x97, 0x37, 0x6c, 0xad, + 0x89, 0x74, 0x07, 0xb5, 0xec, 0x68, 0x50, 0x35, 0xf9, 0x8e, 0x34, 0xda, 0x5a, 0x92, 0x31, 0x34, + 0x2d, 0x55, 0xef, 0x28, 0x10, 0x5f, 0xe6, 0x64, 0x95, 0x92, 0xd5, 0x98, 0xac, 0x72, 0xe4, 0xfc, + 0xe9, 0x58, 0xa6, 0xed, 0xb1, 0x6e, 0xad, 0xa5, 0xd0, 0x06, 0x24, 0xeb, 0xf3, 0xa7, 0x17, 0xbf, + 0x0a, 0xb6, 0xd8, 0x90, 0xc7, 0xbb, 0x4b, 0x29, 0x69, 0xb0, 0x81, 0x0b, 0x76, 0xda, 0x3b, 0x34, + 0xad, 0x3b, 0x88, 0x62, 0x55, 0xac, 0xe7, 0xcd, 0x24, 0xf9, 0x39, 0x9b, 0x0f, 0x1e, 0x9c, 0x6d, + 0x0d, 0x88, 0xa3, 0x55, 0xb1, 0x2e, 0x9b, 0x3f, 0x9a, 0x3f, 0x61, 0xb3, 0x01, 0x95, 0x98, 0xad, + 0x8a, 0xf5, 0xac, 0x89, 0xdb, 0xe8, 0x68, 0x54, 0xe2, 0x41, 0x76, 0x34, 0x2a, 0xfe, 0x82, 0x3d, + 0xde, 0x93, 0x81, 0x9d, 0x42, 0x07, 0x32, 0x90, 0x3b, 0x88, 0xe3, 0x54, 0xe5, 0x51, 0x74, 0xdf, + 0x4c, 0x26, 0x3f, 0x63, 0xc7, 0x7e, 0x0f, 0x5d, 0x27, 0x4e, 0x12, 0xcd, 0x22, 0xba, 0x1a, 0x24, + 0x79, 0x71, 0x9a, 0xdd, 0x24, 0xf8, 0x92, 0x95, 0xfe, 0xe0, 0x03, 0x98, 0x1d, 0x2a, 0x31, 0xcf, + 0x77, 0xca, 0xc6, 0x8d, 0xe2, 0xcf, 0x18, 0x6b, 0x73, 0x53, 0x91, 0x96, 0x89, 0x96, 0xa3, 0x73, + 0xa3, 0x2e, 0x02, 0x5b, 0x7c, 0xf4, 0xfb, 0xcd, 0x70, 0xdb, 0xa1, 0x7c, 0x07, 0x87, 0x78, 0xe1, + 0x6f, 0x90, 0x9b, 0x2e, 0x9b, 0xb8, 0xe5, 0x2f, 0xd9, 0x19, 0xdc, 0xf5, 0xe8, 0xd2, 0x83, 0xed, + 0x02, 0x1a, 0xd8, 0x0d, 0x1e, 0x64, 0x6a, 0x7e, 0xd6, 0xf0, 0xbf, 0xec, 0x13, 0x1a, 0xf8, 0xec, + 0x41, 0xf2, 0x15, 0x7b, 0xf8, 0x15, 0xad, 0x06, 0xd7, 0x3b, 0xb4, 0x21, 0x3d, 0x47, 0xd9, 0xfc, + 0x6b, 0x5d, 0xfd, 0x28, 0xd8, 0x73, 0x49, 0xa6, 0xba, 0x67, 0x62, 0x57, 0x8b, 0x0f, 0xfe, 0x7d, + 0xd4, 0x9b, 0x38, 0xa1, 0x2f, 0x97, 0x63, 0x54, 0x53, 0xd7, 0x5a, 0x5d, 0x91, 0xd3, 0xb5, 0x06, + 0x9b, 0xa6, 0x57, 0x67, 0xd4, 0xf6, 0xe8, 0xff, 0xfb, 0x97, 0xbc, 0xce, 0xcb, 0xf7, 0xa3, 0xe5, + 0xdb, 0x5c, 0xe3, 0x3a, 0x1d, 0x37, 0x96, 0xaf, 0xae, 0x13, 0xfd, 0x39, 0xd1, 0x6d, 0xa2, 0xdb, + 0x91, 0x6e, 0x33, 0xbd, 0x3d, 0x49, 0x27, 0xbd, 0xfa, 0x1d, 0x00, 0x00, 0xff, 0xff, 0xdc, 0x30, + 0xf7, 0x5b, 0x8e, 0x02, 0x00, 0x00, } diff --git a/vendor/google.golang.org/genproto/googleapis/cloud/oslogin/v1/oslogin.pb.go b/vendor/google.golang.org/genproto/googleapis/cloud/oslogin/v1/oslogin.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..9ebcb38a7ca3b5ba5d98626f7c26fb1848387ec3 --- /dev/null +++ b/vendor/google.golang.org/genproto/googleapis/cloud/oslogin/v1/oslogin.pb.go @@ -0,0 +1,584 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: google/cloud/oslogin/v1/oslogin.proto + +/* +Package oslogin is a generated protocol buffer package. + +It is generated from these files: + google/cloud/oslogin/v1/oslogin.proto + +It has these top-level messages: + LoginProfile + DeletePosixAccountRequest + DeleteSshPublicKeyRequest + GetLoginProfileRequest + GetSshPublicKeyRequest + ImportSshPublicKeyRequest + ImportSshPublicKeyResponse + UpdateSshPublicKeyRequest +*/ +package oslogin + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import _ "google.golang.org/genproto/googleapis/api/annotations" +import google_cloud_oslogin_common "google.golang.org/genproto/googleapis/cloud/oslogin/common" +import google_protobuf1 "github.com/golang/protobuf/ptypes/empty" +import google_protobuf2 "google.golang.org/genproto/protobuf/field_mask" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +// The user profile information used for logging in to a virtual machine on +// Google Compute Engine. +type LoginProfile struct { + // The primary email address that uniquely identifies the user. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // The list of POSIX accounts associated with the user. + PosixAccounts []*google_cloud_oslogin_common.PosixAccount `protobuf:"bytes,2,rep,name=posix_accounts,json=posixAccounts" json:"posix_accounts,omitempty"` + // A map from SSH public key fingerprint to the associated key object. + SshPublicKeys map[string]*google_cloud_oslogin_common.SshPublicKey `protobuf:"bytes,3,rep,name=ssh_public_keys,json=sshPublicKeys" json:"ssh_public_keys,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + // Indicates if the user is suspended. A suspended user cannot log in but + // their profile information is retained. + Suspended bool `protobuf:"varint,4,opt,name=suspended" json:"suspended,omitempty"` +} + +func (m *LoginProfile) Reset() { *m = LoginProfile{} } +func (m *LoginProfile) String() string { return proto.CompactTextString(m) } +func (*LoginProfile) ProtoMessage() {} +func (*LoginProfile) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +func (m *LoginProfile) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *LoginProfile) GetPosixAccounts() []*google_cloud_oslogin_common.PosixAccount { + if m != nil { + return m.PosixAccounts + } + return nil +} + +func (m *LoginProfile) GetSshPublicKeys() map[string]*google_cloud_oslogin_common.SshPublicKey { + if m != nil { + return m.SshPublicKeys + } + return nil +} + +func (m *LoginProfile) GetSuspended() bool { + if m != nil { + return m.Suspended + } + return false +} + +// A request message for deleting a POSIX account entry. +type DeletePosixAccountRequest struct { + // A reference to the POSIX account to update. POSIX accounts are identified + // by the project ID they are associated with. A reference to the POSIX + // account is in format `users/{user}/projects/{project}`. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` +} + +func (m *DeletePosixAccountRequest) Reset() { *m = DeletePosixAccountRequest{} } +func (m *DeletePosixAccountRequest) String() string { return proto.CompactTextString(m) } +func (*DeletePosixAccountRequest) ProtoMessage() {} +func (*DeletePosixAccountRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +func (m *DeletePosixAccountRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +// A request message for deleting an SSH public key. +type DeleteSshPublicKeyRequest struct { + // The fingerprint of the public key to update. Public keys are identified by + // their SHA-256 fingerprint. The fingerprint of the public key is in format + // `users/{user}/sshPublicKeys/{fingerprint}`. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` +} + +func (m *DeleteSshPublicKeyRequest) Reset() { *m = DeleteSshPublicKeyRequest{} } +func (m *DeleteSshPublicKeyRequest) String() string { return proto.CompactTextString(m) } +func (*DeleteSshPublicKeyRequest) ProtoMessage() {} +func (*DeleteSshPublicKeyRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } + +func (m *DeleteSshPublicKeyRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +// A request message for retrieving the login profile information for a user. +type GetLoginProfileRequest struct { + // The unique ID for the user in format `users/{user}`. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` +} + +func (m *GetLoginProfileRequest) Reset() { *m = GetLoginProfileRequest{} } +func (m *GetLoginProfileRequest) String() string { return proto.CompactTextString(m) } +func (*GetLoginProfileRequest) ProtoMessage() {} +func (*GetLoginProfileRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } + +func (m *GetLoginProfileRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +// A request message for retrieving an SSH public key. +type GetSshPublicKeyRequest struct { + // The fingerprint of the public key to retrieve. Public keys are identified + // by their SHA-256 fingerprint. The fingerprint of the public key is in + // format `users/{user}/sshPublicKeys/{fingerprint}`. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` +} + +func (m *GetSshPublicKeyRequest) Reset() { *m = GetSshPublicKeyRequest{} } +func (m *GetSshPublicKeyRequest) String() string { return proto.CompactTextString(m) } +func (*GetSshPublicKeyRequest) ProtoMessage() {} +func (*GetSshPublicKeyRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } + +func (m *GetSshPublicKeyRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +// A request message for importing an SSH public key. +type ImportSshPublicKeyRequest struct { + // The unique ID for the user in format `users/{user}`. + Parent string `protobuf:"bytes,1,opt,name=parent" json:"parent,omitempty"` + // The SSH public key and expiration time. + SshPublicKey *google_cloud_oslogin_common.SshPublicKey `protobuf:"bytes,2,opt,name=ssh_public_key,json=sshPublicKey" json:"ssh_public_key,omitempty"` + // The project ID of the Google Cloud Platform project. + ProjectId string `protobuf:"bytes,3,opt,name=project_id,json=projectId" json:"project_id,omitempty"` +} + +func (m *ImportSshPublicKeyRequest) Reset() { *m = ImportSshPublicKeyRequest{} } +func (m *ImportSshPublicKeyRequest) String() string { return proto.CompactTextString(m) } +func (*ImportSshPublicKeyRequest) ProtoMessage() {} +func (*ImportSshPublicKeyRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } + +func (m *ImportSshPublicKeyRequest) GetParent() string { + if m != nil { + return m.Parent + } + return "" +} + +func (m *ImportSshPublicKeyRequest) GetSshPublicKey() *google_cloud_oslogin_common.SshPublicKey { + if m != nil { + return m.SshPublicKey + } + return nil +} + +func (m *ImportSshPublicKeyRequest) GetProjectId() string { + if m != nil { + return m.ProjectId + } + return "" +} + +// A response message for importing an SSH public key. +type ImportSshPublicKeyResponse struct { + // The login profile information for the user. + LoginProfile *LoginProfile `protobuf:"bytes,1,opt,name=login_profile,json=loginProfile" json:"login_profile,omitempty"` +} + +func (m *ImportSshPublicKeyResponse) Reset() { *m = ImportSshPublicKeyResponse{} } +func (m *ImportSshPublicKeyResponse) String() string { return proto.CompactTextString(m) } +func (*ImportSshPublicKeyResponse) ProtoMessage() {} +func (*ImportSshPublicKeyResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } + +func (m *ImportSshPublicKeyResponse) GetLoginProfile() *LoginProfile { + if m != nil { + return m.LoginProfile + } + return nil +} + +// A request message for updating an SSH public key. +type UpdateSshPublicKeyRequest struct { + // The fingerprint of the public key to update. Public keys are identified by + // their SHA-256 fingerprint. The fingerprint of the public key is in format + // `users/{user}/sshPublicKeys/{fingerprint}`. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // The SSH public key and expiration time. + SshPublicKey *google_cloud_oslogin_common.SshPublicKey `protobuf:"bytes,2,opt,name=ssh_public_key,json=sshPublicKey" json:"ssh_public_key,omitempty"` + // Mask to control which fields get updated. Updates all if not present. + UpdateMask *google_protobuf2.FieldMask `protobuf:"bytes,3,opt,name=update_mask,json=updateMask" json:"update_mask,omitempty"` +} + +func (m *UpdateSshPublicKeyRequest) Reset() { *m = UpdateSshPublicKeyRequest{} } +func (m *UpdateSshPublicKeyRequest) String() string { return proto.CompactTextString(m) } +func (*UpdateSshPublicKeyRequest) ProtoMessage() {} +func (*UpdateSshPublicKeyRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } + +func (m *UpdateSshPublicKeyRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *UpdateSshPublicKeyRequest) GetSshPublicKey() *google_cloud_oslogin_common.SshPublicKey { + if m != nil { + return m.SshPublicKey + } + return nil +} + +func (m *UpdateSshPublicKeyRequest) GetUpdateMask() *google_protobuf2.FieldMask { + if m != nil { + return m.UpdateMask + } + return nil +} + +func init() { + proto.RegisterType((*LoginProfile)(nil), "google.cloud.oslogin.v1.LoginProfile") + proto.RegisterType((*DeletePosixAccountRequest)(nil), "google.cloud.oslogin.v1.DeletePosixAccountRequest") + proto.RegisterType((*DeleteSshPublicKeyRequest)(nil), "google.cloud.oslogin.v1.DeleteSshPublicKeyRequest") + proto.RegisterType((*GetLoginProfileRequest)(nil), "google.cloud.oslogin.v1.GetLoginProfileRequest") + proto.RegisterType((*GetSshPublicKeyRequest)(nil), "google.cloud.oslogin.v1.GetSshPublicKeyRequest") + proto.RegisterType((*ImportSshPublicKeyRequest)(nil), "google.cloud.oslogin.v1.ImportSshPublicKeyRequest") + proto.RegisterType((*ImportSshPublicKeyResponse)(nil), "google.cloud.oslogin.v1.ImportSshPublicKeyResponse") + proto.RegisterType((*UpdateSshPublicKeyRequest)(nil), "google.cloud.oslogin.v1.UpdateSshPublicKeyRequest") +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// Client API for OsLoginService service + +type OsLoginServiceClient interface { + // Deletes a POSIX account. + DeletePosixAccount(ctx context.Context, in *DeletePosixAccountRequest, opts ...grpc.CallOption) (*google_protobuf1.Empty, error) + // Deletes an SSH public key. + DeleteSshPublicKey(ctx context.Context, in *DeleteSshPublicKeyRequest, opts ...grpc.CallOption) (*google_protobuf1.Empty, error) + // Retrieves the profile information used for logging in to a virtual machine + // on Google Compute Engine. + GetLoginProfile(ctx context.Context, in *GetLoginProfileRequest, opts ...grpc.CallOption) (*LoginProfile, error) + // Retrieves an SSH public key. + GetSshPublicKey(ctx context.Context, in *GetSshPublicKeyRequest, opts ...grpc.CallOption) (*google_cloud_oslogin_common.SshPublicKey, error) + // Adds an SSH public key and returns the profile information. Default POSIX + // account information is set when no username and UID exist as part of the + // login profile. + ImportSshPublicKey(ctx context.Context, in *ImportSshPublicKeyRequest, opts ...grpc.CallOption) (*ImportSshPublicKeyResponse, error) + // Updates an SSH public key and returns the profile information. This method + // supports patch semantics. + UpdateSshPublicKey(ctx context.Context, in *UpdateSshPublicKeyRequest, opts ...grpc.CallOption) (*google_cloud_oslogin_common.SshPublicKey, error) +} + +type osLoginServiceClient struct { + cc *grpc.ClientConn +} + +func NewOsLoginServiceClient(cc *grpc.ClientConn) OsLoginServiceClient { + return &osLoginServiceClient{cc} +} + +func (c *osLoginServiceClient) DeletePosixAccount(ctx context.Context, in *DeletePosixAccountRequest, opts ...grpc.CallOption) (*google_protobuf1.Empty, error) { + out := new(google_protobuf1.Empty) + err := grpc.Invoke(ctx, "/google.cloud.oslogin.v1.OsLoginService/DeletePosixAccount", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *osLoginServiceClient) DeleteSshPublicKey(ctx context.Context, in *DeleteSshPublicKeyRequest, opts ...grpc.CallOption) (*google_protobuf1.Empty, error) { + out := new(google_protobuf1.Empty) + err := grpc.Invoke(ctx, "/google.cloud.oslogin.v1.OsLoginService/DeleteSshPublicKey", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *osLoginServiceClient) GetLoginProfile(ctx context.Context, in *GetLoginProfileRequest, opts ...grpc.CallOption) (*LoginProfile, error) { + out := new(LoginProfile) + err := grpc.Invoke(ctx, "/google.cloud.oslogin.v1.OsLoginService/GetLoginProfile", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *osLoginServiceClient) GetSshPublicKey(ctx context.Context, in *GetSshPublicKeyRequest, opts ...grpc.CallOption) (*google_cloud_oslogin_common.SshPublicKey, error) { + out := new(google_cloud_oslogin_common.SshPublicKey) + err := grpc.Invoke(ctx, "/google.cloud.oslogin.v1.OsLoginService/GetSshPublicKey", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *osLoginServiceClient) ImportSshPublicKey(ctx context.Context, in *ImportSshPublicKeyRequest, opts ...grpc.CallOption) (*ImportSshPublicKeyResponse, error) { + out := new(ImportSshPublicKeyResponse) + err := grpc.Invoke(ctx, "/google.cloud.oslogin.v1.OsLoginService/ImportSshPublicKey", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *osLoginServiceClient) UpdateSshPublicKey(ctx context.Context, in *UpdateSshPublicKeyRequest, opts ...grpc.CallOption) (*google_cloud_oslogin_common.SshPublicKey, error) { + out := new(google_cloud_oslogin_common.SshPublicKey) + err := grpc.Invoke(ctx, "/google.cloud.oslogin.v1.OsLoginService/UpdateSshPublicKey", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for OsLoginService service + +type OsLoginServiceServer interface { + // Deletes a POSIX account. + DeletePosixAccount(context.Context, *DeletePosixAccountRequest) (*google_protobuf1.Empty, error) + // Deletes an SSH public key. + DeleteSshPublicKey(context.Context, *DeleteSshPublicKeyRequest) (*google_protobuf1.Empty, error) + // Retrieves the profile information used for logging in to a virtual machine + // on Google Compute Engine. + GetLoginProfile(context.Context, *GetLoginProfileRequest) (*LoginProfile, error) + // Retrieves an SSH public key. + GetSshPublicKey(context.Context, *GetSshPublicKeyRequest) (*google_cloud_oslogin_common.SshPublicKey, error) + // Adds an SSH public key and returns the profile information. Default POSIX + // account information is set when no username and UID exist as part of the + // login profile. + ImportSshPublicKey(context.Context, *ImportSshPublicKeyRequest) (*ImportSshPublicKeyResponse, error) + // Updates an SSH public key and returns the profile information. This method + // supports patch semantics. + UpdateSshPublicKey(context.Context, *UpdateSshPublicKeyRequest) (*google_cloud_oslogin_common.SshPublicKey, error) +} + +func RegisterOsLoginServiceServer(s *grpc.Server, srv OsLoginServiceServer) { + s.RegisterService(&_OsLoginService_serviceDesc, srv) +} + +func _OsLoginService_DeletePosixAccount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeletePosixAccountRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(OsLoginServiceServer).DeletePosixAccount(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.oslogin.v1.OsLoginService/DeletePosixAccount", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(OsLoginServiceServer).DeletePosixAccount(ctx, req.(*DeletePosixAccountRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _OsLoginService_DeleteSshPublicKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteSshPublicKeyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(OsLoginServiceServer).DeleteSshPublicKey(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.oslogin.v1.OsLoginService/DeleteSshPublicKey", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(OsLoginServiceServer).DeleteSshPublicKey(ctx, req.(*DeleteSshPublicKeyRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _OsLoginService_GetLoginProfile_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetLoginProfileRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(OsLoginServiceServer).GetLoginProfile(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.oslogin.v1.OsLoginService/GetLoginProfile", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(OsLoginServiceServer).GetLoginProfile(ctx, req.(*GetLoginProfileRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _OsLoginService_GetSshPublicKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetSshPublicKeyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(OsLoginServiceServer).GetSshPublicKey(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.oslogin.v1.OsLoginService/GetSshPublicKey", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(OsLoginServiceServer).GetSshPublicKey(ctx, req.(*GetSshPublicKeyRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _OsLoginService_ImportSshPublicKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ImportSshPublicKeyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(OsLoginServiceServer).ImportSshPublicKey(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.oslogin.v1.OsLoginService/ImportSshPublicKey", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(OsLoginServiceServer).ImportSshPublicKey(ctx, req.(*ImportSshPublicKeyRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _OsLoginService_UpdateSshPublicKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdateSshPublicKeyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(OsLoginServiceServer).UpdateSshPublicKey(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.cloud.oslogin.v1.OsLoginService/UpdateSshPublicKey", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(OsLoginServiceServer).UpdateSshPublicKey(ctx, req.(*UpdateSshPublicKeyRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _OsLoginService_serviceDesc = grpc.ServiceDesc{ + ServiceName: "google.cloud.oslogin.v1.OsLoginService", + HandlerType: (*OsLoginServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "DeletePosixAccount", + Handler: _OsLoginService_DeletePosixAccount_Handler, + }, + { + MethodName: "DeleteSshPublicKey", + Handler: _OsLoginService_DeleteSshPublicKey_Handler, + }, + { + MethodName: "GetLoginProfile", + Handler: _OsLoginService_GetLoginProfile_Handler, + }, + { + MethodName: "GetSshPublicKey", + Handler: _OsLoginService_GetSshPublicKey_Handler, + }, + { + MethodName: "ImportSshPublicKey", + Handler: _OsLoginService_ImportSshPublicKey_Handler, + }, + { + MethodName: "UpdateSshPublicKey", + Handler: _OsLoginService_UpdateSshPublicKey_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "google/cloud/oslogin/v1/oslogin.proto", +} + +func init() { proto.RegisterFile("google/cloud/oslogin/v1/oslogin.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 774 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0xcd, 0x6e, 0xd3, 0x40, + 0x10, 0x96, 0x93, 0x52, 0xe8, 0x26, 0x6d, 0xd1, 0x1e, 0xda, 0xd4, 0x6d, 0xd5, 0x60, 0x51, 0x35, + 0x44, 0xc8, 0x56, 0x52, 0x0e, 0x25, 0x15, 0x54, 0x14, 0x4a, 0x55, 0x7e, 0xd4, 0x28, 0x15, 0x3d, + 0xa0, 0x4a, 0xc1, 0x75, 0xb6, 0xae, 0x89, 0xed, 0x5d, 0xbc, 0x76, 0x44, 0x84, 0x7a, 0xe1, 0xc2, + 0x85, 0x13, 0x9c, 0x38, 0x22, 0x6e, 0x5c, 0x78, 0x02, 0x78, 0x00, 0x24, 0x4e, 0x3c, 0x01, 0x12, + 0x0f, 0x82, 0xbc, 0x5e, 0xb7, 0x4e, 0x6c, 0xa7, 0xae, 0xc4, 0x29, 0xbb, 0x9e, 0xf9, 0x66, 0xbf, + 0xfd, 0x76, 0xbe, 0x51, 0xc0, 0xb2, 0x8e, 0xb1, 0x6e, 0x22, 0x45, 0x33, 0xb1, 0xd7, 0x51, 0x30, + 0x35, 0xb1, 0x6e, 0xd8, 0x4a, 0xaf, 0x16, 0x2e, 0x65, 0xe2, 0x60, 0x17, 0xc3, 0xd9, 0x20, 0x4d, + 0x66, 0x69, 0x72, 0x18, 0xeb, 0xd5, 0xc4, 0x05, 0x8e, 0x57, 0x89, 0xa1, 0xa8, 0xb6, 0x8d, 0x5d, + 0xd5, 0x35, 0xb0, 0x4d, 0x03, 0x98, 0x58, 0x49, 0xac, 0xae, 0x61, 0xcb, 0xc2, 0xe1, 0x0f, 0xcf, + 0x9c, 0xe7, 0x99, 0x6c, 0x77, 0xe8, 0x1d, 0x29, 0xc8, 0x22, 0x6e, 0x9f, 0x07, 0xcb, 0xc3, 0xc1, + 0x23, 0x03, 0x99, 0x9d, 0xb6, 0xa5, 0xd2, 0x6e, 0x90, 0x21, 0xfd, 0xc9, 0x81, 0xe2, 0x13, 0xbf, + 0x78, 0xd3, 0xc1, 0x47, 0x86, 0x89, 0x20, 0x04, 0x63, 0xb6, 0x6a, 0xa1, 0x92, 0x50, 0x16, 0x2a, + 0x13, 0x2d, 0xb6, 0x86, 0x4d, 0x30, 0x45, 0x30, 0x35, 0x5e, 0xb7, 0x55, 0x4d, 0xc3, 0x9e, 0xed, + 0xd2, 0x52, 0xae, 0x9c, 0xaf, 0x14, 0xea, 0x37, 0xe4, 0xc4, 0xdb, 0x71, 0x7e, 0x4d, 0x1f, 0x72, + 0x2f, 0x40, 0xb4, 0x26, 0x49, 0x64, 0x47, 0xe1, 0x0b, 0x30, 0x4d, 0xe9, 0x71, 0x9b, 0x78, 0x87, + 0xa6, 0xa1, 0xb5, 0xbb, 0xa8, 0x4f, 0x4b, 0x79, 0x56, 0x72, 0x4d, 0x4e, 0x11, 0x4c, 0x8e, 0xb2, + 0x94, 0xf7, 0xe8, 0x71, 0x93, 0x61, 0x1f, 0xa3, 0x3e, 0xdd, 0xb2, 0x5d, 0xa7, 0xdf, 0x9a, 0xa4, + 0xd1, 0x6f, 0x70, 0x01, 0x4c, 0x50, 0x8f, 0x12, 0x64, 0x77, 0x50, 0xa7, 0x34, 0x56, 0x16, 0x2a, + 0x57, 0x5a, 0x67, 0x1f, 0xc4, 0x2e, 0x80, 0xf1, 0x12, 0xf0, 0x2a, 0xc8, 0x77, 0x51, 0x9f, 0x5f, + 0xdd, 0x5f, 0xc2, 0x0d, 0x70, 0xa9, 0xa7, 0x9a, 0x1e, 0x2a, 0xe5, 0xca, 0xc2, 0xb9, 0x17, 0x8e, + 0x56, 0x6c, 0x05, 0xb8, 0x46, 0x6e, 0x4d, 0x90, 0x14, 0x30, 0xf7, 0x00, 0x99, 0xc8, 0x45, 0x03, + 0x8a, 0xa0, 0x57, 0x1e, 0xa2, 0x6e, 0x92, 0xde, 0x67, 0x80, 0x81, 0x8a, 0x23, 0x00, 0x37, 0xc1, + 0xcc, 0x36, 0x72, 0xa3, 0x0a, 0x9d, 0x9f, 0x9d, 0xb5, 0xf6, 0x17, 0x01, 0xcc, 0xed, 0x58, 0x04, + 0x3b, 0x89, 0x88, 0x19, 0x30, 0x4e, 0x54, 0x07, 0xd9, 0x2e, 0xc7, 0xf0, 0x1d, 0xdc, 0x05, 0x53, + 0x83, 0x0f, 0x7c, 0x71, 0x05, 0x8b, 0xd1, 0x07, 0x85, 0x8b, 0x00, 0x10, 0x07, 0xbf, 0x44, 0x9a, + 0xdb, 0x36, 0x3a, 0xa5, 0x3c, 0x3b, 0x6c, 0x82, 0x7f, 0xd9, 0xe9, 0x48, 0xc7, 0x40, 0x4c, 0x22, + 0x49, 0x09, 0xb6, 0x29, 0x82, 0x8f, 0xc0, 0x24, 0x3b, 0xa7, 0x4d, 0x02, 0x75, 0x18, 0xd9, 0x42, + 0x7d, 0x39, 0x53, 0xb3, 0xb5, 0x8a, 0x66, 0x64, 0x27, 0x7d, 0x17, 0xc0, 0xdc, 0x33, 0xd2, 0x51, + 0x33, 0xbf, 0xce, 0xff, 0xd7, 0x62, 0x1d, 0x14, 0x3c, 0xc6, 0x80, 0x39, 0x99, 0x89, 0x51, 0xa8, + 0x8b, 0x61, 0xb5, 0xd0, 0xec, 0xf2, 0x43, 0xdf, 0xec, 0x4f, 0x55, 0xda, 0x6d, 0x81, 0x20, 0xdd, + 0x5f, 0xd7, 0x7f, 0x5d, 0x06, 0x53, 0xbb, 0x94, 0x5d, 0x70, 0x0f, 0x39, 0x3d, 0x43, 0x43, 0xf0, + 0x9d, 0x00, 0x60, 0xbc, 0x43, 0x61, 0x3d, 0x55, 0x9e, 0xd4, 0x76, 0x16, 0x67, 0x62, 0x2c, 0xb6, + 0xfc, 0x79, 0x24, 0x2d, 0xbf, 0xfd, 0xfd, 0xf7, 0x63, 0x6e, 0xa9, 0xba, 0xe8, 0x8f, 0xc8, 0x37, + 0xbe, 0x2c, 0x77, 0x3c, 0x8a, 0x1c, 0xaa, 0x54, 0x15, 0xfe, 0x88, 0x54, 0xa9, 0x9e, 0xc0, 0xf7, + 0xa7, 0x4c, 0xa2, 0xd7, 0x3f, 0x97, 0x49, 0xc2, 0x4b, 0xa4, 0x32, 0xa9, 0x32, 0x26, 0xd7, 0xab, + 0x52, 0x9c, 0xc9, 0xc0, 0x04, 0xf1, 0xe9, 0x7c, 0x10, 0xc0, 0xf4, 0x90, 0xb1, 0xa0, 0x92, 0xca, + 0x25, 0xd9, 0x82, 0x62, 0xb6, 0x2e, 0x93, 0x56, 0x18, 0xaf, 0x6b, 0x70, 0x29, 0xc6, 0xeb, 0x44, + 0x89, 0x36, 0x20, 0xfc, 0x14, 0x90, 0x1a, 0x10, 0x68, 0x24, 0xa9, 0x24, 0x75, 0xb2, 0xf7, 0x5e, + 0x28, 0x18, 0xcc, 0x22, 0xd8, 0x0f, 0x01, 0xc0, 0xb8, 0x0f, 0x47, 0xbc, 0x5f, 0xea, 0x64, 0x11, + 0x57, 0x2f, 0x84, 0x09, 0x8c, 0x2e, 0x6d, 0x30, 0xae, 0xb7, 0xa5, 0x15, 0xc6, 0x35, 0x98, 0x45, + 0xa7, 0x32, 0x36, 0x8c, 0x18, 0xb0, 0x31, 0xe4, 0x4c, 0xf8, 0x4d, 0x00, 0x30, 0xee, 0xee, 0x11, + 0x17, 0x48, 0x1d, 0x05, 0x17, 0x91, 0xb8, 0xc1, 0x68, 0xdf, 0xaa, 0x67, 0x90, 0x78, 0x98, 0xf1, + 0xe6, 0x67, 0x01, 0xcc, 0x6b, 0xd8, 0x4a, 0x23, 0xb8, 0x59, 0xe4, 0x66, 0x6f, 0xfa, 0x36, 0x68, + 0x0a, 0xcf, 0xef, 0xf2, 0x44, 0x1d, 0x9b, 0xaa, 0xad, 0xcb, 0xd8, 0xd1, 0x15, 0x1d, 0xd9, 0xcc, + 0x24, 0x4a, 0x10, 0x52, 0x89, 0x41, 0x63, 0xff, 0x6b, 0xd6, 0xf9, 0xf2, 0x6b, 0x6e, 0x76, 0x3b, + 0x28, 0x70, 0x9f, 0x9d, 0xc4, 0xab, 0xcb, 0xfb, 0xb5, 0x9f, 0x61, 0xe4, 0x80, 0x45, 0x0e, 0x78, + 0xe4, 0x60, 0xbf, 0x76, 0x38, 0xce, 0xca, 0xaf, 0xfe, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x8e, 0x79, + 0x9f, 0xd6, 0x35, 0x09, 0x00, 0x00, +} diff --git a/vendor/google.golang.org/genproto/googleapis/cloud/oslogin/v1alpha/oslogin.pb.go b/vendor/google.golang.org/genproto/googleapis/cloud/oslogin/v1alpha/oslogin.pb.go index 62b1ba721b56e1054e25f3c115a364cbc3c7b516..5fbc3b300af85f365958752b6e983423b48689cf 100644 --- a/vendor/google.golang.org/genproto/googleapis/cloud/oslogin/v1alpha/oslogin.pb.go +++ b/vendor/google.golang.org/genproto/googleapis/cloud/oslogin/v1alpha/oslogin.pb.go @@ -530,52 +530,54 @@ var _OsLoginService_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("google/cloud/oslogin/v1alpha/oslogin.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 745 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0xcd, 0x6e, 0xd3, 0x4c, - 0x14, 0x95, 0x93, 0x7e, 0x55, 0x3b, 0x49, 0xdb, 0x4f, 0xb3, 0xa8, 0x52, 0x53, 0xa4, 0x60, 0x55, - 0xd0, 0x5a, 0x95, 0x47, 0x04, 0x24, 0x4a, 0xab, 0x52, 0x51, 0x5a, 0x50, 0x05, 0xa8, 0x91, 0x2b, - 0x36, 0x6c, 0xa2, 0xa9, 0x3d, 0x75, 0x4d, 0x6c, 0xcf, 0xe0, 0xb1, 0x0b, 0x11, 0xea, 0x86, 0x37, - 0x40, 0x95, 0xd8, 0xa3, 0x3e, 0x05, 0x0b, 0x1e, 0x81, 0x15, 0xaf, 0x80, 0x78, 0x0e, 0xe4, 0xf1, - 0xa4, 0x71, 0x12, 0x27, 0x71, 0x24, 0x76, 0xbe, 0x33, 0xf7, 0xdc, 0x39, 0xf7, 0xdc, 0x1f, 0x19, - 0xe8, 0x0e, 0xa5, 0x8e, 0x47, 0x90, 0xe5, 0xd1, 0xd8, 0x46, 0x94, 0x7b, 0xd4, 0x71, 0x03, 0x74, - 0x71, 0x1f, 0x7b, 0xec, 0x1c, 0x77, 0x6d, 0x83, 0x85, 0x34, 0xa2, 0x70, 0x35, 0xf5, 0x35, 0x84, - 0xaf, 0xd1, 0xbd, 0x93, 0xbe, 0xaa, 0xbc, 0x45, 0x98, 0xb9, 0x08, 0x07, 0x01, 0x8d, 0x70, 0xe4, - 0xd2, 0x80, 0xa7, 0x58, 0xf5, 0x4e, 0xee, 0x3b, 0x16, 0xf5, 0x7d, 0x2a, 0xc3, 0xab, 0xb7, 0xa4, - 0x8b, 0xb0, 0x4e, 0xe3, 0x33, 0x44, 0x7c, 0x16, 0x75, 0xe4, 0x65, 0x7d, 0xf0, 0xf2, 0xcc, 0x25, - 0x9e, 0xdd, 0xf2, 0x31, 0x6f, 0xa7, 0x1e, 0xda, 0x9f, 0x12, 0xa8, 0xbe, 0x4a, 0xa2, 0x36, 0x43, - 0x7a, 0xe6, 0x7a, 0x04, 0x42, 0x30, 0x13, 0x60, 0x9f, 0xd4, 0x94, 0xba, 0xb2, 0x3e, 0x6f, 0x8a, - 0x6f, 0xd8, 0x04, 0x8b, 0x8c, 0x72, 0xf7, 0x63, 0x0b, 0x5b, 0x16, 0x8d, 0x83, 0x88, 0xd7, 0x4a, - 0xf5, 0xf2, 0x7a, 0xa5, 0xb1, 0x61, 0xe4, 0xe6, 0x26, 0xf9, 0x35, 0x13, 0xc8, 0xd3, 0x14, 0x61, - 0x2e, 0xb0, 0x8c, 0xc5, 0x21, 0x01, 0x4b, 0x9c, 0x9f, 0xb7, 0x58, 0x7c, 0xea, 0xb9, 0x56, 0xab, - 0x4d, 0x3a, 0xbc, 0x56, 0x16, 0x21, 0x77, 0x8d, 0x71, 0x72, 0x19, 0x59, 0xaa, 0xc6, 0x09, 0x3f, - 0x6f, 0x8a, 0x00, 0x2f, 0x49, 0x87, 0x1f, 0x06, 0x51, 0xd8, 0x31, 0x17, 0x78, 0xf6, 0x0c, 0xae, - 0x82, 0x79, 0x1e, 0x73, 0x46, 0x02, 0x9b, 0xd8, 0xb5, 0x99, 0xba, 0xb2, 0x3e, 0x67, 0xf6, 0x0e, - 0xd4, 0x36, 0x80, 0xc3, 0x21, 0xe0, 0xff, 0xa0, 0xdc, 0x26, 0x1d, 0x99, 0x7f, 0xf2, 0x09, 0xf7, - 0xc0, 0x7f, 0x17, 0xd8, 0x8b, 0x49, 0xad, 0x54, 0x57, 0x26, 0x66, 0x9d, 0x8d, 0x68, 0xa6, 0xb8, - 0xed, 0xd2, 0x96, 0xa2, 0x21, 0xb0, 0x72, 0x40, 0x3c, 0x12, 0x91, 0x3e, 0x59, 0xc8, 0xfb, 0x98, - 0xf0, 0x28, 0x4f, 0xf4, 0x1e, 0xa0, 0x2f, 0xe2, 0x18, 0xc0, 0x26, 0x58, 0x7e, 0x41, 0xa2, 0xac, - 0x42, 0x93, 0xbd, 0x8b, 0xc6, 0xbe, 0x56, 0xc0, 0xca, 0x91, 0xcf, 0x68, 0x98, 0x8b, 0x58, 0x06, - 0xb3, 0x0c, 0x87, 0x24, 0x88, 0x24, 0x46, 0x5a, 0xf0, 0x18, 0x2c, 0xf6, 0x57, 0x79, 0x7a, 0x05, - 0xab, 0xd9, 0x82, 0xc2, 0xdb, 0x00, 0xb0, 0x90, 0xbe, 0x23, 0x56, 0xd4, 0x72, 0xed, 0x5a, 0x59, - 0x3c, 0x36, 0x2f, 0x4f, 0x8e, 0x6c, 0xcd, 0x07, 0x6a, 0x1e, 0x49, 0xce, 0x68, 0xc0, 0x09, 0x3c, - 0x06, 0x0b, 0xe2, 0x9d, 0x16, 0x4b, 0xd5, 0x11, 0x64, 0x2b, 0x0d, 0xbd, 0x78, 0xc7, 0x99, 0x55, - 0x2f, 0x63, 0x69, 0x3f, 0x14, 0xb0, 0xf2, 0x86, 0xd9, 0xb8, 0x70, 0x89, 0xfe, 0xbd, 0x20, 0x3b, - 0xa0, 0x12, 0x0b, 0x06, 0x62, 0xa6, 0x85, 0x22, 0x95, 0x86, 0xda, 0x8d, 0xd6, 0x1d, 0x7b, 0xe3, - 0x79, 0x32, 0xf6, 0xaf, 0x31, 0x6f, 0x9b, 0x20, 0x75, 0x4f, 0xbe, 0x1b, 0x57, 0x73, 0x60, 0xf1, - 0x98, 0x8b, 0x04, 0x4f, 0x48, 0x78, 0xe1, 0x5a, 0x04, 0x7e, 0x51, 0x00, 0x1c, 0x6e, 0x53, 0xf8, - 0x68, 0xbc, 0x46, 0x23, 0x1b, 0x5b, 0x5d, 0x1e, 0xa2, 0x72, 0x98, 0xac, 0x27, 0x4d, 0xff, 0xfc, - 0xeb, 0xf7, 0x55, 0x69, 0x4d, 0xd7, 0x6e, 0x96, 0xe6, 0xa7, 0x44, 0xa0, 0xdd, 0x98, 0x93, 0x90, - 0x23, 0x1d, 0xc9, 0x9a, 0x72, 0xa4, 0x5f, 0xc2, 0xaf, 0x37, 0x9c, 0xb2, 0x42, 0x14, 0xe3, 0x94, - 0x53, 0x98, 0x91, 0x9c, 0x90, 0xe0, 0xb4, 0xa1, 0xdf, 0x1b, 0xc1, 0xa9, 0x6f, 0xb5, 0x24, 0xc4, - 0xbe, 0x29, 0x60, 0x69, 0x60, 0xe2, 0xe0, 0xc3, 0xf1, 0xac, 0xf2, 0x07, 0x54, 0x9d, 0xa2, 0x07, - 0xb5, 0x4d, 0x41, 0xf3, 0x2e, 0x5c, 0xcb, 0xa7, 0x79, 0x89, 0xb2, 0x3d, 0x0a, 0xaf, 0x53, 0x8e, - 0x7d, 0xca, 0x4d, 0xe6, 0x98, 0x27, 0x5b, 0xf1, 0x1e, 0xed, 0x2a, 0x09, 0x0b, 0x2b, 0xf9, 0x53, - 0x01, 0x70, 0x78, 0x72, 0x27, 0x95, 0x78, 0xe4, 0x42, 0x52, 0xb7, 0xa6, 0x07, 0xa6, 0x4b, 0x42, - 0x3b, 0x10, 0xd4, 0x9f, 0x68, 0x9b, 0x3d, 0xea, 0xe9, 0x32, 0xbb, 0xd1, 0x77, 0xdb, 0x1d, 0x42, - 0x6f, 0x0f, 0x4c, 0x35, 0xfc, 0xae, 0x00, 0x38, 0xbc, 0x19, 0x26, 0xe5, 0x33, 0x72, 0x97, 0x4c, - 0xa3, 0xfd, 0x9e, 0x48, 0xe0, 0x71, 0xa3, 0xa8, 0xf6, 0x83, 0xdc, 0xf7, 0x3f, 0x80, 0xba, 0x45, - 0xfd, 0xb1, 0x4c, 0xf7, 0xab, 0x72, 0x6d, 0x34, 0x93, 0x09, 0x6a, 0x2a, 0x6f, 0x9f, 0x49, 0x6f, - 0x87, 0x7a, 0x38, 0x70, 0x0c, 0x1a, 0x3a, 0xc8, 0x21, 0x81, 0x98, 0x2f, 0x94, 0x5e, 0x61, 0xe6, - 0xf2, 0xfc, 0xdf, 0xa5, 0x1d, 0x69, 0x9f, 0xce, 0x0a, 0xff, 0x07, 0x7f, 0x03, 0x00, 0x00, 0xff, - 0xff, 0xa6, 0x7e, 0xc7, 0x43, 0x5d, 0x09, 0x00, 0x00, + // 779 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0xcd, 0x6a, 0xdb, 0x4a, + 0x14, 0x46, 0x76, 0x6e, 0x48, 0xc6, 0x4e, 0x72, 0x99, 0x45, 0x70, 0x74, 0x73, 0xc1, 0x88, 0xd0, + 0x3a, 0x26, 0x68, 0x88, 0x5b, 0x68, 0x9a, 0x90, 0x86, 0xfc, 0x35, 0x84, 0xb6, 0xc4, 0x38, 0x34, + 0x8b, 0x12, 0x30, 0x13, 0x79, 0xa2, 0xa8, 0x96, 0x34, 0x53, 0x8d, 0x14, 0x6a, 0x4a, 0x36, 0x7d, + 0x83, 0x12, 0xe8, 0xbe, 0x64, 0xd7, 0x7d, 0x17, 0x5d, 0xf4, 0x05, 0x0a, 0x5d, 0xf5, 0x15, 0x4a, + 0x9f, 0xa3, 0x68, 0x34, 0x4a, 0x64, 0x5b, 0xb6, 0x65, 0xe8, 0xca, 0x3a, 0x73, 0xfe, 0xbe, 0xf3, + 0x9d, 0x1f, 0x0c, 0xaa, 0x26, 0xa5, 0xa6, 0x4d, 0x90, 0x61, 0xd3, 0xa0, 0x85, 0x28, 0xb7, 0xa9, + 0x69, 0xb9, 0xe8, 0x72, 0x15, 0xdb, 0xec, 0x02, 0xc7, 0xb2, 0xce, 0x3c, 0xea, 0x53, 0xb8, 0x18, + 0xd9, 0xea, 0xc2, 0x56, 0x8f, 0x75, 0xd2, 0x56, 0x95, 0x5a, 0x84, 0x99, 0x85, 0xb0, 0xeb, 0x52, + 0x1f, 0xfb, 0x16, 0x75, 0x79, 0xe4, 0xab, 0x56, 0x52, 0xf3, 0x18, 0xd4, 0x71, 0x68, 0xfc, 0x23, + 0x2d, 0xff, 0x93, 0x96, 0x42, 0x3a, 0x0b, 0xce, 0x11, 0x71, 0x98, 0xdf, 0x91, 0xca, 0x72, 0xaf, + 0xf2, 0xdc, 0x22, 0x76, 0xab, 0xe9, 0x60, 0xde, 0x8e, 0x2c, 0xb4, 0xdf, 0x39, 0x50, 0x7c, 0x1e, + 0x06, 0xaf, 0x7b, 0xf4, 0xdc, 0xb2, 0x09, 0x84, 0x60, 0xc2, 0xc5, 0x0e, 0x29, 0x29, 0x65, 0xa5, + 0x32, 0xdd, 0x10, 0xdf, 0xb0, 0x0e, 0x66, 0x19, 0xe5, 0xd6, 0xdb, 0x26, 0x36, 0x0c, 0x1a, 0xb8, + 0x3e, 0x2f, 0xe5, 0xca, 0xf9, 0x4a, 0xa1, 0xb6, 0xac, 0xa7, 0x96, 0x28, 0xf1, 0xd5, 0x43, 0x97, + 0xed, 0xc8, 0xa3, 0x31, 0xc3, 0x12, 0x12, 0x87, 0x04, 0xcc, 0x71, 0x7e, 0xd1, 0x64, 0xc1, 0x99, + 0x6d, 0x19, 0xcd, 0x36, 0xe9, 0xf0, 0x52, 0x5e, 0x84, 0xdc, 0xd4, 0x87, 0xb1, 0xa6, 0x27, 0xa1, + 0xea, 0xc7, 0xfc, 0xa2, 0x2e, 0x02, 0x3c, 0x23, 0x1d, 0xbe, 0xef, 0xfa, 0x5e, 0xa7, 0x31, 0xc3, + 0x93, 0x6f, 0x70, 0x11, 0x4c, 0xf3, 0x80, 0x33, 0xe2, 0xb6, 0x48, 0xab, 0x34, 0x51, 0x56, 0x2a, + 0x53, 0x8d, 0xbb, 0x07, 0xb5, 0x0d, 0x60, 0x7f, 0x08, 0xf8, 0x2f, 0xc8, 0xb7, 0x49, 0x47, 0xd6, + 0x1f, 0x7e, 0xc2, 0x2d, 0xf0, 0xcf, 0x25, 0xb6, 0x03, 0x52, 0xca, 0x95, 0x95, 0x91, 0x55, 0x27, + 0x23, 0x36, 0x22, 0xbf, 0xf5, 0xdc, 0x9a, 0xa2, 0x21, 0xb0, 0xb0, 0x47, 0x6c, 0xe2, 0x93, 0x2e, + 0x5a, 0xc8, 0x9b, 0x80, 0x70, 0x3f, 0x8d, 0xf4, 0x3b, 0x87, 0xae, 0x88, 0x43, 0x1c, 0x56, 0xc0, + 0xfc, 0x01, 0xf1, 0x93, 0x0c, 0x8d, 0xb6, 0xce, 0x1a, 0xfb, 0x46, 0x01, 0x0b, 0x87, 0x0e, 0xa3, + 0x5e, 0xaa, 0xc7, 0x3c, 0x98, 0x64, 0xd8, 0x23, 0xae, 0x2f, 0x7d, 0xa4, 0x04, 0x8f, 0xc0, 0x6c, + 0x77, 0x97, 0xc7, 0x67, 0xb0, 0x98, 0x6c, 0x28, 0xfc, 0x1f, 0x00, 0xe6, 0xd1, 0xd7, 0xc4, 0xf0, + 0x9b, 0x56, 0xab, 0x94, 0x17, 0xc9, 0xa6, 0xe5, 0xcb, 0x61, 0x4b, 0x73, 0x80, 0x9a, 0x06, 0x92, + 0x33, 0xea, 0x72, 0x02, 0x8f, 0xc0, 0x8c, 0xc8, 0xd3, 0x64, 0x11, 0x3b, 0x02, 0x6c, 0xa1, 0x56, + 0xcd, 0x3e, 0x71, 0x8d, 0xa2, 0x9d, 0x90, 0xb4, 0x6f, 0x0a, 0x58, 0x78, 0xc9, 0x5a, 0x38, 0x73, + 0x8b, 0xfe, 0x3e, 0x21, 0x1b, 0xa0, 0x10, 0x08, 0x04, 0x62, 0xa7, 0x05, 0x23, 0x85, 0x9a, 0x1a, + 0x47, 0x8b, 0xd7, 0x5e, 0x7f, 0x1a, 0xae, 0xfd, 0x0b, 0xcc, 0xdb, 0x0d, 0x10, 0x99, 0x87, 0xdf, + 0xb5, 0xeb, 0x29, 0x30, 0x7b, 0xc4, 0x45, 0x81, 0xc7, 0xc4, 0xbb, 0xb4, 0x0c, 0x02, 0x3f, 0x28, + 0x00, 0xf6, 0x8f, 0x29, 0x7c, 0x34, 0x9c, 0xa3, 0x81, 0x83, 0xad, 0xce, 0xf7, 0x41, 0xd9, 0x0f, + 0xcf, 0x93, 0x56, 0x7d, 0xff, 0xf3, 0xd7, 0x75, 0x6e, 0xa9, 0xaa, 0xdd, 0xde, 0xce, 0x77, 0x21, + 0x41, 0x9b, 0x01, 0x27, 0x1e, 0x47, 0x55, 0x24, 0x7b, 0xca, 0x51, 0xf5, 0x0a, 0x7e, 0xbc, 0xc5, + 0x94, 0x24, 0x22, 0x1b, 0xa6, 0x94, 0xc6, 0x0c, 0xc4, 0x84, 0x04, 0xa6, 0xe5, 0xea, 0xfd, 0x01, + 0x98, 0xba, 0x4e, 0x4b, 0x08, 0xec, 0x93, 0x02, 0xe6, 0x7a, 0x36, 0x0e, 0x3e, 0x1c, 0x8e, 0x2a, + 0x7d, 0x41, 0xd5, 0x31, 0x66, 0x50, 0x5b, 0x11, 0x30, 0xef, 0xc1, 0xa5, 0x74, 0x98, 0x57, 0x28, + 0x39, 0xa3, 0xf0, 0x26, 0xc2, 0xd8, 0xc5, 0xdc, 0x68, 0x8c, 0x69, 0xb4, 0x65, 0x9f, 0xd1, 0x98, + 0x49, 0x98, 0x99, 0xc9, 0x1f, 0x0a, 0x80, 0xfd, 0x9b, 0x3b, 0xaa, 0xc5, 0x03, 0x0f, 0x92, 0xba, + 0x36, 0xbe, 0x63, 0x74, 0x24, 0xb4, 0x3d, 0x01, 0xfd, 0x89, 0xb6, 0x72, 0x07, 0x3d, 0x3a, 0x66, + 0xb7, 0xfc, 0xae, 0x5b, 0x7d, 0xde, 0xeb, 0x3d, 0x5b, 0x0d, 0xbf, 0x2a, 0x00, 0xf6, 0x5f, 0x86, + 0x51, 0xf5, 0x0c, 0xbc, 0x25, 0xe3, 0x70, 0xbf, 0x25, 0x0a, 0x78, 0x5c, 0xcb, 0xca, 0x7d, 0x2f, + 0xf6, 0x9d, 0x2f, 0x0a, 0x28, 0x1b, 0xd4, 0x19, 0x0a, 0x75, 0xa7, 0x28, 0xef, 0x46, 0x3d, 0x5c, + 0xa1, 0xba, 0xf2, 0x6a, 0x57, 0x5a, 0x9b, 0xd4, 0xc6, 0xae, 0xa9, 0x53, 0xcf, 0x44, 0x26, 0x71, + 0xc5, 0x82, 0xa1, 0x48, 0x85, 0x99, 0xc5, 0xd3, 0xff, 0x36, 0x6d, 0x48, 0xf9, 0x73, 0x6e, 0xf1, + 0x20, 0x8a, 0xb2, 0x2b, 0x72, 0xca, 0x14, 0xfa, 0xc9, 0xea, 0x76, 0x68, 0xf6, 0x3d, 0x56, 0x9f, + 0x0a, 0xf5, 0xa9, 0x54, 0x9f, 0x9e, 0x44, 0x51, 0xce, 0x26, 0x45, 0xb6, 0x07, 0x7f, 0x02, 0x00, + 0x00, 0xff, 0xff, 0xf8, 0xf2, 0xe5, 0x19, 0xa3, 0x09, 0x00, 0x00, } diff --git a/vendor/google.golang.org/genproto/googleapis/cloud/oslogin/v1beta/oslogin.pb.go b/vendor/google.golang.org/genproto/googleapis/cloud/oslogin/v1beta/oslogin.pb.go index 681ab2d98a89916f97e96c30091cb43414ab036e..9171c69e11c4b113e335ae8e83c72d478f61d34b 100644 --- a/vendor/google.golang.org/genproto/googleapis/cloud/oslogin/v1beta/oslogin.pb.go +++ b/vendor/google.golang.org/genproto/googleapis/cloud/oslogin/v1beta/oslogin.pb.go @@ -532,53 +532,53 @@ func init() { proto.RegisterFile("google/cloud/oslogin/v1beta/oslogin.proto", fi var fileDescriptor0 = []byte{ // 780 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0xcd, 0x4e, 0xdb, 0x4a, - 0x14, 0x96, 0x13, 0x2e, 0x82, 0x21, 0xc0, 0xd5, 0x2c, 0x50, 0x30, 0x5c, 0xdd, 0x60, 0xd4, 0x2a, - 0x84, 0xca, 0x16, 0x41, 0x6a, 0x11, 0x94, 0x56, 0x0d, 0xa5, 0x08, 0xf5, 0x87, 0x28, 0xa8, 0x2c, - 0x2a, 0xa4, 0x68, 0x62, 0x0f, 0xc6, 0x8d, 0xed, 0x99, 0x7a, 0x6c, 0xd4, 0xa8, 0x62, 0x53, 0xa9, - 0xeb, 0x2e, 0xda, 0x75, 0xa5, 0xaa, 0xbb, 0xee, 0xba, 0xea, 0xaa, 0x2f, 0xc0, 0xb6, 0xaf, 0xd0, - 0xbe, 0x47, 0xe5, 0xf1, 0x18, 0x9c, 0xc4, 0x49, 0x8c, 0xd4, 0x9d, 0x67, 0xce, 0x39, 0xdf, 0xf9, - 0xe6, 0x3b, 0x3f, 0x32, 0x58, 0x31, 0x09, 0x31, 0x6d, 0xac, 0xe9, 0x36, 0x09, 0x0c, 0x8d, 0x30, - 0x9b, 0x98, 0x96, 0xab, 0x9d, 0xad, 0xb5, 0xb0, 0x8f, 0xe2, 0xa3, 0x4a, 0x3d, 0xe2, 0x13, 0xb8, - 0x10, 0xb9, 0xaa, 0xdc, 0x55, 0x8d, 0x6d, 0x91, 0xab, 0xbc, 0x28, 0x70, 0x10, 0xb5, 0x34, 0xe4, - 0xba, 0xc4, 0x47, 0xbe, 0x45, 0x5c, 0x16, 0x85, 0xca, 0x4b, 0xa9, 0x59, 0x74, 0xe2, 0x38, 0x44, - 0xa0, 0xcb, 0x02, 0x5d, 0xe3, 0xa7, 0x56, 0x70, 0xa2, 0x61, 0x87, 0xfa, 0x1d, 0x61, 0x2c, 0xf5, - 0x1a, 0x4f, 0x2c, 0x6c, 0x1b, 0x4d, 0x07, 0xb1, 0x76, 0xe4, 0xa1, 0xfc, 0xce, 0x81, 0xc2, 0x93, - 0x10, 0xb5, 0xee, 0x91, 0x13, 0xcb, 0xc6, 0x10, 0x82, 0x31, 0x17, 0x39, 0xb8, 0x28, 0x95, 0xa4, - 0xf2, 0x64, 0x83, 0x7f, 0xc3, 0x3a, 0x98, 0xa1, 0x84, 0x59, 0xaf, 0x9b, 0x48, 0xd7, 0x49, 0xe0, - 0xfa, 0xac, 0x98, 0x2b, 0xe5, 0xcb, 0x53, 0xd5, 0x15, 0x35, 0xf5, 0x69, 0x82, 0x5f, 0x3d, 0x0c, - 0x79, 0x10, 0x45, 0x34, 0xa6, 0x69, 0xe2, 0xc4, 0xa0, 0x01, 0x66, 0x19, 0x3b, 0x6d, 0xd2, 0xa0, - 0x65, 0x5b, 0x7a, 0xb3, 0x8d, 0x3b, 0xac, 0x98, 0xe7, 0x90, 0x77, 0xd5, 0x21, 0x6a, 0xa9, 0x49, - 0xa6, 0xea, 0x21, 0x3b, 0xad, 0xf3, 0xf8, 0xc7, 0xb8, 0xc3, 0x76, 0x5d, 0xdf, 0xeb, 0x34, 0xa6, - 0x59, 0xf2, 0x0e, 0x2e, 0x82, 0x49, 0x16, 0x30, 0x8a, 0x5d, 0x03, 0x1b, 0xc5, 0xb1, 0x92, 0x54, - 0x9e, 0x68, 0x5c, 0x5d, 0xc8, 0x6d, 0x00, 0xfb, 0x21, 0xe0, 0xbf, 0x20, 0xdf, 0xc6, 0x1d, 0xf1, - 0xfc, 0xf0, 0x13, 0xde, 0x07, 0xff, 0x9c, 0x21, 0x3b, 0xc0, 0xc5, 0x5c, 0x49, 0x1a, 0xf9, 0xe8, - 0x24, 0x62, 0x23, 0x8a, 0xdb, 0xcc, 0x6d, 0x48, 0x8a, 0x06, 0xe6, 0x1f, 0x62, 0x1b, 0xfb, 0xb8, - 0x4b, 0x15, 0xfc, 0x2a, 0xc0, 0xcc, 0x4f, 0xd3, 0xfc, 0x2a, 0xa0, 0x0b, 0x71, 0x48, 0xc0, 0x2d, - 0x30, 0xb7, 0x87, 0xfd, 0xa4, 0x42, 0xa3, 0xbd, 0xb3, 0x62, 0x7f, 0x91, 0xc0, 0xfc, 0xbe, 0x43, - 0x89, 0x97, 0x1a, 0x31, 0x07, 0xc6, 0x29, 0xf2, 0xb0, 0xeb, 0x8b, 0x18, 0x71, 0x82, 0x07, 0x60, - 0xa6, 0xbb, 0xc8, 0xd7, 0x57, 0xb0, 0x90, 0x2c, 0x28, 0xfc, 0x0f, 0x00, 0xea, 0x91, 0x97, 0x58, - 0xf7, 0x9b, 0x96, 0x51, 0xcc, 0xf3, 0x64, 0x93, 0xe2, 0x66, 0xdf, 0x50, 0x6c, 0x20, 0xa7, 0x91, - 0x64, 0x94, 0xb8, 0x0c, 0xc3, 0x67, 0x60, 0x9a, 0xe7, 0x69, 0xd2, 0x48, 0x1d, 0x4e, 0x76, 0x20, - 0x99, 0x94, 0x86, 0x6b, 0x14, 0xec, 0xc4, 0x49, 0xf9, 0x21, 0x81, 0xf9, 0xe7, 0xd4, 0x40, 0x99, - 0x2b, 0xf4, 0xf7, 0xf5, 0xd8, 0x02, 0x53, 0x01, 0x67, 0xc0, 0x27, 0x9a, 0x0b, 0x32, 0x55, 0x95, - 0x63, 0xb4, 0x78, 0xe8, 0xd5, 0x47, 0xe1, 0xd0, 0x3f, 0x45, 0xac, 0xdd, 0x00, 0x91, 0x7b, 0xf8, - 0x5d, 0x7d, 0x37, 0x01, 0x66, 0x0e, 0x18, 0x7f, 0xe0, 0x21, 0xf6, 0xce, 0x2c, 0x1d, 0xc3, 0xf7, - 0x12, 0x80, 0xfd, 0x5d, 0x0a, 0x6f, 0x0f, 0x95, 0x68, 0x60, 0x5b, 0xcb, 0x73, 0x7d, 0x4c, 0x76, - 0xc3, 0xdd, 0xa4, 0xac, 0xbc, 0xfd, 0xf9, 0xeb, 0x43, 0x6e, 0xb9, 0xb2, 0x14, 0xef, 0xcb, 0x37, - 0xa1, 0x3c, 0xdb, 0x01, 0xc3, 0x1e, 0xd3, 0x2a, 0x9a, 0x28, 0x28, 0xd3, 0x2a, 0xe7, 0xf0, 0xe3, - 0x25, 0xa3, 0xa4, 0x0c, 0x99, 0x18, 0xa5, 0x54, 0x65, 0x20, 0x23, 0x95, 0x33, 0x2a, 0x57, 0x6e, - 0xa6, 0x33, 0xea, 0xda, 0x2a, 0x21, 0xad, 0x4f, 0x12, 0x98, 0xed, 0x19, 0x36, 0xb8, 0x3e, 0x94, - 0x53, 0xfa, 0x68, 0xca, 0xd9, 0xbb, 0x4f, 0x59, 0xe5, 0x1c, 0x6f, 0xc0, 0xe5, 0x54, 0x8e, 0xe7, - 0x5a, 0xb2, 0x39, 0xe1, 0xe7, 0x88, 0x60, 0x97, 0x68, 0x23, 0x09, 0xa6, 0x29, 0x96, 0xbd, 0x37, - 0x63, 0x11, 0x61, 0x56, 0x11, 0x2f, 0x24, 0x00, 0xfb, 0xe7, 0x75, 0x44, 0x6d, 0x07, 0x6e, 0x21, - 0xf9, 0xce, 0xb5, 0xe3, 0xa2, 0xc5, 0xa0, 0xec, 0x70, 0xde, 0xdb, 0xca, 0xea, 0x25, 0xef, 0x68, - 0x7f, 0x5d, 0x4a, 0xbb, 0x69, 0xf5, 0x05, 0x6f, 0xf6, 0x4c, 0x32, 0xfc, 0x2e, 0x01, 0xd8, 0xbf, - 0x0d, 0x46, 0x3c, 0x66, 0xe0, 0xfa, 0xb8, 0x8e, 0xec, 0xf7, 0x38, 0xfd, 0x8d, 0x6a, 0x46, 0xd9, - 0x7b, 0x99, 0xd7, 0xbe, 0x49, 0xe0, 0x7f, 0x9d, 0x38, 0xc3, 0x88, 0xd6, 0x0a, 0x62, 0x51, 0xd4, - 0xc3, 0xb1, 0xa9, 0x4b, 0x2f, 0x6a, 0xc2, 0xd9, 0x24, 0x36, 0x72, 0x4d, 0x95, 0x78, 0xa6, 0x66, - 0x62, 0x97, 0x0f, 0x95, 0x16, 0x99, 0x10, 0xb5, 0x58, 0xea, 0xcf, 0xd1, 0x96, 0x38, 0x7e, 0xcd, - 0x2d, 0xec, 0x45, 0x20, 0x3b, 0x3c, 0xa3, 0xc8, 0xa0, 0x1e, 0xad, 0xd5, 0xb0, 0x8f, 0x2e, 0x62, - 0xeb, 0x31, 0xb7, 0x1e, 0x0b, 0xeb, 0xf1, 0x11, 0xc7, 0x68, 0x8d, 0xf3, 0x54, 0xeb, 0x7f, 0x02, - 0x00, 0x00, 0xff, 0xff, 0x63, 0x03, 0xf6, 0x66, 0x86, 0x09, 0x00, 0x00, + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x96, 0x4f, 0x4f, 0x13, 0x4f, + 0x18, 0xc7, 0xb3, 0x2d, 0x3f, 0x02, 0x43, 0x81, 0x5f, 0xe6, 0x40, 0xca, 0x82, 0xb1, 0x2e, 0xd1, + 0x94, 0x62, 0x76, 0x43, 0x49, 0x94, 0x80, 0x68, 0x2c, 0x22, 0x21, 0xfe, 0xa1, 0x29, 0x91, 0x83, + 0x21, 0x69, 0xa6, 0xbb, 0xc3, 0xb2, 0x76, 0x77, 0x67, 0xdc, 0xd9, 0x25, 0x36, 0x86, 0x8b, 0x89, + 0x67, 0x0f, 0x7a, 0x36, 0x31, 0xde, 0xbc, 0x79, 0xf2, 0xe4, 0x1b, 0xe0, 0xea, 0x5b, 0xd0, 0xf7, + 0x61, 0x76, 0x76, 0x16, 0xb6, 0xed, 0xb6, 0x5d, 0x12, 0x4f, 0xdd, 0x99, 0xe7, 0xdf, 0x67, 0xbe, + 0x33, 0xcf, 0x93, 0x82, 0x65, 0x93, 0x10, 0xd3, 0xc6, 0x9a, 0x6e, 0x93, 0xc0, 0xd0, 0x08, 0xb3, + 0x89, 0x69, 0xb9, 0xda, 0xe9, 0x6a, 0x0b, 0xfb, 0x28, 0x5e, 0xaa, 0xd4, 0x23, 0x3e, 0x81, 0x0b, + 0x91, 0xab, 0xca, 0x5d, 0xd5, 0xd8, 0x16, 0xb9, 0xca, 0x8b, 0x22, 0x0f, 0xa2, 0x96, 0x86, 0x5c, + 0x97, 0xf8, 0xc8, 0xb7, 0x88, 0xcb, 0xa2, 0x50, 0xb9, 0x9c, 0x5a, 0x45, 0x27, 0x8e, 0x43, 0xe2, + 0x1f, 0xe1, 0x29, 0x8a, 0x68, 0x7c, 0xd5, 0x0a, 0x8e, 0x35, 0xec, 0x50, 0xbf, 0x23, 0x8c, 0xa5, + 0x5e, 0xe3, 0xb1, 0x85, 0x6d, 0xa3, 0xe9, 0x20, 0xd6, 0x8e, 0x3c, 0x94, 0x3f, 0x39, 0x50, 0x78, + 0x1a, 0x26, 0xaf, 0x7b, 0xe4, 0xd8, 0xb2, 0x31, 0x84, 0x60, 0xcc, 0x45, 0x0e, 0x2e, 0x4a, 0x25, + 0xa9, 0x3c, 0xd9, 0xe0, 0xdf, 0xb0, 0x0e, 0x66, 0x28, 0x61, 0xd6, 0x9b, 0x26, 0xd2, 0x75, 0x12, + 0xb8, 0x3e, 0x2b, 0xe6, 0x4a, 0xf9, 0xf2, 0x54, 0x75, 0x59, 0x4d, 0x3d, 0xa1, 0xe0, 0xab, 0x87, + 0x21, 0x0f, 0xa3, 0x88, 0xc6, 0x34, 0x4d, 0xac, 0x18, 0x34, 0xc0, 0x2c, 0x63, 0x27, 0x4d, 0x1a, + 0xb4, 0x6c, 0x4b, 0x6f, 0xb6, 0x71, 0x87, 0x15, 0xf3, 0x3c, 0xe5, 0x3d, 0x75, 0x88, 0x68, 0x6a, + 0x92, 0x54, 0x3d, 0x60, 0x27, 0x75, 0x1e, 0xff, 0x04, 0x77, 0xd8, 0x8e, 0xeb, 0x7b, 0x9d, 0xc6, + 0x34, 0x4b, 0xee, 0xc1, 0x45, 0x30, 0xc9, 0x02, 0x46, 0xb1, 0x6b, 0x60, 0xa3, 0x38, 0x56, 0x92, + 0xca, 0x13, 0x8d, 0xcb, 0x0d, 0xb9, 0x0d, 0x60, 0x7f, 0x0a, 0xf8, 0x3f, 0xc8, 0xb7, 0x71, 0x47, + 0x1c, 0x3f, 0xfc, 0x84, 0x0f, 0xc0, 0x7f, 0xa7, 0xc8, 0x0e, 0x70, 0x31, 0x57, 0x92, 0x46, 0x1e, + 0x3a, 0x99, 0xb1, 0x11, 0xc5, 0x6d, 0xe4, 0xd6, 0x25, 0x45, 0x03, 0xf3, 0x8f, 0xb0, 0x8d, 0x7d, + 0xdc, 0xa5, 0x0a, 0x7e, 0x1d, 0x60, 0xe6, 0xa7, 0x69, 0x7e, 0x19, 0xd0, 0x95, 0x71, 0x48, 0xc0, + 0x6d, 0x30, 0xb7, 0x8b, 0xfd, 0xa4, 0x42, 0xa3, 0xbd, 0xb3, 0xe6, 0xfe, 0x2a, 0x81, 0xf9, 0x3d, + 0x87, 0x12, 0x2f, 0x35, 0x62, 0x0e, 0x8c, 0x53, 0xe4, 0x61, 0xd7, 0x17, 0x31, 0x62, 0x05, 0xf7, + 0xc1, 0x4c, 0xf7, 0x25, 0x5f, 0x5d, 0xc1, 0x42, 0xf2, 0x42, 0xe1, 0x35, 0x00, 0xa8, 0x47, 0x5e, + 0x61, 0xdd, 0x6f, 0x5a, 0x46, 0x31, 0xcf, 0x8b, 0x4d, 0x8a, 0x9d, 0x3d, 0x43, 0xb1, 0x81, 0x9c, + 0x06, 0xc9, 0x28, 0x71, 0x19, 0x86, 0xcf, 0xc1, 0x34, 0xaf, 0xd3, 0xa4, 0x91, 0x3a, 0x1c, 0x76, + 0x20, 0x4c, 0xca, 0x83, 0x6b, 0x14, 0xec, 0xc4, 0x4a, 0xf9, 0x29, 0x81, 0xf9, 0x17, 0xd4, 0x40, + 0x99, 0x6f, 0xe8, 0xdf, 0xeb, 0xb1, 0x09, 0xa6, 0x02, 0x4e, 0xc0, 0x3b, 0x9a, 0x0b, 0x32, 0x55, + 0x95, 0xe3, 0x6c, 0x71, 0xd3, 0xab, 0x8f, 0xc3, 0xa6, 0x7f, 0x86, 0x58, 0xbb, 0x01, 0x22, 0xf7, + 0xf0, 0xbb, 0xfa, 0x7e, 0x02, 0xcc, 0xec, 0x33, 0x7e, 0xc0, 0x03, 0xec, 0x9d, 0x5a, 0x3a, 0x86, + 0x1f, 0x24, 0x00, 0xfb, 0x5f, 0x29, 0xbc, 0x33, 0x54, 0xa2, 0x81, 0xcf, 0x5a, 0x9e, 0xeb, 0x23, + 0xd9, 0x09, 0x67, 0x93, 0xb2, 0xfc, 0xee, 0xd7, 0xef, 0x8f, 0xb9, 0xa5, 0xca, 0x8d, 0x78, 0x6c, + 0xbe, 0x0d, 0xe5, 0xd9, 0x0a, 0x18, 0xf6, 0x98, 0x56, 0xd1, 0xc4, 0x85, 0x32, 0xad, 0x72, 0x06, + 0x3f, 0x5d, 0x10, 0x25, 0x65, 0xc8, 0x44, 0x94, 0x72, 0x2b, 0x03, 0x89, 0x54, 0x4e, 0x54, 0xae, + 0xdc, 0x4a, 0x27, 0xea, 0x9a, 0x2a, 0x21, 0xd6, 0x67, 0x09, 0xcc, 0xf6, 0x34, 0x1b, 0x5c, 0x1b, + 0xca, 0x94, 0xde, 0x9a, 0x72, 0xf6, 0xd7, 0xa7, 0xac, 0x70, 0xc6, 0x9b, 0x70, 0x29, 0x95, 0xf1, + 0x4c, 0x4b, 0x3e, 0x4e, 0xf8, 0x25, 0x02, 0xec, 0x12, 0x6d, 0x24, 0x60, 0x9a, 0x62, 0xd9, 0xdf, + 0x66, 0x2c, 0x22, 0xcc, 0x2a, 0xe2, 0xb9, 0x04, 0x60, 0x7f, 0xbf, 0x8e, 0xb8, 0xdb, 0x81, 0x53, + 0x48, 0xbe, 0x7b, 0xe5, 0xb8, 0x68, 0x30, 0x28, 0xdb, 0x9c, 0x7b, 0x4b, 0x59, 0xb9, 0xe0, 0x8e, + 0xe6, 0xd7, 0x85, 0xb4, 0x1b, 0x56, 0x5f, 0xf0, 0x46, 0x4f, 0x27, 0xc3, 0x1f, 0x12, 0x80, 0xfd, + 0xd3, 0x60, 0xc4, 0x61, 0x06, 0x8e, 0x8f, 0xab, 0xc8, 0x7e, 0x9f, 0xe3, 0xaf, 0x57, 0x33, 0xca, + 0xde, 0x4b, 0x5e, 0xfb, 0x2e, 0x81, 0xeb, 0x3a, 0x71, 0x86, 0x81, 0xd6, 0x0a, 0x62, 0x50, 0xd4, + 0xc3, 0xb6, 0xa9, 0x4b, 0x2f, 0x6b, 0xc2, 0xd9, 0x24, 0x36, 0x72, 0x4d, 0x95, 0x78, 0xa6, 0x66, + 0x62, 0x97, 0x37, 0x95, 0x16, 0x99, 0x10, 0xb5, 0x58, 0xea, 0x7f, 0xa4, 0x4d, 0xb1, 0xfc, 0x96, + 0x5b, 0xd8, 0x8d, 0x92, 0x6c, 0xf3, 0x8a, 0xa2, 0x82, 0x7a, 0xb8, 0x5a, 0xc3, 0x3e, 0x3a, 0x8f, + 0xad, 0x47, 0xdc, 0x7a, 0x24, 0xac, 0x47, 0x87, 0x3c, 0x47, 0x6b, 0x9c, 0x97, 0x5a, 0xfb, 0x1b, + 0x00, 0x00, 0xff, 0xff, 0xc7, 0x96, 0xd9, 0xc2, 0x8d, 0x09, 0x00, 0x00, } diff --git a/vendor/google.golang.org/genproto/googleapis/devtools/cloudbuild/v1/cloudbuild.pb.go b/vendor/google.golang.org/genproto/googleapis/devtools/cloudbuild/v1/cloudbuild.pb.go index fbd3b6cde45fd5de3e724da276a8e0836c48dfa8..0b62fd0d80adc99a1d14d74f4b5ef100c54f9759 100644 --- a/vendor/google.golang.org/genproto/googleapis/devtools/cloudbuild/v1/cloudbuild.pb.go +++ b/vendor/google.golang.org/genproto/googleapis/devtools/cloudbuild/v1/cloudbuild.pb.go @@ -18,6 +18,7 @@ It has these top-level messages: Volume Results Build + TimeSpan BuildOperationMetadata SourceProvenance FileHashes @@ -135,7 +136,7 @@ var Hash_HashType_value = map[string]int32{ func (x Hash_HashType) String() string { return proto.EnumName(Hash_HashType_name, int32(x)) } -func (Hash_HashType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{13, 0} } +func (Hash_HashType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{14, 0} } // Specifies the manner in which the build should be verified, if at all. type BuildOptions_VerifyOption int32 @@ -160,7 +161,7 @@ func (x BuildOptions_VerifyOption) String() string { return proto.EnumName(BuildOptions_VerifyOption_name, int32(x)) } func (BuildOptions_VerifyOption) EnumDescriptor() ([]byte, []int) { - return fileDescriptor0, []int{27, 0} + return fileDescriptor0, []int{28, 0} } // Supported VM sizes. @@ -169,9 +170,9 @@ type BuildOptions_MachineType int32 const ( // Standard machine type. BuildOptions_UNSPECIFIED BuildOptions_MachineType = 0 - // Medium size. + // Highcpu machine with 8 CPUs. BuildOptions_N1_HIGHCPU_8 BuildOptions_MachineType = 1 - // Large size. + // Highcpu machine with 32 CPUs. BuildOptions_N1_HIGHCPU_32 BuildOptions_MachineType = 2 ) @@ -189,7 +190,7 @@ var BuildOptions_MachineType_value = map[string]int32{ func (x BuildOptions_MachineType) String() string { return proto.EnumName(BuildOptions_MachineType_name, int32(x)) } -func (BuildOptions_MachineType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{27, 1} } +func (BuildOptions_MachineType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{28, 1} } // Specifies the behavior when there is an error in the substitution checks. type BuildOptions_SubstitutionOption int32 @@ -215,7 +216,7 @@ func (x BuildOptions_SubstitutionOption) String() string { return proto.EnumName(BuildOptions_SubstitutionOption_name, int32(x)) } func (BuildOptions_SubstitutionOption) EnumDescriptor() ([]byte, []int) { - return fileDescriptor0, []int{27, 2} + return fileDescriptor0, []int{28, 2} } // Specifies the behavior when writing build logs to Google Cloud Storage. @@ -246,7 +247,7 @@ func (x BuildOptions_LogStreamingOption) String() string { return proto.EnumName(BuildOptions_LogStreamingOption_name, int32(x)) } func (BuildOptions_LogStreamingOption) EnumDescriptor() ([]byte, []int) { - return fileDescriptor0, []int{27, 3} + return fileDescriptor0, []int{28, 3} } // RetryBuildRequest specifies a build to retry. @@ -661,6 +662,8 @@ type BuiltImage struct { Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` // Docker Registry 2.0 digest. Digest string `protobuf:"bytes,3,opt,name=digest" json:"digest,omitempty"` + // Stores timing information for pushing the specified image. + PushTiming *TimeSpan `protobuf:"bytes,4,opt,name=push_timing,json=pushTiming" json:"push_timing,omitempty"` } func (m *BuiltImage) Reset() { *m = BuiltImage{} } @@ -682,6 +685,13 @@ func (m *BuiltImage) GetDigest() string { return "" } +func (m *BuiltImage) GetPushTiming() *TimeSpan { + if m != nil { + return m.PushTiming + } + return nil +} + // BuildStep describes a step to perform in the build pipeline. type BuildStep struct { // The name of the container image that will run this particular build step. @@ -740,6 +750,8 @@ type BuildStep struct { // Using a named volume in only one step is not valid as it is indicative // of a mis-configured build request. Volumes []*Volume `protobuf:"bytes,9,rep,name=volumes" json:"volumes,omitempty"` + // Stores timing information for executing this build step. + Timing *TimeSpan `protobuf:"bytes,10,opt,name=timing" json:"timing,omitempty"` } func (m *BuildStep) Reset() { *m = BuildStep{} } @@ -810,6 +822,13 @@ func (m *BuildStep) GetVolumes() []*Volume { return nil } +func (m *BuildStep) GetTiming() *TimeSpan { + if m != nil { + return m.Timing + } + return nil +} + // Volume describes a Docker container volume which is mounted into build steps // in order to persist files across build step execution. type Volume struct { @@ -959,6 +978,14 @@ type Build struct { Tags []string `protobuf:"bytes,31,rep,name=tags" json:"tags,omitempty"` // Secrets to decrypt using Cloud KMS. Secrets []*Secret `protobuf:"bytes,32,rep,name=secrets" json:"secrets,omitempty"` + // Stores timing information for phases of the build. + // Valid keys are: + // - BUILD: time to execute all build steps + // - PUSH: time to push all specified images. + // - FETCHSOURCE: time to fetch source. + // If the build does not specify source, or does not specify images, + // these keys will not be included. + Timing map[string]*TimeSpan `protobuf:"bytes,33,rep,name=timing" json:"timing,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` } func (m *Build) Reset() { *m = Build{} } @@ -1106,6 +1133,40 @@ func (m *Build) GetSecrets() []*Secret { return nil } +func (m *Build) GetTiming() map[string]*TimeSpan { + if m != nil { + return m.Timing + } + return nil +} + +// Stores start and end times for a build execution phase. +type TimeSpan struct { + // Start of time span. + StartTime *google_protobuf5.Timestamp `protobuf:"bytes,1,opt,name=start_time,json=startTime" json:"start_time,omitempty"` + // End of time span. + EndTime *google_protobuf5.Timestamp `protobuf:"bytes,2,opt,name=end_time,json=endTime" json:"end_time,omitempty"` +} + +func (m *TimeSpan) Reset() { *m = TimeSpan{} } +func (m *TimeSpan) String() string { return proto.CompactTextString(m) } +func (*TimeSpan) ProtoMessage() {} +func (*TimeSpan) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } + +func (m *TimeSpan) GetStartTime() *google_protobuf5.Timestamp { + if m != nil { + return m.StartTime + } + return nil +} + +func (m *TimeSpan) GetEndTime() *google_protobuf5.Timestamp { + if m != nil { + return m.EndTime + } + return nil +} + // Metadata for build operations. type BuildOperationMetadata struct { // The build that the operation is tracking. @@ -1115,7 +1176,7 @@ type BuildOperationMetadata struct { func (m *BuildOperationMetadata) Reset() { *m = BuildOperationMetadata{} } func (m *BuildOperationMetadata) String() string { return proto.CompactTextString(m) } func (*BuildOperationMetadata) ProtoMessage() {} -func (*BuildOperationMetadata) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } +func (*BuildOperationMetadata) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } func (m *BuildOperationMetadata) GetBuild() *Build { if m != nil { @@ -1149,7 +1210,7 @@ type SourceProvenance struct { func (m *SourceProvenance) Reset() { *m = SourceProvenance{} } func (m *SourceProvenance) String() string { return proto.CompactTextString(m) } func (*SourceProvenance) ProtoMessage() {} -func (*SourceProvenance) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } +func (*SourceProvenance) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } func (m *SourceProvenance) GetResolvedStorageSource() *StorageSource { if m != nil { @@ -1182,7 +1243,7 @@ type FileHashes struct { func (m *FileHashes) Reset() { *m = FileHashes{} } func (m *FileHashes) String() string { return proto.CompactTextString(m) } func (*FileHashes) ProtoMessage() {} -func (*FileHashes) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } +func (*FileHashes) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } func (m *FileHashes) GetFileHash() []*Hash { if m != nil { @@ -1202,7 +1263,7 @@ type Hash struct { func (m *Hash) Reset() { *m = Hash{} } func (m *Hash) String() string { return proto.CompactTextString(m) } func (*Hash) ProtoMessage() {} -func (*Hash) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } +func (*Hash) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } func (m *Hash) GetType() Hash_HashType { if m != nil { @@ -1235,7 +1296,7 @@ type Secret struct { func (m *Secret) Reset() { *m = Secret{} } func (m *Secret) String() string { return proto.CompactTextString(m) } func (*Secret) ProtoMessage() {} -func (*Secret) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } +func (*Secret) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } func (m *Secret) GetKmsKeyName() string { if m != nil { @@ -1262,7 +1323,7 @@ type CreateBuildRequest struct { func (m *CreateBuildRequest) Reset() { *m = CreateBuildRequest{} } func (m *CreateBuildRequest) String() string { return proto.CompactTextString(m) } func (*CreateBuildRequest) ProtoMessage() {} -func (*CreateBuildRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } +func (*CreateBuildRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } func (m *CreateBuildRequest) GetProjectId() string { if m != nil { @@ -1289,7 +1350,7 @@ type GetBuildRequest struct { func (m *GetBuildRequest) Reset() { *m = GetBuildRequest{} } func (m *GetBuildRequest) String() string { return proto.CompactTextString(m) } func (*GetBuildRequest) ProtoMessage() {} -func (*GetBuildRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } +func (*GetBuildRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } func (m *GetBuildRequest) GetProjectId() string { if m != nil { @@ -1320,7 +1381,7 @@ type ListBuildsRequest struct { func (m *ListBuildsRequest) Reset() { *m = ListBuildsRequest{} } func (m *ListBuildsRequest) String() string { return proto.CompactTextString(m) } func (*ListBuildsRequest) ProtoMessage() {} -func (*ListBuildsRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } +func (*ListBuildsRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } func (m *ListBuildsRequest) GetProjectId() string { if m != nil { @@ -1361,7 +1422,7 @@ type ListBuildsResponse struct { func (m *ListBuildsResponse) Reset() { *m = ListBuildsResponse{} } func (m *ListBuildsResponse) String() string { return proto.CompactTextString(m) } func (*ListBuildsResponse) ProtoMessage() {} -func (*ListBuildsResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } +func (*ListBuildsResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} } func (m *ListBuildsResponse) GetBuilds() []*Build { if m != nil { @@ -1388,7 +1449,7 @@ type CancelBuildRequest struct { func (m *CancelBuildRequest) Reset() { *m = CancelBuildRequest{} } func (m *CancelBuildRequest) String() string { return proto.CompactTextString(m) } func (*CancelBuildRequest) ProtoMessage() {} -func (*CancelBuildRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} } +func (*CancelBuildRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} } func (m *CancelBuildRequest) GetProjectId() string { if m != nil { @@ -1438,7 +1499,7 @@ type BuildTrigger struct { func (m *BuildTrigger) Reset() { *m = BuildTrigger{} } func (m *BuildTrigger) String() string { return proto.CompactTextString(m) } func (*BuildTrigger) ProtoMessage() {} -func (*BuildTrigger) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} } +func (*BuildTrigger) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{21} } type isBuildTrigger_BuildTemplate interface { isBuildTrigger_BuildTemplate() @@ -1598,7 +1659,7 @@ type CreateBuildTriggerRequest struct { func (m *CreateBuildTriggerRequest) Reset() { *m = CreateBuildTriggerRequest{} } func (m *CreateBuildTriggerRequest) String() string { return proto.CompactTextString(m) } func (*CreateBuildTriggerRequest) ProtoMessage() {} -func (*CreateBuildTriggerRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{21} } +func (*CreateBuildTriggerRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{22} } func (m *CreateBuildTriggerRequest) GetProjectId() string { if m != nil { @@ -1625,7 +1686,7 @@ type GetBuildTriggerRequest struct { func (m *GetBuildTriggerRequest) Reset() { *m = GetBuildTriggerRequest{} } func (m *GetBuildTriggerRequest) String() string { return proto.CompactTextString(m) } func (*GetBuildTriggerRequest) ProtoMessage() {} -func (*GetBuildTriggerRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{22} } +func (*GetBuildTriggerRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{23} } func (m *GetBuildTriggerRequest) GetProjectId() string { if m != nil { @@ -1650,7 +1711,7 @@ type ListBuildTriggersRequest struct { func (m *ListBuildTriggersRequest) Reset() { *m = ListBuildTriggersRequest{} } func (m *ListBuildTriggersRequest) String() string { return proto.CompactTextString(m) } func (*ListBuildTriggersRequest) ProtoMessage() {} -func (*ListBuildTriggersRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{23} } +func (*ListBuildTriggersRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{24} } func (m *ListBuildTriggersRequest) GetProjectId() string { if m != nil { @@ -1668,7 +1729,7 @@ type ListBuildTriggersResponse struct { func (m *ListBuildTriggersResponse) Reset() { *m = ListBuildTriggersResponse{} } func (m *ListBuildTriggersResponse) String() string { return proto.CompactTextString(m) } func (*ListBuildTriggersResponse) ProtoMessage() {} -func (*ListBuildTriggersResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{24} } +func (*ListBuildTriggersResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{25} } func (m *ListBuildTriggersResponse) GetTriggers() []*BuildTrigger { if m != nil { @@ -1688,7 +1749,7 @@ type DeleteBuildTriggerRequest struct { func (m *DeleteBuildTriggerRequest) Reset() { *m = DeleteBuildTriggerRequest{} } func (m *DeleteBuildTriggerRequest) String() string { return proto.CompactTextString(m) } func (*DeleteBuildTriggerRequest) ProtoMessage() {} -func (*DeleteBuildTriggerRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{25} } +func (*DeleteBuildTriggerRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{26} } func (m *DeleteBuildTriggerRequest) GetProjectId() string { if m != nil { @@ -1717,7 +1778,7 @@ type UpdateBuildTriggerRequest struct { func (m *UpdateBuildTriggerRequest) Reset() { *m = UpdateBuildTriggerRequest{} } func (m *UpdateBuildTriggerRequest) String() string { return proto.CompactTextString(m) } func (*UpdateBuildTriggerRequest) ProtoMessage() {} -func (*UpdateBuildTriggerRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{26} } +func (*UpdateBuildTriggerRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{27} } func (m *UpdateBuildTriggerRequest) GetProjectId() string { if m != nil { @@ -1765,7 +1826,7 @@ type BuildOptions struct { func (m *BuildOptions) Reset() { *m = BuildOptions{} } func (m *BuildOptions) String() string { return proto.CompactTextString(m) } func (*BuildOptions) ProtoMessage() {} -func (*BuildOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{27} } +func (*BuildOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{28} } func (m *BuildOptions) GetSourceProvenanceHash() []Hash_HashType { if m != nil { @@ -1820,6 +1881,7 @@ func init() { proto.RegisterType((*Volume)(nil), "google.devtools.cloudbuild.v1.Volume") proto.RegisterType((*Results)(nil), "google.devtools.cloudbuild.v1.Results") proto.RegisterType((*Build)(nil), "google.devtools.cloudbuild.v1.Build") + proto.RegisterType((*TimeSpan)(nil), "google.devtools.cloudbuild.v1.TimeSpan") proto.RegisterType((*BuildOperationMetadata)(nil), "google.devtools.cloudbuild.v1.BuildOperationMetadata") proto.RegisterType((*SourceProvenance)(nil), "google.devtools.cloudbuild.v1.SourceProvenance") proto.RegisterType((*FileHashes)(nil), "google.devtools.cloudbuild.v1.FileHashes") @@ -1875,28 +1937,6 @@ type CloudBuildClient interface { ListBuilds(ctx context.Context, in *ListBuildsRequest, opts ...grpc.CallOption) (*ListBuildsResponse, error) // Cancels a requested build in progress. CancelBuild(ctx context.Context, in *CancelBuildRequest, opts ...grpc.CallOption) (*Build, error) - // Creates a new BuildTrigger. - // - // This API is experimental. - CreateBuildTrigger(ctx context.Context, in *CreateBuildTriggerRequest, opts ...grpc.CallOption) (*BuildTrigger, error) - // Gets information about a BuildTrigger. - // - // This API is experimental. - GetBuildTrigger(ctx context.Context, in *GetBuildTriggerRequest, opts ...grpc.CallOption) (*BuildTrigger, error) - // Lists existing BuildTrigger. - // - // This API is experimental. - ListBuildTriggers(ctx context.Context, in *ListBuildTriggersRequest, opts ...grpc.CallOption) (*ListBuildTriggersResponse, error) - // Deletes an BuildTrigger by its project ID and trigger ID. - // - // This API is experimental. - DeleteBuildTrigger(ctx context.Context, in *DeleteBuildTriggerRequest, opts ...grpc.CallOption) (*google_protobuf3.Empty, error) - // Updates an BuildTrigger by its project ID and trigger ID. - // - // This API is experimental. - UpdateBuildTrigger(ctx context.Context, in *UpdateBuildTriggerRequest, opts ...grpc.CallOption) (*BuildTrigger, error) - // Runs a BuildTrigger at a particular source revision. - RunBuildTrigger(ctx context.Context, in *RunBuildTriggerRequest, opts ...grpc.CallOption) (*google_longrunning.Operation, error) // Creates a new build based on the given build. // // This API creates a new build using the original build request, which may @@ -1925,6 +1965,28 @@ type CloudBuildClient interface { // object, which may or may not be available depending on the bucket's // lifecycle management settings. RetryBuild(ctx context.Context, in *RetryBuildRequest, opts ...grpc.CallOption) (*google_longrunning.Operation, error) + // Creates a new BuildTrigger. + // + // This API is experimental. + CreateBuildTrigger(ctx context.Context, in *CreateBuildTriggerRequest, opts ...grpc.CallOption) (*BuildTrigger, error) + // Gets information about a BuildTrigger. + // + // This API is experimental. + GetBuildTrigger(ctx context.Context, in *GetBuildTriggerRequest, opts ...grpc.CallOption) (*BuildTrigger, error) + // Lists existing BuildTrigger. + // + // This API is experimental. + ListBuildTriggers(ctx context.Context, in *ListBuildTriggersRequest, opts ...grpc.CallOption) (*ListBuildTriggersResponse, error) + // Deletes an BuildTrigger by its project ID and trigger ID. + // + // This API is experimental. + DeleteBuildTrigger(ctx context.Context, in *DeleteBuildTriggerRequest, opts ...grpc.CallOption) (*google_protobuf3.Empty, error) + // Updates an BuildTrigger by its project ID and trigger ID. + // + // This API is experimental. + UpdateBuildTrigger(ctx context.Context, in *UpdateBuildTriggerRequest, opts ...grpc.CallOption) (*BuildTrigger, error) + // Runs a BuildTrigger at a particular source revision. + RunBuildTrigger(ctx context.Context, in *RunBuildTriggerRequest, opts ...grpc.CallOption) (*google_longrunning.Operation, error) } type cloudBuildClient struct { @@ -1971,6 +2033,15 @@ func (c *cloudBuildClient) CancelBuild(ctx context.Context, in *CancelBuildReque return out, nil } +func (c *cloudBuildClient) RetryBuild(ctx context.Context, in *RetryBuildRequest, opts ...grpc.CallOption) (*google_longrunning.Operation, error) { + out := new(google_longrunning.Operation) + err := grpc.Invoke(ctx, "/google.devtools.cloudbuild.v1.CloudBuild/RetryBuild", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *cloudBuildClient) CreateBuildTrigger(ctx context.Context, in *CreateBuildTriggerRequest, opts ...grpc.CallOption) (*BuildTrigger, error) { out := new(BuildTrigger) err := grpc.Invoke(ctx, "/google.devtools.cloudbuild.v1.CloudBuild/CreateBuildTrigger", in, out, c.cc, opts...) @@ -2025,15 +2096,6 @@ func (c *cloudBuildClient) RunBuildTrigger(ctx context.Context, in *RunBuildTrig return out, nil } -func (c *cloudBuildClient) RetryBuild(ctx context.Context, in *RetryBuildRequest, opts ...grpc.CallOption) (*google_longrunning.Operation, error) { - out := new(google_longrunning.Operation) - err := grpc.Invoke(ctx, "/google.devtools.cloudbuild.v1.CloudBuild/RetryBuild", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - // Server API for CloudBuild service type CloudBuildServer interface { @@ -2055,28 +2117,6 @@ type CloudBuildServer interface { ListBuilds(context.Context, *ListBuildsRequest) (*ListBuildsResponse, error) // Cancels a requested build in progress. CancelBuild(context.Context, *CancelBuildRequest) (*Build, error) - // Creates a new BuildTrigger. - // - // This API is experimental. - CreateBuildTrigger(context.Context, *CreateBuildTriggerRequest) (*BuildTrigger, error) - // Gets information about a BuildTrigger. - // - // This API is experimental. - GetBuildTrigger(context.Context, *GetBuildTriggerRequest) (*BuildTrigger, error) - // Lists existing BuildTrigger. - // - // This API is experimental. - ListBuildTriggers(context.Context, *ListBuildTriggersRequest) (*ListBuildTriggersResponse, error) - // Deletes an BuildTrigger by its project ID and trigger ID. - // - // This API is experimental. - DeleteBuildTrigger(context.Context, *DeleteBuildTriggerRequest) (*google_protobuf3.Empty, error) - // Updates an BuildTrigger by its project ID and trigger ID. - // - // This API is experimental. - UpdateBuildTrigger(context.Context, *UpdateBuildTriggerRequest) (*BuildTrigger, error) - // Runs a BuildTrigger at a particular source revision. - RunBuildTrigger(context.Context, *RunBuildTriggerRequest) (*google_longrunning.Operation, error) // Creates a new build based on the given build. // // This API creates a new build using the original build request, which may @@ -2105,6 +2145,28 @@ type CloudBuildServer interface { // object, which may or may not be available depending on the bucket's // lifecycle management settings. RetryBuild(context.Context, *RetryBuildRequest) (*google_longrunning.Operation, error) + // Creates a new BuildTrigger. + // + // This API is experimental. + CreateBuildTrigger(context.Context, *CreateBuildTriggerRequest) (*BuildTrigger, error) + // Gets information about a BuildTrigger. + // + // This API is experimental. + GetBuildTrigger(context.Context, *GetBuildTriggerRequest) (*BuildTrigger, error) + // Lists existing BuildTrigger. + // + // This API is experimental. + ListBuildTriggers(context.Context, *ListBuildTriggersRequest) (*ListBuildTriggersResponse, error) + // Deletes an BuildTrigger by its project ID and trigger ID. + // + // This API is experimental. + DeleteBuildTrigger(context.Context, *DeleteBuildTriggerRequest) (*google_protobuf3.Empty, error) + // Updates an BuildTrigger by its project ID and trigger ID. + // + // This API is experimental. + UpdateBuildTrigger(context.Context, *UpdateBuildTriggerRequest) (*BuildTrigger, error) + // Runs a BuildTrigger at a particular source revision. + RunBuildTrigger(context.Context, *RunBuildTriggerRequest) (*google_longrunning.Operation, error) } func RegisterCloudBuildServer(s *grpc.Server, srv CloudBuildServer) { @@ -2183,6 +2245,24 @@ func _CloudBuild_CancelBuild_Handler(srv interface{}, ctx context.Context, dec f return interceptor(ctx, in, info, handler) } +func _CloudBuild_RetryBuild_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RetryBuildRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(CloudBuildServer).RetryBuild(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.devtools.cloudbuild.v1.CloudBuild/RetryBuild", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(CloudBuildServer).RetryBuild(ctx, req.(*RetryBuildRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _CloudBuild_CreateBuildTrigger_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(CreateBuildTriggerRequest) if err := dec(in); err != nil { @@ -2291,24 +2371,6 @@ func _CloudBuild_RunBuildTrigger_Handler(srv interface{}, ctx context.Context, d return interceptor(ctx, in, info, handler) } -func _CloudBuild_RetryBuild_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RetryBuildRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(CloudBuildServer).RetryBuild(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/google.devtools.cloudbuild.v1.CloudBuild/RetryBuild", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(CloudBuildServer).RetryBuild(ctx, req.(*RetryBuildRequest)) - } - return interceptor(ctx, in, info, handler) -} - var _CloudBuild_serviceDesc = grpc.ServiceDesc{ ServiceName: "google.devtools.cloudbuild.v1.CloudBuild", HandlerType: (*CloudBuildServer)(nil), @@ -2329,6 +2391,10 @@ var _CloudBuild_serviceDesc = grpc.ServiceDesc{ MethodName: "CancelBuild", Handler: _CloudBuild_CancelBuild_Handler, }, + { + MethodName: "RetryBuild", + Handler: _CloudBuild_RetryBuild_Handler, + }, { MethodName: "CreateBuildTrigger", Handler: _CloudBuild_CreateBuildTrigger_Handler, @@ -2353,10 +2419,6 @@ var _CloudBuild_serviceDesc = grpc.ServiceDesc{ MethodName: "RunBuildTrigger", Handler: _CloudBuild_RunBuildTrigger_Handler, }, - { - MethodName: "RetryBuild", - Handler: _CloudBuild_RetryBuild_Handler, - }, }, Streams: []grpc.StreamDesc{}, Metadata: "google/devtools/cloudbuild/v1/cloudbuild.proto", @@ -2365,160 +2427,166 @@ var _CloudBuild_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("google/devtools/cloudbuild/v1/cloudbuild.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 2467 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x59, 0x5b, 0x73, 0x23, 0x47, - 0x15, 0xf6, 0x48, 0xb2, 0x2e, 0x47, 0xbe, 0xcc, 0x76, 0x36, 0xce, 0x58, 0x9b, 0xcd, 0x9a, 0xc9, - 0x05, 0x67, 0x93, 0x48, 0xb1, 0x97, 0x64, 0x1d, 0xe7, 0x66, 0x5b, 0x96, 0x2f, 0xb5, 0xb6, 0xbc, - 0x8c, 0xa4, 0xdd, 0x22, 0x40, 0x0d, 0x23, 0x4d, 0x7b, 0x3c, 0x78, 0x34, 0x33, 0xcc, 0xb4, 0x44, - 0xbc, 0x5b, 0x5b, 0x40, 0xaa, 0xe0, 0x15, 0xaa, 0x28, 0x1e, 0x28, 0x1e, 0xb8, 0x3c, 0x53, 0x14, - 0x05, 0x0f, 0x54, 0x51, 0x95, 0x67, 0x7e, 0x00, 0x3f, 0x01, 0x7e, 0x08, 0xd5, 0x97, 0x91, 0x46, - 0xd2, 0x2e, 0x23, 0x65, 0xe1, 0xc5, 0xee, 0x3e, 0xdd, 0xe7, 0xf4, 0xe9, 0x73, 0xfd, 0x5a, 0x03, - 0x65, 0xcb, 0xf3, 0x2c, 0x07, 0x57, 0x4c, 0xdc, 0x27, 0x9e, 0xe7, 0x84, 0x95, 0x8e, 0xe3, 0xf5, - 0xcc, 0x76, 0xcf, 0x76, 0xcc, 0x4a, 0x7f, 0x23, 0x36, 0x2b, 0xfb, 0x81, 0x47, 0x3c, 0x74, 0x93, - 0xef, 0x2f, 0x47, 0xfb, 0xcb, 0xb1, 0x1d, 0xfd, 0x8d, 0xd2, 0xcb, 0x42, 0x9c, 0xe1, 0xdb, 0x15, - 0xc3, 0x75, 0x3d, 0x62, 0x10, 0xdb, 0x73, 0x43, 0xce, 0x5c, 0x52, 0xc5, 0x2a, 0xe3, 0xa9, 0x18, - 0x3d, 0xd3, 0x26, 0xfc, 0xaf, 0xee, 0x78, 0x96, 0xd8, 0xf3, 0xaa, 0xd8, 0xe3, 0x78, 0xae, 0x15, - 0xf4, 0x5c, 0xd7, 0x76, 0xad, 0x8a, 0xe7, 0xe3, 0x60, 0x44, 0xd0, 0x2b, 0x62, 0x13, 0x9b, 0xb5, - 0x7b, 0xe7, 0x15, 0xb3, 0xc7, 0x37, 0x88, 0xf5, 0x1b, 0xe3, 0xeb, 0xb8, 0xeb, 0x93, 0x2b, 0xb1, - 0x78, 0x6b, 0x7c, 0x91, 0xd8, 0x5d, 0x1c, 0x12, 0xa3, 0xeb, 0xf3, 0x0d, 0xea, 0x1e, 0x5c, 0xd3, - 0x30, 0x09, 0xae, 0xf6, 0xe8, 0xad, 0x34, 0xfc, 0x83, 0x1e, 0x0e, 0x09, 0xba, 0x09, 0xe0, 0x07, - 0xde, 0xf7, 0x71, 0x87, 0xe8, 0xb6, 0xa9, 0x48, 0x6b, 0xd2, 0x7a, 0x41, 0x2b, 0x08, 0xca, 0xb1, - 0x89, 0x96, 0x20, 0x65, 0x9b, 0x4a, 0x8a, 0x91, 0x53, 0xb6, 0xa9, 0xfe, 0x5a, 0x82, 0x15, 0xad, - 0xe7, 0x32, 0x11, 0xcd, 0xc0, 0xb6, 0x2c, 0x1c, 0x4c, 0x29, 0xe9, 0x26, 0x00, 0xe1, 0x0c, 0xfa, - 0x40, 0x62, 0x41, 0x50, 0x8e, 0x4d, 0xb4, 0x0b, 0xd9, 0xd0, 0xeb, 0x05, 0x1d, 0xac, 0xa4, 0xd7, - 0xa4, 0xf5, 0xe2, 0xe6, 0x9b, 0xe5, 0xff, 0xea, 0x91, 0xb2, 0x86, 0x7d, 0xaf, 0xc1, 0x18, 0x34, - 0xc1, 0xa8, 0xea, 0xb0, 0xd8, 0x20, 0x5e, 0x60, 0x58, 0x98, 0x2f, 0xa0, 0x15, 0xc8, 0xb6, 0x7b, - 0x9d, 0x4b, 0x4c, 0x84, 0x36, 0x62, 0x46, 0xe9, 0x5e, 0x9b, 0xaa, 0x25, 0xd4, 0x10, 0x33, 0xf4, - 0x0a, 0x80, 0x85, 0x5d, 0xe1, 0x13, 0xa6, 0x47, 0x5a, 0x8b, 0x51, 0xd4, 0x7f, 0x48, 0x00, 0xc3, - 0x73, 0x93, 0x2e, 0x7c, 0x03, 0x0a, 0x01, 0xf6, 0x3d, 0xdd, 0x35, 0xba, 0x58, 0x1c, 0x94, 0xa7, - 0x84, 0xba, 0xd1, 0xc5, 0xe8, 0x6b, 0x50, 0x6c, 0x07, 0x86, 0xdb, 0xb9, 0xe0, 0xcb, 0xf4, 0xac, - 0xc2, 0xd1, 0x9c, 0x06, 0x9c, 0xc8, 0xb6, 0xdc, 0x80, 0x3c, 0x31, 0x2c, 0xbe, 0x9e, 0x11, 0xeb, - 0x39, 0x62, 0x58, 0x6c, 0xf1, 0x16, 0x40, 0xc7, 0xeb, 0x76, 0x6d, 0xa2, 0x87, 0x17, 0x86, 0x32, - 0x2f, 0x96, 0x0b, 0x9c, 0xd6, 0xb8, 0x30, 0x90, 0x0c, 0x69, 0xd3, 0x0e, 0x94, 0x1c, 0x3b, 0x97, - 0x0e, 0xf7, 0x00, 0xf2, 0x01, 0xee, 0xdb, 0x21, 0xbd, 0xc9, 0xdf, 0x24, 0xc8, 0x8a, 0x5b, 0xb4, - 0x60, 0x29, 0xe4, 0x56, 0xd3, 0x85, 0x03, 0x52, 0xcc, 0x01, 0x6f, 0x27, 0x38, 0x60, 0xc4, 0xd4, - 0x47, 0x73, 0xda, 0x62, 0x38, 0x62, 0xfb, 0x13, 0x28, 0xb2, 0xdb, 0x7f, 0x45, 0xa7, 0x52, 0x5b, - 0x04, 0x83, 0xd9, 0x5e, 0x3e, 0x8a, 0x0e, 0x75, 0x0b, 0x80, 0x06, 0x1f, 0x39, 0xee, 0x1a, 0x16, - 0x46, 0x08, 0x32, 0xcc, 0x3e, 0xdc, 0xf8, 0x6c, 0x4c, 0xbd, 0x6b, 0xda, 0x16, 0x0e, 0x09, 0xb7, - 0xaa, 0x26, 0x66, 0xea, 0x17, 0x29, 0x28, 0xb0, 0xb8, 0x6d, 0x10, 0xec, 0x3f, 0x95, 0x53, 0x86, - 0x34, 0x76, 0xfb, 0x4a, 0x6a, 0x2d, 0x4d, 0x6d, 0x86, 0xdd, 0x3e, 0xdd, 0x65, 0x04, 0x56, 0xa8, - 0xa4, 0x19, 0x89, 0x8d, 0x23, 0xcb, 0x66, 0x06, 0x96, 0x15, 0x49, 0x32, 0x1f, 0x25, 0x09, 0x5a, - 0x85, 0xfc, 0x0f, 0x0d, 0x9b, 0xe8, 0xe7, 0x5e, 0xa0, 0x64, 0x19, 0x67, 0x8e, 0xce, 0x0f, 0xbc, - 0x80, 0x86, 0x18, 0x76, 0x49, 0x70, 0xe5, 0x7b, 0xb6, 0x4b, 0x84, 0x77, 0x62, 0x14, 0x1a, 0x53, - 0x21, 0xee, 0x04, 0x98, 0xe8, 0x54, 0x93, 0x3c, 0x63, 0x2e, 0x70, 0x4a, 0xcd, 0xed, 0xa3, 0x4f, - 0x21, 0xd7, 0xf7, 0x9c, 0x5e, 0x17, 0x87, 0x4a, 0x61, 0x2d, 0xbd, 0x5e, 0xdc, 0x7c, 0x3d, 0xc1, - 0xa2, 0x0f, 0xd8, 0x6e, 0x2d, 0xe2, 0x52, 0xdf, 0x85, 0x2c, 0x27, 0x3d, 0xd5, 0x00, 0x08, 0x32, - 0xbe, 0x41, 0x2e, 0x44, 0xb4, 0xb2, 0xb1, 0xfa, 0x39, 0xe4, 0x34, 0x1c, 0xf6, 0x1c, 0x12, 0xd2, - 0x1c, 0xb5, 0xa9, 0xd9, 0x43, 0x66, 0xa2, 0x64, 0x77, 0x0e, 0x1d, 0xa5, 0x09, 0x46, 0x74, 0x1b, - 0xae, 0xb1, 0x65, 0x3d, 0x24, 0xd8, 0xd7, 0x85, 0x34, 0x6e, 0xdd, 0xe5, 0x76, 0xe4, 0x1c, 0xc6, - 0x12, 0xaa, 0xff, 0x2a, 0xc0, 0x3c, 0x73, 0x98, 0x30, 0xb0, 0x34, 0x30, 0xf0, 0x68, 0xe6, 0xc9, - 0xe3, 0x99, 0x57, 0x85, 0x6c, 0x48, 0x0c, 0xd2, 0x0b, 0xd9, 0x45, 0x96, 0x36, 0xdf, 0x9a, 0x42, - 0x4f, 0xb3, 0xdc, 0x60, 0x2c, 0x9a, 0x60, 0x45, 0xaf, 0xc2, 0x22, 0x1f, 0xe9, 0x26, 0x26, 0x86, - 0xed, 0x28, 0x0a, 0x3b, 0x66, 0x81, 0x13, 0xf7, 0x19, 0x0d, 0x7d, 0x3c, 0x56, 0xb5, 0x92, 0xdc, - 0x31, 0x5a, 0xb1, 0xd0, 0x27, 0x30, 0x4f, 0xed, 0x10, 0x2a, 0x45, 0x66, 0xcf, 0xf5, 0x69, 0xf4, - 0xa4, 0x06, 0xd2, 0x38, 0x1b, 0xda, 0x81, 0x5c, 0xc0, 0x7d, 0xa3, 0x00, 0x3b, 0xff, 0x8d, 0xc4, - 0x04, 0x63, 0xbb, 0xb5, 0x88, 0x0d, 0x7d, 0x08, 0xc5, 0x4e, 0x80, 0x0d, 0x82, 0x75, 0xda, 0x2d, - 0x94, 0x2c, 0x93, 0x52, 0x8a, 0xa4, 0x44, 0xad, 0xa4, 0xdc, 0x8c, 0x5a, 0x89, 0x06, 0x7c, 0x3b, - 0x25, 0xa0, 0x0f, 0x00, 0x42, 0x62, 0x04, 0x84, 0xf3, 0xe6, 0x12, 0x79, 0x0b, 0x6c, 0x37, 0x63, - 0xfd, 0x10, 0x8a, 0xe7, 0xb6, 0x6b, 0x87, 0x17, 0x9c, 0x37, 0x9f, 0x7c, 0x2e, 0xdf, 0xce, 0x98, - 0xef, 0x40, 0x8e, 0x72, 0x79, 0x3d, 0xa2, 0x2c, 0x30, 0xc6, 0xd5, 0x09, 0xc6, 0x7d, 0xd1, 0x38, - 0xb5, 0x68, 0x27, 0x2d, 0x0b, 0x22, 0xdc, 0x16, 0x59, 0xb8, 0x45, 0x11, 0x79, 0x0b, 0x8a, 0x8e, - 0x67, 0x85, 0xba, 0xe8, 0x14, 0x2f, 0xf0, 0x94, 0xa4, 0xa4, 0x3d, 0xde, 0x2d, 0xbe, 0x03, 0xd7, - 0xb8, 0xbb, 0x74, 0x3f, 0xf0, 0xfa, 0xd8, 0x35, 0xdc, 0x0e, 0x56, 0x5e, 0x64, 0xe7, 0x56, 0xa6, - 0x72, 0xf7, 0xfd, 0x01, 0x9b, 0x26, 0x87, 0x63, 0x14, 0xb4, 0x0e, 0x32, 0x4f, 0x88, 0x58, 0x73, - 0x5c, 0x61, 0x3a, 0x2c, 0xb5, 0x63, 0x4d, 0xf6, 0xd8, 0x44, 0x35, 0xc8, 0x79, 0x3e, 0x43, 0x0b, - 0xca, 0x4b, 0xec, 0xf4, 0xa9, 0xc2, 0xfa, 0x8c, 0xb3, 0x68, 0x11, 0x2f, 0x7a, 0x09, 0x72, 0x8e, - 0x67, 0xe9, 0xbd, 0xc0, 0x51, 0x56, 0x79, 0x7d, 0x74, 0x3c, 0xab, 0x15, 0x38, 0xe8, 0xbb, 0xb0, - 0x18, 0xf6, 0xda, 0x21, 0xb1, 0x49, 0x8f, 0x9f, 0x72, 0x93, 0x05, 0xe5, 0xdd, 0xe9, 0x92, 0x27, - 0xce, 0x59, 0xa3, 0xf5, 0x4c, 0x1b, 0x95, 0x46, 0x6b, 0x0b, 0x31, 0xac, 0x50, 0xb9, 0xc5, 0x4b, - 0x29, 0x1d, 0xd3, 0x72, 0xc6, 0x6b, 0x5b, 0xa8, 0xac, 0x4d, 0x55, 0xce, 0x1a, 0x6c, 0xb7, 0x16, - 0x71, 0x95, 0x76, 0x00, 0x4d, 0x9e, 0x4c, 0x2b, 0xf4, 0x25, 0xbe, 0x12, 0xf5, 0x82, 0x0e, 0xd1, - 0x75, 0x98, 0xef, 0x1b, 0x4e, 0x2f, 0xea, 0xc3, 0x7c, 0xb2, 0x9d, 0xda, 0x92, 0xd4, 0x1f, 0x41, - 0x96, 0x27, 0x3e, 0x42, 0xb0, 0xd4, 0x68, 0xee, 0x36, 0x5b, 0x0d, 0xbd, 0x55, 0xbf, 0x57, 0x3f, - 0x7b, 0x58, 0x97, 0xe7, 0x10, 0x40, 0xf6, 0x9b, 0xad, 0x5a, 0xab, 0xb6, 0x2f, 0x4b, 0xa8, 0x08, - 0xb9, 0x87, 0x67, 0xda, 0xbd, 0xe3, 0xfa, 0xa1, 0x9c, 0xa2, 0x93, 0x46, 0xab, 0x5a, 0xad, 0x35, - 0x1a, 0x72, 0x9a, 0x4e, 0x0e, 0x76, 0x8f, 0x4f, 0x5a, 0x5a, 0x4d, 0xce, 0x50, 0x31, 0xc7, 0xf5, - 0x66, 0x4d, 0xab, 0xef, 0x9e, 0xe8, 0x35, 0x4d, 0x3b, 0xd3, 0xe4, 0x79, 0xba, 0xa1, 0x79, 0x7c, - 0x5a, 0x3b, 0x6b, 0x35, 0xe5, 0x2c, 0x5a, 0x84, 0x42, 0x75, 0xb7, 0x5e, 0xad, 0x9d, 0x9c, 0xd4, - 0xf6, 0xe5, 0x9c, 0xda, 0x84, 0x15, 0xe1, 0x28, 0x01, 0x33, 0x4e, 0x31, 0x31, 0x4c, 0x83, 0x18, - 0x68, 0x1b, 0xe6, 0xd9, 0xc5, 0xd9, 0x45, 0x8a, 0x9b, 0xaf, 0x4d, 0xe3, 0x08, 0x8d, 0xb3, 0xa8, - 0xbf, 0x4f, 0x83, 0x3c, 0x1e, 0x7d, 0xc8, 0x84, 0x97, 0x02, 0x1c, 0x7a, 0x4e, 0x1f, 0xd3, 0xfa, - 0x3b, 0xd2, 0xf3, 0xd3, 0xb3, 0xf7, 0x7c, 0xed, 0xc5, 0x48, 0xd8, 0x28, 0xea, 0xfa, 0x36, 0x5c, - 0x1f, 0x9c, 0x12, 0x87, 0x00, 0xd9, 0x59, 0x71, 0x1d, 0x8a, 0xc4, 0xc4, 0x30, 0xd7, 0xf7, 0x68, - 0xdd, 0x70, 0xb0, 0x7e, 0x61, 0x84, 0x17, 0x38, 0x54, 0x32, 0x2c, 0x6a, 0x3e, 0x9d, 0x31, 0x0d, - 0xcb, 0x07, 0xb6, 0x83, 0x8f, 0x98, 0x04, 0x1e, 0xaa, 0x70, 0x3e, 0x20, 0x94, 0x2e, 0x60, 0x79, - 0x6c, 0xf9, 0x29, 0xf1, 0xf4, 0x69, 0x3c, 0x9e, 0x92, 0x2f, 0x35, 0x14, 0x18, 0x0f, 0xbd, 0x3a, - 0xc0, 0x70, 0x01, 0xed, 0x40, 0x61, 0x70, 0x33, 0x45, 0x62, 0xf7, 0x7a, 0x35, 0x41, 0x2c, 0xe5, - 0xd4, 0xf2, 0x91, 0xee, 0xea, 0x8f, 0x25, 0xc8, 0xd0, 0x01, 0xda, 0x81, 0x0c, 0xb9, 0xf2, 0x79, - 0x6b, 0x5f, 0x4a, 0x74, 0x2a, 0x65, 0x61, 0x7f, 0x9a, 0x57, 0x3e, 0xd6, 0x18, 0xe7, 0x68, 0xbe, - 0x2c, 0x08, 0xa5, 0xd5, 0x35, 0xc8, 0x47, 0xfb, 0x50, 0x1e, 0x32, 0xf5, 0xb3, 0x7a, 0x8d, 0xe7, - 0x48, 0xe3, 0x68, 0x77, 0xf3, 0xbd, 0xf7, 0x65, 0x49, 0xfd, 0x92, 0xe2, 0x4a, 0x96, 0x9b, 0x68, - 0x0d, 0x16, 0x2e, 0xbb, 0xa1, 0x7e, 0x89, 0xaf, 0xf4, 0x18, 0xce, 0x80, 0xcb, 0x6e, 0x78, 0x0f, - 0x5f, 0x31, 0x0c, 0xdb, 0x18, 0xc1, 0x3a, 0x69, 0x76, 0xe5, 0x6f, 0x4c, 0x55, 0x00, 0xc4, 0xbf, - 0x9a, 0xdb, 0xe7, 0xfe, 0x1b, 0x22, 0xa4, 0xd2, 0x47, 0xb0, 0x34, 0xba, 0x98, 0x54, 0x0d, 0x16, - 0xe2, 0x2e, 0xf1, 0x00, 0x55, 0x59, 0x7f, 0x9b, 0xe5, 0x8d, 0x34, 0xc8, 0xd3, 0xd4, 0xec, 0x79, - 0xba, 0x03, 0xcb, 0x87, 0x98, 0x3c, 0xcf, 0x8b, 0xec, 0x67, 0x12, 0x5c, 0x3b, 0xb1, 0x43, 0x2e, - 0x23, 0x9c, 0x52, 0xc8, 0x0d, 0x28, 0xf8, 0x2c, 0xfb, 0xed, 0x47, 0xdc, 0x0a, 0xf3, 0x5a, 0x9e, - 0x12, 0x1a, 0xf6, 0x23, 0xfe, 0xae, 0xa1, 0x8b, 0xc4, 0xbb, 0xc4, 0xae, 0x00, 0xd1, 0x6c, 0x7b, - 0x93, 0x12, 0x68, 0x23, 0x3d, 0xb7, 0x1d, 0x82, 0x03, 0xd6, 0xb5, 0x0b, 0x9a, 0x98, 0xa9, 0x8f, - 0x00, 0xc5, 0xf5, 0x08, 0x7d, 0xcf, 0x0d, 0x31, 0xfa, 0x88, 0xbe, 0xc1, 0x28, 0x45, 0xc4, 0xf4, - 0x74, 0xd6, 0x11, 0x3c, 0xe8, 0x0d, 0x58, 0x76, 0xf1, 0xe7, 0x44, 0x8f, 0xe9, 0xc3, 0x6f, 0xbe, - 0x48, 0xc9, 0xf7, 0x23, 0x9d, 0xd4, 0x2a, 0xa0, 0x2a, 0xcd, 0x6c, 0xe7, 0x79, 0x2c, 0xf9, 0xd3, - 0x0c, 0x2c, 0xc4, 0x1f, 0xb6, 0x13, 0xb0, 0x73, 0x0d, 0x8a, 0x26, 0x0e, 0x3b, 0x81, 0xcd, 0x5a, - 0x29, 0x83, 0x5c, 0x05, 0x2d, 0x4e, 0x42, 0x4d, 0x90, 0xa3, 0x3e, 0x4e, 0x70, 0xd7, 0x77, 0x0c, - 0x12, 0xe1, 0xa2, 0x19, 0xea, 0xde, 0xb2, 0x10, 0xd1, 0x14, 0x12, 0xd0, 0x47, 0x51, 0x80, 0x65, - 0xa6, 0x0f, 0xb0, 0xa3, 0x39, 0x11, 0x62, 0xe8, 0x65, 0x60, 0x25, 0x82, 0x25, 0x61, 0x5e, 0x3c, - 0x14, 0x07, 0x94, 0x71, 0x00, 0x38, 0x3f, 0x13, 0x00, 0x2c, 0x41, 0xde, 0xb4, 0x43, 0xa3, 0xed, - 0x60, 0x53, 0x29, 0xac, 0x49, 0xeb, 0x79, 0x6d, 0x30, 0x47, 0xe6, 0x38, 0x9c, 0xe0, 0x18, 0xf7, - 0x93, 0x69, 0x94, 0x17, 0x0e, 0x48, 0x46, 0x15, 0xcf, 0x0f, 0x00, 0xf6, 0x64, 0x58, 0x12, 0x00, - 0x4c, 0x98, 0x5b, 0xfd, 0x89, 0x04, 0xab, 0xb1, 0x2a, 0x30, 0xdb, 0xcf, 0x1c, 0x35, 0xc8, 0x09, - 0xf7, 0x89, 0x72, 0xf0, 0xd6, 0x0c, 0x17, 0xd6, 0x22, 0x5e, 0xf5, 0x01, 0xac, 0x44, 0x75, 0xe1, - 0x7f, 0xf9, 0x33, 0x8b, 0xfa, 0x01, 0x28, 0x83, 0x24, 0x15, 0x82, 0xa7, 0xac, 0x19, 0xaa, 0x09, - 0xab, 0x4f, 0x61, 0x15, 0x69, 0x7e, 0x08, 0x79, 0x71, 0x48, 0x94, 0xe8, 0x33, 0xdd, 0x7b, 0xc0, - 0xac, 0x7e, 0x0b, 0x56, 0xf7, 0xb1, 0x83, 0xbf, 0x92, 0xed, 0x13, 0xee, 0xfe, 0x3b, 0x09, 0x56, - 0x5b, 0xbe, 0x69, 0xfc, 0x1f, 0x64, 0xc7, 0xdd, 0x9e, 0x7e, 0x0e, 0xb7, 0xff, 0x3d, 0x2b, 0x4a, - 0x90, 0x80, 0xed, 0xa8, 0x0d, 0x2b, 0x13, 0x8f, 0x8f, 0x21, 0x44, 0x98, 0xb5, 0xb9, 0x5f, 0x1f, - 0x7f, 0x7e, 0x30, 0xb8, 0xe0, 0x53, 0x58, 0xc8, 0x8c, 0x80, 0x4d, 0xbd, 0x8f, 0x03, 0xfb, 0xfc, - 0x4a, 0xe7, 0xaf, 0x05, 0xf1, 0x7e, 0xde, 0x9a, 0xe1, 0xa1, 0x51, 0x7e, 0xc0, 0x04, 0xf0, 0x19, - 0x85, 0x88, 0x42, 0x70, 0x9c, 0x8c, 0x3e, 0x83, 0x85, 0xae, 0xd1, 0xb9, 0xb0, 0x5d, 0xac, 0x33, - 0xa0, 0x92, 0x66, 0xc7, 0xdc, 0x9d, 0xe5, 0x98, 0x53, 0xce, 0xcf, 0xae, 0x55, 0xec, 0x0e, 0x27, - 0x14, 0x77, 0x98, 0x76, 0x78, 0xc9, 0x5a, 0x9b, 0x6e, 0xb5, 0x19, 0xec, 0x4c, 0x6b, 0x40, 0x69, - 0xb4, 0xbb, 0x1d, 0xb6, 0x91, 0x07, 0x2f, 0xc4, 0x8b, 0x48, 0x74, 0xd7, 0x0c, 0x53, 0xe2, 0x93, - 0x59, 0x94, 0x88, 0x97, 0x1e, 0x71, 0x63, 0x14, 0x4e, 0xd0, 0x90, 0x0f, 0xd7, 0xe9, 0x93, 0x2b, - 0x24, 0x01, 0x36, 0xba, 0xb6, 0x6b, 0x45, 0x27, 0xce, 0xcf, 0x7e, 0xe2, 0x89, 0x67, 0x35, 0x22, - 0x31, 0xd1, 0x89, 0xce, 0x04, 0x4d, 0x2d, 0xc3, 0xc2, 0x88, 0xc1, 0x65, 0x58, 0xa8, 0x9f, 0x35, - 0xf5, 0x07, 0x35, 0xed, 0xf8, 0xe0, 0xb8, 0xb6, 0x2f, 0xcf, 0xa1, 0x05, 0xc8, 0x0f, 0x66, 0x92, - 0x5a, 0x85, 0x62, 0xcc, 0xa0, 0x68, 0x19, 0x8a, 0xad, 0x7a, 0xe3, 0x7e, 0xad, 0x1a, 0xed, 0xa6, - 0xfc, 0x1b, 0xfa, 0xd1, 0xf1, 0xe1, 0x51, 0xf5, 0x7e, 0x4b, 0xdf, 0x92, 0x25, 0x74, 0x0d, 0x16, - 0x63, 0x94, 0x3b, 0x9b, 0x72, 0x4a, 0x7d, 0x6f, 0xb4, 0x16, 0x8b, 0xa3, 0x97, 0x00, 0x4e, 0x5b, - 0x8d, 0xa6, 0x7e, 0xba, 0xdb, 0xac, 0x1e, 0xc9, 0x73, 0x54, 0xf6, 0xee, 0xc9, 0xc9, 0xd9, 0x43, - 0xfd, 0xe4, 0xec, 0xac, 0x51, 0x93, 0x25, 0xf5, 0x10, 0xd0, 0xe4, 0xad, 0xf8, 0x6b, 0x4c, 0xab, - 0xed, 0x9e, 0xea, 0xfb, 0xb5, 0x83, 0xdd, 0xd6, 0x49, 0x53, 0x9e, 0xa3, 0x2f, 0x27, 0x41, 0x3b, - 0xab, 0xcb, 0x12, 0x95, 0x1c, 0x4d, 0x0f, 0x0e, 0xe4, 0xd4, 0xe6, 0x5f, 0x97, 0x00, 0xaa, 0xd4, - 0x74, 0xfc, 0x47, 0xa3, 0x5f, 0x48, 0x50, 0x8c, 0x95, 0x71, 0xb4, 0x91, 0x60, 0xe7, 0x49, 0xe0, - 0x57, 0xba, 0x19, 0xb1, 0xc4, 0x7e, 0xb5, 0x2f, 0x0f, 0x1e, 0x6a, 0x6a, 0xe5, 0x8b, 0x7f, 0xfe, - 0xfb, 0x97, 0xa9, 0x37, 0xd5, 0xb5, 0x4a, 0x7f, 0xa3, 0x22, 0x4a, 0x45, 0x58, 0x79, 0x3c, 0x2c, - 0x23, 0x4f, 0x2a, 0x1c, 0xc7, 0x6c, 0x8b, 0x56, 0xfc, 0x73, 0x09, 0xf2, 0x51, 0x59, 0x47, 0xe5, - 0x04, 0x7d, 0xc6, 0x70, 0x61, 0x69, 0xaa, 0xb6, 0xaf, 0xbe, 0xc3, 0x74, 0xfa, 0x3a, 0x7a, 0x3d, - 0x49, 0xa7, 0xca, 0x63, 0xdb, 0x7c, 0x82, 0x7e, 0x23, 0x01, 0x0c, 0x51, 0x1b, 0x7a, 0x37, 0xe1, - 0x8c, 0x09, 0xa0, 0x59, 0xda, 0x98, 0x81, 0x83, 0xf7, 0x0a, 0x75, 0x9d, 0xa9, 0xa8, 0xa2, 0x44, - 0xb3, 0xa1, 0xdf, 0x52, 0x17, 0x0e, 0x71, 0x5d, 0xb2, 0x0b, 0x27, 0x30, 0xe0, 0x94, 0x56, 0xbb, - 0xcb, 0x54, 0xda, 0x50, 0xdf, 0x9e, 0xca, 0x6a, 0xdb, 0x1d, 0x76, 0xce, 0xb6, 0x74, 0x1b, 0xfd, - 0x59, 0x1a, 0x79, 0x31, 0x44, 0xc8, 0x71, 0x6b, 0xfa, 0x58, 0x1b, 0x6d, 0x43, 0xa5, 0x59, 0xfa, - 0x86, 0x7a, 0x87, 0xa9, 0xfd, 0x8e, 0xaa, 0x3e, 0x5b, 0xed, 0xa8, 0xb1, 0x6e, 0x47, 0x3d, 0x06, - 0xfd, 0x49, 0x1a, 0xbe, 0x39, 0x22, 0x7d, 0xdf, 0x9b, 0x32, 0x16, 0x9f, 0x47, 0x59, 0x61, 0x63, - 0x54, 0x49, 0x56, 0xb6, 0xf2, 0x78, 0xd8, 0x6b, 0x9f, 0xa0, 0xbf, 0xc4, 0x5f, 0x38, 0x11, 0xf2, - 0x40, 0x77, 0xa7, 0x0d, 0xbc, 0x31, 0x98, 0x53, 0xda, 0x9a, 0x9d, 0x51, 0x04, 0xee, 0x6d, 0x76, - 0x83, 0xd7, 0xd0, 0x14, 0xe6, 0xa6, 0xa1, 0x8b, 0x26, 0x81, 0x4c, 0x62, 0x60, 0x3c, 0x13, 0xfb, - 0x94, 0x56, 0x26, 0x30, 0x79, 0xad, 0xeb, 0x93, 0xab, 0xc8, 0xac, 0xb7, 0x67, 0x36, 0xeb, 0x97, - 0x12, 0xa0, 0x49, 0x38, 0x94, 0xa8, 0xe1, 0x33, 0x11, 0xd4, 0x6c, 0xd1, 0xb0, 0xc3, 0xd4, 0xde, - 0xde, 0x9c, 0x55, 0xed, 0x61, 0x1c, 0xff, 0x51, 0x82, 0xe5, 0xb1, 0x4f, 0x91, 0x89, 0x71, 0xfc, - 0xf4, 0x4f, 0x97, 0x49, 0x75, 0xbe, 0xca, 0x74, 0xfd, 0x58, 0xbd, 0x33, 0xab, 0xae, 0x41, 0xcf, - 0xdd, 0x8e, 0x7e, 0xeb, 0xff, 0x15, 0xfb, 0x78, 0x18, 0x7d, 0x7e, 0x4d, 0xac, 0xb4, 0x13, 0x5f, - 0x6a, 0x93, 0x94, 0x7c, 0x9f, 0x29, 0xf9, 0xae, 0xfa, 0xd6, 0x74, 0x25, 0x2c, 0xa0, 0xf2, 0xb7, - 0xa5, 0xdb, 0x7b, 0x97, 0xa0, 0x74, 0xbc, 0x6e, 0x24, 0x7b, 0x44, 0x89, 0xfb, 0xd2, 0x67, 0x87, - 0x82, 0x6e, 0x79, 0x8e, 0xe1, 0x5a, 0x65, 0x2f, 0xb0, 0x2a, 0x16, 0x76, 0x59, 0x08, 0x56, 0xf8, - 0x92, 0xe1, 0xdb, 0xe1, 0x33, 0x3e, 0xb3, 0x7f, 0x38, 0x9c, 0xfd, 0x21, 0x95, 0x3e, 0xac, 0xee, - 0xb5, 0xb3, 0x8c, 0xf3, 0xce, 0x7f, 0x02, 0x00, 0x00, 0xff, 0xff, 0xba, 0xc5, 0x54, 0x96, 0x9f, - 0x1f, 0x00, 0x00, + // 2567 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x5a, 0x5b, 0x73, 0xdb, 0xc6, + 0x15, 0x16, 0x48, 0x8a, 0x97, 0x43, 0x5d, 0xe0, 0x8d, 0xa3, 0x40, 0x74, 0x1c, 0x2b, 0xc8, 0x4d, + 0x71, 0x12, 0x32, 0x92, 0xeb, 0xd8, 0x51, 0x2e, 0xb6, 0x44, 0x51, 0x97, 0x89, 0x4c, 0xb9, 0x20, + 0xe9, 0x4c, 0xd3, 0x76, 0x50, 0x90, 0x58, 0x43, 0xa8, 0x40, 0x00, 0x05, 0x96, 0x6c, 0x94, 0xd4, + 0xd3, 0x36, 0x33, 0xed, 0x6b, 0xdb, 0xe9, 0xf4, 0xa1, 0xd3, 0x87, 0x5e, 0x9e, 0x3b, 0x9d, 0x4e, + 0xfb, 0xd0, 0x99, 0xce, 0xe4, 0xa9, 0x0f, 0xfd, 0x01, 0xfd, 0x0b, 0xfd, 0x21, 0x9d, 0xbd, 0x80, + 0x04, 0x49, 0xbb, 0x20, 0xe2, 0xf6, 0x45, 0xe6, 0x9e, 0xdd, 0xef, 0xec, 0xd9, 0x73, 0xdb, 0x6f, + 0x49, 0x43, 0xd5, 0xf2, 0x3c, 0xcb, 0xc1, 0x35, 0x13, 0x0f, 0x89, 0xe7, 0x39, 0x61, 0xad, 0xe7, + 0x78, 0x03, 0xb3, 0x3b, 0xb0, 0x1d, 0xb3, 0x36, 0xdc, 0x8a, 0x8d, 0xaa, 0x7e, 0xe0, 0x11, 0x0f, + 0x5d, 0xe5, 0xeb, 0xab, 0xd1, 0xfa, 0x6a, 0x6c, 0xc5, 0x70, 0xab, 0xf2, 0xbc, 0x50, 0x67, 0xf8, + 0x76, 0xcd, 0x70, 0x5d, 0x8f, 0x18, 0xc4, 0xf6, 0xdc, 0x90, 0x83, 0x2b, 0xaa, 0x98, 0x65, 0x98, + 0x9a, 0x31, 0x30, 0x6d, 0xc2, 0xff, 0xea, 0x8e, 0x67, 0x89, 0x35, 0x2f, 0x89, 0x35, 0x8e, 0xe7, + 0x5a, 0xc1, 0xc0, 0x75, 0x6d, 0xd7, 0xaa, 0x79, 0x3e, 0x0e, 0x26, 0x14, 0xbd, 0x20, 0x16, 0xb1, + 0x51, 0x77, 0xf0, 0xb0, 0x66, 0x0e, 0xf8, 0x02, 0x31, 0x7f, 0x65, 0x7a, 0x1e, 0xf7, 0x7d, 0x72, + 0x21, 0x26, 0xaf, 0x4d, 0x4f, 0x12, 0xbb, 0x8f, 0x43, 0x62, 0xf4, 0x7d, 0xbe, 0x40, 0xdd, 0x83, + 0x4b, 0x1a, 0x26, 0xc1, 0xc5, 0x1e, 0x3d, 0x95, 0x86, 0xbf, 0x37, 0xc0, 0x21, 0x41, 0x57, 0x01, + 0xfc, 0xc0, 0xfb, 0x2e, 0xee, 0x11, 0xdd, 0x36, 0x15, 0x69, 0x43, 0xda, 0x2c, 0x69, 0x25, 0x21, + 0x39, 0x36, 0xd1, 0x0a, 0x64, 0x6c, 0x53, 0xc9, 0x30, 0x71, 0xc6, 0x36, 0xd5, 0x5f, 0x4b, 0xb0, + 0xa6, 0x0d, 0x5c, 0xa6, 0xa2, 0x1d, 0xd8, 0x96, 0x85, 0x83, 0x39, 0x35, 0x5d, 0x05, 0x20, 0x1c, + 0xa0, 0x8f, 0x34, 0x96, 0x84, 0xe4, 0xd8, 0x44, 0xbb, 0x90, 0x0f, 0xbd, 0x41, 0xd0, 0xc3, 0x4a, + 0x76, 0x43, 0xda, 0x2c, 0x6f, 0xbf, 0x5e, 0xfd, 0xaf, 0x11, 0xa9, 0x6a, 0xd8, 0xf7, 0x5a, 0x0c, + 0xa0, 0x09, 0xa0, 0xaa, 0xc3, 0x72, 0x8b, 0x78, 0x81, 0x61, 0x61, 0x3e, 0x81, 0xd6, 0x20, 0xdf, + 0x1d, 0xf4, 0xce, 0x31, 0x11, 0xd6, 0x88, 0x11, 0x95, 0x7b, 0x5d, 0x6a, 0x96, 0x30, 0x43, 0x8c, + 0xd0, 0x0b, 0x00, 0x16, 0x76, 0x45, 0x4c, 0x98, 0x1d, 0x59, 0x2d, 0x26, 0x51, 0xff, 0x29, 0x01, + 0x8c, 0xf7, 0x4d, 0x3a, 0xf0, 0x15, 0x28, 0x05, 0xd8, 0xf7, 0x74, 0xd7, 0xe8, 0x63, 0xb1, 0x51, + 0x91, 0x0a, 0x9a, 0x46, 0x1f, 0xa3, 0x17, 0xa1, 0xdc, 0x0d, 0x0c, 0xb7, 0x77, 0xc6, 0xa7, 0xe9, + 0x5e, 0xa5, 0xa3, 0x05, 0x0d, 0xb8, 0x90, 0x2d, 0xb9, 0x02, 0x45, 0x62, 0x58, 0x7c, 0x3e, 0x27, + 0xe6, 0x0b, 0xc4, 0xb0, 0xd8, 0xe4, 0x35, 0x80, 0x9e, 0xd7, 0xef, 0xdb, 0x44, 0x0f, 0xcf, 0x0c, + 0x65, 0x51, 0x4c, 0x97, 0xb8, 0xac, 0x75, 0x66, 0x20, 0x19, 0xb2, 0xa6, 0x1d, 0x28, 0x05, 0xb6, + 0x2f, 0xfd, 0xb8, 0x07, 0x50, 0x0c, 0xf0, 0xd0, 0x0e, 0xe9, 0x49, 0xfe, 0x26, 0x41, 0x5e, 0x9c, + 0xa2, 0x03, 0x2b, 0x21, 0xf7, 0x9a, 0x2e, 0x02, 0x90, 0x61, 0x01, 0x78, 0x33, 0x21, 0x00, 0x13, + 0xae, 0x3e, 0x5a, 0xd0, 0x96, 0xc3, 0x09, 0xdf, 0x9f, 0x40, 0x99, 0x9d, 0xfe, 0x2b, 0x06, 0x95, + 0xfa, 0x22, 0x18, 0x8d, 0xf6, 0x8a, 0x51, 0x76, 0xa8, 0x5f, 0x48, 0x00, 0x34, 0xfb, 0xc8, 0x71, + 0xdf, 0xb0, 0x30, 0x42, 0x90, 0x63, 0x0e, 0xe2, 0xde, 0x67, 0x9f, 0x69, 0x78, 0x4d, 0xdb, 0xc2, + 0x21, 0xe1, 0x6e, 0xd5, 0xc4, 0x08, 0x1d, 0x41, 0xd9, 0x1f, 0x84, 0x67, 0x3a, 0xb1, 0xfb, 0xb6, + 0x6b, 0x31, 0x9f, 0x96, 0xb7, 0x5f, 0x4b, 0x30, 0xa9, 0x6d, 0xf7, 0x71, 0xcb, 0x37, 0x5c, 0x0d, + 0x28, 0xb6, 0xcd, 0xa0, 0xea, 0x3f, 0x32, 0x50, 0x62, 0x25, 0xd0, 0x22, 0xd8, 0x7f, 0xac, 0x0d, + 0x32, 0x64, 0xb1, 0x3b, 0x54, 0x32, 0x1b, 0x59, 0xea, 0x7e, 0xec, 0x0e, 0xe9, 0x2a, 0x23, 0xb0, + 0x42, 0x25, 0xcb, 0x44, 0xec, 0x73, 0x14, 0xa4, 0xdc, 0x28, 0x48, 0xa2, 0xde, 0x16, 0xa3, 0x7a, + 0x43, 0xeb, 0x50, 0xfc, 0xbe, 0x61, 0x13, 0xfd, 0xa1, 0x17, 0x28, 0x79, 0x86, 0x2c, 0xd0, 0xf1, + 0x81, 0x17, 0xd0, 0x6c, 0xc5, 0x2e, 0x09, 0x2e, 0x7c, 0xcf, 0x76, 0x89, 0x08, 0x74, 0x4c, 0x42, + 0xd3, 0x33, 0xc4, 0xbd, 0x00, 0x13, 0x9d, 0x5a, 0x52, 0x64, 0xe0, 0x12, 0x97, 0x34, 0xdc, 0x21, + 0xba, 0x03, 0x85, 0xa1, 0xe7, 0x0c, 0xfa, 0x38, 0x54, 0x4a, 0x1b, 0xd9, 0xcd, 0xf2, 0xf6, 0x2b, + 0x09, 0x9e, 0x78, 0xc0, 0x56, 0x6b, 0x11, 0x0a, 0xdd, 0x81, 0xbc, 0xf0, 0x24, 0xa4, 0xf3, 0xa4, + 0x80, 0xa9, 0x6f, 0x43, 0x9e, 0xeb, 0x7c, 0xac, 0x07, 0x11, 0xe4, 0x7c, 0x83, 0x9c, 0x89, 0xca, + 0x61, 0x9f, 0xd5, 0x4f, 0xa1, 0xa0, 0xe1, 0x70, 0xe0, 0x90, 0x90, 0xf6, 0x0b, 0x9b, 0x66, 0x40, + 0xc8, 0x7c, 0x9c, 0x9c, 0x5a, 0xe3, 0x9c, 0xd1, 0x04, 0x10, 0x5d, 0x87, 0x4b, 0x6c, 0x5a, 0x0f, + 0x09, 0xf6, 0x75, 0xa1, 0x8d, 0x87, 0x67, 0xb5, 0x1b, 0x45, 0x97, 0x41, 0x42, 0xf5, 0x17, 0x65, + 0x58, 0x64, 0x11, 0x17, 0x11, 0x92, 0x46, 0x11, 0x9a, 0xec, 0x02, 0xf2, 0x74, 0x17, 0xa8, 0x43, + 0x3e, 0x24, 0x06, 0x19, 0x84, 0xec, 0x20, 0x2b, 0xdb, 0x6f, 0xcc, 0x61, 0xa7, 0x59, 0x6d, 0x31, + 0x88, 0x26, 0xa0, 0xe8, 0x25, 0x58, 0xe6, 0x9f, 0x74, 0x13, 0x13, 0xc3, 0x76, 0x14, 0x85, 0x6d, + 0xb3, 0xc4, 0x85, 0xfb, 0x4c, 0x86, 0x3e, 0x98, 0xea, 0xa0, 0x49, 0xf1, 0x9c, 0xec, 0x9e, 0xe8, + 0x43, 0x58, 0xa4, 0x7e, 0x08, 0x95, 0x32, 0xf3, 0xe7, 0xe6, 0x3c, 0x76, 0x52, 0x07, 0x69, 0x1c, + 0x86, 0xee, 0x42, 0x21, 0xe0, 0xb1, 0x11, 0xf9, 0xf0, 0x6a, 0x62, 0xb1, 0xb3, 0xd5, 0x5a, 0x04, + 0x43, 0xef, 0x41, 0xb9, 0x17, 0x60, 0x83, 0x60, 0x5a, 0xa1, 0x58, 0xc9, 0x33, 0x2d, 0x95, 0x48, + 0x4b, 0x74, 0xad, 0xb1, 0x3c, 0x62, 0xd7, 0x9a, 0x06, 0x7c, 0x39, 0x15, 0xa0, 0x77, 0x01, 0x42, + 0x62, 0x04, 0x84, 0x63, 0x0b, 0x89, 0xd8, 0x12, 0x5b, 0xcd, 0xa0, 0xef, 0x41, 0xf9, 0xa1, 0xed, + 0xda, 0xbc, 0x33, 0x60, 0xa5, 0x98, 0xbc, 0x2f, 0x5f, 0xce, 0xc0, 0x37, 0xa0, 0x40, 0x51, 0xde, + 0x80, 0x28, 0x4b, 0x0c, 0xb8, 0x3e, 0x03, 0xdc, 0x17, 0x97, 0xb8, 0x16, 0xad, 0xa4, 0x1d, 0x4a, + 0xa4, 0xdb, 0x32, 0x4b, 0xb7, 0x28, 0x23, 0xaf, 0x41, 0xd9, 0xf1, 0xac, 0x50, 0x17, 0xb7, 0xd6, + 0x33, 0xbc, 0xa6, 0xa9, 0x68, 0x8f, 0xdf, 0x5c, 0xdf, 0x82, 0x4b, 0x3c, 0x5c, 0xba, 0x1f, 0x78, + 0x43, 0xec, 0x1a, 0x6e, 0x0f, 0x2b, 0xcf, 0xb2, 0x7d, 0x6b, 0x73, 0x85, 0xfb, 0xfe, 0x08, 0xa6, + 0xc9, 0xe1, 0x94, 0x04, 0x6d, 0x82, 0xcc, 0x0b, 0x22, 0x76, 0x51, 0xaf, 0x31, 0x1b, 0x56, 0xba, + 0xb1, 0x0b, 0xff, 0xd8, 0x44, 0x0d, 0x28, 0x78, 0x3e, 0x63, 0x2e, 0xca, 0x73, 0x6c, 0xf7, 0xb9, + 0xd2, 0xfa, 0x94, 0x43, 0xb4, 0x08, 0x8b, 0x9e, 0x83, 0x82, 0xe3, 0x59, 0xfa, 0x20, 0x70, 0x94, + 0x75, 0xde, 0xaa, 0x1d, 0xcf, 0xea, 0x04, 0x0e, 0xfa, 0x36, 0x2c, 0x87, 0x83, 0x6e, 0x48, 0x6c, + 0x32, 0xe0, 0xbb, 0x5c, 0x65, 0x49, 0x79, 0x6b, 0xbe, 0xe2, 0x89, 0x23, 0x1b, 0xb4, 0x21, 0x6a, + 0x93, 0xda, 0x68, 0x6f, 0x21, 0x86, 0x15, 0x2a, 0xd7, 0x78, 0x2f, 0xa6, 0x9f, 0x69, 0x3f, 0xe4, + 0xcd, 0x31, 0x54, 0x36, 0xe6, 0xea, 0x87, 0x2d, 0xb6, 0x5a, 0x8b, 0x50, 0xe8, 0x68, 0xd4, 0x0f, + 0x5f, 0x64, 0xf8, 0xb7, 0xe7, 0x32, 0x96, 0xdf, 0x28, 0xdc, 0x4a, 0x81, 0xaf, 0xdc, 0x05, 0x34, + 0x7b, 0x06, 0x7a, 0x59, 0x9c, 0xe3, 0x0b, 0xd1, 0x79, 0xe8, 0x47, 0x74, 0x19, 0x16, 0x87, 0x86, + 0x33, 0x88, 0xd8, 0x05, 0x1f, 0xec, 0x64, 0x6e, 0x4b, 0x95, 0x2e, 0x94, 0x63, 0x8a, 0x1f, 0x03, + 0xfd, 0x20, 0x0e, 0x4d, 0xd1, 0xbb, 0xc7, 0x7b, 0xa8, 0x3f, 0x84, 0x3c, 0x6f, 0x53, 0x08, 0xc1, + 0x4a, 0xab, 0xbd, 0xdb, 0xee, 0xb4, 0xf4, 0x4e, 0xf3, 0xa3, 0xe6, 0xe9, 0xc7, 0x4d, 0x79, 0x01, + 0x01, 0xe4, 0xbf, 0xde, 0x69, 0x74, 0x1a, 0xfb, 0xb2, 0x84, 0xca, 0x50, 0xf8, 0xf8, 0x54, 0xfb, + 0xe8, 0xb8, 0x79, 0x28, 0x67, 0xe8, 0xa0, 0xd5, 0xa9, 0xd7, 0x1b, 0xad, 0x96, 0x9c, 0xa5, 0x83, + 0x83, 0xdd, 0xe3, 0x93, 0x8e, 0xd6, 0x90, 0x73, 0x54, 0xcd, 0x71, 0xb3, 0xdd, 0xd0, 0x9a, 0xbb, + 0x27, 0x7a, 0x43, 0xd3, 0x4e, 0x35, 0x79, 0x91, 0x2e, 0x68, 0x1f, 0xdf, 0x6b, 0x9c, 0x76, 0xda, + 0x72, 0x1e, 0x2d, 0x43, 0xa9, 0xbe, 0xdb, 0xac, 0x37, 0x4e, 0x4e, 0x1a, 0xfb, 0x72, 0x41, 0xfd, + 0x01, 0x14, 0x23, 0xbb, 0xa6, 0xca, 0x5f, 0x4a, 0x53, 0xfe, 0x37, 0xa1, 0x88, 0x5d, 0x93, 0x03, + 0x33, 0x89, 0xc0, 0x02, 0x76, 0x4d, 0x3a, 0x52, 0xdb, 0xb0, 0x26, 0x92, 0x5a, 0xd0, 0xc3, 0x7b, + 0x98, 0x18, 0xa6, 0x41, 0x0c, 0xb4, 0x03, 0x8b, 0xcc, 0x71, 0xc2, 0x8c, 0x97, 0xe7, 0xc9, 0x03, + 0x8d, 0x43, 0xd4, 0xdf, 0x67, 0x41, 0x9e, 0xae, 0x54, 0x64, 0xc2, 0x73, 0x01, 0x0e, 0x3d, 0x67, + 0x88, 0xe9, 0x5d, 0x35, 0xc1, 0xd5, 0xb2, 0xe9, 0xb9, 0x9a, 0xf6, 0x6c, 0xa4, 0x6c, 0x92, 0x2d, + 0x7f, 0x13, 0x2e, 0x8f, 0x76, 0x89, 0x53, 0xb7, 0x7c, 0x5a, 0x3e, 0x8e, 0x22, 0x35, 0x31, 0xae, + 0xfc, 0x1d, 0xda, 0x63, 0x1d, 0xac, 0x9f, 0x19, 0xe1, 0x19, 0x0e, 0x95, 0x1c, 0xab, 0x90, 0x3b, + 0x29, 0x5b, 0x56, 0xf5, 0xc0, 0x76, 0xf0, 0x11, 0xd3, 0xc0, 0x0b, 0x06, 0x1e, 0x8e, 0x04, 0x95, + 0x33, 0x58, 0x9d, 0x9a, 0x7e, 0x4c, 0xda, 0xdf, 0x99, 0x4c, 0xfb, 0xa4, 0x43, 0x8d, 0x15, 0xc6, + 0x13, 0xbf, 0x09, 0x30, 0x9e, 0x40, 0x77, 0xa1, 0x34, 0x3a, 0x99, 0x22, 0xb1, 0x73, 0xbd, 0x94, + 0xa0, 0x96, 0x22, 0xb5, 0x62, 0x64, 0xbb, 0xfa, 0x23, 0x09, 0x72, 0xf4, 0x03, 0xba, 0x0b, 0x39, + 0x72, 0xe1, 0xf3, 0xf4, 0x5d, 0x49, 0x0c, 0x2a, 0x85, 0xb0, 0x3f, 0xed, 0x0b, 0x1f, 0x6b, 0x0c, + 0x39, 0xd9, 0x11, 0x96, 0x84, 0xd1, 0xea, 0x06, 0x14, 0xa3, 0x75, 0xa8, 0x08, 0xb9, 0xe6, 0x69, + 0xb3, 0xc1, 0x2b, 0xb4, 0x75, 0xb4, 0xbb, 0x7d, 0xf3, 0x1d, 0x59, 0x52, 0xbf, 0xa4, 0xef, 0x01, + 0xd6, 0xc7, 0xd0, 0x06, 0x2c, 0x9d, 0xf7, 0x43, 0xfd, 0x1c, 0x5f, 0xe8, 0x31, 0x4e, 0x06, 0xe7, + 0xfd, 0xf0, 0x23, 0x7c, 0xc1, 0xde, 0x1e, 0xad, 0x09, 0x62, 0x99, 0x65, 0x47, 0xfe, 0xda, 0x5c, + 0xcd, 0x52, 0xfc, 0xd3, 0x70, 0x87, 0x3c, 0x7e, 0x63, 0x3a, 0x5a, 0x79, 0x1f, 0x56, 0x26, 0x27, + 0x93, 0xfa, 0xdd, 0x52, 0x3c, 0x24, 0x1e, 0xa0, 0x3a, 0xe3, 0x02, 0x69, 0xde, 0xb6, 0xa3, 0x3a, + 0xcd, 0xa4, 0xaf, 0xd3, 0xbb, 0xb0, 0x7a, 0x88, 0xc9, 0xd3, 0xbc, 0xa4, 0x7f, 0x2a, 0xc1, 0xa5, + 0x13, 0x3b, 0xe4, 0x3a, 0xc2, 0x39, 0x95, 0x5c, 0x81, 0x92, 0xcf, 0xaa, 0xdf, 0xfe, 0x8c, 0x7b, + 0x61, 0x51, 0x2b, 0x52, 0x41, 0xcb, 0xfe, 0x8c, 0xbf, 0x47, 0xe9, 0x24, 0xf1, 0xce, 0xb1, 0x2b, + 0xde, 0x3e, 0x6c, 0x79, 0x9b, 0x0a, 0x28, 0xe9, 0x78, 0x68, 0x3b, 0x04, 0x07, 0x8c, 0xe1, 0x94, + 0x34, 0x31, 0x52, 0x3f, 0x03, 0x14, 0xb7, 0x23, 0xf4, 0x3d, 0x37, 0xc4, 0xe8, 0x7d, 0xfa, 0x76, + 0xa6, 0x12, 0x91, 0xd3, 0xf3, 0x79, 0x47, 0x60, 0xd0, 0xab, 0xb0, 0xea, 0xe2, 0x4f, 0x89, 0x1e, + 0xb3, 0x87, 0x9f, 0x7c, 0x99, 0x8a, 0xef, 0x47, 0x36, 0xa9, 0x75, 0x40, 0x75, 0x5a, 0xd9, 0xce, + 0xd3, 0x78, 0xf2, 0x27, 0x39, 0x58, 0x8a, 0x7f, 0x21, 0x31, 0x43, 0xd1, 0x37, 0xa0, 0x6c, 0xe2, + 0xb0, 0x17, 0xd8, 0x8c, 0x76, 0x30, 0x7a, 0x5a, 0xd2, 0xe2, 0x22, 0xd4, 0x06, 0x39, 0xe2, 0x3c, + 0x04, 0xf7, 0x7d, 0xc7, 0x20, 0x11, 0x87, 0x4c, 0xd1, 0xf7, 0x56, 0x85, 0x8a, 0xb6, 0xd0, 0x80, + 0xde, 0x8f, 0x12, 0x2c, 0x37, 0x7f, 0x82, 0x1d, 0x2d, 0x88, 0x14, 0x43, 0xcf, 0x03, 0x6b, 0x11, + 0xac, 0x08, 0x8b, 0xe2, 0x81, 0x3f, 0x92, 0x4c, 0x93, 0xe5, 0xc5, 0x54, 0x64, 0xb9, 0x02, 0x45, + 0xd3, 0x0e, 0x8d, 0xae, 0x83, 0x4d, 0xa5, 0xb4, 0x21, 0x6d, 0x16, 0xb5, 0xd1, 0x18, 0x99, 0xd3, + 0xd4, 0x8b, 0xbf, 0x07, 0x3e, 0x9c, 0xc7, 0x78, 0x11, 0x80, 0x64, 0x06, 0xf6, 0xf4, 0x14, 0x67, + 0x4f, 0x86, 0x15, 0x41, 0x56, 0x85, 0xbb, 0xd5, 0x1f, 0x4b, 0xb0, 0x1e, 0xeb, 0x02, 0xe9, 0xbe, + 0x9e, 0x6a, 0x40, 0x41, 0x84, 0x4f, 0xb4, 0x83, 0x37, 0x52, 0x1c, 0x58, 0x8b, 0xb0, 0xea, 0x03, + 0x58, 0x8b, 0xfa, 0xc2, 0xff, 0xf2, 0xeb, 0x31, 0xf5, 0x5d, 0x50, 0x46, 0x45, 0x2a, 0x14, 0xcf, + 0xd9, 0x33, 0x54, 0x13, 0xd6, 0x1f, 0x03, 0x15, 0x65, 0x7e, 0x08, 0x45, 0xb1, 0x49, 0x54, 0xe8, + 0xa9, 0xce, 0x3d, 0x02, 0xab, 0xdf, 0x80, 0xf5, 0x7d, 0xec, 0xe0, 0xaf, 0xe4, 0xfb, 0x84, 0xb3, + 0xff, 0x4e, 0x82, 0xf5, 0x8e, 0x6f, 0x1a, 0xff, 0x07, 0xdd, 0xf1, 0xb0, 0x67, 0x9f, 0x22, 0xec, + 0x7f, 0xcf, 0x8b, 0x16, 0x24, 0x9e, 0x38, 0xa8, 0x0b, 0x6b, 0x33, 0x0f, 0xb5, 0x31, 0x45, 0x48, + 0x7b, 0xb9, 0x5f, 0x9e, 0x7e, 0xaa, 0x31, 0xba, 0xe0, 0x53, 0x5a, 0xc8, 0x9c, 0x80, 0x4d, 0x7d, + 0x88, 0x03, 0xfb, 0xe1, 0x85, 0xce, 0x5f, 0x56, 0xe2, 0xbb, 0x86, 0xdb, 0x29, 0x1e, 0x65, 0xd5, + 0x07, 0x4c, 0x01, 0x1f, 0x51, 0x8a, 0x28, 0x14, 0xc7, 0xc5, 0xe8, 0x13, 0x58, 0xea, 0x1b, 0xbd, + 0x33, 0xdb, 0xc5, 0x3a, 0x23, 0x2a, 0x59, 0xb6, 0xcd, 0xad, 0x34, 0xdb, 0xdc, 0xe3, 0x78, 0x76, + 0xac, 0x72, 0x7f, 0x3c, 0xa0, 0xbc, 0xc3, 0xb4, 0xc3, 0x73, 0x76, 0xb5, 0xe9, 0x56, 0x97, 0xd1, + 0xce, 0xac, 0x06, 0x54, 0x46, 0x6f, 0xb7, 0xc3, 0x2e, 0xf2, 0xe0, 0x99, 0x78, 0x13, 0x89, 0xce, + 0x9a, 0x63, 0x46, 0x7c, 0x98, 0xc6, 0x88, 0x78, 0xeb, 0x11, 0x27, 0x46, 0xe1, 0x8c, 0x0c, 0xf9, + 0x70, 0x99, 0x3e, 0x4f, 0x43, 0x12, 0x60, 0x83, 0x3e, 0xa6, 0xa2, 0x1d, 0x17, 0xd3, 0xef, 0x78, + 0xe2, 0x59, 0xad, 0x48, 0x4d, 0xb4, 0xa3, 0x33, 0x23, 0x53, 0xab, 0xb0, 0x34, 0xe1, 0x70, 0x19, + 0x96, 0x9a, 0xa7, 0x6d, 0xfd, 0x41, 0x43, 0x3b, 0x3e, 0x38, 0x6e, 0xec, 0xcb, 0x0b, 0x68, 0x09, + 0x8a, 0xa3, 0x91, 0xa4, 0xd6, 0xa1, 0x1c, 0x73, 0x28, 0x5a, 0x85, 0x72, 0xa7, 0xd9, 0xba, 0xdf, + 0xa8, 0x47, 0xab, 0x29, 0x7e, 0x4b, 0x3f, 0x3a, 0x3e, 0x3c, 0xaa, 0xdf, 0xef, 0xe8, 0xb7, 0x65, + 0x09, 0x5d, 0x82, 0xe5, 0x98, 0xe4, 0xc6, 0xb6, 0x9c, 0x51, 0x6f, 0x4e, 0xf6, 0x62, 0xb1, 0xf5, + 0x0a, 0xc0, 0xbd, 0x4e, 0xab, 0xad, 0xdf, 0xdb, 0x6d, 0xd7, 0x8f, 0xe4, 0x05, 0xaa, 0x7b, 0xf7, + 0xe4, 0xe4, 0xf4, 0x63, 0xfd, 0xe4, 0xf4, 0xb4, 0xd5, 0x90, 0x25, 0xf5, 0x10, 0xd0, 0xec, 0xa9, + 0xf8, 0x5b, 0x50, 0x6b, 0xec, 0xde, 0xd3, 0xf7, 0x1b, 0x07, 0xbb, 0x9d, 0x93, 0xb6, 0xbc, 0x40, + 0xdf, 0x6d, 0x42, 0x76, 0xda, 0x94, 0x25, 0xaa, 0x39, 0x1a, 0x1e, 0x1c, 0xc8, 0x99, 0xed, 0xbf, + 0xae, 0x00, 0xd4, 0xa9, 0xeb, 0xf8, 0x17, 0x6c, 0x3f, 0x97, 0xa0, 0x1c, 0x6b, 0xe3, 0x68, 0x2b, + 0xc1, 0xcf, 0xb3, 0xc4, 0xaf, 0x72, 0x35, 0x82, 0xc4, 0x7e, 0x6d, 0xa9, 0x8e, 0x1e, 0x6a, 0x6a, + 0xed, 0x8b, 0x7f, 0xfd, 0xfb, 0x97, 0x99, 0xd7, 0xd5, 0x8d, 0xda, 0x70, 0xab, 0x26, 0x5a, 0x45, + 0x58, 0xfb, 0x7c, 0xdc, 0x46, 0x1e, 0xd5, 0x38, 0x8f, 0xd9, 0x11, 0x57, 0xf1, 0xcf, 0x24, 0x28, + 0x46, 0x6d, 0x1d, 0x55, 0x13, 0xec, 0x99, 0xe2, 0x85, 0x95, 0xb9, 0xae, 0x7d, 0xf5, 0x2d, 0x66, + 0xd3, 0x6b, 0xe8, 0x95, 0x24, 0x9b, 0x6a, 0x9f, 0xdb, 0xe6, 0x23, 0xf4, 0x1b, 0x09, 0x60, 0xcc, + 0xda, 0x50, 0xd2, 0x77, 0x0d, 0x33, 0x44, 0xb3, 0xb2, 0x95, 0x02, 0xc1, 0xef, 0x0a, 0x75, 0x93, + 0x99, 0xa8, 0xa2, 0x44, 0xb7, 0xa1, 0xdf, 0xd2, 0x10, 0x8e, 0x79, 0x5d, 0x72, 0x08, 0x67, 0x38, + 0xe0, 0x9c, 0x5e, 0xbb, 0xc5, 0x4c, 0xda, 0x52, 0xdf, 0x9c, 0xcb, 0x6b, 0x3b, 0x3d, 0xb6, 0xcf, + 0x8e, 0x74, 0x1d, 0xfd, 0x8a, 0xfd, 0x94, 0x13, 0xfd, 0x18, 0x96, 0xe8, 0xbf, 0x99, 0xdf, 0xcd, + 0x92, 0x52, 0xec, 0x1d, 0x66, 0xd8, 0xdb, 0xea, 0x1b, 0xf3, 0x19, 0x16, 0x50, 0xfd, 0xd4, 0xae, + 0x3f, 0x4b, 0x13, 0x2f, 0x99, 0x88, 0xd1, 0xde, 0x9e, 0xbf, 0x06, 0x26, 0xaf, 0xc7, 0x4a, 0x9a, + 0xfb, 0x4c, 0xbd, 0xc1, 0xac, 0x7e, 0x4b, 0x55, 0x9f, 0x6c, 0x75, 0x74, 0xe1, 0xef, 0x44, 0x77, + 0x1f, 0xfa, 0x93, 0x34, 0x7e, 0x0b, 0x45, 0xf6, 0xde, 0x9c, 0xb3, 0x46, 0x9e, 0xc6, 0x58, 0x11, + 0x7b, 0x54, 0x4b, 0x36, 0xb6, 0xf6, 0xf9, 0x98, 0x03, 0x3c, 0x42, 0x7f, 0x89, 0xbf, 0xbc, 0x22, + 0x46, 0x84, 0x6e, 0xcd, 0x5b, 0x10, 0x53, 0xf4, 0xab, 0x72, 0x3b, 0x3d, 0x50, 0x14, 0xd4, 0x75, + 0x76, 0x82, 0x97, 0xd1, 0x1c, 0xee, 0xa6, 0x25, 0x85, 0x66, 0x09, 0x56, 0x62, 0x62, 0x3c, 0x91, + 0x93, 0x55, 0xd6, 0x66, 0xde, 0x0a, 0x8d, 0xbe, 0x4f, 0x2e, 0x22, 0xb7, 0x5e, 0x4f, 0xed, 0xd6, + 0x2f, 0x25, 0x40, 0xb3, 0x34, 0x2d, 0xd1, 0xc2, 0x27, 0x32, 0xbb, 0x74, 0xd9, 0x70, 0x97, 0x99, + 0xbd, 0xb3, 0x9d, 0xd6, 0xec, 0x71, 0x1e, 0xff, 0x51, 0x82, 0xd5, 0xa9, 0x9f, 0xb6, 0x13, 0xf3, + 0xf8, 0xf1, 0x3f, 0x85, 0x27, 0x35, 0x87, 0x3a, 0xb3, 0xf5, 0x03, 0xf5, 0x46, 0x5a, 0x5b, 0x83, + 0x81, 0xbb, 0x23, 0x7e, 0xaf, 0xd9, 0x3b, 0x07, 0xa5, 0xe7, 0xf5, 0xa3, 0x8d, 0x26, 0xcc, 0xba, + 0x2f, 0x7d, 0x72, 0x28, 0xe4, 0x96, 0xe7, 0x18, 0xae, 0x55, 0xf5, 0x02, 0xab, 0x66, 0x61, 0x97, + 0x85, 0xba, 0xc6, 0xa7, 0x0c, 0xdf, 0x0e, 0x9f, 0xf0, 0xdf, 0x23, 0xde, 0x1b, 0x8f, 0xfe, 0x90, + 0xc9, 0x1e, 0xd6, 0xf7, 0xba, 0x79, 0x86, 0xbc, 0xf1, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x17, + 0x08, 0x55, 0x51, 0x57, 0x21, 0x00, 0x00, } diff --git a/vendor/google.golang.org/genproto/googleapis/devtools/clouddebugger/v2/controller.pb.go b/vendor/google.golang.org/genproto/googleapis/devtools/clouddebugger/v2/controller.pb.go index 1e54c283d1a035f4b1348b10f6d26ba3bb1512e1..558f6fb432b31922c1e4141a8508e13223403572 100644 --- a/vendor/google.golang.org/genproto/googleapis/devtools/clouddebugger/v2/controller.pb.go +++ b/vendor/google.golang.org/genproto/googleapis/devtools/clouddebugger/v2/controller.pb.go @@ -434,42 +434,43 @@ var _Controller2_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("google/devtools/clouddebugger/v2/controller.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 589 bytes of a gzipped FileDescriptorProto + // 602 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0xdd, 0x6a, 0xd4, 0x40, - 0x14, 0x66, 0x5a, 0x94, 0xf6, 0x44, 0x69, 0x19, 0x50, 0x43, 0x6c, 0x75, 0x1b, 0xa4, 0x94, 0x5a, - 0x32, 0x18, 0xbd, 0x71, 0x05, 0x7f, 0xb6, 0x6a, 0x11, 0x5a, 0x2d, 0x4b, 0x55, 0xf0, 0x66, 0xc9, - 0x26, 0xc7, 0x30, 0x34, 0x9d, 0x89, 0x99, 0xc9, 0x5a, 0x29, 0xbd, 0xf1, 0x56, 0xf1, 0xc6, 0x47, - 0xf0, 0xce, 0x17, 0x10, 0x7c, 0x0d, 0x7d, 0x04, 0xaf, 0x7c, 0x0a, 0xc9, 0xdf, 0xee, 0xf6, 0x67, - 0x9b, 0x76, 0xf1, 0x32, 0xdf, 0x9c, 0xef, 0x3b, 0xdf, 0x37, 0x39, 0x73, 0xe0, 0x56, 0x28, 0x65, - 0x18, 0x21, 0x0b, 0xb0, 0xa7, 0xa5, 0x8c, 0x14, 0xf3, 0x23, 0x99, 0x06, 0x01, 0x76, 0xd3, 0x30, - 0xc4, 0x84, 0xf5, 0x5c, 0xe6, 0x4b, 0xa1, 0x13, 0x19, 0x45, 0x98, 0x38, 0x71, 0x22, 0xb5, 0xa4, - 0x8d, 0x82, 0xe2, 0x54, 0x14, 0xe7, 0x00, 0xc5, 0xe9, 0xb9, 0xd6, 0x5c, 0x29, 0xea, 0xc5, 0x9c, - 0x79, 0x42, 0x48, 0xed, 0x69, 0x2e, 0x85, 0x2a, 0xf8, 0xd6, 0xcd, 0xda, 0x96, 0x81, 0xa7, 0xbd, - 0xb2, 0xf8, 0x6a, 0x59, 0x9c, 0x7f, 0x75, 0xd3, 0xb7, 0x0c, 0x77, 0x62, 0xfd, 0xa1, 0x38, 0xb4, - 0x3d, 0xb8, 0xd2, 0xc6, 0x90, 0x2b, 0x8d, 0xc9, 0xe3, 0x82, 0x8e, 0x6d, 0x7c, 0x97, 0xa2, 0xd2, - 0xf4, 0x29, 0x4c, 0x95, 0x8a, 0x68, 0x92, 0x06, 0x59, 0x32, 0xdc, 0x65, 0xa7, 0xce, 0xb7, 0xd3, - 0x17, 0xe9, 0x73, 0xed, 0x2e, 0x98, 0x47, 0x5b, 0xa8, 0x58, 0x0a, 0x85, 0xff, 0xad, 0xc7, 0x67, - 0x02, 0x73, 0xeb, 0x5c, 0xe9, 0x47, 0xbe, 0xe6, 0x3d, 0x6c, 0x25, 0xe8, 0x6d, 0xc7, 0x92, 0x0b, - 0xad, 0xaa, 0x30, 0xd7, 0xc1, 0xa8, 0x8a, 0x3b, 0x3c, 0xc8, 0x7b, 0x4d, 0xb7, 0xa1, 0x82, 0x9e, - 0x05, 0x74, 0x1e, 0xe0, 0xbd, 0xc7, 0x75, 0x47, 0xcb, 0x6d, 0x14, 0xe6, 0x44, 0x7e, 0x3e, 0x9d, - 0x21, 0x5b, 0x19, 0x40, 0x57, 0x80, 0xaa, 0xd4, 0xf7, 0x51, 0xa9, 0x8e, 0x14, 0x1d, 0xcd, 0x77, - 0x50, 0xa6, 0xda, 0x9c, 0x6c, 0x90, 0xa5, 0xa9, 0xf6, 0x6c, 0x79, 0xf2, 0x42, 0x6c, 0x15, 0xb8, - 0xfd, 0x93, 0xc0, 0xfc, 0x08, 0x3b, 0x65, 0xf0, 0xe7, 0x60, 0x74, 0x07, 0xb0, 0x49, 0x1a, 0x93, - 0x4b, 0x86, 0xbb, 0x52, 0x9f, 0x7d, 0xa0, 0xd5, 0x1e, 0x16, 0xa0, 0x8b, 0x30, 0x23, 0x70, 0x57, - 0x77, 0x8e, 0x64, 0xb8, 0x98, 0xc1, 0xaf, 0xfb, 0x39, 0x16, 0xe0, 0x42, 0x5e, 0x82, 0xbb, 0x31, - 0x4f, 0x30, 0x28, 0x13, 0x18, 0x19, 0xf6, 0xa4, 0x80, 0xec, 0x2f, 0x04, 0xe6, 0x5f, 0xc6, 0x81, - 0xa7, 0xf1, 0xb0, 0xfd, 0x53, 0x5f, 0xe6, 0x3a, 0xc0, 0xc0, 0x5c, 0x6e, 0xe4, 0xac, 0xe1, 0x86, - 0xf8, 0x76, 0x03, 0xae, 0x8d, 0xf2, 0x53, 0xdc, 0xa6, 0xfb, 0xe9, 0x1c, 0x18, 0xab, 0xfd, 0x47, - 0xe6, 0xd2, 0x1f, 0x04, 0x66, 0x0f, 0xcf, 0x1c, 0xbd, 0x5b, 0x6f, 0x60, 0xc4, 0x53, 0xb0, 0x9a, - 0xe3, 0x50, 0x0b, 0x6f, 0xf6, 0xca, 0xc7, 0x5f, 0x7f, 0xbe, 0x4e, 0x2c, 0xda, 0x0b, 0x07, 0x37, - 0x01, 0xab, 0xae, 0x4b, 0xb1, 0xa4, 0xa4, 0x36, 0xc9, 0x32, 0xfd, 0x4d, 0xe0, 0xd2, 0xb1, 0x93, - 0x43, 0xef, 0xd7, 0x7b, 0x38, 0xe9, 0x05, 0x58, 0x0f, 0xc6, 0xe6, 0x97, 0x41, 0x9a, 0x79, 0x90, - 0x3b, 0xd4, 0x1d, 0x19, 0x64, 0x6f, 0x68, 0x2a, 0xf6, 0xd9, 0xf0, 0x78, 0xfe, 0x25, 0x70, 0xf9, - 0xf8, 0x7f, 0x48, 0x4f, 0xe1, 0xeb, 0xc4, 0x69, 0xb4, 0x1e, 0x8e, 0x2f, 0x50, 0x26, 0xdb, 0xc8, - 0x93, 0xad, 0x59, 0xad, 0xb3, 0x27, 0x63, 0x7b, 0x83, 0x0f, 0x87, 0x07, 0xfb, 0x4d, 0xb2, 0xdc, - 0xfa, 0x46, 0xe0, 0x86, 0x2f, 0x77, 0x6a, 0x6d, 0xb5, 0x66, 0x06, 0x33, 0xbb, 0x99, 0x6d, 0xe3, - 0x4d, 0xf2, 0x66, 0xa3, 0x24, 0x85, 0x32, 0xf2, 0x44, 0xe8, 0xc8, 0x24, 0x64, 0x21, 0x8a, 0x7c, - 0x57, 0xb3, 0xe2, 0xc8, 0x8b, 0xb9, 0x1a, 0xbd, 0xf8, 0xef, 0x1d, 0x00, 0xbe, 0x4f, 0x98, 0x6b, - 0x85, 0xde, 0x6a, 0x06, 0x57, 0x9b, 0x33, 0x71, 0x5e, 0xb9, 0xdd, 0xf3, 0xb9, 0xe8, 0xed, 0x7f, - 0x01, 0x00, 0x00, 0xff, 0xff, 0x05, 0xef, 0x37, 0xb4, 0xbf, 0x06, 0x00, 0x00, + 0x14, 0x66, 0x5a, 0x94, 0x76, 0xa2, 0xb4, 0x0c, 0xa8, 0x21, 0xb6, 0xba, 0x0d, 0x52, 0x96, 0x75, + 0xc9, 0x60, 0xf4, 0xc6, 0x15, 0xfc, 0xd9, 0xaa, 0x45, 0x68, 0xb5, 0x2c, 0xb5, 0x82, 0x2c, 0x2c, + 0xd9, 0xe4, 0x18, 0x86, 0x66, 0x67, 0x62, 0x66, 0xb2, 0x56, 0x4a, 0x6f, 0xbc, 0x55, 0xbc, 0xf1, + 0x2d, 0x7c, 0x01, 0xc1, 0x0b, 0x1f, 0xc0, 0x5b, 0x7d, 0x04, 0xaf, 0x7c, 0x0a, 0xc9, 0xdf, 0xfe, + 0xb4, 0xdd, 0xa6, 0x5d, 0xbc, 0xcc, 0x77, 0xe6, 0xfb, 0xce, 0xf7, 0x4d, 0xce, 0x1c, 0x7c, 0xcb, + 0x17, 0xc2, 0x0f, 0x80, 0x7a, 0xd0, 0x57, 0x42, 0x04, 0x92, 0xba, 0x81, 0x88, 0x3d, 0x0f, 0xba, + 0xb1, 0xef, 0x43, 0x44, 0xfb, 0x36, 0x75, 0x05, 0x57, 0x91, 0x08, 0x02, 0x88, 0xac, 0x30, 0x12, + 0x4a, 0x90, 0x4a, 0x46, 0xb1, 0x0a, 0x8a, 0x35, 0x46, 0xb1, 0xfa, 0xb6, 0xb1, 0x94, 0x8b, 0x3a, + 0x21, 0xa3, 0x0e, 0xe7, 0x42, 0x39, 0x8a, 0x09, 0x2e, 0x33, 0xbe, 0x71, 0xb3, 0xb4, 0xa5, 0xe7, + 0x28, 0x27, 0x3f, 0x7c, 0x35, 0x3f, 0x9c, 0x7e, 0x75, 0xe3, 0x37, 0x14, 0x7a, 0xa1, 0x7a, 0x9f, + 0x15, 0x4d, 0x07, 0x5f, 0x69, 0x81, 0xcf, 0xa4, 0x82, 0xe8, 0x71, 0x46, 0x87, 0x16, 0xbc, 0x8d, + 0x41, 0x2a, 0xf2, 0x14, 0xcf, 0xe5, 0x8a, 0xa0, 0xa3, 0x0a, 0xaa, 0x6a, 0x76, 0xcd, 0x2a, 0xf3, + 0x6d, 0x0d, 0x44, 0x06, 0x5c, 0xb3, 0x8b, 0xf5, 0xa3, 0x2d, 0x64, 0x28, 0xb8, 0x84, 0xff, 0xd6, + 0xe3, 0x13, 0xc2, 0x4b, 0x1b, 0x4c, 0xaa, 0x47, 0xae, 0x62, 0x7d, 0x68, 0x46, 0xe0, 0xec, 0x86, + 0x82, 0x71, 0x25, 0x8b, 0x30, 0xd7, 0xb1, 0x56, 0x1c, 0xee, 0x30, 0x2f, 0xed, 0x35, 0xdf, 0xc2, + 0x05, 0xf4, 0xcc, 0x23, 0xcb, 0x18, 0xbf, 0x73, 0x98, 0xea, 0x28, 0xb1, 0x0b, 0x5c, 0x9f, 0x49, + 0xeb, 0xf3, 0x09, 0xb2, 0x9d, 0x00, 0xa4, 0x8e, 0x89, 0x8c, 0x5d, 0x17, 0xa4, 0xec, 0x08, 0xde, + 0x51, 0xac, 0x07, 0x22, 0x56, 0xfa, 0x6c, 0x05, 0x55, 0xe7, 0x5a, 0x8b, 0x79, 0xe5, 0x05, 0xdf, + 0xce, 0x70, 0xf3, 0x3b, 0xc2, 0xcb, 0x13, 0xec, 0xe4, 0xc1, 0x9f, 0x63, 0xad, 0x3b, 0x84, 0x75, + 0x54, 0x99, 0xad, 0x6a, 0x76, 0xbd, 0x3c, 0xfb, 0x50, 0xab, 0x35, 0x2a, 0x40, 0x56, 0xf1, 0x02, + 0x87, 0x3d, 0xd5, 0x39, 0x92, 0xe1, 0x62, 0x02, 0xbf, 0x1a, 0xe4, 0x58, 0xc1, 0x17, 0xd2, 0x23, + 0xb0, 0x17, 0xb2, 0x08, 0xbc, 0x3c, 0x81, 0x96, 0x60, 0x4f, 0x32, 0xc8, 0xfc, 0x8c, 0xf0, 0xf2, + 0xcb, 0xd0, 0x73, 0x14, 0x1c, 0xb6, 0x7f, 0xea, 0xcb, 0xdc, 0xc0, 0x78, 0x68, 0x2e, 0x35, 0x72, + 0xd6, 0x70, 0x23, 0x7c, 0xb3, 0x82, 0xaf, 0x4d, 0xf2, 0x93, 0xdd, 0xa6, 0xfd, 0xf1, 0x1c, 0xd6, + 0xd6, 0x06, 0x8f, 0xcc, 0x26, 0xdf, 0x10, 0x5e, 0x3c, 0x3c, 0x73, 0xe4, 0x6e, 0xb9, 0x81, 0x09, + 0x4f, 0xc1, 0x68, 0x4c, 0x43, 0xcd, 0xbc, 0x99, 0xf5, 0x0f, 0xbf, 0xfe, 0x7c, 0x99, 0x59, 0x35, + 0x57, 0xc6, 0x37, 0x01, 0x2d, 0xae, 0x4b, 0xd2, 0x28, 0xa7, 0x36, 0x50, 0x8d, 0xfc, 0x46, 0xf8, + 0xd2, 0xb1, 0x93, 0x43, 0xee, 0x97, 0x7b, 0x38, 0xe9, 0x05, 0x18, 0x0f, 0xa6, 0xe6, 0xe7, 0x41, + 0x1a, 0x69, 0x90, 0x3b, 0xc4, 0x9e, 0x18, 0x64, 0x7f, 0x64, 0x2a, 0x0e, 0xe8, 0xe8, 0x78, 0xfe, + 0x45, 0xf8, 0xf2, 0xf1, 0xff, 0x90, 0x9c, 0xc2, 0xd7, 0x89, 0xd3, 0x68, 0x3c, 0x9c, 0x5e, 0x20, + 0x4f, 0xb6, 0x99, 0x26, 0x5b, 0x37, 0x9a, 0x67, 0x4f, 0x46, 0xf7, 0x87, 0x1f, 0x16, 0xf3, 0x0e, + 0x1a, 0xa8, 0xd6, 0xfc, 0x81, 0xf0, 0x0d, 0x57, 0xf4, 0x4a, 0x6d, 0x35, 0x17, 0x86, 0x33, 0xbb, + 0x95, 0x6c, 0xe3, 0x2d, 0xf4, 0x7a, 0x33, 0x27, 0xf9, 0x22, 0x70, 0xb8, 0x6f, 0x89, 0xc8, 0xa7, + 0x3e, 0xf0, 0x74, 0x57, 0xd3, 0xac, 0xe4, 0x84, 0x4c, 0x4e, 0x5e, 0xfc, 0xf7, 0xc6, 0x80, 0xaf, + 0x33, 0xfa, 0x7a, 0xa6, 0xb7, 0x96, 0xc0, 0xc5, 0xe6, 0x8c, 0xac, 0x1d, 0xfb, 0x67, 0x51, 0x6a, + 0xa7, 0xa5, 0x76, 0x51, 0x6a, 0xef, 0xd8, 0xdd, 0xf3, 0x69, 0xbf, 0xdb, 0xff, 0x02, 0x00, 0x00, + 0xff, 0xff, 0x54, 0xe1, 0x5c, 0x2a, 0xda, 0x06, 0x00, 0x00, } diff --git a/vendor/google.golang.org/genproto/googleapis/devtools/clouddebugger/v2/data.pb.go b/vendor/google.golang.org/genproto/googleapis/devtools/clouddebugger/v2/data.pb.go index b41e215e813b23cf16ddbf6fa4ddb1327e76bf7a..b280628d6c21cacb64a5c22613cd11173b2ad888 100644 --- a/vendor/google.golang.org/genproto/googleapis/devtools/clouddebugger/v2/data.pb.go +++ b/vendor/google.golang.org/genproto/googleapis/devtools/clouddebugger/v2/data.pb.go @@ -806,84 +806,85 @@ func init() { func init() { proto.RegisterFile("google/devtools/clouddebugger/v2/data.proto", fileDescriptor1) } var fileDescriptor1 = []byte{ - // 1251 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x57, 0xdd, 0x72, 0xda, 0x46, - 0x14, 0x0e, 0x3f, 0x06, 0xe9, 0x60, 0x30, 0xd9, 0x26, 0x1d, 0xc5, 0x4d, 0x1d, 0x86, 0xe6, 0xc2, - 0xd3, 0x66, 0x20, 0x21, 0xd3, 0x4e, 0xd2, 0x5c, 0x61, 0x2c, 0xbb, 0x4c, 0x08, 0x90, 0xc5, 0xa6, - 0x9d, 0xde, 0xa8, 0x6b, 0xb4, 0xa8, 0x6a, 0x84, 0xa4, 0xee, 0x2e, 0xd4, 0xb9, 0xcf, 0x63, 0xb4, - 0x2f, 0xd0, 0xe9, 0x3b, 0xf5, 0xae, 0xcf, 0xd1, 0xd9, 0xd5, 0x8a, 0x88, 0xa4, 0x2d, 0x71, 0x93, - 0xbb, 0xb3, 0xdf, 0x7e, 0xe7, 0x5b, 0x71, 0xf6, 0x3b, 0x47, 0x02, 0xbe, 0xf0, 0xa2, 0xc8, 0x0b, - 0x68, 0xdb, 0xa5, 0x2b, 0x11, 0x45, 0x01, 0x6f, 0xcf, 0x82, 0x68, 0xe9, 0xba, 0xf4, 0x62, 0xe9, - 0x79, 0x94, 0xb5, 0x57, 0x9d, 0xb6, 0x4b, 0x04, 0x69, 0xc5, 0x2c, 0x12, 0x11, 0x6a, 0x24, 0xe4, - 0x56, 0x4a, 0x6e, 0x6d, 0x90, 0x5b, 0xab, 0xce, 0xfe, 0x6d, 0x2d, 0x47, 0x62, 0xbf, 0x4d, 0xc2, - 0x30, 0x12, 0x44, 0xf8, 0x51, 0xc8, 0x93, 0xfc, 0xfd, 0xd6, 0x9b, 0x87, 0xf1, 0x68, 0xc9, 0x66, - 0xb4, 0xbd, 0x7a, 0xa0, 0x23, 0x67, 0x16, 0x85, 0x82, 0x5e, 0x0a, 0xcd, 0xbf, 0xa3, 0xf9, 0x6a, - 0x75, 0xb1, 0x9c, 0xb7, 0x85, 0xbf, 0xa0, 0x5c, 0x90, 0x45, 0xac, 0x09, 0x07, 0x6f, 0x12, 0x7e, - 0x61, 0x24, 0x8e, 0x29, 0xd3, 0x07, 0x36, 0x4f, 0xa1, 0x7a, 0x12, 0xb1, 0x05, 0x11, 0xcf, 0x28, - 0xe7, 0xc4, 0xa3, 0xe8, 0x63, 0x28, 0xcd, 0x15, 0x60, 0xe5, 0x1a, 0xb9, 0x43, 0x13, 0xeb, 0x15, - 0x3a, 0x00, 0x88, 0x09, 0x23, 0x0b, 0x2a, 0x28, 0xe3, 0x56, 0xbe, 0x51, 0x38, 0x34, 0x71, 0x06, - 0x69, 0xbe, 0x2a, 0x40, 0x75, 0x22, 0x88, 0x58, 0xf2, 0x54, 0xe9, 0x16, 0x18, 0x3e, 0x77, 0x28, - 0x63, 0x11, 0x53, 0x5a, 0x06, 0x2e, 0xfb, 0xdc, 0x96, 0x4b, 0x34, 0x05, 0x93, 0xd1, 0x39, 0x65, - 0xdc, 0x11, 0x91, 0x95, 0x6f, 0xe4, 0x0e, 0x6b, 0x9d, 0xc7, 0xad, 0x6d, 0xa5, 0x6b, 0x6d, 0xc8, - 0xb7, 0xb0, 0x14, 0xa0, 0xe1, 0x8c, 0x62, 0x23, 0xd1, 0x3a, 0x8b, 0xd0, 0x73, 0xa8, 0xb8, 0x94, - 0xcf, 0x98, 0x1f, 0xcb, 0xa2, 0x5a, 0x85, 0x46, 0xee, 0xb0, 0xd2, 0x69, 0x6f, 0x57, 0xde, 0x28, - 0x01, 0xce, 0x6a, 0x34, 0xff, 0xc8, 0x81, 0xb9, 0x3e, 0x0a, 0xed, 0x41, 0xe5, 0x7c, 0x38, 0x19, - 0xdb, 0xbd, 0xfe, 0x49, 0xdf, 0x3e, 0xae, 0x5f, 0x43, 0x07, 0xb0, 0x7f, 0x84, 0xed, 0xee, 0xd3, - 0xf1, 0xa8, 0x3f, 0x3c, 0x73, 0x26, 0xa3, 0x73, 0xdc, 0xb3, 0x9d, 0xc1, 0xa8, 0xd7, 0x3d, 0xeb, - 0x8f, 0x86, 0xf5, 0x02, 0xb2, 0xe0, 0x46, 0x66, 0xbf, 0x37, 0x1a, 0x1e, 0xf7, 0xd5, 0x4e, 0x11, - 0xdd, 0x82, 0x9b, 0x99, 0x1d, 0xfb, 0xbb, 0x31, 0xb6, 0x27, 0x13, 0xb9, 0x55, 0x46, 0x08, 0x6a, - 0x99, 0xad, 0xee, 0xa9, 0x5d, 0x37, 0xd0, 0x75, 0xa8, 0x4e, 0xbb, 0xb8, 0xdf, 0x3d, 0x1a, 0xd8, - 0xce, 0xb0, 0xfb, 0xcc, 0xae, 0xef, 0x48, 0xda, 0x1a, 0x9a, 0x76, 0x07, 0xe7, 0x76, 0xbd, 0xd4, - 0x7c, 0x04, 0xb5, 0x89, 0x32, 0xca, 0x20, 0x9a, 0x29, 0x67, 0x21, 0x04, 0xc5, 0x98, 0x88, 0x1f, - 0xf5, 0x75, 0xaa, 0x58, 0x62, 0x81, 0x1f, 0x52, 0x55, 0xfa, 0x1d, 0xac, 0xe2, 0xe6, 0xaf, 0x79, - 0x30, 0xa6, 0x84, 0xf9, 0xe4, 0x22, 0xa0, 0x92, 0x10, 0x92, 0x05, 0x4d, 0x93, 0x64, 0x8c, 0x6e, - 0xc0, 0xce, 0x8a, 0x04, 0xcb, 0x24, 0xcb, 0xc4, 0xc9, 0x42, 0x32, 0xc5, 0xcb, 0x98, 0x5a, 0xa5, - 0x84, 0x29, 0x63, 0x74, 0x0c, 0xe5, 0x05, 0x5d, 0x5c, 0x48, 0xa3, 0x14, 0x1a, 0x85, 0xc3, 0x4a, - 0xe7, 0xf3, 0xed, 0x57, 0x90, 0x1e, 0x8d, 0xd3, 0x54, 0xd4, 0x83, 0xbd, 0x15, 0x61, 0x8e, 0x90, - 0xa8, 0xe3, 0x87, 0x2e, 0xbd, 0xb4, 0x8a, 0xea, 0x42, 0x3f, 0x49, 0xd5, 0x52, 0x53, 0xb7, 0xfa, - 0xa1, 0x78, 0xd8, 0x99, 0xca, 0xe7, 0xc1, 0xd5, 0x15, 0x61, 0x67, 0x32, 0xa5, 0x2f, 0x33, 0xd0, - 0x29, 0x94, 0xb8, 0xb2, 0x8d, 0xb5, 0xf3, 0xae, 0x66, 0xd8, 0xb0, 0x19, 0xd6, 0xe9, 0xcd, 0x57, - 0x79, 0x80, 0x89, 0x20, 0xb3, 0x17, 0x27, 0xd2, 0xf2, 0x68, 0x1f, 0x8c, 0xf9, 0x32, 0x9c, 0x29, - 0x9b, 0x25, 0x45, 0x5a, 0xaf, 0xd1, 0x00, 0x8c, 0x40, 0x57, 0x5f, 0xd5, 0xaa, 0xd2, 0xb9, 0xff, - 0x0e, 0xa7, 0x6e, 0xdc, 0x1a, 0x5e, 0x2b, 0xa0, 0x6f, 0xc0, 0x24, 0xcc, 0x5b, 0x2e, 0x68, 0x28, - 0xfe, 0x4f, 0x39, 0x5f, 0x27, 0xa3, 0x23, 0x28, 0x49, 0xd5, 0x80, 0x5b, 0xc5, 0x2b, 0xcb, 0xe8, - 0xcc, 0xe6, 0x9f, 0x06, 0xc0, 0x11, 0xa3, 0xe4, 0x45, 0x1c, 0xf9, 0xa1, 0x40, 0x35, 0xc8, 0xfb, - 0xae, 0x2e, 0x40, 0xde, 0x77, 0xd1, 0x53, 0x28, 0x91, 0xa4, 0x28, 0x55, 0xd5, 0xd5, 0x0f, 0xb7, - 0x1f, 0xf1, 0x5a, 0xad, 0xd5, 0x55, 0xa9, 0x58, 0x4b, 0x7c, 0xe0, 0x3a, 0xde, 0x06, 0x73, 0x16, - 0x85, 0xae, 0xbf, 0x9e, 0x0c, 0x26, 0x7e, 0x0d, 0xa0, 0x06, 0x54, 0xe8, 0x65, 0xcc, 0x28, 0xe7, - 0x72, 0x1a, 0xab, 0x02, 0x99, 0x38, 0x0b, 0xa1, 0x7b, 0x80, 0x82, 0xc8, 0x73, 0x16, 0x89, 0x2f, - 0x1c, 0x3d, 0x24, 0x6b, 0x4a, 0xa8, 0x1e, 0x44, 0x9e, 0x36, 0x4c, 0x32, 0x4a, 0x10, 0x06, 0x53, - 0xb2, 0x03, 0xba, 0xa2, 0x81, 0xb5, 0xa7, 0x6a, 0xf1, 0xe5, 0x95, 0x6a, 0x31, 0x88, 0xbc, 0x81, - 0x4c, 0x96, 0xbf, 0x20, 0x89, 0xd0, 0x5d, 0xa8, 0xf9, 0xdc, 0x99, 0xfb, 0x21, 0x09, 0x1c, 0xe9, - 0x4a, 0xaa, 0x3c, 0x6d, 0xe0, 0x5d, 0x9f, 0x9f, 0x48, 0x50, 0x1a, 0x97, 0xa2, 0x27, 0x50, 0x99, - 0x31, 0x4a, 0x04, 0x75, 0xe4, 0xbb, 0xc0, 0xaa, 0xa8, 0xc2, 0xed, 0xbf, 0xd5, 0x32, 0x67, 0xe9, - 0x8b, 0x02, 0x43, 0x42, 0x97, 0x00, 0x7a, 0x0c, 0x90, 0xe8, 0xab, 0xdc, 0xdd, 0xad, 0xb9, 0xa6, - 0x62, 0xab, 0xd4, 0x4f, 0x01, 0x96, 0x9c, 0x32, 0x87, 0x2e, 0x88, 0x1f, 0x58, 0xf5, 0xa4, 0xc0, - 0x12, 0xb1, 0x25, 0x90, 0x69, 0x44, 0x78, 0xaf, 0x46, 0x44, 0x23, 0xd8, 0xe5, 0xb2, 0x0f, 0x9d, - 0xb9, 0x6c, 0x44, 0x6e, 0x95, 0x95, 0x97, 0xef, 0xbd, 0x93, 0x9c, 0xee, 0x5e, 0x5c, 0xe1, 0xeb, - 0x98, 0x23, 0x07, 0x6e, 0x52, 0x39, 0xcb, 0x88, 0xa0, 0xae, 0x93, 0x35, 0x81, 0x71, 0xe5, 0x2e, - 0xb9, 0xb1, 0x16, 0xb2, 0x33, 0xce, 0x79, 0x0e, 0xb5, 0x95, 0x66, 0x24, 0xd3, 0xcc, 0x32, 0xaf, - 0xac, 0x5c, 0x4d, 0x15, 0xd4, 0x6c, 0x43, 0x63, 0x28, 0x05, 0xe4, 0x82, 0x06, 0xdc, 0xba, 0xae, - 0xa4, 0x1e, 0x5d, 0xcd, 0x5b, 0x2a, 0xd5, 0x0e, 0x05, 0x7b, 0x89, 0xb5, 0xce, 0xfe, 0x63, 0xa8, - 0x64, 0x60, 0x54, 0x87, 0xc2, 0x0b, 0xfa, 0x52, 0x77, 0xb6, 0x0c, 0xff, 0x79, 0xfc, 0x7f, 0x9d, - 0x7f, 0x94, 0x6b, 0x1e, 0x40, 0x29, 0xe9, 0x5c, 0x54, 0x81, 0x72, 0xaf, 0x3b, 0x3e, 0x3b, 0xc7, - 0x76, 0xfd, 0x1a, 0x2a, 0x43, 0x61, 0x30, 0x3a, 0xad, 0xe7, 0x9a, 0xf7, 0xc0, 0x48, 0xdd, 0x8c, - 0x0c, 0x28, 0xf6, 0x87, 0x27, 0xa3, 0xfa, 0x35, 0xc9, 0xfd, 0xb6, 0x8b, 0x87, 0xfd, 0xe1, 0x69, - 0x3d, 0x87, 0x4c, 0xd8, 0xb1, 0x31, 0x1e, 0xe1, 0x7a, 0xbe, 0xf9, 0x57, 0x11, 0x8c, 0xe3, 0xe4, - 0xb9, 0xe9, 0x5b, 0xf3, 0xc5, 0x82, 0x72, 0xcc, 0xa2, 0x9f, 0xe8, 0x4c, 0xe8, 0xc7, 0x48, 0x97, - 0xf2, 0xfb, 0x64, 0x19, 0xfa, 0x3f, 0x2f, 0xfd, 0xb9, 0x4f, 0x99, 0xee, 0xef, 0x0c, 0x22, 0x1b, - 0x3c, 0xfb, 0x69, 0x50, 0x54, 0x84, 0x2c, 0x84, 0xee, 0x40, 0xc5, 0xe7, 0x8e, 0x1f, 0xca, 0xe9, - 0xb3, 0x4a, 0x7b, 0x0b, 0x7c, 0xde, 0xd7, 0x08, 0xfa, 0x0c, 0xaa, 0xc4, 0xa3, 0xa1, 0x70, 0x56, - 0x94, 0xc9, 0x9b, 0xd5, 0xef, 0xbc, 0x5d, 0x05, 0x4e, 0x13, 0x4c, 0xab, 0xb8, 0x3e, 0x97, 0xf7, - 0xe4, 0x5a, 0xe5, 0x54, 0xe5, 0x58, 0x23, 0x99, 0x46, 0x30, 0xde, 0xaf, 0x11, 0x9e, 0xc3, 0xde, - 0xe6, 0x37, 0x21, 0xd7, 0xbe, 0x3a, 0x7c, 0x4b, 0x31, 0xe1, 0xb5, 0x56, 0x0f, 0xf4, 0x78, 0xec, - 0x25, 0x09, 0xb8, 0xc6, 0xb3, 0x4b, 0x8e, 0x7e, 0x80, 0x8f, 0xe8, 0xa5, 0x70, 0xde, 0x94, 0xad, - 0x2a, 0xd9, 0xfb, 0xff, 0x21, 0x6b, 0x5f, 0x0a, 0x1a, 0xba, 0xd4, 0xdd, 0x94, 0xbf, 0x4e, 0x2f, - 0xc5, 0x64, 0xf3, 0x84, 0xe1, 0xda, 0xb8, 0x15, 0x25, 0xfa, 0xd5, 0xf6, 0x5f, 0x9f, 0x9a, 0xe1, - 0x03, 0xdb, 0xf6, 0xe8, 0xb7, 0x1c, 0xdc, 0x9d, 0x45, 0x8b, 0xad, 0x0f, 0x70, 0x64, 0x1e, 0x13, - 0x41, 0xc6, 0x72, 0xf8, 0x8d, 0x73, 0xdf, 0x3f, 0xd3, 0x74, 0x2f, 0x0a, 0x48, 0xe8, 0xb5, 0x22, - 0xe6, 0xb5, 0x3d, 0x1a, 0xaa, 0xd1, 0xd8, 0x4e, 0xb6, 0x48, 0xec, 0xf3, 0x7f, 0xff, 0xb7, 0xf0, - 0x64, 0x03, 0xf8, 0x3d, 0x6f, 0x9d, 0x26, 0x7a, 0x3d, 0x09, 0xa7, 0xbf, 0x95, 0xb5, 0xa6, 0x9d, - 0x8b, 0x92, 0x12, 0x7d, 0xf8, 0x77, 0x00, 0x00, 0x00, 0xff, 0xff, 0x06, 0xfd, 0x4c, 0xc8, 0x81, - 0x0c, 0x00, 0x00, + // 1270 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x57, 0x5d, 0x92, 0xda, 0xc6, + 0x16, 0x36, 0x3f, 0x03, 0xd2, 0x61, 0x60, 0x70, 0x5f, 0xfb, 0x96, 0x3c, 0xd7, 0x77, 0x4c, 0x71, + 0xfd, 0x30, 0x75, 0xe3, 0x02, 0x1b, 0x57, 0x52, 0x76, 0xfc, 0xc4, 0x30, 0x9a, 0x09, 0x65, 0x0c, + 0xb8, 0x99, 0x21, 0xa9, 0x94, 0xab, 0x94, 0x1e, 0xd4, 0x28, 0x8a, 0x85, 0xa4, 0x74, 0x37, 0x64, + 0xfc, 0xee, 0x65, 0x64, 0x05, 0xa9, 0x2c, 0x20, 0x6b, 0xc8, 0x26, 0xf2, 0x96, 0x75, 0xa4, 0xba, + 0xd5, 0xc2, 0xc2, 0x4e, 0x82, 0x27, 0xf6, 0x5b, 0xf7, 0x77, 0xbe, 0xf3, 0xb5, 0x38, 0xfd, 0x9d, + 0x23, 0x01, 0x9f, 0x78, 0x51, 0xe4, 0x05, 0xb4, 0xed, 0xd2, 0x95, 0x88, 0xa2, 0x80, 0xb7, 0x67, + 0x41, 0xb4, 0x74, 0x5d, 0x7a, 0xb1, 0xf4, 0x3c, 0xca, 0xda, 0xab, 0x4e, 0xdb, 0x25, 0x82, 0xb4, + 0x62, 0x16, 0x89, 0x08, 0x35, 0x12, 0x72, 0x2b, 0x25, 0xb7, 0x36, 0xc8, 0xad, 0x55, 0x67, 0xff, + 0xb6, 0x96, 0x23, 0xb1, 0xdf, 0x26, 0x61, 0x18, 0x09, 0x22, 0xfc, 0x28, 0xe4, 0x49, 0xfe, 0x7e, + 0xeb, 0xed, 0xc3, 0x78, 0xb4, 0x64, 0x33, 0xda, 0x5e, 0x3d, 0xd0, 0x2b, 0x67, 0x16, 0x85, 0x82, + 0x5e, 0x0a, 0xcd, 0xbf, 0xa3, 0xf9, 0x6a, 0x77, 0xb1, 0x9c, 0xb7, 0x85, 0xbf, 0xa0, 0x5c, 0x90, + 0x45, 0xac, 0x09, 0x07, 0x6f, 0x13, 0x7e, 0x60, 0x24, 0x8e, 0x29, 0xd3, 0x07, 0x36, 0x4f, 0xa1, + 0x7a, 0x12, 0xb1, 0x05, 0x11, 0xcf, 0x28, 0xe7, 0xc4, 0xa3, 0xe8, 0xdf, 0x50, 0x9a, 0x2b, 0xc0, + 0xca, 0x35, 0x72, 0x87, 0x26, 0xd6, 0x3b, 0x74, 0x00, 0x10, 0x13, 0x46, 0x16, 0x54, 0x50, 0xc6, + 0xad, 0x7c, 0xa3, 0x70, 0x68, 0xe2, 0x0c, 0xd2, 0x7c, 0x5d, 0x80, 0xea, 0x44, 0x10, 0xb1, 0xe4, + 0xa9, 0xd2, 0x2d, 0x30, 0x7c, 0xee, 0x50, 0xc6, 0x22, 0xa6, 0xb4, 0x0c, 0x5c, 0xf6, 0xb9, 0x2d, + 0xb7, 0x68, 0x0a, 0x26, 0xa3, 0x73, 0xca, 0xb8, 0x23, 0x22, 0x2b, 0xdf, 0xc8, 0x1d, 0xd6, 0x3a, + 0x8f, 0x5b, 0xdb, 0x4a, 0xd7, 0xda, 0x90, 0x6f, 0x61, 0x29, 0x40, 0xc3, 0x19, 0xc5, 0x46, 0xa2, + 0x75, 0x16, 0xa1, 0xe7, 0x50, 0x71, 0x29, 0x9f, 0x31, 0x3f, 0x96, 0x45, 0xb5, 0x0a, 0x8d, 0xdc, + 0x61, 0xa5, 0xd3, 0xde, 0xae, 0xbc, 0x51, 0x02, 0x9c, 0xd5, 0x68, 0xfe, 0x9c, 0x03, 0x73, 0x7d, + 0x14, 0xda, 0x83, 0xca, 0xf9, 0x70, 0x32, 0xb6, 0x7b, 0xfd, 0x93, 0xbe, 0x7d, 0x5c, 0xbf, 0x86, + 0x0e, 0x60, 0xff, 0x08, 0xdb, 0xdd, 0xa7, 0xe3, 0x51, 0x7f, 0x78, 0xe6, 0x4c, 0x46, 0xe7, 0xb8, + 0x67, 0x3b, 0x83, 0x51, 0xaf, 0x7b, 0xd6, 0x1f, 0x0d, 0xeb, 0x05, 0x64, 0xc1, 0x8d, 0x4c, 0xbc, + 0x37, 0x1a, 0x1e, 0xf7, 0x55, 0xa4, 0x88, 0x6e, 0xc1, 0xcd, 0x4c, 0xc4, 0xfe, 0x6a, 0x8c, 0xed, + 0xc9, 0x44, 0x86, 0xca, 0x08, 0x41, 0x2d, 0x13, 0xea, 0x9e, 0xda, 0x75, 0x03, 0x5d, 0x87, 0xea, + 0xb4, 0x8b, 0xfb, 0xdd, 0xa3, 0x81, 0xed, 0x0c, 0xbb, 0xcf, 0xec, 0xfa, 0x8e, 0xa4, 0xad, 0xa1, + 0x69, 0x77, 0x70, 0x6e, 0xd7, 0x4b, 0xcd, 0x47, 0x50, 0x9b, 0x28, 0xa3, 0x0c, 0xa2, 0x99, 0x72, + 0x16, 0x42, 0x50, 0x8c, 0x89, 0xf8, 0x56, 0x5f, 0xa7, 0x5a, 0x4b, 0x2c, 0xf0, 0x43, 0xaa, 0x4a, + 0xbf, 0x83, 0xd5, 0xba, 0xf9, 0x63, 0x1e, 0x8c, 0x29, 0x61, 0x3e, 0xb9, 0x08, 0xa8, 0x24, 0x84, + 0x64, 0x41, 0xd3, 0x24, 0xb9, 0x46, 0x37, 0x60, 0x67, 0x45, 0x82, 0x65, 0x92, 0x65, 0xe2, 0x64, + 0x23, 0x99, 0xe2, 0x55, 0x4c, 0xad, 0x52, 0xc2, 0x94, 0x6b, 0x74, 0x0c, 0xe5, 0x05, 0x5d, 0x5c, + 0x48, 0xa3, 0x14, 0x1a, 0x85, 0xc3, 0x4a, 0xe7, 0xff, 0xdb, 0xaf, 0x20, 0x3d, 0x1a, 0xa7, 0xa9, + 0xa8, 0x07, 0x7b, 0x2b, 0xc2, 0x1c, 0x21, 0x51, 0xc7, 0x0f, 0x5d, 0x7a, 0x69, 0x15, 0xd5, 0x85, + 0xfe, 0x27, 0x55, 0x4b, 0x4d, 0xdd, 0xea, 0x87, 0xe2, 0x61, 0x67, 0x2a, 0x9f, 0x07, 0x57, 0x57, + 0x84, 0x9d, 0xc9, 0x94, 0xbe, 0xcc, 0x40, 0xa7, 0x50, 0xe2, 0xca, 0x36, 0xd6, 0xce, 0xfb, 0x9a, + 0x61, 0xc3, 0x66, 0x58, 0xa7, 0x37, 0x5f, 0xe7, 0x01, 0x26, 0x82, 0xcc, 0x5e, 0x9e, 0x48, 0xcb, + 0xa3, 0x7d, 0x30, 0xe6, 0xcb, 0x70, 0xa6, 0x6c, 0x96, 0x14, 0x69, 0xbd, 0x47, 0x03, 0x30, 0x02, + 0x5d, 0x7d, 0x55, 0xab, 0x4a, 0xe7, 0xfe, 0x7b, 0x9c, 0xba, 0x71, 0x6b, 0x78, 0xad, 0x80, 0xbe, + 0x00, 0x93, 0x30, 0x6f, 0xb9, 0xa0, 0xa1, 0xf8, 0x27, 0xe5, 0x7c, 0x93, 0x8c, 0x8e, 0xa0, 0x24, + 0x55, 0x03, 0x6e, 0x15, 0xaf, 0x2c, 0xa3, 0x33, 0x9b, 0xbf, 0x19, 0x00, 0x47, 0x8c, 0x92, 0x97, + 0x71, 0xe4, 0x87, 0x02, 0xd5, 0x20, 0xef, 0xbb, 0xba, 0x00, 0x79, 0xdf, 0x45, 0x4f, 0xa1, 0x44, + 0x92, 0xa2, 0x54, 0x55, 0x57, 0x3f, 0xdc, 0x7e, 0xc4, 0x1b, 0xb5, 0x56, 0x57, 0xa5, 0x62, 0x2d, + 0xf1, 0x91, 0xeb, 0x78, 0x1b, 0xcc, 0x59, 0x14, 0xba, 0xfe, 0x7a, 0x32, 0x98, 0xf8, 0x0d, 0x80, + 0x1a, 0x50, 0xa1, 0x97, 0x31, 0xa3, 0x9c, 0xcb, 0x69, 0xac, 0x0a, 0x64, 0xe2, 0x2c, 0x84, 0xee, + 0x01, 0x0a, 0x22, 0xcf, 0x59, 0x24, 0xbe, 0x70, 0xf4, 0x90, 0xac, 0x29, 0xa1, 0x7a, 0x10, 0x79, + 0xda, 0x30, 0xc9, 0x28, 0x41, 0x18, 0x4c, 0xc9, 0x0e, 0xe8, 0x8a, 0x06, 0xd6, 0x9e, 0xaa, 0xc5, + 0xa7, 0x57, 0xaa, 0xc5, 0x20, 0xf2, 0x06, 0x32, 0x59, 0xfe, 0x82, 0x64, 0x85, 0xee, 0x42, 0xcd, + 0xe7, 0xce, 0xdc, 0x0f, 0x49, 0xe0, 0x48, 0x57, 0x52, 0xe5, 0x69, 0x03, 0xef, 0xfa, 0xfc, 0x44, + 0x82, 0xd2, 0xb8, 0x14, 0x3d, 0x81, 0xca, 0x8c, 0x51, 0x22, 0xa8, 0x23, 0xdf, 0x05, 0x56, 0x45, + 0x15, 0x6e, 0xff, 0x9d, 0x96, 0x39, 0x4b, 0x5f, 0x14, 0x18, 0x12, 0xba, 0x04, 0xd0, 0x63, 0x80, + 0x44, 0x5f, 0xe5, 0xee, 0x6e, 0xcd, 0x35, 0x15, 0x5b, 0xa5, 0xfe, 0x17, 0x60, 0xc9, 0x29, 0x73, + 0xe8, 0x82, 0xf8, 0x81, 0x55, 0x4f, 0x0a, 0x2c, 0x11, 0x5b, 0x02, 0x99, 0x46, 0x84, 0x0f, 0x6a, + 0x44, 0x34, 0x82, 0x5d, 0x2e, 0xfb, 0xd0, 0x99, 0xcb, 0x46, 0xe4, 0x56, 0x59, 0x79, 0xf9, 0xde, + 0x7b, 0xc9, 0xe9, 0xee, 0xc5, 0x15, 0xbe, 0x5e, 0x73, 0xe4, 0xc0, 0x4d, 0x2a, 0x67, 0x19, 0x11, + 0xd4, 0x75, 0xb2, 0x26, 0x30, 0xae, 0xdc, 0x25, 0x37, 0xd6, 0x42, 0x76, 0xc6, 0x39, 0xcf, 0xa1, + 0xb6, 0xd2, 0x8c, 0x64, 0x9a, 0x59, 0xe6, 0x95, 0x95, 0xab, 0xa9, 0x82, 0x9a, 0x6d, 0x68, 0x0c, + 0xa5, 0x80, 0x5c, 0xd0, 0x80, 0x5b, 0xd7, 0x95, 0xd4, 0xa3, 0xab, 0x79, 0x4b, 0xa5, 0xda, 0xa1, + 0x60, 0xaf, 0xb0, 0xd6, 0xd9, 0x7f, 0x0c, 0x95, 0x0c, 0x8c, 0xea, 0x50, 0x78, 0x49, 0x5f, 0xe9, + 0xce, 0x96, 0xcb, 0x3f, 0x1f, 0xff, 0x9f, 0xe7, 0x1f, 0xe5, 0x9a, 0x07, 0x50, 0x4a, 0x3a, 0x17, + 0x55, 0xa0, 0xdc, 0xeb, 0x8e, 0xcf, 0xce, 0xb1, 0x5d, 0xbf, 0x86, 0xca, 0x50, 0x18, 0x8c, 0x4e, + 0xeb, 0xb9, 0xe6, 0x3d, 0x30, 0x52, 0x37, 0x23, 0x03, 0x8a, 0xfd, 0xe1, 0xc9, 0xa8, 0x7e, 0x4d, + 0x72, 0xbf, 0xec, 0xe2, 0x61, 0x7f, 0x78, 0x5a, 0xcf, 0x21, 0x13, 0x76, 0x6c, 0x8c, 0x47, 0xb8, + 0x9e, 0x6f, 0xfe, 0x5e, 0x04, 0xe3, 0x38, 0x79, 0x6e, 0xfa, 0xce, 0x7c, 0xb1, 0xa0, 0x1c, 0xb3, + 0xe8, 0x3b, 0x3a, 0x13, 0xfa, 0x31, 0xd2, 0xad, 0xfc, 0x3e, 0x59, 0x86, 0xfe, 0xf7, 0x4b, 0x7f, + 0xee, 0x53, 0xa6, 0xfb, 0x3b, 0x83, 0xc8, 0x06, 0xcf, 0x7e, 0x1a, 0x14, 0x15, 0x21, 0x0b, 0xa1, + 0x3b, 0x50, 0xf1, 0xb9, 0xe3, 0x87, 0x72, 0xfa, 0xac, 0xd2, 0xde, 0x02, 0x9f, 0xf7, 0x35, 0x82, + 0xfe, 0x07, 0x55, 0xe2, 0xd1, 0x50, 0x38, 0x2b, 0xca, 0xe4, 0xcd, 0xea, 0x77, 0xde, 0xae, 0x02, + 0xa7, 0x09, 0xa6, 0x55, 0x5c, 0x9f, 0xcb, 0x7b, 0x72, 0xad, 0x72, 0xaa, 0x72, 0xac, 0x91, 0x4c, + 0x23, 0x18, 0x1f, 0xd6, 0x08, 0xcf, 0x61, 0x6f, 0xf3, 0x9b, 0x90, 0x6b, 0x5f, 0x1d, 0xbe, 0xa3, + 0x98, 0xf0, 0x5a, 0xab, 0x07, 0x7a, 0x3c, 0xf6, 0x92, 0x04, 0x5c, 0xe3, 0xd9, 0x2d, 0x47, 0xdf, + 0xc0, 0xbf, 0xe8, 0xa5, 0x70, 0xde, 0x96, 0xad, 0x2a, 0xd9, 0xfb, 0x7f, 0x23, 0x6b, 0x5f, 0x0a, + 0x1a, 0xba, 0xd4, 0xdd, 0x94, 0xbf, 0x4e, 0x2f, 0xc5, 0x64, 0xf3, 0x84, 0xe1, 0xda, 0xb8, 0x15, + 0x25, 0xfa, 0xd9, 0xf6, 0x5f, 0x9f, 0x9a, 0xe1, 0x23, 0xdb, 0xf6, 0xe8, 0x97, 0x1c, 0xdc, 0x9d, + 0x45, 0x8b, 0xad, 0x0f, 0x70, 0x64, 0x1e, 0x13, 0x41, 0xc6, 0x72, 0xf8, 0x8d, 0x73, 0x5f, 0x3f, + 0xd3, 0x74, 0x2f, 0x0a, 0x48, 0xe8, 0xb5, 0x22, 0xe6, 0xb5, 0x3d, 0x1a, 0xaa, 0xd1, 0xd8, 0x4e, + 0x42, 0x24, 0xf6, 0xf9, 0x5f, 0xff, 0x5b, 0x78, 0xb2, 0x01, 0xfc, 0x94, 0xb7, 0x4e, 0x13, 0xbd, + 0x9e, 0x84, 0xd3, 0xdf, 0xca, 0x5a, 0xd3, 0xce, 0xaf, 0x69, 0xe8, 0x85, 0x0a, 0xbd, 0x48, 0x43, + 0x2f, 0xa6, 0x9d, 0x8b, 0x92, 0x3a, 0xef, 0xe1, 0x1f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x75, 0x2e, + 0xfe, 0xb1, 0x9c, 0x0c, 0x00, 0x00, } diff --git a/vendor/google.golang.org/genproto/googleapis/devtools/clouddebugger/v2/debugger.pb.go b/vendor/google.golang.org/genproto/googleapis/devtools/clouddebugger/v2/debugger.pb.go index 7454ee2e04f13fd0d5a9a4d30c5c61aa3c96b36b..40bf0efe38257292e5389766e5b7d61c84d8cafe 100644 --- a/vendor/google.golang.org/genproto/googleapis/devtools/clouddebugger/v2/debugger.pb.go +++ b/vendor/google.golang.org/genproto/googleapis/devtools/clouddebugger/v2/debugger.pb.go @@ -594,54 +594,55 @@ var _Debugger2_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("google/devtools/clouddebugger/v2/debugger.proto", fileDescriptor2) } var fileDescriptor2 = []byte{ - // 781 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0xcb, 0x6e, 0xd3, 0x4c, - 0x18, 0xd5, 0xa4, 0x7f, 0x2f, 0xf9, 0xd2, 0xb4, 0xfd, 0x47, 0xbd, 0x58, 0xe1, 0x16, 0x99, 0x8b, - 0x4a, 0x41, 0x36, 0x72, 0x11, 0xb4, 0xb0, 0xa1, 0xa1, 0x28, 0x8d, 0x54, 0xaa, 0x2a, 0x40, 0x91, - 0xd8, 0x44, 0x4e, 0x3c, 0xb5, 0x4c, 0x5d, 0x8f, 0xf1, 0x8c, 0x03, 0xa8, 0xea, 0xa6, 0x48, 0xec, - 0x11, 0x2f, 0x00, 0x5b, 0x84, 0xc4, 0x13, 0x20, 0xb1, 0x43, 0x62, 0xcb, 0x2b, 0xf0, 0x20, 0xc8, - 0xf6, 0xb8, 0x71, 0x82, 0x21, 0x71, 0x2a, 0x75, 0xe7, 0x9c, 0xcc, 0x77, 0x7c, 0xce, 0x99, 0x6f, - 0xbe, 0x31, 0xa8, 0x26, 0xa5, 0xa6, 0x4d, 0x54, 0x83, 0xb4, 0x39, 0xa5, 0x36, 0x53, 0x5b, 0x36, - 0xf5, 0x0d, 0x83, 0x34, 0x7d, 0xd3, 0x24, 0x9e, 0xda, 0xd6, 0xd4, 0xf8, 0x59, 0x71, 0x3d, 0xca, - 0x29, 0x2e, 0x47, 0x05, 0x4a, 0x5c, 0xa0, 0x74, 0x15, 0x28, 0x6d, 0xad, 0x74, 0x56, 0x50, 0xea, - 0xae, 0xa5, 0xea, 0x8e, 0x43, 0xb9, 0xce, 0x2d, 0xea, 0xb0, 0xa8, 0xbe, 0x74, 0xad, 0xff, 0x0b, - 0x75, 0xae, 0x8b, 0xc5, 0x67, 0xc4, 0xe2, 0xf0, 0x57, 0xd3, 0xdf, 0x55, 0xc9, 0xbe, 0xcb, 0x5f, - 0x47, 0x7f, 0xca, 0x9f, 0x11, 0xcc, 0x3e, 0x22, 0xbc, 0xe2, 0x11, 0x7d, 0xcf, 0xa5, 0x96, 0xc3, - 0xeb, 0xe4, 0x85, 0x4f, 0x18, 0xc7, 0x17, 0xa0, 0x20, 0xf8, 0x48, 0xc3, 0x32, 0x24, 0x54, 0x46, - 0x8b, 0xf9, 0x3a, 0xc4, 0x50, 0xcd, 0xc0, 0x9b, 0x00, 0xcd, 0xe3, 0x2a, 0x29, 0x57, 0x46, 0x8b, - 0x05, 0xed, 0xba, 0xd2, 0xcf, 0x98, 0x92, 0x78, 0x53, 0xa2, 0x1e, 0x5f, 0x86, 0xa9, 0x96, 0x6d, - 0x11, 0x87, 0x37, 0xda, 0xc4, 0x63, 0x16, 0x75, 0xa4, 0xff, 0xc2, 0x37, 0x16, 0x23, 0x74, 0x27, - 0x02, 0x65, 0x02, 0x73, 0x3d, 0x6a, 0x99, 0x4b, 0x1d, 0x46, 0x7a, 0xd4, 0xa0, 0x93, 0xa9, 0x91, - 0xdf, 0x20, 0x98, 0xad, 0x0e, 0x95, 0xca, 0x45, 0x28, 0x76, 0x78, 0x82, 0x25, 0xb9, 0x70, 0xc9, - 0x64, 0x07, 0xac, 0x19, 0x19, 0xcc, 0x56, 0x4f, 0xc1, 0xec, 0x5b, 0x04, 0x0b, 0xeb, 0xc4, 0x26, - 0x9c, 0x9c, 0x9e, 0xdf, 0x91, 0x34, 0xbf, 0xdf, 0x47, 0x60, 0x7e, 0xd3, 0x62, 0x09, 0xc7, 0x6c, - 0x60, 0x1d, 0x4b, 0xf0, 0xbf, 0xe5, 0xb4, 0x6c, 0xdf, 0x20, 0x0d, 0xdd, 0xb6, 0x1b, 0x3e, 0x23, - 0x1e, 0x0b, 0xb5, 0x4c, 0xd4, 0xa7, 0xc5, 0x1f, 0x6b, 0xb6, 0xfd, 0x24, 0x80, 0xf1, 0x55, 0x98, - 0x89, 0xd7, 0x5a, 0x8e, 0xde, 0xe2, 0x56, 0x9b, 0x84, 0x82, 0x3a, 0x4b, 0x6b, 0x02, 0xc6, 0xbb, - 0x30, 0x16, 0x3c, 0x89, 0x1d, 0x2a, 0x68, 0x5b, 0xfd, 0x53, 0x4e, 0x77, 0x90, 0x08, 0x7f, 0x2d, - 0x24, 0xdc, 0xd1, 0x6d, 0x9f, 0xd4, 0x05, 0x7b, 0x10, 0x23, 0xe3, 0x9e, 0xe5, 0x36, 0x3c, 0xc2, - 0x7c, 0x9b, 0x33, 0x69, 0x34, 0xd4, 0x33, 0x19, 0x82, 0xf5, 0x08, 0xc3, 0xe7, 0x00, 0x5e, 0xea, - 0x16, 0x6f, 0x70, 0xba, 0x47, 0x1c, 0x69, 0x2c, 0xcc, 0x20, 0x1f, 0x20, 0x8f, 0x03, 0x20, 0x25, - 0xe5, 0x89, 0x94, 0x94, 0x4b, 0x4d, 0x98, 0x4b, 0xd5, 0x82, 0x6b, 0x30, 0xda, 0x0e, 0x1e, 0xc2, - 0x74, 0xa7, 0xb4, 0xe5, 0x2c, 0x0d, 0xa5, 0x44, 0x44, 0xf5, 0x88, 0x41, 0x7e, 0x87, 0x60, 0xe1, - 0x8f, 0x1c, 0x44, 0xf3, 0x6e, 0x41, 0xa1, 0xd3, 0x1c, 0x4c, 0x42, 0xe5, 0x91, 0xcc, 0xdd, 0x9b, - 0x24, 0xc0, 0x57, 0x60, 0xda, 0x21, 0xaf, 0x78, 0x23, 0x11, 0x4d, 0xd4, 0x83, 0xc5, 0x00, 0x7e, - 0x1a, 0xc7, 0x23, 0x1f, 0x21, 0x98, 0x0d, 0x34, 0xad, 0x8b, 0xa6, 0x39, 0xee, 0x2d, 0x09, 0xc6, - 0x5d, 0x8f, 0x3e, 0x27, 0x2d, 0x2e, 0x0a, 0xe3, 0x9f, 0x59, 0x1a, 0x65, 0xc0, 0x23, 0xad, 0xc3, - 0x5c, 0x8f, 0x06, 0x91, 0xca, 0x06, 0xe4, 0xe3, 0x6e, 0x8e, 0x33, 0x59, 0xea, 0x9f, 0x49, 0xcc, - 0x53, 0xef, 0x14, 0x6b, 0x5f, 0xc7, 0x21, 0x2f, 0x70, 0x4f, 0xc3, 0x3f, 0x10, 0x14, 0xbb, 0x26, - 0x26, 0xbe, 0xd5, 0x9f, 0x36, 0xed, 0x42, 0x28, 0xdd, 0xce, 0x5c, 0x17, 0x59, 0x93, 0x37, 0x8e, - 0x7e, 0xfe, 0x7a, 0x9f, 0xab, 0xc8, 0x37, 0x93, 0x17, 0xa1, 0x7a, 0x2c, 0x58, 0x3d, 0x48, 0x9c, - 0xec, 0x43, 0x35, 0xb1, 0xb5, 0x2a, 0x23, 0xfc, 0x4e, 0xf2, 0x92, 0x08, 0xcc, 0x54, 0xb3, 0x9a, - 0xa9, 0x0e, 0x69, 0xa6, 0xfa, 0x2f, 0x33, 0xf8, 0x5e, 0x66, 0x33, 0x07, 0x5d, 0x73, 0xf2, 0x10, - 0x7f, 0x41, 0x30, 0xd3, 0x3b, 0x76, 0xf1, 0xea, 0x20, 0x7b, 0x9e, 0x3a, 0xaa, 0x4b, 0xf3, 0x71, - 0x69, 0x7c, 0xcf, 0x2b, 0x0f, 0x82, 0x7b, 0x3e, 0x56, 0xbc, 0x74, 0x72, 0xc5, 0xdf, 0x10, 0x4c, - 0xf7, 0x9c, 0x6a, 0xbc, 0x32, 0xec, 0x40, 0x2c, 0xad, 0x0e, 0x51, 0x29, 0x36, 0x61, 0x25, 0xb4, - 0xa4, 0xe1, 0x1b, 0x59, 0x2d, 0xe1, 0x0f, 0x08, 0x8a, 0x5d, 0x07, 0x70, 0x90, 0x0e, 0x4a, 0x9b, - 0x1a, 0x83, 0x74, 0x50, 0xea, 0x49, 0x97, 0xcf, 0x87, 0xe2, 0x25, 0x3c, 0x9f, 0x2e, 0xbe, 0xf2, - 0x11, 0xc1, 0xa5, 0x16, 0xdd, 0xef, 0x4b, 0x5f, 0x29, 0xc6, 0xa7, 0x7c, 0x3b, 0xd8, 0xf0, 0x6d, - 0xf4, 0xec, 0xa1, 0x28, 0x31, 0xa9, 0xad, 0x3b, 0xa6, 0x42, 0x3d, 0x53, 0x35, 0x89, 0x13, 0xb6, - 0x83, 0xf8, 0x42, 0xd5, 0x5d, 0x8b, 0xfd, 0xfd, 0xa3, 0xf1, 0x6e, 0x17, 0xf0, 0x29, 0x27, 0x55, - 0x23, 0xbe, 0xfb, 0x01, 0x1c, 0xcf, 0x1a, 0x4f, 0xd9, 0xd1, 0x9a, 0x63, 0x21, 0xe9, 0xf2, 0xef, - 0x00, 0x00, 0x00, 0xff, 0xff, 0x66, 0xf8, 0x5d, 0x68, 0xf9, 0x0a, 0x00, 0x00, + // 797 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0xdd, 0x6a, 0xdb, 0x48, + 0x14, 0x66, 0x9c, 0xcd, 0x8f, 0x8f, 0xe3, 0x24, 0x3b, 0xe4, 0x47, 0x78, 0xff, 0x8c, 0xf6, 0x87, + 0x6c, 0x76, 0x91, 0x16, 0x65, 0xd9, 0x4d, 0x76, 0x6f, 0x1a, 0x37, 0xc5, 0x31, 0xa4, 0x21, 0xb8, + 0xad, 0x0b, 0x25, 0x60, 0x64, 0x7b, 0x22, 0xd4, 0x28, 0x1a, 0x55, 0x33, 0x72, 0x5b, 0x42, 0x6e, + 0x52, 0xe8, 0x7d, 0xe9, 0x0b, 0xf4, 0xba, 0x14, 0xfa, 0x02, 0x2d, 0xf4, 0xae, 0x90, 0xdb, 0xbe, + 0x42, 0x1f, 0xa4, 0x48, 0x9a, 0x89, 0x65, 0x57, 0xad, 0x2d, 0x07, 0x72, 0x37, 0xfa, 0x66, 0xce, + 0x99, 0xef, 0xfb, 0xe6, 0xcc, 0x19, 0x81, 0x6e, 0x51, 0x6a, 0x39, 0x44, 0xef, 0x90, 0x2e, 0xa7, + 0xd4, 0x61, 0x7a, 0xdb, 0xa1, 0x41, 0xa7, 0x43, 0x5a, 0x81, 0x65, 0x11, 0x5f, 0xef, 0x1a, 0xba, + 0x1c, 0x6b, 0x9e, 0x4f, 0x39, 0xc5, 0xe5, 0x38, 0x40, 0x93, 0x01, 0x5a, 0x5f, 0x80, 0xd6, 0x35, + 0x4a, 0xdf, 0x8b, 0x94, 0xa6, 0x67, 0xeb, 0xa6, 0xeb, 0x52, 0x6e, 0x72, 0x9b, 0xba, 0x2c, 0x8e, + 0x2f, 0xfd, 0x31, 0x7c, 0x43, 0x93, 0x9b, 0x62, 0xf1, 0x77, 0x62, 0x71, 0xf4, 0xd5, 0x0a, 0x0e, + 0x75, 0x72, 0xec, 0xf1, 0xc7, 0xf1, 0xa4, 0xfa, 0x0a, 0xc1, 0xe2, 0x2d, 0xc2, 0x2b, 0x3e, 0x31, + 0x8f, 0x3c, 0x6a, 0xbb, 0xbc, 0x4e, 0x1e, 0x04, 0x84, 0x71, 0xfc, 0x13, 0x14, 0x44, 0x3e, 0xd2, + 0xb4, 0x3b, 0x0a, 0x2a, 0xa3, 0xd5, 0x7c, 0x1d, 0x24, 0x54, 0xeb, 0xe0, 0x5d, 0x80, 0xd6, 0x45, + 0x94, 0x92, 0x2b, 0xa3, 0xd5, 0x82, 0xf1, 0xa7, 0x36, 0x4c, 0x98, 0x96, 0xd8, 0x29, 0x11, 0x8f, + 0x7f, 0x85, 0xb9, 0xb6, 0x63, 0x13, 0x97, 0x37, 0xbb, 0xc4, 0x67, 0x36, 0x75, 0x95, 0x6f, 0xa2, + 0x1d, 0x8b, 0x31, 0xda, 0x88, 0x41, 0x95, 0xc0, 0xd2, 0x00, 0x5b, 0xe6, 0x51, 0x97, 0x91, 0x01, + 0x36, 0xe8, 0x72, 0x6c, 0xd4, 0x27, 0x08, 0x16, 0xab, 0x63, 0xb9, 0xf2, 0x33, 0x14, 0x7b, 0x79, + 0xc2, 0x25, 0xb9, 0x68, 0xc9, 0x6c, 0x0f, 0xac, 0x75, 0x32, 0x88, 0xad, 0x5e, 0x81, 0xd8, 0xa7, + 0x08, 0x56, 0xb6, 0x89, 0x43, 0x38, 0xb9, 0x3a, 0xbd, 0x13, 0x69, 0x7a, 0xdf, 0x4f, 0xc0, 0xf2, + 0xae, 0xcd, 0x12, 0x8a, 0xd9, 0xc8, 0x3c, 0xd6, 0xe0, 0x5b, 0xdb, 0x6d, 0x3b, 0x41, 0x87, 0x34, + 0x4d, 0xc7, 0x69, 0x06, 0x8c, 0xf8, 0x2c, 0xe2, 0x32, 0x53, 0x9f, 0x17, 0x13, 0x5b, 0x8e, 0x73, + 0x27, 0x84, 0xf1, 0xef, 0xb0, 0x20, 0xd7, 0xda, 0xae, 0xd9, 0xe6, 0x76, 0x97, 0x44, 0x84, 0x7a, + 0x4b, 0x6b, 0x02, 0xc6, 0x87, 0x30, 0x15, 0x8e, 0xc4, 0x09, 0x15, 0x8c, 0xbd, 0xe1, 0x2e, 0xa7, + 0x2b, 0x48, 0x98, 0xbf, 0x15, 0x25, 0x6c, 0x98, 0x4e, 0x40, 0xea, 0x22, 0x7b, 0x68, 0x23, 0xe3, + 0xbe, 0xed, 0x35, 0x7d, 0xc2, 0x02, 0x87, 0x33, 0x65, 0x32, 0xe2, 0x33, 0x1b, 0x81, 0xf5, 0x18, + 0xc3, 0x3f, 0x00, 0x3c, 0x34, 0x6d, 0xde, 0xe4, 0xf4, 0x88, 0xb8, 0xca, 0x54, 0xe4, 0x41, 0x3e, + 0x44, 0x6e, 0x87, 0x40, 0x8a, 0xcb, 0x33, 0x29, 0x2e, 0x97, 0x5a, 0xb0, 0x94, 0xca, 0x05, 0xd7, + 0x60, 0xb2, 0x1b, 0x0e, 0x22, 0x77, 0xe7, 0x8c, 0xf5, 0x2c, 0x05, 0xa5, 0xc5, 0x89, 0xea, 0x71, + 0x06, 0xf5, 0x19, 0x82, 0x95, 0xcf, 0x7c, 0x10, 0xc5, 0xbb, 0x07, 0x85, 0x5e, 0x71, 0x30, 0x05, + 0x95, 0x27, 0x32, 0x57, 0x6f, 0x32, 0x01, 0xfe, 0x0d, 0xe6, 0x5d, 0xf2, 0x88, 0x37, 0x13, 0xd6, + 0xc4, 0x35, 0x58, 0x0c, 0xe1, 0xbb, 0xd2, 0x1e, 0xf5, 0x0c, 0xc1, 0x62, 0xc8, 0x69, 0x5b, 0x14, + 0xcd, 0x45, 0x6d, 0x29, 0x30, 0xed, 0xf9, 0xf4, 0x3e, 0x69, 0x73, 0x11, 0x28, 0x3f, 0xb3, 0x14, + 0xca, 0x88, 0x57, 0xda, 0x84, 0xa5, 0x01, 0x0e, 0xc2, 0x95, 0x1d, 0xc8, 0xcb, 0x6a, 0x96, 0x9e, + 0xac, 0x0d, 0xf7, 0x44, 0xe6, 0xa9, 0xf7, 0x82, 0x8d, 0xb7, 0xd3, 0x90, 0x17, 0xb8, 0x6f, 0xe0, + 0x73, 0x04, 0xc5, 0xbe, 0x8e, 0x89, 0xff, 0x19, 0x9e, 0x36, 0xed, 0x41, 0x28, 0xfd, 0x9b, 0x39, + 0x2e, 0x96, 0xa6, 0xee, 0x9c, 0x7d, 0xf8, 0xf8, 0x3c, 0x57, 0x51, 0xff, 0x4e, 0x3e, 0x84, 0xfa, + 0x05, 0x61, 0xfd, 0x24, 0x71, 0xb3, 0x4f, 0xf5, 0xc4, 0xd1, 0xea, 0x8c, 0xf0, 0xff, 0x92, 0x8f, + 0x44, 0x28, 0xa6, 0x9a, 0x55, 0x4c, 0x75, 0x4c, 0x31, 0xd5, 0xaf, 0x89, 0xc1, 0xd7, 0x32, 0x8b, + 0x39, 0xe9, 0xeb, 0x93, 0xa7, 0xf8, 0x35, 0x82, 0x85, 0xc1, 0xb6, 0x8b, 0x37, 0x47, 0x39, 0xf3, + 0xd4, 0x56, 0x5d, 0x5a, 0x96, 0xa1, 0xf2, 0x9d, 0xd7, 0x6e, 0x84, 0xef, 0xbc, 0x64, 0xbc, 0x76, + 0x79, 0xc6, 0xef, 0x10, 0xcc, 0x0f, 0xdc, 0x6a, 0xbc, 0x31, 0x6e, 0x43, 0x2c, 0x6d, 0x8e, 0x11, + 0x29, 0x0e, 0x61, 0x23, 0x92, 0x64, 0xe0, 0xbf, 0xb2, 0x4a, 0xc2, 0x2f, 0x10, 0x14, 0xfb, 0x2e, + 0xe0, 0x28, 0x15, 0x94, 0xd6, 0x35, 0x46, 0xa9, 0xa0, 0xd4, 0x9b, 0xae, 0xfe, 0x18, 0x91, 0x57, + 0xf0, 0x72, 0x3a, 0xf9, 0xca, 0x1b, 0x04, 0xbf, 0xb4, 0xe9, 0xf1, 0xd0, 0xf4, 0x95, 0xa2, 0xbc, + 0xe5, 0xfb, 0xe1, 0x81, 0xef, 0xa3, 0x7b, 0x37, 0x45, 0x88, 0x45, 0x1d, 0xd3, 0xb5, 0x34, 0xea, + 0x5b, 0xba, 0x45, 0xdc, 0xa8, 0x1c, 0xc4, 0x1f, 0xaa, 0xe9, 0xd9, 0xec, 0xcb, 0x3f, 0x8d, 0xff, + 0xf7, 0x01, 0x2f, 0x73, 0x4a, 0x35, 0xce, 0x77, 0x3d, 0x84, 0x65, 0xaf, 0xf1, 0xb5, 0x86, 0x71, + 0x2e, 0xa7, 0x0e, 0xa2, 0xa9, 0x03, 0x39, 0x75, 0xd0, 0x30, 0x5a, 0x53, 0xd1, 0x7e, 0xeb, 0x9f, + 0x02, 0x00, 0x00, 0xff, 0xff, 0x52, 0x23, 0xb7, 0x95, 0x14, 0x0b, 0x00, 0x00, } diff --git a/vendor/google.golang.org/genproto/googleapis/devtools/remoteworkers/v1test2/bots.pb.go b/vendor/google.golang.org/genproto/googleapis/devtools/remoteworkers/v1test2/bots.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..604399a1235e34d4cb2ad397f0371075911abf04 --- /dev/null +++ b/vendor/google.golang.org/genproto/googleapis/devtools/remoteworkers/v1test2/bots.pb.go @@ -0,0 +1,1015 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: google/devtools/remoteworkers/v1test2/bots.proto + +/* +Package remoteworkers is a generated protocol buffer package. + +It is generated from these files: + google/devtools/remoteworkers/v1test2/bots.proto + google/devtools/remoteworkers/v1test2/command.proto + google/devtools/remoteworkers/v1test2/tasks.proto + +It has these top-level messages: + BotSession + Lease + Worker + Device + AdminTemp + CreateBotSessionRequest + UpdateBotSessionRequest + PostBotEventTempRequest + CommandTask + CommandOutputs + CommandOverhead + FileMetadata + DirectoryMetadata + Digest + Directory + Task + TaskResult + GetTaskRequest + UpdateTaskResultRequest + AddTaskLogRequest + AddTaskLogResponse +*/ +package remoteworkers + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import _ "google.golang.org/genproto/googleapis/api/annotations" +import google_protobuf1 "github.com/golang/protobuf/ptypes/any" +import google_protobuf2 "github.com/golang/protobuf/ptypes/empty" +import google_protobuf3 "google.golang.org/genproto/protobuf/field_mask" +import google_protobuf4 "github.com/golang/protobuf/ptypes/timestamp" +import google_rpc "google.golang.org/genproto/googleapis/rpc/status" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +// A coarse description of the status of the bot that the server uses to +// determine whether to assign the bot new leases. +type BotStatus int32 + +const ( + // Default value; do not use. + BotStatus_BOT_STATUS_UNSPECIFIED BotStatus = 0 + // The bot is healthy, and will accept leases as normal. + BotStatus_OK BotStatus = 1 + // The bot is unhealthy and will not accept new leases. For example, the bot + // may have detected that available disk space is too low. This situation may + // resolve itself, but will typically require human intervention. + BotStatus_UNHEALTHY BotStatus = 2 + // The bot has been asked to reboot the host. The bot will not accept new + // leases; once all leases are complete, this session will no longer be + // updated but the bot will be expected to establish a new session after the + // reboot completes. + BotStatus_HOST_REBOOTING BotStatus = 3 + // The bot has been asked to shut down. As with HOST_REBOOTING, once all + // leases are completed, the session will no longer be updated and the bot + // will not be expected to establish a new session. + // + // Bots are typically only asked to shut down if its host computer will be + // modified in some way, such as deleting a VM. + BotStatus_BOT_TERMINATING BotStatus = 4 +) + +var BotStatus_name = map[int32]string{ + 0: "BOT_STATUS_UNSPECIFIED", + 1: "OK", + 2: "UNHEALTHY", + 3: "HOST_REBOOTING", + 4: "BOT_TERMINATING", +} +var BotStatus_value = map[string]int32{ + "BOT_STATUS_UNSPECIFIED": 0, + "OK": 1, + "UNHEALTHY": 2, + "HOST_REBOOTING": 3, + "BOT_TERMINATING": 4, +} + +func (x BotStatus) String() string { + return proto.EnumName(BotStatus_name, int32(x)) +} +func (BotStatus) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +// The state of the lease. All leases start in the PENDING state. A bot can +// change PENDING to ACTIVE or (in the case of an error) COMPLETED, or from +// ACTIVE to COMPLETED. The server can change PENDING or ACTIVE to CANCELLED if +// it wants the bot to release its resources - for example, if the bot needs to +// be quarantined (it's producing bad output) or a cell needs to be drained. +type LeaseState int32 + +const ( + // Default value; do not use. + LeaseState_LEASE_STATE_UNSPECIFIED LeaseState = 0 + // Pending: the server expects the bot to accept this lease. This may only be + // set by the server. + LeaseState_PENDING LeaseState = 1 + // Active: the bot has accepted this lease. This may only be set by the bot. + LeaseState_ACTIVE LeaseState = 2 + // Completed: the bot is no longer leased. This may only be set by the bot, + // and the status field must be populated iff the state is COMPLETED. + LeaseState_COMPLETED LeaseState = 4 + // Cancelled: The bot should immediately release all resources associated with + // the lease. This may only be set by the server. + LeaseState_CANCELLED LeaseState = 5 +) + +var LeaseState_name = map[int32]string{ + 0: "LEASE_STATE_UNSPECIFIED", + 1: "PENDING", + 2: "ACTIVE", + 4: "COMPLETED", + 5: "CANCELLED", +} +var LeaseState_value = map[string]int32{ + "LEASE_STATE_UNSPECIFIED": 0, + "PENDING": 1, + "ACTIVE": 2, + "COMPLETED": 4, + "CANCELLED": 5, +} + +func (x LeaseState) String() string { + return proto.EnumName(LeaseState_name, int32(x)) +} +func (LeaseState) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +// Possible administration actions. +type AdminTemp_Command int32 + +const ( + // Illegal value. + AdminTemp_UNSPECIFIED AdminTemp_Command = 0 + // Download and run a new version of the bot. `arg` will be a resource + // accessible via `ByteStream.Read` to obtain the new bot code. + AdminTemp_BOT_UPDATE AdminTemp_Command = 1 + // Restart the bot without downloading a new version. `arg` will be a + // message to log. + AdminTemp_BOT_RESTART AdminTemp_Command = 2 + // Shut down the bot. `arg` will be a task resource name (similar to those + // in tasks.proto) that the bot can use to tell the server that it is + // terminating. + AdminTemp_BOT_TERMINATE AdminTemp_Command = 3 + // Restart the host computer. `arg` will be a message to log. + AdminTemp_HOST_RESTART AdminTemp_Command = 4 +) + +var AdminTemp_Command_name = map[int32]string{ + 0: "UNSPECIFIED", + 1: "BOT_UPDATE", + 2: "BOT_RESTART", + 3: "BOT_TERMINATE", + 4: "HOST_RESTART", +} +var AdminTemp_Command_value = map[string]int32{ + "UNSPECIFIED": 0, + "BOT_UPDATE": 1, + "BOT_RESTART": 2, + "BOT_TERMINATE": 3, + "HOST_RESTART": 4, +} + +func (x AdminTemp_Command) String() string { + return proto.EnumName(AdminTemp_Command_name, int32(x)) +} +func (AdminTemp_Command) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{4, 0} } + +// Types of bot events. +type PostBotEventTempRequest_Type int32 + +const ( + // Illegal value. + PostBotEventTempRequest_UNSPECIFIED PostBotEventTempRequest_Type = 0 + // Interesting but harmless event. + PostBotEventTempRequest_INFO PostBotEventTempRequest_Type = 1 + // Error condition. + PostBotEventTempRequest_ERROR PostBotEventTempRequest_Type = 2 +) + +var PostBotEventTempRequest_Type_name = map[int32]string{ + 0: "UNSPECIFIED", + 1: "INFO", + 2: "ERROR", +} +var PostBotEventTempRequest_Type_value = map[string]int32{ + "UNSPECIFIED": 0, + "INFO": 1, + "ERROR": 2, +} + +func (x PostBotEventTempRequest_Type) String() string { + return proto.EnumName(PostBotEventTempRequest_Type_name, int32(x)) +} +func (PostBotEventTempRequest_Type) EnumDescriptor() ([]byte, []int) { + return fileDescriptor0, []int{7, 0} +} + +// A bot session represents the state of a bot while in continuous contact with +// the server for a period of time. The session includes information about the +// worker - that is, the *worker* (the physical or virtual hardware) is +// considered to be a property of the bot (the software agent running on that +// hardware), which is the reverse of real life, but more natural from the point +// of the view of this API, which communicates solely with the bot and not +// directly with the underlying worker. +type BotSession struct { + // The bot session name, as selected by the server. Output only during a call + // to CreateBotSession. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // A unique bot ID within the farm used to persistently identify this bot over + // time (i.e., over multiple sessions). This ID must be unique within a + // farm. Typically, the bot ID will be the same as the name of the primary + // device in the worker (e.g., what you'd get from typing `uname -n` on *nix), + // but this is not required since a single device may allow multiple bots to + // run on it, each with access to different resources. What is important is + // that this ID is meaningful to humans, who might need to hunt a physical + // machine down to fix it. + // + // When CreateBotSession is successfully called with a bot_id, all prior + // sessions with the same ID are invalidated. If a bot attempts to update an + // invalid session, the server must reject that request, and may also + // quarantine the other bot with the same bot IDs (ie, stop sending it new + // leases and alert an admin). + BotId string `protobuf:"bytes,2,opt,name=bot_id,json=botId" json:"bot_id,omitempty"` + // The status of the bot. This must be populated in every call to + // UpdateBotSession. + Status BotStatus `protobuf:"varint,3,opt,name=status,enum=google.devtools.remoteworkers.v1test2.BotStatus" json:"status,omitempty"` + // A description of the worker hosting this bot. The Worker message is used + // here in the Status context (see Worker for more information). If multiple + // bots are running on the worker, this field should only describe the + // resources accessible from this bot. + // + // During the call to CreateBotSession, the server may make arbitrary changes + // to the worker's `server_properties` field (see that field for more + // information). Otherwise, this field is input-only. + Worker *Worker `protobuf:"bytes,4,opt,name=worker" json:"worker,omitempty"` + // A list of all leases that are a part of this session. See the Lease message + // for details. + Leases []*Lease `protobuf:"bytes,5,rep,name=leases" json:"leases,omitempty"` + // The time at which this bot session will expire, unless the bot calls + // UpdateBotSession again. Output only. + ExpireTime *google_protobuf4.Timestamp `protobuf:"bytes,6,opt,name=expire_time,json=expireTime" json:"expire_time,omitempty"` + // The version of the bot code currently running. The server may use this + // information to issue an admin action to tell the bot to update itself. + Version string `protobuf:"bytes,7,opt,name=version" json:"version,omitempty"` +} + +func (m *BotSession) Reset() { *m = BotSession{} } +func (m *BotSession) String() string { return proto.CompactTextString(m) } +func (*BotSession) ProtoMessage() {} +func (*BotSession) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +func (m *BotSession) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *BotSession) GetBotId() string { + if m != nil { + return m.BotId + } + return "" +} + +func (m *BotSession) GetStatus() BotStatus { + if m != nil { + return m.Status + } + return BotStatus_BOT_STATUS_UNSPECIFIED +} + +func (m *BotSession) GetWorker() *Worker { + if m != nil { + return m.Worker + } + return nil +} + +func (m *BotSession) GetLeases() []*Lease { + if m != nil { + return m.Leases + } + return nil +} + +func (m *BotSession) GetExpireTime() *google_protobuf4.Timestamp { + if m != nil { + return m.ExpireTime + } + return nil +} + +func (m *BotSession) GetVersion() string { + if m != nil { + return m.Version + } + return "" +} + +// A Lease is a lease that the scheduler has assigned to this bot. If the bot +// notices (by UpdateBotSession) that it has any leases in the PENDING state, it +// should call UpdateBotSession to put the leases into the ACTIVE state and +// start executing their assignments. +// +// All fields in this message are output-only, *except* the `state` and `status` +// fields. Note that repeated fields can only be updated as a unit, so on every +// update the bot must provide an update for *all* the leases the server expects +// it to report on. +// +// The scheduler *should* ensure that all leases scheduled to a bot can actually +// be accepted, but race conditions may occur. In such cases, the bot should +// attempt to accept the leases in the order they are listed by the server, to +// allow the server to control priorities. +// +// The server will remove COMPLETED leases from time to time, after which the +// bot shouldn't report on them any more (the server will ignore superfluous +// COMPLETED records). +type Lease struct { + // The assignment, which is typically a resource that can be accessed through + // some other services. The assignment must be meaningful to the bot based + // solely on this name, either because the bot only understands one type of + // assignment (e.g., tasks served through the Tasks interface) or through some + // implementation-defined schema. + // + // For example, if the worker is executing a Task as defined by the Tasks + // interface, this field might be projects/{projectid}/tasks/{taskid}. + // However, it the worker is being assigned pull from a *queue* of tasks, the + // resource would be the name of the queue, something like + // projects/{projectid}/locations/{locationid}/queues/{queueid}. That queue + // may then provide the bot with tasks through another interface, which the + // bot then processes through the [Tasks] + // [google.devtools.remoteworkers.v1test2.Tasks] interface. + // + // Note that the assignment may be a [full resource name] + // [https://cloud.google.com/apis/design/resource_names#full_resource_name] if + // it should be accessed through an endpoint that is not already known to the + // bot. + Assignment string `protobuf:"bytes,1,opt,name=assignment" json:"assignment,omitempty"` + // The state of the lease. See LeaseState for more information. + State LeaseState `protobuf:"varint,2,opt,name=state,enum=google.devtools.remoteworkers.v1test2.LeaseState" json:"state,omitempty"` + // The final status of the lease (should be populated by the bot if the state + // is completed). This is the status of the lease, not of any task represented + // by the lease. For example, if the bot could not accept the lease because it + // asked for some resource the bot didn't have, this status will be + // FAILED_PRECONDITION. But if the assignment in the lease didn't execute + // correctly, this field will be `OK` while the failure of the assignment must + // be tracked elsewhere (e.g., through the Tasks interface). + Status *google_rpc.Status `protobuf:"bytes,3,opt,name=status" json:"status,omitempty"` + // The requirements that are being claimed by this lease. This field may be + // omitted by the server if the lease is not pending. + Requirements *Worker `protobuf:"bytes,4,opt,name=requirements" json:"requirements,omitempty"` + // The time at which this lease expires. The server *may* extend this over + // time, but due to race conditions, the bot is not *required* to respect any + // expiry date except the first one. + ExpireTime *google_protobuf4.Timestamp `protobuf:"bytes,5,opt,name=expire_time,json=expireTime" json:"expire_time,omitempty"` + // While the `assignment` field is a resource name that allows the bot to + // get the actual assignment, the server can also optionally include the + // assignment itself inline in order to save a round trip to the server. + // + // This doesn't necessarily need to be the resource pointed to by + // `assignment`. For example, if the assignment is a task, this field could + // be task.description, not the entire task, since that's all the bot needs + // to know to get started. As with `assignment` itself, all that's necessary + // is that the bot knows how to handle the type of message received here. + // + // This field may be omitted by the server if the lease is not in the + // `PENDING` state. + InlineAssignment *google_protobuf1.Any `protobuf:"bytes,6,opt,name=inline_assignment,json=inlineAssignment" json:"inline_assignment,omitempty"` +} + +func (m *Lease) Reset() { *m = Lease{} } +func (m *Lease) String() string { return proto.CompactTextString(m) } +func (*Lease) ProtoMessage() {} +func (*Lease) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +func (m *Lease) GetAssignment() string { + if m != nil { + return m.Assignment + } + return "" +} + +func (m *Lease) GetState() LeaseState { + if m != nil { + return m.State + } + return LeaseState_LEASE_STATE_UNSPECIFIED +} + +func (m *Lease) GetStatus() *google_rpc.Status { + if m != nil { + return m.Status + } + return nil +} + +func (m *Lease) GetRequirements() *Worker { + if m != nil { + return m.Requirements + } + return nil +} + +func (m *Lease) GetExpireTime() *google_protobuf4.Timestamp { + if m != nil { + return m.ExpireTime + } + return nil +} + +func (m *Lease) GetInlineAssignment() *google_protobuf1.Any { + if m != nil { + return m.InlineAssignment + } + return nil +} + +// Describes a worker, which is a list of one or more devices and the +// connections between them. A device could be a computer, a phone, or even an +// accelerator like a GPU; it's up to the farm administrator to decide how to +// model their farm. For example, if a farm only has one type of GPU, the GPU +// could be modelled as a "has_gpu" property on its host computer; if it has +// many subproperties itself, it might be better to model it as a separate +// device. +// +// The first device in the worker is the "primary device" - that is, the device +// running a bot and which is responsible for actually executing commands. All +// other devices are considered to be attached devices, and must be controllable +// by the primary device. +// +// This message (and all its submessages) can be used in two contexts: +// +// * Status: sent by the bot to report the current capabilities of the device to +// allow reservation matching. +// * Request: sent by a client to request a device with certain capabilities in +// a reservation. +// +// Several of the fields in this message have different semantics depending on +// which of which of these contexts it is used. These semantics are described +// below. +// +// Several messages in Worker and its submessages have the concept of keys and +// values, such as `Worker.Property` and `Device.Property`. All keys are simple +// strings, but certain keys are "standard" keys and should be broadly supported +// across farms and implementations; these are listed below each relevant +// message. Bot implementations or farm admins may add *additional* keys, but +// these SHOULD all begin with an underscore so they do not conflict with +// standard keys that may be added in the future. +// +// Keys are not context sensitive. +// +// See http://goo.gl/NurY8g for more information on the Worker message. +type Worker struct { + // A list of devices; the first device is the primary device. See the `Device` + // message for more information. + Devices []*Device `protobuf:"bytes,1,rep,name=devices" json:"devices,omitempty"` + // A worker may contain "global" properties. For example, certain machines + // might be reserved for certain types of jobs, like short-running compilation + // versus long-running integration tests. This property is known as a "pool" + // and is not related to any one device within the worker; rather, it applies + // to the worker as a whole. + // + // The behaviour of repeated keys is identical to that of Device.Property. + Properties []*Worker_Property `protobuf:"bytes,2,rep,name=properties" json:"properties,omitempty"` +} + +func (m *Worker) Reset() { *m = Worker{} } +func (m *Worker) String() string { return proto.CompactTextString(m) } +func (*Worker) ProtoMessage() {} +func (*Worker) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } + +func (m *Worker) GetDevices() []*Device { + if m != nil { + return m.Devices + } + return nil +} + +func (m *Worker) GetProperties() []*Worker_Property { + if m != nil { + return m.Properties + } + return nil +} + +// A global property; see the `properties` field for more information. +type Worker_Property struct { + // For general information on keys, see the documentation to `Worker`. + // + // The current set of standard keys are: + // + // * pool: different workers can be reserved for different purposes. For + // example, an admin might want to segregate long-running integration tests + // from short-running unit tests, so unit tests will always get some + // throughput. To support this, the server can assign different values for + // `pool` (such as "itest" and "utest") to different workers, and then have + // jobs request workers from those pools. + Key string `protobuf:"bytes,1,opt,name=key" json:"key,omitempty"` + // The property's value. + Value string `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"` +} + +func (m *Worker_Property) Reset() { *m = Worker_Property{} } +func (m *Worker_Property) String() string { return proto.CompactTextString(m) } +func (*Worker_Property) ProtoMessage() {} +func (*Worker_Property) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2, 0} } + +func (m *Worker_Property) GetKey() string { + if m != nil { + return m.Key + } + return "" +} + +func (m *Worker_Property) GetValue() string { + if m != nil { + return m.Value + } + return "" +} + +// Any device, including computers, phones, accelerators (e.g. GPUs), etc. All +// names must be unique. +type Device struct { + // The handle can be thought of as the "name" of the device, and must be + // unique within a Worker. + // + // In the Status context, the handle should be some human-understandable name, + // perhaps corresponding to a label physically written on the device to make + // it easy to locate. In the Request context, the name should be the + // *logical* name expected by the task. The bot is responsible for mapping the + // logical name expected by the task to a machine-readable name that the task + // can actually use, such as a USB address. The method by which this mapping + // is communicated to the task is not covered in this API. + Handle string `protobuf:"bytes,1,opt,name=handle" json:"handle,omitempty"` + // Properties of this device that don't change based on the tasks that are + // running on it, e.g. OS, CPU architecture, etc. + // + // Keys may be repeated, and have the following interpretation: + // + // * Status context: the device can support *any* the listed values. For + // example, an "ISA" property might include "x86", "x86-64" and "sse4". + // + // * Request context: the device *must* support *all* of the listed values. + Properties []*Device_Property `protobuf:"bytes,2,rep,name=properties" json:"properties,omitempty"` +} + +func (m *Device) Reset() { *m = Device{} } +func (m *Device) String() string { return proto.CompactTextString(m) } +func (*Device) ProtoMessage() {} +func (*Device) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } + +func (m *Device) GetHandle() string { + if m != nil { + return m.Handle + } + return "" +} + +func (m *Device) GetProperties() []*Device_Property { + if m != nil { + return m.Properties + } + return nil +} + +// A device property; see `properties` for more information. +type Device_Property struct { + // For general information on keys, see the documentation to `Worker`. + // + // The current set of standard keys are: + // + // * os: a human-readable description of the OS. Examples include `linux`, + // `ubuntu` and `ubuntu 14.04` (note that a bot may advertise itself as more + // than one). This will be replaced in the future by more well-structured + // keys and values to represent OS variants. + // + // * has-docker: "true" if the bot has Docker installed. This will be + // replaced in the future by a more structured message for Docker support. + Key string `protobuf:"bytes,1,opt,name=key" json:"key,omitempty"` + // The property's value. + Value string `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"` +} + +func (m *Device_Property) Reset() { *m = Device_Property{} } +func (m *Device_Property) String() string { return proto.CompactTextString(m) } +func (*Device_Property) ProtoMessage() {} +func (*Device_Property) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3, 0} } + +func (m *Device_Property) GetKey() string { + if m != nil { + return m.Key + } + return "" +} + +func (m *Device_Property) GetValue() string { + if m != nil { + return m.Value + } + return "" +} + +// AdminTemp is a prelimiary set of administration tasks. It's called "Temp" +// because we do not yet know the best way to represent admin tasks; it's +// possible that this will be entirely replaced in later versions of this API. +// If this message proves to be sufficient, it will be renamed in the alpha or +// beta release of this API. +// +// This message (suitably marshalled into a protobuf.Any) can be used as the +// inline_assignment field in a lease; the lease assignment field should simply +// be `"admin"` in these cases. +// +// This message is heavily based on Swarming administration tasks from the LUCI +// project (http://github.com/luci/luci-py/appengine/swarming). +type AdminTemp struct { + // The admin action; see `Command` for legal values. + Command AdminTemp_Command `protobuf:"varint,1,opt,name=command,enum=google.devtools.remoteworkers.v1test2.AdminTemp_Command" json:"command,omitempty"` + // The argument to the admin action; see `Command` for semantics. + Arg string `protobuf:"bytes,2,opt,name=arg" json:"arg,omitempty"` +} + +func (m *AdminTemp) Reset() { *m = AdminTemp{} } +func (m *AdminTemp) String() string { return proto.CompactTextString(m) } +func (*AdminTemp) ProtoMessage() {} +func (*AdminTemp) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } + +func (m *AdminTemp) GetCommand() AdminTemp_Command { + if m != nil { + return m.Command + } + return AdminTemp_UNSPECIFIED +} + +func (m *AdminTemp) GetArg() string { + if m != nil { + return m.Arg + } + return "" +} + +// Request message for CreateBotSession. +type CreateBotSessionRequest struct { + // The farm resource. + Parent string `protobuf:"bytes,1,opt,name=parent" json:"parent,omitempty"` + // The bot session to create. Server-assigned fields like name must be unset. + BotSession *BotSession `protobuf:"bytes,2,opt,name=bot_session,json=botSession" json:"bot_session,omitempty"` +} + +func (m *CreateBotSessionRequest) Reset() { *m = CreateBotSessionRequest{} } +func (m *CreateBotSessionRequest) String() string { return proto.CompactTextString(m) } +func (*CreateBotSessionRequest) ProtoMessage() {} +func (*CreateBotSessionRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } + +func (m *CreateBotSessionRequest) GetParent() string { + if m != nil { + return m.Parent + } + return "" +} + +func (m *CreateBotSessionRequest) GetBotSession() *BotSession { + if m != nil { + return m.BotSession + } + return nil +} + +// Request message for UpdateBotSession. +type UpdateBotSessionRequest struct { + // The bot session name. Must match bot_session.name. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // The bot session resource to update. + BotSession *BotSession `protobuf:"bytes,2,opt,name=bot_session,json=botSession" json:"bot_session,omitempty"` + // The fields on the bot that should be updated. See the BotSession resource + // for which fields are updatable by which caller. + UpdateMask *google_protobuf3.FieldMask `protobuf:"bytes,3,opt,name=update_mask,json=updateMask" json:"update_mask,omitempty"` +} + +func (m *UpdateBotSessionRequest) Reset() { *m = UpdateBotSessionRequest{} } +func (m *UpdateBotSessionRequest) String() string { return proto.CompactTextString(m) } +func (*UpdateBotSessionRequest) ProtoMessage() {} +func (*UpdateBotSessionRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } + +func (m *UpdateBotSessionRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *UpdateBotSessionRequest) GetBotSession() *BotSession { + if m != nil { + return m.BotSession + } + return nil +} + +func (m *UpdateBotSessionRequest) GetUpdateMask() *google_protobuf3.FieldMask { + if m != nil { + return m.UpdateMask + } + return nil +} + +// Request message for PostBotEventTemp +type PostBotEventTempRequest struct { + // The bot session name. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // The type of bot event. + Type PostBotEventTempRequest_Type `protobuf:"varint,2,opt,name=type,enum=google.devtools.remoteworkers.v1test2.PostBotEventTempRequest_Type" json:"type,omitempty"` + // A human-readable message. + Msg string `protobuf:"bytes,3,opt,name=msg" json:"msg,omitempty"` +} + +func (m *PostBotEventTempRequest) Reset() { *m = PostBotEventTempRequest{} } +func (m *PostBotEventTempRequest) String() string { return proto.CompactTextString(m) } +func (*PostBotEventTempRequest) ProtoMessage() {} +func (*PostBotEventTempRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } + +func (m *PostBotEventTempRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *PostBotEventTempRequest) GetType() PostBotEventTempRequest_Type { + if m != nil { + return m.Type + } + return PostBotEventTempRequest_UNSPECIFIED +} + +func (m *PostBotEventTempRequest) GetMsg() string { + if m != nil { + return m.Msg + } + return "" +} + +func init() { + proto.RegisterType((*BotSession)(nil), "google.devtools.remoteworkers.v1test2.BotSession") + proto.RegisterType((*Lease)(nil), "google.devtools.remoteworkers.v1test2.Lease") + proto.RegisterType((*Worker)(nil), "google.devtools.remoteworkers.v1test2.Worker") + proto.RegisterType((*Worker_Property)(nil), "google.devtools.remoteworkers.v1test2.Worker.Property") + proto.RegisterType((*Device)(nil), "google.devtools.remoteworkers.v1test2.Device") + proto.RegisterType((*Device_Property)(nil), "google.devtools.remoteworkers.v1test2.Device.Property") + proto.RegisterType((*AdminTemp)(nil), "google.devtools.remoteworkers.v1test2.AdminTemp") + proto.RegisterType((*CreateBotSessionRequest)(nil), "google.devtools.remoteworkers.v1test2.CreateBotSessionRequest") + proto.RegisterType((*UpdateBotSessionRequest)(nil), "google.devtools.remoteworkers.v1test2.UpdateBotSessionRequest") + proto.RegisterType((*PostBotEventTempRequest)(nil), "google.devtools.remoteworkers.v1test2.PostBotEventTempRequest") + proto.RegisterEnum("google.devtools.remoteworkers.v1test2.BotStatus", BotStatus_name, BotStatus_value) + proto.RegisterEnum("google.devtools.remoteworkers.v1test2.LeaseState", LeaseState_name, LeaseState_value) + proto.RegisterEnum("google.devtools.remoteworkers.v1test2.AdminTemp_Command", AdminTemp_Command_name, AdminTemp_Command_value) + proto.RegisterEnum("google.devtools.remoteworkers.v1test2.PostBotEventTempRequest_Type", PostBotEventTempRequest_Type_name, PostBotEventTempRequest_Type_value) +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// Client API for Bots service + +type BotsClient interface { + // CreateBotSession is called when the bot first joins the farm, and + // establishes a session ID to ensure that multiple machines do not register + // using the same name accidentally. + CreateBotSession(ctx context.Context, in *CreateBotSessionRequest, opts ...grpc.CallOption) (*BotSession, error) + // UpdateBotSession must be called periodically by the bot (on a schedule + // determined by the server) to let the server know about its status, and to + // pick up new lease requests from the server. + UpdateBotSession(ctx context.Context, in *UpdateBotSessionRequest, opts ...grpc.CallOption) (*BotSession, error) + // PostBotEventTemp may be called by the bot to indicate that some exceptional + // event has occurred. This method is subject to change or removal in future + // revisions of this API; we may simply want to replace it with StackDriver or + // some other common interface. + PostBotEventTemp(ctx context.Context, in *PostBotEventTempRequest, opts ...grpc.CallOption) (*google_protobuf2.Empty, error) +} + +type botsClient struct { + cc *grpc.ClientConn +} + +func NewBotsClient(cc *grpc.ClientConn) BotsClient { + return &botsClient{cc} +} + +func (c *botsClient) CreateBotSession(ctx context.Context, in *CreateBotSessionRequest, opts ...grpc.CallOption) (*BotSession, error) { + out := new(BotSession) + err := grpc.Invoke(ctx, "/google.devtools.remoteworkers.v1test2.Bots/CreateBotSession", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *botsClient) UpdateBotSession(ctx context.Context, in *UpdateBotSessionRequest, opts ...grpc.CallOption) (*BotSession, error) { + out := new(BotSession) + err := grpc.Invoke(ctx, "/google.devtools.remoteworkers.v1test2.Bots/UpdateBotSession", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *botsClient) PostBotEventTemp(ctx context.Context, in *PostBotEventTempRequest, opts ...grpc.CallOption) (*google_protobuf2.Empty, error) { + out := new(google_protobuf2.Empty) + err := grpc.Invoke(ctx, "/google.devtools.remoteworkers.v1test2.Bots/PostBotEventTemp", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for Bots service + +type BotsServer interface { + // CreateBotSession is called when the bot first joins the farm, and + // establishes a session ID to ensure that multiple machines do not register + // using the same name accidentally. + CreateBotSession(context.Context, *CreateBotSessionRequest) (*BotSession, error) + // UpdateBotSession must be called periodically by the bot (on a schedule + // determined by the server) to let the server know about its status, and to + // pick up new lease requests from the server. + UpdateBotSession(context.Context, *UpdateBotSessionRequest) (*BotSession, error) + // PostBotEventTemp may be called by the bot to indicate that some exceptional + // event has occurred. This method is subject to change or removal in future + // revisions of this API; we may simply want to replace it with StackDriver or + // some other common interface. + PostBotEventTemp(context.Context, *PostBotEventTempRequest) (*google_protobuf2.Empty, error) +} + +func RegisterBotsServer(s *grpc.Server, srv BotsServer) { + s.RegisterService(&_Bots_serviceDesc, srv) +} + +func _Bots_CreateBotSession_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateBotSessionRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(BotsServer).CreateBotSession(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.devtools.remoteworkers.v1test2.Bots/CreateBotSession", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(BotsServer).CreateBotSession(ctx, req.(*CreateBotSessionRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Bots_UpdateBotSession_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdateBotSessionRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(BotsServer).UpdateBotSession(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.devtools.remoteworkers.v1test2.Bots/UpdateBotSession", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(BotsServer).UpdateBotSession(ctx, req.(*UpdateBotSessionRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Bots_PostBotEventTemp_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PostBotEventTempRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(BotsServer).PostBotEventTemp(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.devtools.remoteworkers.v1test2.Bots/PostBotEventTemp", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(BotsServer).PostBotEventTemp(ctx, req.(*PostBotEventTempRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Bots_serviceDesc = grpc.ServiceDesc{ + ServiceName: "google.devtools.remoteworkers.v1test2.Bots", + HandlerType: (*BotsServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "CreateBotSession", + Handler: _Bots_CreateBotSession_Handler, + }, + { + MethodName: "UpdateBotSession", + Handler: _Bots_UpdateBotSession_Handler, + }, + { + MethodName: "PostBotEventTemp", + Handler: _Bots_PostBotEventTemp_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "google/devtools/remoteworkers/v1test2/bots.proto", +} + +func init() { proto.RegisterFile("google/devtools/remoteworkers/v1test2/bots.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 1083 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x56, 0xdd, 0x8e, 0xdb, 0x44, + 0x14, 0xc6, 0xd9, 0xc4, 0x69, 0x4e, 0xda, 0xad, 0x3b, 0x94, 0x6e, 0x48, 0x11, 0x44, 0x96, 0x90, + 0x56, 0x51, 0xb1, 0xdb, 0x20, 0x10, 0x6a, 0x55, 0x24, 0x27, 0xf1, 0xee, 0x46, 0x64, 0x93, 0x30, + 0xf1, 0xb6, 0x82, 0x9b, 0xd4, 0xd9, 0x4c, 0x83, 0xb5, 0xb1, 0xc7, 0xf5, 0x4c, 0x02, 0x11, 0xea, + 0x0d, 0x12, 0x4f, 0xc0, 0x13, 0x70, 0xc7, 0x05, 0x8f, 0x80, 0xb8, 0xe4, 0x05, 0x7a, 0xcd, 0x1d, + 0x5c, 0xf3, 0x0a, 0x68, 0xc6, 0x76, 0xfe, 0xb6, 0x4b, 0xb3, 0x14, 0xee, 0xe6, 0xe7, 0x7c, 0xdf, + 0xf9, 0xfc, 0xcd, 0x39, 0xe3, 0x81, 0xbb, 0x63, 0x4a, 0xc7, 0x13, 0x62, 0x8e, 0xc8, 0x8c, 0x53, + 0x3a, 0x61, 0x66, 0x44, 0x7c, 0xca, 0xc9, 0xd7, 0x34, 0x3a, 0x23, 0x11, 0x33, 0x67, 0xf7, 0x38, + 0x61, 0xbc, 0x66, 0x0e, 0x29, 0x67, 0x46, 0x18, 0x51, 0x4e, 0xd1, 0xfb, 0x31, 0xc2, 0x48, 0x11, + 0xc6, 0x1a, 0xc2, 0x48, 0x10, 0xe5, 0x77, 0x12, 0x62, 0x37, 0xf4, 0x4c, 0x37, 0x08, 0x28, 0x77, + 0xb9, 0x47, 0x83, 0x84, 0xa4, 0xfc, 0x76, 0xb2, 0x2b, 0x67, 0xc3, 0xe9, 0x53, 0xd3, 0x0d, 0xe6, + 0xc9, 0xd6, 0xed, 0xcd, 0x2d, 0xe2, 0x87, 0x3c, 0xdd, 0xac, 0x6c, 0x6e, 0x3e, 0xf5, 0xc8, 0x64, + 0x34, 0xf0, 0x5d, 0x76, 0x96, 0x44, 0xbc, 0xb7, 0x19, 0xc1, 0x3d, 0x9f, 0x30, 0xee, 0xfa, 0x61, + 0x12, 0xb0, 0x97, 0x04, 0x44, 0xe1, 0xa9, 0xc9, 0xb8, 0xcb, 0xa7, 0x89, 0x26, 0xfd, 0xcf, 0x0c, + 0x40, 0x9d, 0xf2, 0x3e, 0x61, 0xcc, 0xa3, 0x01, 0x42, 0x90, 0x0d, 0x5c, 0x9f, 0x94, 0x94, 0x8a, + 0xb2, 0x5f, 0xc0, 0x72, 0x8c, 0xde, 0x02, 0x75, 0x48, 0xf9, 0xc0, 0x1b, 0x95, 0x32, 0x72, 0x35, + 0x37, 0xa4, 0xbc, 0x35, 0x42, 0x47, 0xa0, 0xc6, 0x4c, 0xa5, 0x9d, 0x8a, 0xb2, 0xbf, 0x5b, 0xbb, + 0x6b, 0x6c, 0xe5, 0x91, 0x21, 0xb2, 0x49, 0x1c, 0x4e, 0xf0, 0xc8, 0x06, 0x35, 0x0e, 0x2a, 0x65, + 0x2b, 0xca, 0x7e, 0xb1, 0xf6, 0xc1, 0x96, 0x4c, 0x8f, 0xe5, 0x1c, 0x27, 0x60, 0xd4, 0x04, 0x75, + 0x42, 0x5c, 0x46, 0x58, 0x29, 0x57, 0xd9, 0xd9, 0x2f, 0xd6, 0xee, 0x6c, 0x49, 0xd3, 0x16, 0x20, + 0x9c, 0x60, 0xd1, 0x03, 0x28, 0x92, 0x6f, 0x42, 0x2f, 0x22, 0x03, 0xe1, 0x61, 0x49, 0x95, 0x8a, + 0xca, 0x29, 0x55, 0x6a, 0xb0, 0xe1, 0xa4, 0x06, 0x63, 0x88, 0xc3, 0xc5, 0x02, 0x2a, 0x41, 0x7e, + 0x46, 0x22, 0xe1, 0x64, 0x29, 0x2f, 0xbd, 0x4a, 0xa7, 0xfa, 0x5f, 0x19, 0xc8, 0xc9, 0x44, 0xe8, + 0x5d, 0x00, 0x97, 0x31, 0x6f, 0x1c, 0xf8, 0x24, 0xe0, 0x89, 0xd1, 0x2b, 0x2b, 0xe8, 0x10, 0x72, + 0xc2, 0x17, 0x22, 0xdd, 0xde, 0xad, 0xdd, 0xbb, 0xcc, 0x57, 0x08, 0x63, 0x09, 0x8e, 0xf1, 0xa8, + 0xba, 0x76, 0x40, 0xc5, 0x1a, 0x4a, 0x99, 0xa2, 0xf0, 0xd4, 0xd8, 0x38, 0x82, 0xcf, 0xe1, 0x6a, + 0x44, 0x9e, 0x4d, 0xbd, 0x88, 0x08, 0x0d, 0xec, 0xdf, 0x1d, 0xc4, 0x1a, 0xc5, 0xa6, 0x91, 0xb9, + 0x4b, 0x19, 0x69, 0xc1, 0x0d, 0x2f, 0x98, 0x78, 0x01, 0x19, 0xac, 0x78, 0x15, 0x9f, 0xc5, 0xcd, + 0x73, 0x14, 0x56, 0x30, 0xc7, 0x5a, 0x1c, 0x6e, 0x2d, 0xa2, 0xf5, 0xdf, 0x15, 0x50, 0x63, 0x61, + 0xe8, 0x10, 0xf2, 0x23, 0x32, 0xf3, 0x4e, 0x09, 0x2b, 0x29, 0xb2, 0x34, 0xb6, 0xfd, 0xb0, 0xa6, + 0x44, 0xe1, 0x14, 0x8d, 0x1e, 0x01, 0x84, 0x11, 0x0d, 0x49, 0xc4, 0x3d, 0xc2, 0x4a, 0x19, 0xc9, + 0xf5, 0xf1, 0xa5, 0x4c, 0x32, 0x7a, 0x31, 0x7e, 0x8e, 0x57, 0x98, 0xca, 0x35, 0xb8, 0x92, 0xae, + 0x23, 0x0d, 0x76, 0xce, 0xc8, 0x3c, 0x29, 0x0c, 0x31, 0x44, 0x37, 0x21, 0x37, 0x73, 0x27, 0x53, + 0x92, 0xf6, 0x9f, 0x9c, 0xe8, 0x3f, 0x2b, 0xa0, 0xc6, 0xfa, 0xd0, 0x2d, 0x50, 0xbf, 0x72, 0x83, + 0xd1, 0x24, 0xed, 0xdb, 0x64, 0xf6, 0x5a, 0x72, 0x63, 0xea, 0xff, 0x4e, 0xee, 0x0b, 0x05, 0x0a, + 0xd6, 0xc8, 0xf7, 0x02, 0x87, 0xf8, 0x21, 0xc2, 0x90, 0x3f, 0xa5, 0xbe, 0xef, 0x06, 0x23, 0x89, + 0xdc, 0xad, 0x7d, 0xb2, 0xa5, 0xac, 0x05, 0x85, 0xd1, 0x88, 0xf1, 0x38, 0x25, 0x12, 0x4a, 0xdc, + 0x68, 0x9c, 0x64, 0x15, 0x43, 0xfd, 0x09, 0xe4, 0x93, 0x28, 0x74, 0x1d, 0x8a, 0x27, 0x9d, 0x7e, + 0xcf, 0x6e, 0xb4, 0x0e, 0x5a, 0x76, 0x53, 0x7b, 0x03, 0xed, 0x02, 0xd4, 0xbb, 0xce, 0xe0, 0xa4, + 0xd7, 0xb4, 0x1c, 0x5b, 0x53, 0x44, 0x80, 0x98, 0x63, 0xbb, 0xef, 0x58, 0xd8, 0xd1, 0x32, 0xe8, + 0x06, 0x5c, 0x13, 0x0b, 0x8e, 0x8d, 0x8f, 0x5b, 0x1d, 0x11, 0xb3, 0x83, 0x34, 0xb8, 0x7a, 0xd4, + 0xed, 0x2f, 0x83, 0xb2, 0xfa, 0xf7, 0x0a, 0xec, 0x35, 0x22, 0xe2, 0x72, 0xb2, 0xbc, 0x44, 0x31, + 0x79, 0x36, 0x25, 0x8c, 0x8b, 0x53, 0x09, 0xdd, 0x68, 0xd9, 0xe4, 0xc9, 0x0c, 0x61, 0x28, 0x8a, + 0xfb, 0x94, 0xc5, 0xd1, 0x52, 0x6f, 0x71, 0xeb, 0x36, 0x5f, 0x49, 0x03, 0xc3, 0xc5, 0x58, 0xff, + 0x55, 0x81, 0xbd, 0x93, 0x70, 0xf4, 0x52, 0x1d, 0x2f, 0xbb, 0xd3, 0xff, 0x07, 0x0d, 0xa2, 0xe1, + 0xa7, 0x52, 0x82, 0xfc, 0x33, 0x25, 0x97, 0xce, 0xf9, 0x86, 0x3f, 0x10, 0x3f, 0xaf, 0x63, 0x97, + 0x9d, 0x61, 0x88, 0xc3, 0xc5, 0x58, 0xff, 0x4d, 0x81, 0xbd, 0x1e, 0x65, 0xbc, 0x4e, 0xb9, 0x3d, + 0x23, 0x01, 0x17, 0x47, 0xfc, 0x4f, 0x1f, 0xf0, 0x18, 0xb2, 0x7c, 0x1e, 0xa6, 0x97, 0x64, 0x63, + 0x4b, 0xe5, 0x17, 0x64, 0x30, 0x9c, 0x79, 0x48, 0xb0, 0x24, 0x14, 0x55, 0xe4, 0xb3, 0xb1, 0x54, + 0x5f, 0xc0, 0x62, 0xa8, 0xdf, 0x81, 0xac, 0xd8, 0x3f, 0x5f, 0x42, 0x57, 0x20, 0xdb, 0xea, 0x1c, + 0x74, 0x35, 0x05, 0x15, 0x20, 0x67, 0x63, 0xdc, 0xc5, 0x5a, 0xa6, 0x3a, 0x86, 0xc2, 0xe2, 0x0f, + 0x87, 0xca, 0x70, 0x4b, 0xd4, 0x50, 0xdf, 0xb1, 0x9c, 0x93, 0xfe, 0x60, 0x1d, 0xad, 0x42, 0xa6, + 0xfb, 0x99, 0xa6, 0xa0, 0x6b, 0x50, 0x38, 0xe9, 0x1c, 0xd9, 0x56, 0xdb, 0x39, 0xfa, 0x42, 0xcb, + 0x20, 0x04, 0xbb, 0x49, 0x8d, 0xd5, 0xbb, 0x5d, 0xa7, 0xd5, 0x39, 0xd4, 0x76, 0xd0, 0x9b, 0x70, + 0x7d, 0xb5, 0x14, 0xc5, 0x62, 0xb6, 0xfa, 0x04, 0x60, 0x79, 0xe7, 0xa3, 0xdb, 0xb0, 0xd7, 0xb6, + 0xad, 0xbe, 0x2d, 0x73, 0xd9, 0x1b, 0xa9, 0x8a, 0x90, 0xef, 0xd9, 0x9d, 0xa6, 0xc0, 0x29, 0x08, + 0x40, 0xb5, 0x1a, 0x4e, 0xeb, 0x91, 0xad, 0x65, 0x44, 0xee, 0x46, 0xf7, 0xb8, 0xd7, 0xb6, 0x1d, + 0xbb, 0xa9, 0x65, 0xe5, 0xd4, 0xea, 0x34, 0xec, 0x76, 0xdb, 0x6e, 0x6a, 0xb9, 0xda, 0x4f, 0x59, + 0xc8, 0xd6, 0x29, 0x67, 0xe8, 0x17, 0x05, 0xb4, 0xcd, 0x2a, 0x47, 0x9f, 0x6e, 0xe9, 0xf9, 0x05, + 0xed, 0x51, 0xbe, 0x7c, 0xb5, 0xe9, 0x1f, 0x7d, 0xf7, 0xe2, 0x8f, 0x1f, 0x32, 0xa6, 0x5e, 0x59, + 0x3c, 0xd1, 0xbe, 0x8d, 0x7b, 0xea, 0x61, 0xb5, 0xfa, 0xdc, 0x5c, 0x96, 0x22, 0xbb, 0xbf, 0x5a, + 0xdd, 0x52, 0xfe, 0x66, 0x73, 0x6c, 0x2d, 0xff, 0x82, 0xae, 0x7a, 0x0d, 0xf9, 0xb5, 0x15, 0xf9, + 0xa2, 0x96, 0x1f, 0x56, 0xab, 0xab, 0xda, 0xcd, 0xea, 0xf3, 0x75, 0xf9, 0x3f, 0x2a, 0xa0, 0x6d, + 0x16, 0xee, 0xd6, 0xf2, 0x2f, 0xa8, 0xf8, 0xf2, 0xad, 0x73, 0x7d, 0x69, 0x8b, 0x17, 0xe7, 0xc2, + 0xe2, 0xea, 0x2b, 0x35, 0x86, 0x94, 0xc5, 0xb4, 0xf7, 0x95, 0x6a, 0xdd, 0xf9, 0x12, 0x27, 0x7c, + 0x63, 0x3a, 0x71, 0x83, 0xb1, 0x41, 0xa3, 0xb1, 0x39, 0x26, 0x81, 0x64, 0x37, 0xe3, 0x2d, 0x37, + 0xf4, 0xd8, 0x2b, 0x9e, 0xdc, 0x0f, 0xd6, 0x56, 0x87, 0xaa, 0x84, 0x7f, 0xf8, 0x77, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x7c, 0xc5, 0x7e, 0x38, 0xb0, 0x0b, 0x00, 0x00, +} diff --git a/vendor/google.golang.org/genproto/googleapis/devtools/remoteworkers/v1test2/command.pb.go b/vendor/google.golang.org/genproto/googleapis/devtools/remoteworkers/v1test2/command.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..f5b50095eaa96173352a6cdc1c9b07258e3ceb96 --- /dev/null +++ b/vendor/google.golang.org/genproto/googleapis/devtools/remoteworkers/v1test2/command.pb.go @@ -0,0 +1,468 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: google/devtools/remoteworkers/v1test2/command.proto + +package remoteworkers + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import google_protobuf5 "github.com/golang/protobuf/ptypes/duration" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// Describes a shell-style task to execute. +type CommandTask struct { + // The inputs to the task. + Inputs *CommandTask_Inputs `protobuf:"bytes,1,opt,name=inputs" json:"inputs,omitempty"` + // The expected outputs from the task. + ExpectedOutputs *CommandTask_Outputs `protobuf:"bytes,4,opt,name=expected_outputs,json=expectedOutputs" json:"expected_outputs,omitempty"` + // The timeouts of this task. + Timeouts *CommandTask_Timeouts `protobuf:"bytes,5,opt,name=timeouts" json:"timeouts,omitempty"` +} + +func (m *CommandTask) Reset() { *m = CommandTask{} } +func (m *CommandTask) String() string { return proto.CompactTextString(m) } +func (*CommandTask) ProtoMessage() {} +func (*CommandTask) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} } + +func (m *CommandTask) GetInputs() *CommandTask_Inputs { + if m != nil { + return m.Inputs + } + return nil +} + +func (m *CommandTask) GetExpectedOutputs() *CommandTask_Outputs { + if m != nil { + return m.ExpectedOutputs + } + return nil +} + +func (m *CommandTask) GetTimeouts() *CommandTask_Timeouts { + if m != nil { + return m.Timeouts + } + return nil +} + +// Describes the inputs to a shell-style task. +type CommandTask_Inputs struct { + // The command itself to run (e.g., argv) + Arguments []string `protobuf:"bytes,1,rep,name=arguments" json:"arguments,omitempty"` + // The input filesystem to be set up prior to the task beginning. The + // contents should be a repeated set of FileMetadata messages though other + // formats are allowed if better for the implementation (eg, a LUCI-style + // .isolated file). + // + // This field is repeated since implementations might want to cache the + // metadata, in which case it may be useful to break up portions of the + // filesystem that change frequently (eg, specific input files) from those + // that don't (eg, standard header files). + Files []*Digest `protobuf:"bytes,2,rep,name=files" json:"files,omitempty"` + // All environment variables required by the task. + EnvironmentVariables []*CommandTask_Inputs_EnvironmentVariable `protobuf:"bytes,3,rep,name=environment_variables,json=environmentVariables" json:"environment_variables,omitempty"` +} + +func (m *CommandTask_Inputs) Reset() { *m = CommandTask_Inputs{} } +func (m *CommandTask_Inputs) String() string { return proto.CompactTextString(m) } +func (*CommandTask_Inputs) ProtoMessage() {} +func (*CommandTask_Inputs) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0, 0} } + +func (m *CommandTask_Inputs) GetArguments() []string { + if m != nil { + return m.Arguments + } + return nil +} + +func (m *CommandTask_Inputs) GetFiles() []*Digest { + if m != nil { + return m.Files + } + return nil +} + +func (m *CommandTask_Inputs) GetEnvironmentVariables() []*CommandTask_Inputs_EnvironmentVariable { + if m != nil { + return m.EnvironmentVariables + } + return nil +} + +// An environment variable required by this task. +type CommandTask_Inputs_EnvironmentVariable struct { + // The envvar name. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // The envvar value. + Value string `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"` +} + +func (m *CommandTask_Inputs_EnvironmentVariable) Reset() { + *m = CommandTask_Inputs_EnvironmentVariable{} +} +func (m *CommandTask_Inputs_EnvironmentVariable) String() string { return proto.CompactTextString(m) } +func (*CommandTask_Inputs_EnvironmentVariable) ProtoMessage() {} +func (*CommandTask_Inputs_EnvironmentVariable) Descriptor() ([]byte, []int) { + return fileDescriptor1, []int{0, 0, 0} +} + +func (m *CommandTask_Inputs_EnvironmentVariable) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *CommandTask_Inputs_EnvironmentVariable) GetValue() string { + if m != nil { + return m.Value + } + return "" +} + +// Describes the expected outputs of the command. +type CommandTask_Outputs struct { + // A list of expected files, relative to the execution root. + Files []string `protobuf:"bytes,1,rep,name=files" json:"files,omitempty"` + // A list of expected directories, relative to the execution root. + Directories []string `protobuf:"bytes,2,rep,name=directories" json:"directories,omitempty"` +} + +func (m *CommandTask_Outputs) Reset() { *m = CommandTask_Outputs{} } +func (m *CommandTask_Outputs) String() string { return proto.CompactTextString(m) } +func (*CommandTask_Outputs) ProtoMessage() {} +func (*CommandTask_Outputs) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0, 1} } + +func (m *CommandTask_Outputs) GetFiles() []string { + if m != nil { + return m.Files + } + return nil +} + +func (m *CommandTask_Outputs) GetDirectories() []string { + if m != nil { + return m.Directories + } + return nil +} + +// Describes the timeouts associated with this task. +type CommandTask_Timeouts struct { + // This specifies the maximum time that the task can run, excluding the + // time required to download inputs or upload outputs. That is, the worker + // will terminate the task if it runs longer than this. + Execution *google_protobuf5.Duration `protobuf:"bytes,1,opt,name=execution" json:"execution,omitempty"` + // This specifies the maximum amount of time the task can be idle - that is, + // go without generating some output in either stdout or stderr. If the + // process is silent for more than the specified time, the worker will + // terminate the task. + Idle *google_protobuf5.Duration `protobuf:"bytes,2,opt,name=idle" json:"idle,omitempty"` + // If the execution or IO timeouts are exceeded, the worker will try to + // gracefully terminate the task and return any existing logs. However, + // tasks may be hard-frozen in which case this process will fail. This + // timeout specifies how long to wait for a terminated task to shut down + // gracefully (e.g. via SIGTERM) before we bring down the hammer (e.g. + // SIGKILL on *nix, CTRL_BREAK_EVENT on Windows). + Shutdown *google_protobuf5.Duration `protobuf:"bytes,3,opt,name=shutdown" json:"shutdown,omitempty"` +} + +func (m *CommandTask_Timeouts) Reset() { *m = CommandTask_Timeouts{} } +func (m *CommandTask_Timeouts) String() string { return proto.CompactTextString(m) } +func (*CommandTask_Timeouts) ProtoMessage() {} +func (*CommandTask_Timeouts) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0, 2} } + +func (m *CommandTask_Timeouts) GetExecution() *google_protobuf5.Duration { + if m != nil { + return m.Execution + } + return nil +} + +func (m *CommandTask_Timeouts) GetIdle() *google_protobuf5.Duration { + if m != nil { + return m.Idle + } + return nil +} + +func (m *CommandTask_Timeouts) GetShutdown() *google_protobuf5.Duration { + if m != nil { + return m.Shutdown + } + return nil +} + +// Describes the actual outputs from the task. +type CommandOutputs struct { + // exit_code is only fully reliable if the status' code is OK. If the task + // exceeded its deadline or was cancelled, the process may still produce an + // exit code as it is cancelled, and this will be populated, but a successful + // (zero) is unlikely to be correct unless the status code is OK. + ExitCode int32 `protobuf:"varint,1,opt,name=exit_code,json=exitCode" json:"exit_code,omitempty"` + // The output files. The blob referenced by the digest should contain + // one of the following (implementation-dependent): + // * A marshalled DirectoryMetadata of the returned filesystem + // * A LUCI-style .isolated file + Outputs *Digest `protobuf:"bytes,2,opt,name=outputs" json:"outputs,omitempty"` +} + +func (m *CommandOutputs) Reset() { *m = CommandOutputs{} } +func (m *CommandOutputs) String() string { return proto.CompactTextString(m) } +func (*CommandOutputs) ProtoMessage() {} +func (*CommandOutputs) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{1} } + +func (m *CommandOutputs) GetExitCode() int32 { + if m != nil { + return m.ExitCode + } + return 0 +} + +func (m *CommandOutputs) GetOutputs() *Digest { + if m != nil { + return m.Outputs + } + return nil +} + +// Can be used as part of CompleteRequest.metadata, or are part of a more +// sophisticated message. +type CommandOverhead struct { + // The elapsed time between calling Accept and Complete. The server will also + // have its own idea of what this should be, but this excludes the overhead of + // the RPCs and the bot response time. + Duration *google_protobuf5.Duration `protobuf:"bytes,1,opt,name=duration" json:"duration,omitempty"` + // The amount of time *not* spent executing the command (ie + // uploading/downloading files). + Overhead *google_protobuf5.Duration `protobuf:"bytes,2,opt,name=overhead" json:"overhead,omitempty"` +} + +func (m *CommandOverhead) Reset() { *m = CommandOverhead{} } +func (m *CommandOverhead) String() string { return proto.CompactTextString(m) } +func (*CommandOverhead) ProtoMessage() {} +func (*CommandOverhead) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{2} } + +func (m *CommandOverhead) GetDuration() *google_protobuf5.Duration { + if m != nil { + return m.Duration + } + return nil +} + +func (m *CommandOverhead) GetOverhead() *google_protobuf5.Duration { + if m != nil { + return m.Overhead + } + return nil +} + +// The metadata for a file. Similar to the equivalent message in the Remote +// Execution API. +type FileMetadata struct { + // The path of this file. If this message is part of the + // CommandResult.output_files fields, the path is relative to the execution + // root and must correspond to an entry in CommandTask.outputs.files. If this + // message is part of a Directory message, then the path is relative to the + // root of that directory. + Path string `protobuf:"bytes,1,opt,name=path" json:"path,omitempty"` + // A pointer to the contents of the file. The method by which a client + // retrieves the contents from a CAS system is not defined here. + Digest *Digest `protobuf:"bytes,2,opt,name=digest" json:"digest,omitempty"` + // If the file is small enough, its contents may also or alternatively be + // listed here. + Contents []byte `protobuf:"bytes,3,opt,name=contents,proto3" json:"contents,omitempty"` + // Properties of the file + IsExecutable bool `protobuf:"varint,4,opt,name=is_executable,json=isExecutable" json:"is_executable,omitempty"` +} + +func (m *FileMetadata) Reset() { *m = FileMetadata{} } +func (m *FileMetadata) String() string { return proto.CompactTextString(m) } +func (*FileMetadata) ProtoMessage() {} +func (*FileMetadata) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{3} } + +func (m *FileMetadata) GetPath() string { + if m != nil { + return m.Path + } + return "" +} + +func (m *FileMetadata) GetDigest() *Digest { + if m != nil { + return m.Digest + } + return nil +} + +func (m *FileMetadata) GetContents() []byte { + if m != nil { + return m.Contents + } + return nil +} + +func (m *FileMetadata) GetIsExecutable() bool { + if m != nil { + return m.IsExecutable + } + return false +} + +// The metadata for a directory. Similar to the equivalent message in the Remote +// Execution API. +type DirectoryMetadata struct { + // The path of the directory, as in [FileMetadata.path][google.devtools.remoteworkers.v1test2.FileMetadata.path]. + Path string `protobuf:"bytes,1,opt,name=path" json:"path,omitempty"` + // A pointer to the contents of the directory, in the form of a marshalled + // Directory message. + Digest *Digest `protobuf:"bytes,2,opt,name=digest" json:"digest,omitempty"` +} + +func (m *DirectoryMetadata) Reset() { *m = DirectoryMetadata{} } +func (m *DirectoryMetadata) String() string { return proto.CompactTextString(m) } +func (*DirectoryMetadata) ProtoMessage() {} +func (*DirectoryMetadata) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{4} } + +func (m *DirectoryMetadata) GetPath() string { + if m != nil { + return m.Path + } + return "" +} + +func (m *DirectoryMetadata) GetDigest() *Digest { + if m != nil { + return m.Digest + } + return nil +} + +// A reference to the contents of a file or a directory. If the latter, the has +// refers to the hash of a marshalled Directory message. Similar to the +// equivalent message in the Remote Execution API. +type Digest struct { + // A string-encoded hash (eg "1a2b3c", not the byte array [0x1a, 0x2b, 0x3c]) + // using an implementation-defined hash algorithm (eg SHA-256). + Hash string `protobuf:"bytes,1,opt,name=hash" json:"hash,omitempty"` + // The size of the contents. While this is not strictly required as part of an + // identifier (after all, any given hash will have exactly one canonical + // size), it's useful in almost all cases when one might want to send or + // retrieve blobs of content and is included here for this reason. + SizeBytes int64 `protobuf:"varint,2,opt,name=size_bytes,json=sizeBytes" json:"size_bytes,omitempty"` +} + +func (m *Digest) Reset() { *m = Digest{} } +func (m *Digest) String() string { return proto.CompactTextString(m) } +func (*Digest) ProtoMessage() {} +func (*Digest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{5} } + +func (m *Digest) GetHash() string { + if m != nil { + return m.Hash + } + return "" +} + +func (m *Digest) GetSizeBytes() int64 { + if m != nil { + return m.SizeBytes + } + return 0 +} + +// The contents of a directory. Similar to the equivalent message in the Remote +// Execution API. +type Directory struct { + // The files in this directory + Files []*FileMetadata `protobuf:"bytes,1,rep,name=files" json:"files,omitempty"` + // Any subdirectories + Directories []*DirectoryMetadata `protobuf:"bytes,2,rep,name=directories" json:"directories,omitempty"` +} + +func (m *Directory) Reset() { *m = Directory{} } +func (m *Directory) String() string { return proto.CompactTextString(m) } +func (*Directory) ProtoMessage() {} +func (*Directory) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{6} } + +func (m *Directory) GetFiles() []*FileMetadata { + if m != nil { + return m.Files + } + return nil +} + +func (m *Directory) GetDirectories() []*DirectoryMetadata { + if m != nil { + return m.Directories + } + return nil +} + +func init() { + proto.RegisterType((*CommandTask)(nil), "google.devtools.remoteworkers.v1test2.CommandTask") + proto.RegisterType((*CommandTask_Inputs)(nil), "google.devtools.remoteworkers.v1test2.CommandTask.Inputs") + proto.RegisterType((*CommandTask_Inputs_EnvironmentVariable)(nil), "google.devtools.remoteworkers.v1test2.CommandTask.Inputs.EnvironmentVariable") + proto.RegisterType((*CommandTask_Outputs)(nil), "google.devtools.remoteworkers.v1test2.CommandTask.Outputs") + proto.RegisterType((*CommandTask_Timeouts)(nil), "google.devtools.remoteworkers.v1test2.CommandTask.Timeouts") + proto.RegisterType((*CommandOutputs)(nil), "google.devtools.remoteworkers.v1test2.CommandOutputs") + proto.RegisterType((*CommandOverhead)(nil), "google.devtools.remoteworkers.v1test2.CommandOverhead") + proto.RegisterType((*FileMetadata)(nil), "google.devtools.remoteworkers.v1test2.FileMetadata") + proto.RegisterType((*DirectoryMetadata)(nil), "google.devtools.remoteworkers.v1test2.DirectoryMetadata") + proto.RegisterType((*Digest)(nil), "google.devtools.remoteworkers.v1test2.Digest") + proto.RegisterType((*Directory)(nil), "google.devtools.remoteworkers.v1test2.Directory") +} + +func init() { + proto.RegisterFile("google/devtools/remoteworkers/v1test2/command.proto", fileDescriptor1) +} + +var fileDescriptor1 = []byte{ + // 665 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x95, 0xcb, 0x6e, 0x13, 0x49, + 0x14, 0x86, 0xe5, 0x38, 0x76, 0xec, 0xe3, 0xcc, 0x64, 0xa6, 0x26, 0x23, 0x19, 0x73, 0x51, 0x64, + 0x84, 0x94, 0x4d, 0xba, 0x85, 0x23, 0xc4, 0x25, 0x0b, 0x44, 0x2e, 0xa0, 0x2c, 0x22, 0x44, 0x29, + 0x02, 0x29, 0x1b, 0xab, 0xec, 0x3e, 0x69, 0x97, 0xd2, 0xee, 0xb2, 0xba, 0xaa, 0x3b, 0x09, 0x1b, + 0x24, 0xde, 0x06, 0x76, 0xf0, 0x0a, 0xbc, 0x18, 0xaa, 0x5b, 0xc7, 0x21, 0x08, 0x1b, 0x2f, 0xd8, + 0x55, 0x9f, 0xd4, 0xff, 0xd5, 0xb9, 0xfc, 0x27, 0x86, 0xed, 0x58, 0x88, 0x38, 0xc1, 0x30, 0xc2, + 0x42, 0x09, 0x91, 0xc8, 0x30, 0xc3, 0xb1, 0x50, 0x78, 0x2e, 0xb2, 0x33, 0xcc, 0x64, 0x58, 0x3c, + 0x54, 0x28, 0x55, 0x2f, 0x1c, 0x8a, 0xf1, 0x98, 0xa5, 0x51, 0x30, 0xc9, 0x84, 0x12, 0xe4, 0x81, + 0x15, 0x05, 0x5e, 0x14, 0x5c, 0x13, 0x05, 0x4e, 0xd4, 0xb9, 0xe7, 0xd8, 0x46, 0x34, 0xc8, 0x4f, + 0xc3, 0x28, 0xcf, 0x98, 0xe2, 0x22, 0xb5, 0x98, 0xee, 0xb7, 0x3a, 0xb4, 0xf6, 0x2c, 0xf8, 0x98, + 0xc9, 0x33, 0xf2, 0x06, 0xea, 0x3c, 0x9d, 0xe4, 0x4a, 0xb6, 0x2b, 0x1b, 0x95, 0xcd, 0x56, 0xef, + 0x69, 0x30, 0xd7, 0x3b, 0xc1, 0x14, 0x23, 0x38, 0x34, 0x00, 0xea, 0x40, 0x04, 0xe1, 0x1f, 0xbc, + 0x98, 0xe0, 0x50, 0x61, 0xd4, 0x17, 0xb9, 0x32, 0xf0, 0x65, 0x03, 0x7f, 0xb6, 0x00, 0xfc, 0xb5, + 0x25, 0xd0, 0x35, 0xcf, 0x74, 0x01, 0xf2, 0x0e, 0x1a, 0x8a, 0x8f, 0x51, 0x68, 0x7c, 0xcd, 0xe0, + 0x77, 0x16, 0xc0, 0x1f, 0x3b, 0x04, 0x2d, 0x61, 0x9d, 0x2f, 0x4b, 0x50, 0xb7, 0x25, 0x91, 0x3b, + 0xd0, 0x64, 0x59, 0x9c, 0x8f, 0x31, 0x35, 0x0d, 0xaa, 0x6e, 0x36, 0xe9, 0x55, 0x80, 0xec, 0x41, + 0xed, 0x94, 0x27, 0x28, 0xdb, 0x4b, 0x1b, 0xd5, 0xcd, 0x56, 0x6f, 0x6b, 0xce, 0xe7, 0xf7, 0x79, + 0x8c, 0x52, 0x51, 0xab, 0x25, 0x1f, 0x2b, 0xf0, 0x3f, 0xa6, 0x05, 0xcf, 0x44, 0xaa, 0xa9, 0xfd, + 0x82, 0x65, 0x9c, 0x0d, 0x34, 0xb5, 0x6a, 0xa8, 0x47, 0x0b, 0x0f, 0x24, 0x38, 0xb8, 0xc2, 0xbe, + 0x75, 0x54, 0xba, 0x8e, 0x37, 0x83, 0xb2, 0xf3, 0x1c, 0xfe, 0xfb, 0xc9, 0x65, 0x42, 0x60, 0x39, + 0x65, 0x63, 0x34, 0xd6, 0x68, 0x52, 0x73, 0x26, 0xeb, 0x50, 0x2b, 0x58, 0x92, 0x63, 0x7b, 0xc9, + 0x04, 0xed, 0x47, 0xe7, 0x05, 0xac, 0xf8, 0xb9, 0xac, 0xfb, 0xae, 0xd8, 0x7e, 0xb9, 0x32, 0x37, + 0xa0, 0x15, 0xf1, 0x0c, 0x87, 0x4a, 0x64, 0xdc, 0x75, 0xac, 0x49, 0xa7, 0x43, 0x9d, 0x4f, 0x15, + 0x68, 0xf8, 0x69, 0x90, 0xc7, 0xd0, 0xc4, 0x0b, 0x1c, 0xe6, 0xda, 0xb9, 0xce, 0x99, 0xb7, 0x7c, + 0x23, 0xbc, 0xb5, 0x83, 0x7d, 0x67, 0x6d, 0x7a, 0x75, 0x97, 0x6c, 0xc1, 0x32, 0x8f, 0x12, 0x9b, + 0xdd, 0x2f, 0x35, 0xe6, 0x1a, 0x79, 0x04, 0x0d, 0x39, 0xca, 0x55, 0x24, 0xce, 0xd3, 0x76, 0x75, + 0x96, 0xa4, 0xbc, 0xda, 0x2d, 0xe0, 0x6f, 0xd7, 0x6f, 0x5f, 0xf5, 0x6d, 0x9d, 0x30, 0x57, 0xfd, + 0xa1, 0x88, 0x6c, 0xbf, 0x6a, 0xb4, 0xa1, 0x03, 0x7b, 0x22, 0x42, 0xf2, 0x0a, 0x56, 0xfc, 0x22, + 0xd8, 0xbc, 0x7e, 0xd3, 0x2a, 0x5e, 0xdd, 0xfd, 0x00, 0x6b, 0xfe, 0xdd, 0x02, 0xb3, 0x11, 0xb2, + 0x48, 0x57, 0xe0, 0x57, 0x7c, 0x76, 0xa3, 0xca, 0xab, 0x5a, 0x26, 0x1c, 0x62, 0x76, 0xaf, 0xca, + 0xab, 0xdd, 0xcf, 0x15, 0x58, 0x7d, 0xc9, 0x13, 0x3c, 0x42, 0xc5, 0x22, 0xa6, 0x98, 0xb6, 0xc8, + 0x84, 0xa9, 0x91, 0xb7, 0x88, 0x3e, 0x93, 0x03, 0xa8, 0x47, 0x26, 0xf1, 0xc5, 0xaa, 0x75, 0x62, + 0xd2, 0x81, 0xc6, 0x50, 0xa4, 0xca, 0xec, 0x9e, 0x9e, 0xcd, 0x2a, 0x2d, 0xbf, 0xc9, 0x7d, 0xf8, + 0x8b, 0xcb, 0xbe, 0x1d, 0xbb, 0xb6, 0xaa, 0xf9, 0x07, 0xd3, 0xa0, 0xab, 0x5c, 0x1e, 0x94, 0xb1, + 0x6e, 0x0a, 0xff, 0xee, 0x3b, 0x83, 0x5d, 0xfe, 0x81, 0x84, 0xbb, 0x3b, 0x50, 0xb7, 0x11, 0xfd, + 0xc8, 0x88, 0xc9, 0xf2, 0x11, 0x7d, 0x26, 0x77, 0x01, 0x24, 0x7f, 0x8f, 0xfd, 0xc1, 0xa5, 0x42, + 0xeb, 0x83, 0x2a, 0x6d, 0xea, 0xc8, 0xae, 0x0e, 0x74, 0xbf, 0x56, 0xa0, 0x59, 0x66, 0x4b, 0x0e, + 0xa7, 0x97, 0xa8, 0xd5, 0xdb, 0x9e, 0x33, 0xa1, 0xe9, 0xd1, 0xf8, 0xcd, 0x3b, 0xb9, 0xb9, 0x79, + 0xad, 0xde, 0x93, 0xb9, 0x2b, 0xfc, 0xa1, 0x7f, 0xd7, 0x76, 0x76, 0xf7, 0xf8, 0x84, 0x3a, 0x4e, + 0x2c, 0x12, 0x96, 0xc6, 0x81, 0xc8, 0xe2, 0x30, 0xc6, 0xd4, 0x58, 0x28, 0xb4, 0x7f, 0x62, 0x13, + 0x2e, 0x67, 0xfc, 0xd4, 0xed, 0x5c, 0x8b, 0x0e, 0xea, 0x46, 0xbe, 0xfd, 0x3d, 0x00, 0x00, 0xff, + 0xff, 0x1c, 0x77, 0x2c, 0xa3, 0x28, 0x07, 0x00, 0x00, +} diff --git a/vendor/google.golang.org/genproto/googleapis/devtools/remoteworkers/v1test2/tasks.pb.go b/vendor/google.golang.org/genproto/googleapis/devtools/remoteworkers/v1test2/tasks.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..031366569b58b0436b6eb3150c7be3cc4984eddf --- /dev/null +++ b/vendor/google.golang.org/genproto/googleapis/devtools/remoteworkers/v1test2/tasks.pb.go @@ -0,0 +1,456 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: google/devtools/remoteworkers/v1test2/tasks.proto + +package remoteworkers + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import _ "google.golang.org/genproto/googleapis/api/annotations" +import google_protobuf1 "github.com/golang/protobuf/ptypes/any" +import google_protobuf3 "google.golang.org/genproto/protobuf/field_mask" +import google_rpc "google.golang.org/genproto/googleapis/rpc/status" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// A Task represents a unit of work. Its result and logs are defined as +// subresources. +// +// If all the `Any` fields are populated, this can be a very large message, and +// clients may not want the entire message returned on every call to every +// method. Such clients should request partial responses +// (https://cloud.google.com/apis/design/design_patterns#partial_response) and +// servers should implement partial responses in order to reduce unnecessry +// overhead. +type Task struct { + // The name of this task. Output only. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // The actual task to perform. For example, this could be CommandTask to run a + // command line. + Description *google_protobuf1.Any `protobuf:"bytes,2,opt,name=description" json:"description,omitempty"` + // Handles to logs. The key is a human-readable name like `stdout`, and the + // handle is a resource name that can be passed to ByteStream or other + // accessors. + // + // An implementation may define some logs by default (like `stdout`), and may + // allow clients to add new logs via AddTaskLog. + Logs map[string]string `protobuf:"bytes,3,rep,name=logs" json:"logs,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` +} + +func (m *Task) Reset() { *m = Task{} } +func (m *Task) String() string { return proto.CompactTextString(m) } +func (*Task) ProtoMessage() {} +func (*Task) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{0} } + +func (m *Task) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *Task) GetDescription() *google_protobuf1.Any { + if m != nil { + return m.Description + } + return nil +} + +func (m *Task) GetLogs() map[string]string { + if m != nil { + return m.Logs + } + return nil +} + +// The result and metadata of the task. +type TaskResult struct { + // The name of the task result; must be a name of a `Task` followed by + // `/result`. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // The result may be updated several times; the client must only set + // `complete` to true to indicate that no further updates are allowed. + // If this is not true, the `status` field must not be examined since its zero + // value is equivalent to `OK`. + // + // Once a task is completed, it must not be updated with further results, + // though the implementation may choose to continue to receive logs. + Complete bool `protobuf:"varint,2,opt,name=complete" json:"complete,omitempty"` + // The final status of the task itself. For example, if task.description + // included a timeout which was violated, status.code may be + // DEADLINE_EXCEEDED. This field can only be read if `complete` is true. + Status *google_rpc.Status `protobuf:"bytes,3,opt,name=status" json:"status,omitempty"` + // Any non-log output, such as output files and exit codes. See + // CommandResult as an example. + Output *google_protobuf1.Any `protobuf:"bytes,4,opt,name=output" json:"output,omitempty"` + // Any information about how the command was executed, eg runtime. See + // CommandOverhead as an example. + Meta *google_protobuf1.Any `protobuf:"bytes,5,opt,name=meta" json:"meta,omitempty"` +} + +func (m *TaskResult) Reset() { *m = TaskResult{} } +func (m *TaskResult) String() string { return proto.CompactTextString(m) } +func (*TaskResult) ProtoMessage() {} +func (*TaskResult) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{1} } + +func (m *TaskResult) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *TaskResult) GetComplete() bool { + if m != nil { + return m.Complete + } + return false +} + +func (m *TaskResult) GetStatus() *google_rpc.Status { + if m != nil { + return m.Status + } + return nil +} + +func (m *TaskResult) GetOutput() *google_protobuf1.Any { + if m != nil { + return m.Output + } + return nil +} + +func (m *TaskResult) GetMeta() *google_protobuf1.Any { + if m != nil { + return m.Meta + } + return nil +} + +// Request message for `GetTask`. +type GetTaskRequest struct { + // The task name. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` +} + +func (m *GetTaskRequest) Reset() { *m = GetTaskRequest{} } +func (m *GetTaskRequest) String() string { return proto.CompactTextString(m) } +func (*GetTaskRequest) ProtoMessage() {} +func (*GetTaskRequest) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{2} } + +func (m *GetTaskRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +// Request message for `UpdateTaskResult`. +type UpdateTaskResultRequest struct { + // The task result name; must match `result.name`. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // The result being updated. + Result *TaskResult `protobuf:"bytes,2,opt,name=result" json:"result,omitempty"` + // The fields within `result` that are specified. + UpdateMask *google_protobuf3.FieldMask `protobuf:"bytes,3,opt,name=update_mask,json=updateMask" json:"update_mask,omitempty"` + // If this is being updated by a bot from BotManager, the source should be + // bot.session_id. That way, if two bots accidentally get the same name, we'll + // know to reject updates from the older one. + Source string `protobuf:"bytes,4,opt,name=source" json:"source,omitempty"` +} + +func (m *UpdateTaskResultRequest) Reset() { *m = UpdateTaskResultRequest{} } +func (m *UpdateTaskResultRequest) String() string { return proto.CompactTextString(m) } +func (*UpdateTaskResultRequest) ProtoMessage() {} +func (*UpdateTaskResultRequest) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{3} } + +func (m *UpdateTaskResultRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *UpdateTaskResultRequest) GetResult() *TaskResult { + if m != nil { + return m.Result + } + return nil +} + +func (m *UpdateTaskResultRequest) GetUpdateMask() *google_protobuf3.FieldMask { + if m != nil { + return m.UpdateMask + } + return nil +} + +func (m *UpdateTaskResultRequest) GetSource() string { + if m != nil { + return m.Source + } + return "" +} + +// Request message for `AddTaskLog`. +type AddTaskLogRequest struct { + // The name of the task that will own the new log. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // The human-readable name of the log, like `stdout` or a relative file path. + LogId string `protobuf:"bytes,2,opt,name=log_id,json=logId" json:"log_id,omitempty"` +} + +func (m *AddTaskLogRequest) Reset() { *m = AddTaskLogRequest{} } +func (m *AddTaskLogRequest) String() string { return proto.CompactTextString(m) } +func (*AddTaskLogRequest) ProtoMessage() {} +func (*AddTaskLogRequest) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{4} } + +func (m *AddTaskLogRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *AddTaskLogRequest) GetLogId() string { + if m != nil { + return m.LogId + } + return "" +} + +// Response message for `AddTaskLog`. +type AddTaskLogResponse struct { + // The handle for the new log, as would be returned in Task.logs. + Handle string `protobuf:"bytes,1,opt,name=handle" json:"handle,omitempty"` +} + +func (m *AddTaskLogResponse) Reset() { *m = AddTaskLogResponse{} } +func (m *AddTaskLogResponse) String() string { return proto.CompactTextString(m) } +func (*AddTaskLogResponse) ProtoMessage() {} +func (*AddTaskLogResponse) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{5} } + +func (m *AddTaskLogResponse) GetHandle() string { + if m != nil { + return m.Handle + } + return "" +} + +func init() { + proto.RegisterType((*Task)(nil), "google.devtools.remoteworkers.v1test2.Task") + proto.RegisterType((*TaskResult)(nil), "google.devtools.remoteworkers.v1test2.TaskResult") + proto.RegisterType((*GetTaskRequest)(nil), "google.devtools.remoteworkers.v1test2.GetTaskRequest") + proto.RegisterType((*UpdateTaskResultRequest)(nil), "google.devtools.remoteworkers.v1test2.UpdateTaskResultRequest") + proto.RegisterType((*AddTaskLogRequest)(nil), "google.devtools.remoteworkers.v1test2.AddTaskLogRequest") + proto.RegisterType((*AddTaskLogResponse)(nil), "google.devtools.remoteworkers.v1test2.AddTaskLogResponse") +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// Client API for Tasks service + +type TasksClient interface { + // GetTask reads the current state of the task. Tasks must be created through + // some other interface, and should be immutable once created and exposed to + // the bots. + GetTask(ctx context.Context, in *GetTaskRequest, opts ...grpc.CallOption) (*Task, error) + // UpdateTaskResult updates the result. + UpdateTaskResult(ctx context.Context, in *UpdateTaskResultRequest, opts ...grpc.CallOption) (*TaskResult, error) + // AddTaskLog creates a new streaming log. The log is streamed and marked as + // completed through other interfaces (i.e., ByteStream). This can be called + // by the bot if it wants to create a new log; the server can also predefine + // logs that do not need to be created (e.g. `stdout`). + AddTaskLog(ctx context.Context, in *AddTaskLogRequest, opts ...grpc.CallOption) (*AddTaskLogResponse, error) +} + +type tasksClient struct { + cc *grpc.ClientConn +} + +func NewTasksClient(cc *grpc.ClientConn) TasksClient { + return &tasksClient{cc} +} + +func (c *tasksClient) GetTask(ctx context.Context, in *GetTaskRequest, opts ...grpc.CallOption) (*Task, error) { + out := new(Task) + err := grpc.Invoke(ctx, "/google.devtools.remoteworkers.v1test2.Tasks/GetTask", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *tasksClient) UpdateTaskResult(ctx context.Context, in *UpdateTaskResultRequest, opts ...grpc.CallOption) (*TaskResult, error) { + out := new(TaskResult) + err := grpc.Invoke(ctx, "/google.devtools.remoteworkers.v1test2.Tasks/UpdateTaskResult", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *tasksClient) AddTaskLog(ctx context.Context, in *AddTaskLogRequest, opts ...grpc.CallOption) (*AddTaskLogResponse, error) { + out := new(AddTaskLogResponse) + err := grpc.Invoke(ctx, "/google.devtools.remoteworkers.v1test2.Tasks/AddTaskLog", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for Tasks service + +type TasksServer interface { + // GetTask reads the current state of the task. Tasks must be created through + // some other interface, and should be immutable once created and exposed to + // the bots. + GetTask(context.Context, *GetTaskRequest) (*Task, error) + // UpdateTaskResult updates the result. + UpdateTaskResult(context.Context, *UpdateTaskResultRequest) (*TaskResult, error) + // AddTaskLog creates a new streaming log. The log is streamed and marked as + // completed through other interfaces (i.e., ByteStream). This can be called + // by the bot if it wants to create a new log; the server can also predefine + // logs that do not need to be created (e.g. `stdout`). + AddTaskLog(context.Context, *AddTaskLogRequest) (*AddTaskLogResponse, error) +} + +func RegisterTasksServer(s *grpc.Server, srv TasksServer) { + s.RegisterService(&_Tasks_serviceDesc, srv) +} + +func _Tasks_GetTask_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetTaskRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TasksServer).GetTask(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.devtools.remoteworkers.v1test2.Tasks/GetTask", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TasksServer).GetTask(ctx, req.(*GetTaskRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Tasks_UpdateTaskResult_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdateTaskResultRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TasksServer).UpdateTaskResult(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.devtools.remoteworkers.v1test2.Tasks/UpdateTaskResult", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TasksServer).UpdateTaskResult(ctx, req.(*UpdateTaskResultRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Tasks_AddTaskLog_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AddTaskLogRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TasksServer).AddTaskLog(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.devtools.remoteworkers.v1test2.Tasks/AddTaskLog", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TasksServer).AddTaskLog(ctx, req.(*AddTaskLogRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Tasks_serviceDesc = grpc.ServiceDesc{ + ServiceName: "google.devtools.remoteworkers.v1test2.Tasks", + HandlerType: (*TasksServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetTask", + Handler: _Tasks_GetTask_Handler, + }, + { + MethodName: "UpdateTaskResult", + Handler: _Tasks_UpdateTaskResult_Handler, + }, + { + MethodName: "AddTaskLog", + Handler: _Tasks_AddTaskLog_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "google/devtools/remoteworkers/v1test2/tasks.proto", +} + +func init() { proto.RegisterFile("google/devtools/remoteworkers/v1test2/tasks.proto", fileDescriptor2) } + +var fileDescriptor2 = []byte{ + // 634 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x54, 0xc1, 0x6e, 0xd3, 0x40, + 0x10, 0x95, 0x13, 0xc7, 0x34, 0x13, 0x09, 0x95, 0x55, 0xa1, 0xc6, 0xea, 0x21, 0x58, 0x80, 0xa2, + 0x34, 0xb2, 0x95, 0x20, 0xa0, 0xa4, 0xa2, 0x52, 0x91, 0x00, 0x45, 0x0a, 0x17, 0x53, 0x2e, 0x5c, + 0xaa, 0x6d, 0xbc, 0x5d, 0xac, 0x38, 0x5e, 0xe3, 0x5d, 0x07, 0x45, 0x28, 0x17, 0x4e, 0x5c, 0x11, + 0x1f, 0xc2, 0x95, 0x23, 0x3f, 0xc0, 0x09, 0x89, 0x2f, 0xe0, 0x43, 0x90, 0xd7, 0xeb, 0xb4, 0x69, + 0x9b, 0x90, 0x70, 0xf3, 0x78, 0xde, 0x9b, 0x99, 0x37, 0x6f, 0xb4, 0xd0, 0xa6, 0x8c, 0xd1, 0x90, + 0xb8, 0x3e, 0x19, 0x0b, 0xc6, 0x42, 0xee, 0x26, 0x64, 0xc4, 0x04, 0xf9, 0xc0, 0x92, 0x21, 0x49, + 0xb8, 0x3b, 0x6e, 0x0b, 0xc2, 0x45, 0xc7, 0x15, 0x98, 0x0f, 0xb9, 0x13, 0x27, 0x4c, 0x30, 0x74, + 0x2f, 0xa7, 0x38, 0x05, 0xc5, 0x99, 0xa3, 0x38, 0x8a, 0x62, 0xed, 0xa8, 0xca, 0x38, 0x0e, 0x5c, + 0x1c, 0x45, 0x4c, 0x60, 0x11, 0xb0, 0x48, 0x15, 0xb1, 0x6e, 0xab, 0xac, 0x8c, 0x4e, 0xd2, 0x53, + 0x17, 0x47, 0x13, 0x95, 0xaa, 0x5f, 0x4c, 0x9d, 0x06, 0x24, 0xf4, 0x8f, 0x47, 0x98, 0x0f, 0x15, + 0x62, 0x5b, 0x21, 0x92, 0x78, 0xe0, 0x72, 0x81, 0x45, 0xaa, 0xaa, 0xda, 0xbf, 0x35, 0xd0, 0x8f, + 0x30, 0x1f, 0x22, 0x04, 0x7a, 0x84, 0x47, 0xc4, 0xd4, 0xea, 0x5a, 0xa3, 0xea, 0xc9, 0x6f, 0xf4, + 0x08, 0x6a, 0x3e, 0xe1, 0x83, 0x24, 0x88, 0xb3, 0x41, 0xcc, 0x52, 0x5d, 0x6b, 0xd4, 0x3a, 0x5b, + 0x8e, 0x52, 0x53, 0x74, 0x73, 0x0e, 0xa3, 0x89, 0x77, 0x1e, 0x88, 0x7a, 0xa0, 0x87, 0x8c, 0x72, + 0xb3, 0x5c, 0x2f, 0x37, 0x6a, 0x9d, 0x87, 0xce, 0x4a, 0xf2, 0x9d, 0x6c, 0x0c, 0xa7, 0xcf, 0x28, + 0x7f, 0x1e, 0x89, 0x64, 0xe2, 0xc9, 0x12, 0xd6, 0x63, 0xa8, 0xce, 0x7e, 0xa1, 0x4d, 0x28, 0x0f, + 0xc9, 0x44, 0x8d, 0x98, 0x7d, 0xa2, 0x2d, 0xa8, 0x8c, 0x71, 0x98, 0x12, 0x39, 0x5b, 0xd5, 0xcb, + 0x83, 0x6e, 0x69, 0x4f, 0xb3, 0x7f, 0x68, 0x00, 0x59, 0x45, 0x8f, 0xf0, 0x34, 0x14, 0x57, 0xca, + 0xb3, 0x60, 0x63, 0xc0, 0x46, 0x71, 0x48, 0x44, 0xce, 0xdf, 0xf0, 0x66, 0x31, 0x6a, 0x82, 0x91, + 0xef, 0xc9, 0x2c, 0x4b, 0xd5, 0xa8, 0x10, 0x91, 0xc4, 0x03, 0xe7, 0xb5, 0xcc, 0x78, 0x0a, 0x81, + 0x5a, 0x60, 0xb0, 0x54, 0xc4, 0xa9, 0x30, 0xf5, 0x25, 0x1b, 0x52, 0x18, 0xd4, 0x00, 0x7d, 0x44, + 0x04, 0x36, 0x2b, 0x4b, 0xb0, 0x12, 0x61, 0xdf, 0x85, 0xeb, 0x2f, 0x89, 0xc8, 0x45, 0xbc, 0x4f, + 0x09, 0xbf, 0x52, 0x85, 0xfd, 0x53, 0x83, 0xed, 0x37, 0xb1, 0x8f, 0x05, 0x39, 0x93, 0xbb, 0x04, + 0x8f, 0x7a, 0x60, 0x24, 0x12, 0xa4, 0xfc, 0x6c, 0xaf, 0x61, 0x8f, 0xaa, 0xae, 0x0a, 0xa0, 0x7d, + 0xa8, 0xa5, 0xb2, 0xb3, 0x3c, 0x35, 0xb5, 0x29, 0xeb, 0x92, 0xa2, 0x17, 0xd9, 0x35, 0xbe, 0xca, + 0xe8, 0x90, 0xc3, 0xb3, 0x6f, 0x74, 0x0b, 0x0c, 0xce, 0xd2, 0x64, 0x40, 0xe4, 0xd6, 0xaa, 0x9e, + 0x8a, 0xec, 0x03, 0xb8, 0x71, 0xe8, 0xfb, 0x59, 0xb7, 0x3e, 0xa3, 0xcb, 0x84, 0xdc, 0x04, 0x23, + 0x64, 0xf4, 0x38, 0xf0, 0x0b, 0xf3, 0x43, 0x46, 0x7b, 0xbe, 0xdd, 0x02, 0x74, 0x9e, 0xcf, 0x63, + 0x16, 0x71, 0x92, 0x75, 0x7b, 0x87, 0x23, 0x3f, 0x2c, 0x4a, 0xa8, 0xa8, 0xf3, 0x59, 0x87, 0x4a, + 0x86, 0xe5, 0xe8, 0x8b, 0x06, 0xd7, 0xd4, 0xba, 0xd1, 0xaa, 0x27, 0x3b, 0x6f, 0x8f, 0xb5, 0xbb, + 0xc6, 0x2a, 0x6d, 0xfb, 0xd3, 0xaf, 0x3f, 0x5f, 0x4b, 0x3b, 0xc8, 0x9a, 0x3d, 0x19, 0x1f, 0x33, + 0x59, 0x4f, 0x9b, 0xcd, 0xfc, 0xed, 0x70, 0x9b, 0x53, 0xf4, 0x5d, 0x83, 0xcd, 0x8b, 0xde, 0xa2, + 0x83, 0x15, 0xbb, 0x2c, 0x38, 0x0a, 0x6b, 0x7d, 0xc3, 0xed, 0xb6, 0x9c, 0x75, 0xb7, 0x73, 0x67, + 0xe1, 0xac, 0x6e, 0x7e, 0x12, 0xd3, 0x6e, 0x71, 0x1b, 0xdf, 0x34, 0x80, 0x33, 0x1f, 0xd0, 0xde, + 0x8a, 0x4d, 0x2f, 0x59, 0x6f, 0x3d, 0xf9, 0x0f, 0x66, 0x6e, 0xba, 0xdd, 0x92, 0x63, 0xdf, 0xb7, + 0x17, 0x8f, 0x3d, 0xed, 0x62, 0xdf, 0xef, 0x33, 0xda, 0xd5, 0x9a, 0xcf, 0x8e, 0xde, 0x7a, 0xaa, + 0x13, 0x65, 0x21, 0x8e, 0xa8, 0xc3, 0x12, 0xea, 0x52, 0x12, 0xc9, 0x3b, 0x76, 0xf3, 0x14, 0x8e, + 0x03, 0xfe, 0x8f, 0x97, 0x7f, 0x7f, 0xee, 0xef, 0x89, 0x21, 0xe9, 0x0f, 0xfe, 0x06, 0x00, 0x00, + 0xff, 0xff, 0xb8, 0x8f, 0xed, 0xe0, 0x37, 0x06, 0x00, 0x00, +} diff --git a/vendor/google.golang.org/genproto/googleapis/devtools/source/v1/source_context.pb.go b/vendor/google.golang.org/genproto/googleapis/devtools/source/v1/source_context.pb.go index e67b5c20e10373480d5a8a7ac8f5e21a20cde4ff..81829f627bc4c5790884e6424924ab954d21c044 100644 --- a/vendor/google.golang.org/genproto/googleapis/devtools/source/v1/source_context.pb.go +++ b/vendor/google.golang.org/genproto/googleapis/devtools/source/v1/source_context.pb.go @@ -892,54 +892,55 @@ func init() { func init() { proto.RegisterFile("google/devtools/source/v1/source_context.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 780 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x55, 0xcb, 0x4e, 0xdb, 0x4c, - 0x14, 0x8e, 0xe3, 0x90, 0xe0, 0x13, 0x02, 0xd1, 0xfc, 0x7f, 0xab, 0x00, 0x45, 0x80, 0xa5, 0xaa, - 0x48, 0x54, 0x8e, 0x92, 0x4a, 0x55, 0x4b, 0x2b, 0x51, 0x02, 0x29, 0x89, 0xa0, 0x01, 0x4d, 0x29, - 0xbd, 0x6c, 0x22, 0x63, 0x8f, 0x8c, 0x8b, 0xf1, 0x58, 0xb6, 0x13, 0xe0, 0x25, 0xba, 0xe6, 0x19, - 0xfa, 0x4c, 0x7d, 0x84, 0x2e, 0x2b, 0x75, 0x5b, 0xcd, 0xc5, 0x90, 0x84, 0x60, 0x90, 0xda, 0x95, - 0x67, 0x8e, 0xbf, 0xef, 0x3b, 0x67, 0xce, 0x65, 0x06, 0x0c, 0x87, 0x52, 0xc7, 0x23, 0x55, 0x9b, - 0xf4, 0x63, 0x4a, 0xbd, 0xa8, 0x1a, 0xd1, 0x5e, 0x68, 0x91, 0x6a, 0xbf, 0x26, 0x57, 0x5d, 0x8b, - 0xfa, 0x31, 0x39, 0x8f, 0x8d, 0x20, 0xa4, 0x31, 0x45, 0xb3, 0x02, 0x6f, 0x24, 0x78, 0x43, 0xa0, - 0x8c, 0x7e, 0x6d, 0xee, 0x91, 0x94, 0x32, 0x03, 0xb7, 0x6a, 0xfa, 0x3e, 0x8d, 0xcd, 0xd8, 0xa5, - 0x7e, 0x24, 0x88, 0xfa, 0x8f, 0x2c, 0x94, 0xde, 0x73, 0xec, 0xa6, 0x10, 0x44, 0x18, 0xc0, 0xf2, - 0x68, 0xcf, 0xee, 0x86, 0x24, 0xa0, 0x15, 0x65, 0x49, 0x59, 0x29, 0xd6, 0x6b, 0xc6, 0xad, 0xfa, - 0xc6, 0x26, 0x03, 0x63, 0x12, 0xd0, 0x21, 0x99, 0x56, 0x06, 0x6b, 0x56, 0xf2, 0x07, 0x99, 0x30, - 0x23, 0x34, 0xcf, 0x68, 0x78, 0x12, 0x05, 0xa6, 0x45, 0x2a, 0x59, 0x2e, 0xfc, 0xfc, 0x2e, 0xe1, - 0x8f, 0x09, 0x61, 0x54, 0x7d, 0xda, 0x1a, 0xfa, 0x8d, 0x5a, 0x90, 0x77, 0x48, 0x18, 0xba, 0x71, - 0x45, 0xe5, 0xca, 0x46, 0x8a, 0xf2, 0x36, 0x07, 0x8e, 0x2a, 0x4a, 0x3e, 0x5a, 0x07, 0xd5, 0x71, - 0xe3, 0x4a, 0x9e, 0xcb, 0xac, 0xa6, 0xc9, 0xdc, 0xd4, 0x60, 0xcc, 0x86, 0x06, 0x05, 0x59, 0x1d, - 0xfd, 0xa7, 0x02, 0x0f, 0x9a, 0xe7, 0x31, 0xf1, 0x6d, 0x62, 0x0f, 0xa7, 0xb9, 0x71, 0x05, 0x92, - 0x39, 0x5e, 0x49, 0xf1, 0x34, 0x44, 0xc5, 0x09, 0x11, 0x1d, 0x40, 0xde, 0x33, 0x8f, 0x88, 0x17, - 0x55, 0xb2, 0x4b, 0xea, 0x4a, 0xb1, 0xfe, 0x3a, 0x45, 0x62, 0x6c, 0x14, 0xc6, 0x2e, 0xa7, 0x37, - 0xfd, 0x38, 0xbc, 0xc0, 0x52, 0x6b, 0xee, 0x25, 0x14, 0x07, 0xcc, 0xa8, 0x0c, 0xea, 0x09, 0xb9, - 0xe0, 0x41, 0x6a, 0x98, 0x2d, 0xd1, 0xff, 0x30, 0xd1, 0x37, 0xbd, 0x9e, 0xa8, 0xa1, 0x86, 0xc5, - 0x66, 0x2d, 0xfb, 0x42, 0xd1, 0x2f, 0x15, 0x98, 0xda, 0xf0, 0x5c, 0x33, 0x4a, 0x4e, 0xf9, 0x06, - 0x72, 0x27, 0xae, 0x6f, 0x73, 0xf6, 0x74, 0xfd, 0x69, 0x4a, 0x7c, 0x83, 0x34, 0x63, 0xc7, 0xf5, - 0x6d, 0xcc, 0x99, 0x08, 0x41, 0xce, 0x37, 0x4f, 0x13, 0x5f, 0x7c, 0xad, 0xd7, 0x21, 0xc7, 0x10, - 0xa8, 0x00, 0xea, 0x46, 0xe7, 0x73, 0x39, 0x83, 0x34, 0x98, 0x78, 0xdb, 0xfe, 0xd4, 0xdc, 0x2a, - 0x2b, 0xa8, 0x08, 0x85, 0x77, 0x7b, 0x87, 0x1b, 0x8d, 0xdd, 0x66, 0x39, 0xcb, 0xec, 0x7b, 0x07, - 0xad, 0x26, 0x2e, 0xe7, 0xf4, 0x5f, 0x0a, 0x3c, 0x1c, 0xdf, 0xaa, 0x68, 0x0d, 0x0a, 0xac, 0xd7, - 0xbb, 0xae, 0x2d, 0x4b, 0xb1, 0x9c, 0x12, 0x27, 0xa3, 0xb7, 0x6d, 0x9c, 0x0f, 0xf9, 0x17, 0x2d, - 0x43, 0x31, 0x24, 0x7d, 0x37, 0x72, 0xa9, 0xcf, 0xf8, 0x3c, 0xca, 0x56, 0x06, 0x43, 0x62, 0x6c, - 0xdb, 0x68, 0x11, 0xc0, 0x64, 0x87, 0xeb, 0xf2, 0x73, 0xa8, 0x12, 0xa1, 0x71, 0x5b, 0xc7, 0x3c, - 0x25, 0xa8, 0x03, 0x25, 0x01, 0x48, 0x1a, 0x22, 0xc7, 0xa3, 0x78, 0x72, 0xcf, 0x6c, 0xb5, 0x32, - 0x78, 0xca, 0x1c, 0xd8, 0x37, 0x00, 0x26, 0x13, 0xf7, 0xfa, 0x37, 0x05, 0xe6, 0x53, 0x06, 0x09, - 0x75, 0x60, 0xea, 0x6a, 0x26, 0xaf, 0x13, 0xb0, 0x7a, 0xef, 0xb1, 0x6c, 0xdb, 0xb8, 0x78, 0x76, - 0xbd, 0x41, 0x8b, 0x50, 0x8c, 0x7c, 0x33, 0x88, 0x8e, 0x69, 0x7c, 0x95, 0x0f, 0x0c, 0x89, 0xa9, - 0x6d, 0xeb, 0xbf, 0x15, 0xf8, 0x6f, 0xcc, 0xfc, 0xa1, 0x59, 0x98, 0x3c, 0xa6, 0x51, 0xdc, 0xed, - 0x85, 0xae, 0xec, 0xb5, 0x02, 0xdb, 0x7f, 0x08, 0x5d, 0xf4, 0x18, 0xa6, 0xc5, 0x68, 0x76, 0x83, - 0x90, 0x7e, 0x25, 0x56, 0x2c, 0x65, 0x4b, 0xc2, 0xba, 0x2f, 0x8c, 0xa3, 0xa5, 0x50, 0xef, 0x2c, - 0x45, 0xee, 0x1e, 0xa5, 0x98, 0xf8, 0x77, 0xa5, 0x68, 0x42, 0x79, 0xf4, 0xc6, 0x60, 0xc3, 0xd5, - 0x0b, 0xbd, 0x64, 0xb8, 0x7a, 0xa1, 0xc7, 0x12, 0x78, 0xa3, 0xa1, 0x06, 0xcf, 0xa0, 0xf7, 0x21, - 0x2f, 0x7a, 0x10, 0x61, 0x98, 0x91, 0x09, 0xe9, 0x0e, 0xf7, 0x6f, 0xda, 0x55, 0x22, 0xb3, 0x25, - 0x24, 0x5a, 0x19, 0x5c, 0x0a, 0x06, 0x0d, 0x08, 0x81, 0xda, 0x1b, 0xe8, 0x63, 0xb6, 0x69, 0xe4, - 0x20, 0xeb, 0xda, 0xfa, 0x0e, 0x94, 0x86, 0xb8, 0x68, 0x01, 0x20, 0x71, 0x2f, 0x3d, 0x6b, 0x58, - 0x93, 0x96, 0xb6, 0x8d, 0xe6, 0x41, 0xe3, 0x51, 0x0d, 0x4c, 0xef, 0x24, 0x33, 0xb0, 0x3c, 0xeb, - 0x47, 0x50, 0x1e, 0xed, 0xa3, 0xbf, 0x1a, 0xc3, 0x31, 0xb7, 0x44, 0xe3, 0x52, 0x81, 0x05, 0x8b, - 0x9e, 0xde, 0x2e, 0xd2, 0x40, 0x43, 0xc5, 0xd8, 0x67, 0x0f, 0xe2, 0xbe, 0xf2, 0x65, 0x5d, 0x12, - 0x1c, 0xea, 0x99, 0xbe, 0x63, 0xd0, 0xd0, 0xa9, 0x3a, 0xc4, 0xe7, 0xcf, 0x65, 0x55, 0xfc, 0x32, - 0x03, 0x37, 0x1a, 0xf3, 0x34, 0xbf, 0x12, 0xab, 0xef, 0xd9, 0xc5, 0x6d, 0xa1, 0xc0, 0x8f, 0x68, - 0x6c, 0x91, 0xfe, 0x01, 0x77, 0x2c, 0xbc, 0x19, 0x87, 0xb5, 0xa3, 0x3c, 0x57, 0x7b, 0xf6, 0x27, - 0x00, 0x00, 0xff, 0xff, 0x9e, 0xd0, 0x5c, 0x10, 0xe7, 0x07, 0x00, 0x00, + // 800 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x55, 0xdd, 0x4e, 0xdb, 0x48, + 0x14, 0x8e, 0xe3, 0x90, 0xe0, 0x13, 0x02, 0xd1, 0xec, 0x8f, 0x02, 0x2c, 0x02, 0x2c, 0xad, 0x16, + 0x89, 0x95, 0xa3, 0x64, 0xa5, 0xd5, 0x2e, 0xad, 0x44, 0x09, 0xa4, 0x24, 0x82, 0x06, 0x34, 0xa5, + 0xf4, 0x47, 0x91, 0x22, 0x63, 0x8f, 0x8c, 0x8b, 0xf1, 0x58, 0xb6, 0x13, 0xe0, 0x25, 0x7a, 0xdd, + 0x67, 0xe8, 0x23, 0xf4, 0x11, 0xfa, 0x0c, 0x7d, 0x84, 0x5e, 0x56, 0xea, 0x6d, 0x35, 0x3f, 0x86, + 0x24, 0x04, 0x83, 0xd4, 0x5e, 0x79, 0xe6, 0xf8, 0xfb, 0xbe, 0x73, 0xe6, 0xfc, 0xcc, 0x80, 0xe1, + 0x50, 0xea, 0x78, 0xa4, 0x6a, 0x93, 0x41, 0x4c, 0xa9, 0x17, 0x55, 0x23, 0xda, 0x0f, 0x2d, 0x52, + 0x1d, 0xd4, 0xe4, 0xaa, 0x67, 0x51, 0x3f, 0x26, 0x97, 0xb1, 0x11, 0x84, 0x34, 0xa6, 0x68, 0x5e, + 0xe0, 0x8d, 0x04, 0x6f, 0x08, 0x94, 0x31, 0xa8, 0x2d, 0xfc, 0x21, 0xa5, 0xcc, 0xc0, 0xad, 0x9a, + 0xbe, 0x4f, 0x63, 0x33, 0x76, 0xa9, 0x1f, 0x09, 0xa2, 0xfe, 0x39, 0x0b, 0xa5, 0xe7, 0x1c, 0xbb, + 0x2d, 0x04, 0x11, 0x06, 0xb0, 0x3c, 0xda, 0xb7, 0x7b, 0x21, 0x09, 0x68, 0x45, 0x59, 0x51, 0xd6, + 0x8a, 0xf5, 0x9a, 0x71, 0xa7, 0xbe, 0xb1, 0xcd, 0xc0, 0x98, 0x04, 0x74, 0x44, 0xa6, 0x95, 0xc1, + 0x9a, 0x95, 0xfc, 0x41, 0x26, 0xcc, 0x09, 0xcd, 0x0b, 0x1a, 0x9e, 0x45, 0x81, 0x69, 0x91, 0x4a, + 0x96, 0x0b, 0xff, 0x7b, 0x9f, 0xf0, 0xcb, 0x84, 0x30, 0xae, 0x3e, 0x6b, 0x8d, 0xfc, 0x46, 0x2d, + 0xc8, 0x3b, 0x24, 0x0c, 0xdd, 0xb8, 0xa2, 0x72, 0x65, 0x23, 0x45, 0x79, 0x97, 0x03, 0xc7, 0x15, + 0x25, 0x1f, 0x6d, 0x82, 0xea, 0xb8, 0x71, 0x25, 0xcf, 0x65, 0xd6, 0xd3, 0x64, 0x6e, 0x6b, 0x30, + 0x66, 0x43, 0x83, 0x82, 0xac, 0x8e, 0xfe, 0x45, 0x81, 0xdf, 0x9a, 0x97, 0x31, 0xf1, 0x6d, 0x62, + 0x8f, 0xa6, 0xb9, 0x71, 0x0d, 0x92, 0x39, 0x5e, 0x4b, 0xf1, 0x34, 0x42, 0xc5, 0x09, 0x11, 0x1d, + 0x41, 0xde, 0x33, 0x4f, 0x88, 0x17, 0x55, 0xb2, 0x2b, 0xea, 0x5a, 0xb1, 0xfe, 0x38, 0x45, 0x62, + 0x62, 0x14, 0xc6, 0x3e, 0xa7, 0x37, 0xfd, 0x38, 0xbc, 0xc2, 0x52, 0x6b, 0xe1, 0x7f, 0x28, 0x0e, + 0x99, 0x51, 0x19, 0xd4, 0x33, 0x72, 0xc5, 0x83, 0xd4, 0x30, 0x5b, 0xa2, 0x5f, 0x61, 0x6a, 0x60, + 0x7a, 0x7d, 0x51, 0x43, 0x0d, 0x8b, 0xcd, 0x46, 0xf6, 0x3f, 0x45, 0x7f, 0xaf, 0xc0, 0xcc, 0x96, + 0xe7, 0x9a, 0x51, 0x72, 0xca, 0x27, 0x90, 0x3b, 0x73, 0x7d, 0x9b, 0xb3, 0x67, 0xeb, 0x7f, 0xa7, + 0xc4, 0x37, 0x4c, 0x33, 0xf6, 0x5c, 0xdf, 0xc6, 0x9c, 0x89, 0x10, 0xe4, 0x7c, 0xf3, 0x3c, 0xf1, + 0xc5, 0xd7, 0x7a, 0x1d, 0x72, 0x0c, 0x81, 0x0a, 0xa0, 0x6e, 0x75, 0x5e, 0x97, 0x33, 0x48, 0x83, + 0xa9, 0xa7, 0xed, 0x57, 0xcd, 0x9d, 0xb2, 0x82, 0x8a, 0x50, 0x78, 0x76, 0x70, 0xbc, 0xd5, 0xd8, + 0x6f, 0x96, 0xb3, 0xcc, 0x7e, 0x70, 0xd4, 0x6a, 0xe2, 0x72, 0x4e, 0xff, 0xaa, 0xc0, 0xef, 0x93, + 0x5b, 0x15, 0x6d, 0x40, 0x81, 0xf5, 0x7a, 0xcf, 0xb5, 0x65, 0x29, 0x56, 0x53, 0xe2, 0x64, 0xf4, + 0xb6, 0x8d, 0xf3, 0x21, 0xff, 0xa2, 0x55, 0x28, 0x86, 0x64, 0xe0, 0x46, 0x2e, 0xf5, 0x19, 0x9f, + 0x47, 0xd9, 0xca, 0x60, 0x48, 0x8c, 0x6d, 0x1b, 0x2d, 0x03, 0x98, 0xec, 0x70, 0x3d, 0x7e, 0x0e, + 0x55, 0x22, 0x34, 0x6e, 0xeb, 0x98, 0xe7, 0x04, 0x75, 0xa0, 0x24, 0x00, 0x49, 0x43, 0xe4, 0x78, + 0x14, 0x7f, 0x3d, 0x30, 0x5b, 0xad, 0x0c, 0x9e, 0x31, 0x87, 0xf6, 0x0d, 0x80, 0xe9, 0xc4, 0xbd, + 0xfe, 0x4e, 0x81, 0xc5, 0x94, 0x41, 0x42, 0x1d, 0x98, 0xb9, 0x9e, 0xc9, 0x9b, 0x04, 0xac, 0x3f, + 0x78, 0x2c, 0xdb, 0x36, 0x2e, 0x5e, 0xdc, 0x6c, 0xd0, 0x32, 0x14, 0x23, 0xdf, 0x0c, 0xa2, 0x53, + 0x1a, 0x5f, 0xe7, 0x03, 0x43, 0x62, 0x6a, 0xdb, 0xfa, 0x37, 0x05, 0x7e, 0x99, 0x30, 0x7f, 0x68, + 0x1e, 0xa6, 0x4f, 0x69, 0x14, 0xf7, 0xfa, 0xa1, 0x2b, 0x7b, 0xad, 0xc0, 0xf6, 0x2f, 0x42, 0x17, + 0xfd, 0x09, 0xb3, 0x62, 0x34, 0x7b, 0x41, 0x48, 0xdf, 0x12, 0x2b, 0x96, 0xb2, 0x25, 0x61, 0x3d, + 0x14, 0xc6, 0xf1, 0x52, 0xa8, 0xf7, 0x96, 0x22, 0xf7, 0x80, 0x52, 0x4c, 0xfd, 0xbc, 0x52, 0x34, + 0xa1, 0x3c, 0x7e, 0x63, 0xb0, 0xe1, 0xea, 0x87, 0x5e, 0x32, 0x5c, 0xfd, 0xd0, 0x63, 0x09, 0xbc, + 0xd5, 0x50, 0xc3, 0x67, 0xd0, 0x07, 0x90, 0x17, 0x3d, 0x88, 0x30, 0xcc, 0xc9, 0x84, 0xf4, 0x46, + 0xfb, 0x37, 0xed, 0x2a, 0x91, 0xd9, 0x12, 0x12, 0xad, 0x0c, 0x2e, 0x05, 0xc3, 0x06, 0x84, 0x40, + 0xed, 0x0f, 0xf5, 0x31, 0xdb, 0x34, 0x72, 0x90, 0x75, 0x6d, 0x7d, 0x0f, 0x4a, 0x23, 0x5c, 0xb4, + 0x04, 0x90, 0xb8, 0x97, 0x9e, 0x35, 0xac, 0x49, 0x4b, 0xdb, 0x46, 0x8b, 0xa0, 0xf1, 0xa8, 0x86, + 0xa6, 0x77, 0x9a, 0x19, 0x58, 0x9e, 0xf5, 0x13, 0x28, 0x8f, 0xf7, 0xd1, 0x0f, 0x8d, 0xe1, 0x84, + 0x5b, 0xa2, 0xf1, 0x51, 0x81, 0x25, 0x8b, 0x9e, 0xdf, 0x2d, 0xd2, 0x40, 0x23, 0xc5, 0x38, 0x64, + 0x0f, 0xe2, 0xa1, 0xf2, 0x66, 0x53, 0x12, 0x1c, 0xea, 0x99, 0xbe, 0x63, 0xd0, 0xd0, 0xa9, 0x3a, + 0xc4, 0xe7, 0xcf, 0x65, 0x55, 0xfc, 0x32, 0x03, 0x37, 0x9a, 0xf0, 0x34, 0x3f, 0x12, 0xab, 0x0f, + 0xd9, 0xe5, 0x5d, 0xa1, 0xc0, 0x8f, 0x68, 0xec, 0x90, 0xc1, 0x11, 0x77, 0x2c, 0xbc, 0x19, 0xc7, + 0xb5, 0x4f, 0x09, 0xa2, 0xcb, 0x11, 0xdd, 0x04, 0xd1, 0x15, 0x88, 0xee, 0x71, 0xed, 0x24, 0xcf, + 0xfd, 0xfd, 0xf3, 0x3d, 0x00, 0x00, 0xff, 0xff, 0x54, 0x77, 0xc5, 0xa9, 0x09, 0x08, 0x00, 0x00, } diff --git a/vendor/google.golang.org/genproto/googleapis/privacy/dlp/v2beta2/dlp.pb.go b/vendor/google.golang.org/genproto/googleapis/privacy/dlp/v2beta2/dlp.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..5a89152f26259554517a308cafb864dc01201caa --- /dev/null +++ b/vendor/google.golang.org/genproto/googleapis/privacy/dlp/v2beta2/dlp.pb.go @@ -0,0 +1,7704 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: google/privacy/dlp/v2beta2/dlp.proto + +/* +Package dlp is a generated protocol buffer package. + +It is generated from these files: + google/privacy/dlp/v2beta2/dlp.proto + google/privacy/dlp/v2beta2/storage.proto + +It has these top-level messages: + InspectConfig + ContentItem + Table + InspectResult + Finding + Location + TableLocation + Range + ImageLocation + RedactImageRequest + Color + RedactImageResponse + DeidentifyContentRequest + DeidentifyContentResponse + ReidentifyContentRequest + ReidentifyContentResponse + InspectContentRequest + InspectContentResponse + InspectDataSourceRequest + OutputStorageConfig + InfoTypeStatistics + InspectDataSourceDetails + InfoTypeDescription + ListInfoTypesRequest + ListInfoTypesResponse + AnalyzeDataSourceRiskRequest + RiskAnalysisJobConfig + PrivacyMetric + AnalyzeDataSourceRiskDetails + ValueFrequency + Value + DeidentifyConfig + PrimitiveTransformation + TimePartConfig + CryptoHashConfig + ReplaceValueConfig + ReplaceWithInfoTypeConfig + RedactConfig + CharsToIgnore + CharacterMaskConfig + FixedSizeBucketingConfig + BucketingConfig + CryptoReplaceFfxFpeConfig + CryptoKey + TransientCryptoKey + UnwrappedCryptoKey + KmsWrappedCryptoKey + InfoTypeTransformations + FieldTransformation + RecordTransformations + RecordSuppression + RecordCondition + TransformationOverview + TransformationSummary + InspectTemplate + DeidentifyTemplate + CreateInspectTemplateRequest + UpdateInspectTemplateRequest + GetInspectTemplateRequest + ListInspectTemplatesRequest + ListInspectTemplatesResponse + DeleteInspectTemplateRequest + InspectJobConfig + DlpJob + GetDlpJobRequest + ListDlpJobsRequest + ListDlpJobsResponse + CancelDlpJobRequest + DeleteDlpJobRequest + CreateDeidentifyTemplateRequest + UpdateDeidentifyTemplateRequest + GetDeidentifyTemplateRequest + ListDeidentifyTemplatesRequest + ListDeidentifyTemplatesResponse + DeleteDeidentifyTemplateRequest + InfoType + CustomInfoType + FieldId + PartitionId + KindExpression + DatastoreOptions + CloudStorageOptions + BigQueryOptions + StorageConfig + CloudStorageKey + DatastoreKey + Key + RecordKey + BigQueryTable + EntityId +*/ +package dlp + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import _ "google.golang.org/genproto/googleapis/api/annotations" +import _ "github.com/golang/protobuf/ptypes/duration" +import google_protobuf3 "github.com/golang/protobuf/ptypes/empty" +import google_protobuf4 "google.golang.org/genproto/protobuf/field_mask" +import google_protobuf1 "github.com/golang/protobuf/ptypes/timestamp" +import google_rpc "google.golang.org/genproto/googleapis/rpc/status" +import google_type "google.golang.org/genproto/googleapis/type/date" +import _ "google.golang.org/genproto/googleapis/type/dayofweek" +import google_type2 "google.golang.org/genproto/googleapis/type/timeofday" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +// Parts of the APIs which use certain infoTypes. +type InfoTypeSupportedBy int32 + +const ( + InfoTypeSupportedBy_ENUM_TYPE_UNSPECIFIED InfoTypeSupportedBy = 0 + // Supported by the inspect operations. + InfoTypeSupportedBy_INSPECT InfoTypeSupportedBy = 1 + // Supported by the risk analysis operations. + InfoTypeSupportedBy_RISK_ANALYSIS InfoTypeSupportedBy = 2 +) + +var InfoTypeSupportedBy_name = map[int32]string{ + 0: "ENUM_TYPE_UNSPECIFIED", + 1: "INSPECT", + 2: "RISK_ANALYSIS", +} +var InfoTypeSupportedBy_value = map[string]int32{ + "ENUM_TYPE_UNSPECIFIED": 0, + "INSPECT": 1, + "RISK_ANALYSIS": 2, +} + +func (x InfoTypeSupportedBy) String() string { + return proto.EnumName(InfoTypeSupportedBy_name, int32(x)) +} +func (InfoTypeSupportedBy) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +// Operators available for comparing the value of fields. +type RelationalOperator int32 + +const ( + RelationalOperator_RELATIONAL_OPERATOR_UNSPECIFIED RelationalOperator = 0 + // Equal. + RelationalOperator_EQUAL_TO RelationalOperator = 1 + // Not equal to. + RelationalOperator_NOT_EQUAL_TO RelationalOperator = 2 + // Greater than. + RelationalOperator_GREATER_THAN RelationalOperator = 3 + // Less than. + RelationalOperator_LESS_THAN RelationalOperator = 4 + // Greater than or equals. + RelationalOperator_GREATER_THAN_OR_EQUALS RelationalOperator = 5 + // Less than or equals. + RelationalOperator_LESS_THAN_OR_EQUALS RelationalOperator = 6 + // Exists + RelationalOperator_EXISTS RelationalOperator = 7 +) + +var RelationalOperator_name = map[int32]string{ + 0: "RELATIONAL_OPERATOR_UNSPECIFIED", + 1: "EQUAL_TO", + 2: "NOT_EQUAL_TO", + 3: "GREATER_THAN", + 4: "LESS_THAN", + 5: "GREATER_THAN_OR_EQUALS", + 6: "LESS_THAN_OR_EQUALS", + 7: "EXISTS", +} +var RelationalOperator_value = map[string]int32{ + "RELATIONAL_OPERATOR_UNSPECIFIED": 0, + "EQUAL_TO": 1, + "NOT_EQUAL_TO": 2, + "GREATER_THAN": 3, + "LESS_THAN": 4, + "GREATER_THAN_OR_EQUALS": 5, + "LESS_THAN_OR_EQUALS": 6, + "EXISTS": 7, +} + +func (x RelationalOperator) String() string { + return proto.EnumName(RelationalOperator_name, int32(x)) +} +func (RelationalOperator) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +// An enum to represent the various type of DLP jobs. +type DlpJobType int32 + +const ( + DlpJobType_DLP_JOB_TYPE_UNSPECIFIED DlpJobType = 0 + // The job inspected Google Cloud for sensitive data. + DlpJobType_INSPECT_JOB DlpJobType = 1 + // The job executed a Risk Analysis computation. + DlpJobType_RISK_ANALYSIS_JOB DlpJobType = 2 +) + +var DlpJobType_name = map[int32]string{ + 0: "DLP_JOB_TYPE_UNSPECIFIED", + 1: "INSPECT_JOB", + 2: "RISK_ANALYSIS_JOB", +} +var DlpJobType_value = map[string]int32{ + "DLP_JOB_TYPE_UNSPECIFIED": 0, + "INSPECT_JOB": 1, + "RISK_ANALYSIS_JOB": 2, +} + +func (x DlpJobType) String() string { + return proto.EnumName(DlpJobType_name, int32(x)) +} +func (DlpJobType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } + +type TimePartConfig_TimePart int32 + +const ( + TimePartConfig_TIME_PART_UNSPECIFIED TimePartConfig_TimePart = 0 + // [0-9999] + TimePartConfig_YEAR TimePartConfig_TimePart = 1 + // [1-12] + TimePartConfig_MONTH TimePartConfig_TimePart = 2 + // [1-31] + TimePartConfig_DAY_OF_MONTH TimePartConfig_TimePart = 3 + // [1-7] + TimePartConfig_DAY_OF_WEEK TimePartConfig_TimePart = 4 + // [1-52] + TimePartConfig_WEEK_OF_YEAR TimePartConfig_TimePart = 5 + // [0-23] + TimePartConfig_HOUR_OF_DAY TimePartConfig_TimePart = 6 +) + +var TimePartConfig_TimePart_name = map[int32]string{ + 0: "TIME_PART_UNSPECIFIED", + 1: "YEAR", + 2: "MONTH", + 3: "DAY_OF_MONTH", + 4: "DAY_OF_WEEK", + 5: "WEEK_OF_YEAR", + 6: "HOUR_OF_DAY", +} +var TimePartConfig_TimePart_value = map[string]int32{ + "TIME_PART_UNSPECIFIED": 0, + "YEAR": 1, + "MONTH": 2, + "DAY_OF_MONTH": 3, + "DAY_OF_WEEK": 4, + "WEEK_OF_YEAR": 5, + "HOUR_OF_DAY": 6, +} + +func (x TimePartConfig_TimePart) String() string { + return proto.EnumName(TimePartConfig_TimePart_name, int32(x)) +} +func (TimePartConfig_TimePart) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{33, 0} } + +type CharsToIgnore_CommonCharsToIgnore int32 + +const ( + CharsToIgnore_COMMON_CHARS_TO_IGNORE_UNSPECIFIED CharsToIgnore_CommonCharsToIgnore = 0 + // 0-9 + CharsToIgnore_NUMERIC CharsToIgnore_CommonCharsToIgnore = 1 + // A-Z + CharsToIgnore_ALPHA_UPPER_CASE CharsToIgnore_CommonCharsToIgnore = 2 + // a-z + CharsToIgnore_ALPHA_LOWER_CASE CharsToIgnore_CommonCharsToIgnore = 3 + // US Punctuation, one of !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~ + CharsToIgnore_PUNCTUATION CharsToIgnore_CommonCharsToIgnore = 4 + // Whitespace character, one of [ \t\n\x0B\f\r] + CharsToIgnore_WHITESPACE CharsToIgnore_CommonCharsToIgnore = 5 +) + +var CharsToIgnore_CommonCharsToIgnore_name = map[int32]string{ + 0: "COMMON_CHARS_TO_IGNORE_UNSPECIFIED", + 1: "NUMERIC", + 2: "ALPHA_UPPER_CASE", + 3: "ALPHA_LOWER_CASE", + 4: "PUNCTUATION", + 5: "WHITESPACE", +} +var CharsToIgnore_CommonCharsToIgnore_value = map[string]int32{ + "COMMON_CHARS_TO_IGNORE_UNSPECIFIED": 0, + "NUMERIC": 1, + "ALPHA_UPPER_CASE": 2, + "ALPHA_LOWER_CASE": 3, + "PUNCTUATION": 4, + "WHITESPACE": 5, +} + +func (x CharsToIgnore_CommonCharsToIgnore) String() string { + return proto.EnumName(CharsToIgnore_CommonCharsToIgnore_name, int32(x)) +} +func (CharsToIgnore_CommonCharsToIgnore) EnumDescriptor() ([]byte, []int) { + return fileDescriptor0, []int{38, 0} +} + +// These are commonly used subsets of the alphabet that the FFX mode +// natively supports. In the algorithm, the alphabet is selected using +// the "radix". Therefore each corresponds to particular radix. +type CryptoReplaceFfxFpeConfig_FfxCommonNativeAlphabet int32 + +const ( + CryptoReplaceFfxFpeConfig_FFX_COMMON_NATIVE_ALPHABET_UNSPECIFIED CryptoReplaceFfxFpeConfig_FfxCommonNativeAlphabet = 0 + // [0-9] (radix of 10) + CryptoReplaceFfxFpeConfig_NUMERIC CryptoReplaceFfxFpeConfig_FfxCommonNativeAlphabet = 1 + // [0-9A-F] (radix of 16) + CryptoReplaceFfxFpeConfig_HEXADECIMAL CryptoReplaceFfxFpeConfig_FfxCommonNativeAlphabet = 2 + // [0-9A-Z] (radix of 36) + CryptoReplaceFfxFpeConfig_UPPER_CASE_ALPHA_NUMERIC CryptoReplaceFfxFpeConfig_FfxCommonNativeAlphabet = 3 + // [0-9A-Za-z] (radix of 62) + CryptoReplaceFfxFpeConfig_ALPHA_NUMERIC CryptoReplaceFfxFpeConfig_FfxCommonNativeAlphabet = 4 +) + +var CryptoReplaceFfxFpeConfig_FfxCommonNativeAlphabet_name = map[int32]string{ + 0: "FFX_COMMON_NATIVE_ALPHABET_UNSPECIFIED", + 1: "NUMERIC", + 2: "HEXADECIMAL", + 3: "UPPER_CASE_ALPHA_NUMERIC", + 4: "ALPHA_NUMERIC", +} +var CryptoReplaceFfxFpeConfig_FfxCommonNativeAlphabet_value = map[string]int32{ + "FFX_COMMON_NATIVE_ALPHABET_UNSPECIFIED": 0, + "NUMERIC": 1, + "HEXADECIMAL": 2, + "UPPER_CASE_ALPHA_NUMERIC": 3, + "ALPHA_NUMERIC": 4, +} + +func (x CryptoReplaceFfxFpeConfig_FfxCommonNativeAlphabet) String() string { + return proto.EnumName(CryptoReplaceFfxFpeConfig_FfxCommonNativeAlphabet_name, int32(x)) +} +func (CryptoReplaceFfxFpeConfig_FfxCommonNativeAlphabet) EnumDescriptor() ([]byte, []int) { + return fileDescriptor0, []int{42, 0} +} + +type RecordCondition_Expressions_LogicalOperator int32 + +const ( + RecordCondition_Expressions_LOGICAL_OPERATOR_UNSPECIFIED RecordCondition_Expressions_LogicalOperator = 0 + RecordCondition_Expressions_AND RecordCondition_Expressions_LogicalOperator = 1 +) + +var RecordCondition_Expressions_LogicalOperator_name = map[int32]string{ + 0: "LOGICAL_OPERATOR_UNSPECIFIED", + 1: "AND", +} +var RecordCondition_Expressions_LogicalOperator_value = map[string]int32{ + "LOGICAL_OPERATOR_UNSPECIFIED": 0, + "AND": 1, +} + +func (x RecordCondition_Expressions_LogicalOperator) String() string { + return proto.EnumName(RecordCondition_Expressions_LogicalOperator_name, int32(x)) +} +func (RecordCondition_Expressions_LogicalOperator) EnumDescriptor() ([]byte, []int) { + return fileDescriptor0, []int{51, 2, 0} +} + +// Possible outcomes of transformations. +type TransformationSummary_TransformationResultCode int32 + +const ( + TransformationSummary_TRANSFORMATION_RESULT_CODE_UNSPECIFIED TransformationSummary_TransformationResultCode = 0 + TransformationSummary_SUCCESS TransformationSummary_TransformationResultCode = 1 + TransformationSummary_ERROR TransformationSummary_TransformationResultCode = 2 +) + +var TransformationSummary_TransformationResultCode_name = map[int32]string{ + 0: "TRANSFORMATION_RESULT_CODE_UNSPECIFIED", + 1: "SUCCESS", + 2: "ERROR", +} +var TransformationSummary_TransformationResultCode_value = map[string]int32{ + "TRANSFORMATION_RESULT_CODE_UNSPECIFIED": 0, + "SUCCESS": 1, + "ERROR": 2, +} + +func (x TransformationSummary_TransformationResultCode) String() string { + return proto.EnumName(TransformationSummary_TransformationResultCode_name, int32(x)) +} +func (TransformationSummary_TransformationResultCode) EnumDescriptor() ([]byte, []int) { + return fileDescriptor0, []int{53, 0} +} + +type DlpJob_JobState int32 + +const ( + DlpJob_JOB_STATE_UNSPECIFIED DlpJob_JobState = 0 + // The job has not yet started. + DlpJob_PENDING DlpJob_JobState = 1 + // The job is currently running. + DlpJob_RUNNING DlpJob_JobState = 2 + // The job is no longer running. + DlpJob_DONE DlpJob_JobState = 3 + // The job was canceled before it could complete. + DlpJob_CANCELED DlpJob_JobState = 4 + // The job had an error and did not complete. + DlpJob_FAILED DlpJob_JobState = 5 +) + +var DlpJob_JobState_name = map[int32]string{ + 0: "JOB_STATE_UNSPECIFIED", + 1: "PENDING", + 2: "RUNNING", + 3: "DONE", + 4: "CANCELED", + 5: "FAILED", +} +var DlpJob_JobState_value = map[string]int32{ + "JOB_STATE_UNSPECIFIED": 0, + "PENDING": 1, + "RUNNING": 2, + "DONE": 3, + "CANCELED": 4, + "FAILED": 5, +} + +func (x DlpJob_JobState) String() string { + return proto.EnumName(DlpJob_JobState_name, int32(x)) +} +func (DlpJob_JobState) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{63, 0} } + +// Configuration description of the scanning process. +// When used with redactContent only info_types and min_likelihood are currently +// used. +type InspectConfig struct { + // Restricts what info_types to look for. The values must correspond to + // InfoType values returned by ListInfoTypes or found in documentation. + // Empty info_types runs all enabled detectors. + InfoTypes []*InfoType `protobuf:"bytes,1,rep,name=info_types,json=infoTypes" json:"info_types,omitempty"` + // Only returns findings equal or above this threshold. The default is + // POSSIBLE. + MinLikelihood Likelihood `protobuf:"varint,2,opt,name=min_likelihood,json=minLikelihood,enum=google.privacy.dlp.v2beta2.Likelihood" json:"min_likelihood,omitempty"` + Limits *InspectConfig_FindingLimits `protobuf:"bytes,3,opt,name=limits" json:"limits,omitempty"` + // When true, a contextual quote from the data that triggered a finding is + // included in the response; see Finding.quote. + IncludeQuote bool `protobuf:"varint,4,opt,name=include_quote,json=includeQuote" json:"include_quote,omitempty"` + // When true, excludes type information of the findings. + ExcludeInfoTypes bool `protobuf:"varint,5,opt,name=exclude_info_types,json=excludeInfoTypes" json:"exclude_info_types,omitempty"` + // Custom infoTypes provided by the user. + CustomInfoTypes []*CustomInfoType `protobuf:"bytes,6,rep,name=custom_info_types,json=customInfoTypes" json:"custom_info_types,omitempty"` +} + +func (m *InspectConfig) Reset() { *m = InspectConfig{} } +func (m *InspectConfig) String() string { return proto.CompactTextString(m) } +func (*InspectConfig) ProtoMessage() {} +func (*InspectConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +func (m *InspectConfig) GetInfoTypes() []*InfoType { + if m != nil { + return m.InfoTypes + } + return nil +} + +func (m *InspectConfig) GetMinLikelihood() Likelihood { + if m != nil { + return m.MinLikelihood + } + return Likelihood_LIKELIHOOD_UNSPECIFIED +} + +func (m *InspectConfig) GetLimits() *InspectConfig_FindingLimits { + if m != nil { + return m.Limits + } + return nil +} + +func (m *InspectConfig) GetIncludeQuote() bool { + if m != nil { + return m.IncludeQuote + } + return false +} + +func (m *InspectConfig) GetExcludeInfoTypes() bool { + if m != nil { + return m.ExcludeInfoTypes + } + return false +} + +func (m *InspectConfig) GetCustomInfoTypes() []*CustomInfoType { + if m != nil { + return m.CustomInfoTypes + } + return nil +} + +type InspectConfig_FindingLimits struct { + // Max number of findings that will be returned for each item scanned. + MaxFindingsPerItem int32 `protobuf:"varint,1,opt,name=max_findings_per_item,json=maxFindingsPerItem" json:"max_findings_per_item,omitempty"` + // Max total number of findings that will be returned per request/job. + MaxFindingsPerRequest int32 `protobuf:"varint,2,opt,name=max_findings_per_request,json=maxFindingsPerRequest" json:"max_findings_per_request,omitempty"` + // Configuration of findings limit given for specified infoTypes. + MaxFindingsPerInfoType []*InspectConfig_FindingLimits_InfoTypeLimit `protobuf:"bytes,3,rep,name=max_findings_per_info_type,json=maxFindingsPerInfoType" json:"max_findings_per_info_type,omitempty"` +} + +func (m *InspectConfig_FindingLimits) Reset() { *m = InspectConfig_FindingLimits{} } +func (m *InspectConfig_FindingLimits) String() string { return proto.CompactTextString(m) } +func (*InspectConfig_FindingLimits) ProtoMessage() {} +func (*InspectConfig_FindingLimits) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0, 0} } + +func (m *InspectConfig_FindingLimits) GetMaxFindingsPerItem() int32 { + if m != nil { + return m.MaxFindingsPerItem + } + return 0 +} + +func (m *InspectConfig_FindingLimits) GetMaxFindingsPerRequest() int32 { + if m != nil { + return m.MaxFindingsPerRequest + } + return 0 +} + +func (m *InspectConfig_FindingLimits) GetMaxFindingsPerInfoType() []*InspectConfig_FindingLimits_InfoTypeLimit { + if m != nil { + return m.MaxFindingsPerInfoType + } + return nil +} + +// Max findings configuration per infoType, per content item or long +// running DlpJob. +type InspectConfig_FindingLimits_InfoTypeLimit struct { + // Type of information the findings limit applies to. Only one limit per + // info_type should be provided. If InfoTypeLimit does not have an + // info_type, the DLP API applies the limit against all info_types that + // are found but not specified in another InfoTypeLimit. + InfoType *InfoType `protobuf:"bytes,1,opt,name=info_type,json=infoType" json:"info_type,omitempty"` + // Max findings limit for the given infoType. + MaxFindings int32 `protobuf:"varint,2,opt,name=max_findings,json=maxFindings" json:"max_findings,omitempty"` +} + +func (m *InspectConfig_FindingLimits_InfoTypeLimit) Reset() { + *m = InspectConfig_FindingLimits_InfoTypeLimit{} +} +func (m *InspectConfig_FindingLimits_InfoTypeLimit) String() string { return proto.CompactTextString(m) } +func (*InspectConfig_FindingLimits_InfoTypeLimit) ProtoMessage() {} +func (*InspectConfig_FindingLimits_InfoTypeLimit) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{0, 0, 0} +} + +func (m *InspectConfig_FindingLimits_InfoTypeLimit) GetInfoType() *InfoType { + if m != nil { + return m.InfoType + } + return nil +} + +func (m *InspectConfig_FindingLimits_InfoTypeLimit) GetMaxFindings() int32 { + if m != nil { + return m.MaxFindings + } + return 0 +} + +// Container structure for the content to inspect. +type ContentItem struct { + // Type of the content, as defined in Content-Type HTTP header. + // Supported types are: all "text" types, octet streams, PNG images, + // JPEG images. + Type string `protobuf:"bytes,1,opt,name=type" json:"type,omitempty"` + // Data of the item either in the byte array or UTF-8 string form. + // + // Types that are valid to be assigned to DataItem: + // *ContentItem_Data + // *ContentItem_Value + // *ContentItem_Table + DataItem isContentItem_DataItem `protobuf_oneof:"data_item"` +} + +func (m *ContentItem) Reset() { *m = ContentItem{} } +func (m *ContentItem) String() string { return proto.CompactTextString(m) } +func (*ContentItem) ProtoMessage() {} +func (*ContentItem) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +type isContentItem_DataItem interface { + isContentItem_DataItem() +} + +type ContentItem_Data struct { + Data []byte `protobuf:"bytes,2,opt,name=data,proto3,oneof"` +} +type ContentItem_Value struct { + Value string `protobuf:"bytes,3,opt,name=value,oneof"` +} +type ContentItem_Table struct { + Table *Table `protobuf:"bytes,4,opt,name=table,oneof"` +} + +func (*ContentItem_Data) isContentItem_DataItem() {} +func (*ContentItem_Value) isContentItem_DataItem() {} +func (*ContentItem_Table) isContentItem_DataItem() {} + +func (m *ContentItem) GetDataItem() isContentItem_DataItem { + if m != nil { + return m.DataItem + } + return nil +} + +func (m *ContentItem) GetType() string { + if m != nil { + return m.Type + } + return "" +} + +func (m *ContentItem) GetData() []byte { + if x, ok := m.GetDataItem().(*ContentItem_Data); ok { + return x.Data + } + return nil +} + +func (m *ContentItem) GetValue() string { + if x, ok := m.GetDataItem().(*ContentItem_Value); ok { + return x.Value + } + return "" +} + +func (m *ContentItem) GetTable() *Table { + if x, ok := m.GetDataItem().(*ContentItem_Table); ok { + return x.Table + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*ContentItem) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _ContentItem_OneofMarshaler, _ContentItem_OneofUnmarshaler, _ContentItem_OneofSizer, []interface{}{ + (*ContentItem_Data)(nil), + (*ContentItem_Value)(nil), + (*ContentItem_Table)(nil), + } +} + +func _ContentItem_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*ContentItem) + // data_item + switch x := m.DataItem.(type) { + case *ContentItem_Data: + b.EncodeVarint(2<<3 | proto.WireBytes) + b.EncodeRawBytes(x.Data) + case *ContentItem_Value: + b.EncodeVarint(3<<3 | proto.WireBytes) + b.EncodeStringBytes(x.Value) + case *ContentItem_Table: + b.EncodeVarint(4<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Table); err != nil { + return err + } + case nil: + default: + return fmt.Errorf("ContentItem.DataItem has unexpected type %T", x) + } + return nil +} + +func _ContentItem_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*ContentItem) + switch tag { + case 2: // data_item.data + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeRawBytes(true) + m.DataItem = &ContentItem_Data{x} + return true, err + case 3: // data_item.value + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeStringBytes() + m.DataItem = &ContentItem_Value{x} + return true, err + case 4: // data_item.table + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(Table) + err := b.DecodeMessage(msg) + m.DataItem = &ContentItem_Table{msg} + return true, err + default: + return false, nil + } +} + +func _ContentItem_OneofSizer(msg proto.Message) (n int) { + m := msg.(*ContentItem) + // data_item + switch x := m.DataItem.(type) { + case *ContentItem_Data: + n += proto.SizeVarint(2<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.Data))) + n += len(x.Data) + case *ContentItem_Value: + n += proto.SizeVarint(3<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.Value))) + n += len(x.Value) + case *ContentItem_Table: + s := proto.Size(x.Table) + n += proto.SizeVarint(4<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +// Structured content to inspect. Up to 50,000 `Value`s per request allowed. +type Table struct { + Headers []*FieldId `protobuf:"bytes,1,rep,name=headers" json:"headers,omitempty"` + Rows []*Table_Row `protobuf:"bytes,2,rep,name=rows" json:"rows,omitempty"` +} + +func (m *Table) Reset() { *m = Table{} } +func (m *Table) String() string { return proto.CompactTextString(m) } +func (*Table) ProtoMessage() {} +func (*Table) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } + +func (m *Table) GetHeaders() []*FieldId { + if m != nil { + return m.Headers + } + return nil +} + +func (m *Table) GetRows() []*Table_Row { + if m != nil { + return m.Rows + } + return nil +} + +type Table_Row struct { + Values []*Value `protobuf:"bytes,1,rep,name=values" json:"values,omitempty"` +} + +func (m *Table_Row) Reset() { *m = Table_Row{} } +func (m *Table_Row) String() string { return proto.CompactTextString(m) } +func (*Table_Row) ProtoMessage() {} +func (*Table_Row) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2, 0} } + +func (m *Table_Row) GetValues() []*Value { + if m != nil { + return m.Values + } + return nil +} + +// All the findings for a single scanned item. +type InspectResult struct { + // List of findings for an item. + Findings []*Finding `protobuf:"bytes,1,rep,name=findings" json:"findings,omitempty"` + // If true, then this item might have more findings than were returned, + // and the findings returned are an arbitrary subset of all findings. + // The findings list might be truncated because the input items were too + // large, or because the server reached the maximum amount of resources + // allowed for a single API call. For best results, divide the input into + // smaller batches. + FindingsTruncated bool `protobuf:"varint,2,opt,name=findings_truncated,json=findingsTruncated" json:"findings_truncated,omitempty"` +} + +func (m *InspectResult) Reset() { *m = InspectResult{} } +func (m *InspectResult) String() string { return proto.CompactTextString(m) } +func (*InspectResult) ProtoMessage() {} +func (*InspectResult) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } + +func (m *InspectResult) GetFindings() []*Finding { + if m != nil { + return m.Findings + } + return nil +} + +func (m *InspectResult) GetFindingsTruncated() bool { + if m != nil { + return m.FindingsTruncated + } + return false +} + +// Represents a piece of potentially sensitive content. +type Finding struct { + // The content that was found. Even if the content is not textual, it + // may be converted to a textual representation here. + // Provided if requested by the `InspectConfig`. + Quote string `protobuf:"bytes,1,opt,name=quote" json:"quote,omitempty"` + // The type of content that might have been found. + // Provided if requested by the `InspectConfig`. + InfoType *InfoType `protobuf:"bytes,2,opt,name=info_type,json=infoType" json:"info_type,omitempty"` + // Estimate of how likely it is that the `info_type` is correct. + Likelihood Likelihood `protobuf:"varint,3,opt,name=likelihood,enum=google.privacy.dlp.v2beta2.Likelihood" json:"likelihood,omitempty"` + // Where the content was found. + Location *Location `protobuf:"bytes,4,opt,name=location" json:"location,omitempty"` + // Timestamp when finding was detected. + CreateTime *google_protobuf1.Timestamp `protobuf:"bytes,6,opt,name=create_time,json=createTime" json:"create_time,omitempty"` +} + +func (m *Finding) Reset() { *m = Finding{} } +func (m *Finding) String() string { return proto.CompactTextString(m) } +func (*Finding) ProtoMessage() {} +func (*Finding) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } + +func (m *Finding) GetQuote() string { + if m != nil { + return m.Quote + } + return "" +} + +func (m *Finding) GetInfoType() *InfoType { + if m != nil { + return m.InfoType + } + return nil +} + +func (m *Finding) GetLikelihood() Likelihood { + if m != nil { + return m.Likelihood + } + return Likelihood_LIKELIHOOD_UNSPECIFIED +} + +func (m *Finding) GetLocation() *Location { + if m != nil { + return m.Location + } + return nil +} + +func (m *Finding) GetCreateTime() *google_protobuf1.Timestamp { + if m != nil { + return m.CreateTime + } + return nil +} + +// Specifies the location of the finding. +type Location struct { + // Zero-based byte offsets delimiting the finding. + // These are relative to the finding's containing element. + // Note that when the content is not textual, this references + // the UTF-8 encoded textual representation of the content. + // Omitted if content is an image. + ByteRange *Range `protobuf:"bytes,1,opt,name=byte_range,json=byteRange" json:"byte_range,omitempty"` + // Unicode character offsets delimiting the finding. + // These are relative to the finding's containing element. + // Provided when the content is text. + CodepointRange *Range `protobuf:"bytes,2,opt,name=codepoint_range,json=codepointRange" json:"codepoint_range,omitempty"` + // The area within the image that contained the finding. + // Provided when the content is an image. + ImageBoxes []*ImageLocation `protobuf:"bytes,3,rep,name=image_boxes,json=imageBoxes" json:"image_boxes,omitempty"` + // The pointer to the record in storage that contained the field the + // finding was found in. + // Provided when the finding's containing element is a property + // of a storage object. + RecordKey *RecordKey `protobuf:"bytes,4,opt,name=record_key,json=recordKey" json:"record_key,omitempty"` + // The pointer to the property or cell that contained the finding. + // Provided when the finding's containing element is a cell in a table + // or a property of storage object. + FieldId *FieldId `protobuf:"bytes,5,opt,name=field_id,json=fieldId" json:"field_id,omitempty"` + // The pointer to the row of the table that contained the finding. + // Provided when the finding's containing element is a cell of a table. + TableLocation *TableLocation `protobuf:"bytes,6,opt,name=table_location,json=tableLocation" json:"table_location,omitempty"` +} + +func (m *Location) Reset() { *m = Location{} } +func (m *Location) String() string { return proto.CompactTextString(m) } +func (*Location) ProtoMessage() {} +func (*Location) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } + +func (m *Location) GetByteRange() *Range { + if m != nil { + return m.ByteRange + } + return nil +} + +func (m *Location) GetCodepointRange() *Range { + if m != nil { + return m.CodepointRange + } + return nil +} + +func (m *Location) GetImageBoxes() []*ImageLocation { + if m != nil { + return m.ImageBoxes + } + return nil +} + +func (m *Location) GetRecordKey() *RecordKey { + if m != nil { + return m.RecordKey + } + return nil +} + +func (m *Location) GetFieldId() *FieldId { + if m != nil { + return m.FieldId + } + return nil +} + +func (m *Location) GetTableLocation() *TableLocation { + if m != nil { + return m.TableLocation + } + return nil +} + +// Location of a finding within a table. +type TableLocation struct { + // The zero-based index of the row where the finding is located. + RowIndex int64 `protobuf:"varint,1,opt,name=row_index,json=rowIndex" json:"row_index,omitempty"` +} + +func (m *TableLocation) Reset() { *m = TableLocation{} } +func (m *TableLocation) String() string { return proto.CompactTextString(m) } +func (*TableLocation) ProtoMessage() {} +func (*TableLocation) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } + +func (m *TableLocation) GetRowIndex() int64 { + if m != nil { + return m.RowIndex + } + return 0 +} + +// Generic half-open interval [start, end) +type Range struct { + // Index of the first character of the range (inclusive). + Start int64 `protobuf:"varint,1,opt,name=start" json:"start,omitempty"` + // Index of the last character of the range (exclusive). + End int64 `protobuf:"varint,2,opt,name=end" json:"end,omitempty"` +} + +func (m *Range) Reset() { *m = Range{} } +func (m *Range) String() string { return proto.CompactTextString(m) } +func (*Range) ProtoMessage() {} +func (*Range) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } + +func (m *Range) GetStart() int64 { + if m != nil { + return m.Start + } + return 0 +} + +func (m *Range) GetEnd() int64 { + if m != nil { + return m.End + } + return 0 +} + +// Bounding box encompassing detected text within an image. +type ImageLocation struct { + // Top coordinate of the bounding box. (0,0) is upper left. + Top int32 `protobuf:"varint,1,opt,name=top" json:"top,omitempty"` + // Left coordinate of the bounding box. (0,0) is upper left. + Left int32 `protobuf:"varint,2,opt,name=left" json:"left,omitempty"` + // Width of the bounding box in pixels. + Width int32 `protobuf:"varint,3,opt,name=width" json:"width,omitempty"` + // Height of the bounding box in pixels. + Height int32 `protobuf:"varint,4,opt,name=height" json:"height,omitempty"` +} + +func (m *ImageLocation) Reset() { *m = ImageLocation{} } +func (m *ImageLocation) String() string { return proto.CompactTextString(m) } +func (*ImageLocation) ProtoMessage() {} +func (*ImageLocation) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } + +func (m *ImageLocation) GetTop() int32 { + if m != nil { + return m.Top + } + return 0 +} + +func (m *ImageLocation) GetLeft() int32 { + if m != nil { + return m.Left + } + return 0 +} + +func (m *ImageLocation) GetWidth() int32 { + if m != nil { + return m.Width + } + return 0 +} + +func (m *ImageLocation) GetHeight() int32 { + if m != nil { + return m.Height + } + return 0 +} + +// Request to search for potentially sensitive info in a list of items +// and replace it with a default or provided content. +type RedactImageRequest struct { + // The parent resource name, for example projects/my-project-id. + Parent string `protobuf:"bytes,1,opt,name=parent" json:"parent,omitempty"` + // Configuration for the inspector. + InspectConfig *InspectConfig `protobuf:"bytes,2,opt,name=inspect_config,json=inspectConfig" json:"inspect_config,omitempty"` + // Type of the content, as defined in Content-Type HTTP header. + // Supported types are: PNG, JPEG, SVG, & BMP. + ImageType string `protobuf:"bytes,3,opt,name=image_type,json=imageType" json:"image_type,omitempty"` + // The bytes of the image to redact. + ImageData []byte `protobuf:"bytes,4,opt,name=image_data,json=imageData,proto3" json:"image_data,omitempty"` + // The configuration for specifying what content to redact from images. + ImageRedactionConfigs []*RedactImageRequest_ImageRedactionConfig `protobuf:"bytes,5,rep,name=image_redaction_configs,json=imageRedactionConfigs" json:"image_redaction_configs,omitempty"` +} + +func (m *RedactImageRequest) Reset() { *m = RedactImageRequest{} } +func (m *RedactImageRequest) String() string { return proto.CompactTextString(m) } +func (*RedactImageRequest) ProtoMessage() {} +func (*RedactImageRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } + +func (m *RedactImageRequest) GetParent() string { + if m != nil { + return m.Parent + } + return "" +} + +func (m *RedactImageRequest) GetInspectConfig() *InspectConfig { + if m != nil { + return m.InspectConfig + } + return nil +} + +func (m *RedactImageRequest) GetImageType() string { + if m != nil { + return m.ImageType + } + return "" +} + +func (m *RedactImageRequest) GetImageData() []byte { + if m != nil { + return m.ImageData + } + return nil +} + +func (m *RedactImageRequest) GetImageRedactionConfigs() []*RedactImageRequest_ImageRedactionConfig { + if m != nil { + return m.ImageRedactionConfigs + } + return nil +} + +// Configuration for determining how redaction of images should occur. +type RedactImageRequest_ImageRedactionConfig struct { + // Type of information to redact from images. + // + // Types that are valid to be assigned to Target: + // *RedactImageRequest_ImageRedactionConfig_InfoType + // *RedactImageRequest_ImageRedactionConfig_RedactAllText + Target isRedactImageRequest_ImageRedactionConfig_Target `protobuf_oneof:"target"` + // The color to use when redacting content from an image. If not specified, + // the default is black. + RedactionColor *Color `protobuf:"bytes,3,opt,name=redaction_color,json=redactionColor" json:"redaction_color,omitempty"` +} + +func (m *RedactImageRequest_ImageRedactionConfig) Reset() { + *m = RedactImageRequest_ImageRedactionConfig{} +} +func (m *RedactImageRequest_ImageRedactionConfig) String() string { return proto.CompactTextString(m) } +func (*RedactImageRequest_ImageRedactionConfig) ProtoMessage() {} +func (*RedactImageRequest_ImageRedactionConfig) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{9, 0} +} + +type isRedactImageRequest_ImageRedactionConfig_Target interface { + isRedactImageRequest_ImageRedactionConfig_Target() +} + +type RedactImageRequest_ImageRedactionConfig_InfoType struct { + InfoType *InfoType `protobuf:"bytes,1,opt,name=info_type,json=infoType,oneof"` +} +type RedactImageRequest_ImageRedactionConfig_RedactAllText struct { + RedactAllText bool `protobuf:"varint,2,opt,name=redact_all_text,json=redactAllText,oneof"` +} + +func (*RedactImageRequest_ImageRedactionConfig_InfoType) isRedactImageRequest_ImageRedactionConfig_Target() { +} +func (*RedactImageRequest_ImageRedactionConfig_RedactAllText) isRedactImageRequest_ImageRedactionConfig_Target() { +} + +func (m *RedactImageRequest_ImageRedactionConfig) GetTarget() isRedactImageRequest_ImageRedactionConfig_Target { + if m != nil { + return m.Target + } + return nil +} + +func (m *RedactImageRequest_ImageRedactionConfig) GetInfoType() *InfoType { + if x, ok := m.GetTarget().(*RedactImageRequest_ImageRedactionConfig_InfoType); ok { + return x.InfoType + } + return nil +} + +func (m *RedactImageRequest_ImageRedactionConfig) GetRedactAllText() bool { + if x, ok := m.GetTarget().(*RedactImageRequest_ImageRedactionConfig_RedactAllText); ok { + return x.RedactAllText + } + return false +} + +func (m *RedactImageRequest_ImageRedactionConfig) GetRedactionColor() *Color { + if m != nil { + return m.RedactionColor + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*RedactImageRequest_ImageRedactionConfig) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _RedactImageRequest_ImageRedactionConfig_OneofMarshaler, _RedactImageRequest_ImageRedactionConfig_OneofUnmarshaler, _RedactImageRequest_ImageRedactionConfig_OneofSizer, []interface{}{ + (*RedactImageRequest_ImageRedactionConfig_InfoType)(nil), + (*RedactImageRequest_ImageRedactionConfig_RedactAllText)(nil), + } +} + +func _RedactImageRequest_ImageRedactionConfig_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*RedactImageRequest_ImageRedactionConfig) + // target + switch x := m.Target.(type) { + case *RedactImageRequest_ImageRedactionConfig_InfoType: + b.EncodeVarint(1<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.InfoType); err != nil { + return err + } + case *RedactImageRequest_ImageRedactionConfig_RedactAllText: + t := uint64(0) + if x.RedactAllText { + t = 1 + } + b.EncodeVarint(2<<3 | proto.WireVarint) + b.EncodeVarint(t) + case nil: + default: + return fmt.Errorf("RedactImageRequest_ImageRedactionConfig.Target has unexpected type %T", x) + } + return nil +} + +func _RedactImageRequest_ImageRedactionConfig_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*RedactImageRequest_ImageRedactionConfig) + switch tag { + case 1: // target.info_type + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(InfoType) + err := b.DecodeMessage(msg) + m.Target = &RedactImageRequest_ImageRedactionConfig_InfoType{msg} + return true, err + case 2: // target.redact_all_text + if wire != proto.WireVarint { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeVarint() + m.Target = &RedactImageRequest_ImageRedactionConfig_RedactAllText{x != 0} + return true, err + default: + return false, nil + } +} + +func _RedactImageRequest_ImageRedactionConfig_OneofSizer(msg proto.Message) (n int) { + m := msg.(*RedactImageRequest_ImageRedactionConfig) + // target + switch x := m.Target.(type) { + case *RedactImageRequest_ImageRedactionConfig_InfoType: + s := proto.Size(x.InfoType) + n += proto.SizeVarint(1<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *RedactImageRequest_ImageRedactionConfig_RedactAllText: + n += proto.SizeVarint(2<<3 | proto.WireVarint) + n += 1 + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +// Represents a color in the RGB color space. +type Color struct { + // The amount of red in the color as a value in the interval [0, 1]. + Red float32 `protobuf:"fixed32,1,opt,name=red" json:"red,omitempty"` + // The amount of green in the color as a value in the interval [0, 1]. + Green float32 `protobuf:"fixed32,2,opt,name=green" json:"green,omitempty"` + // The amount of blue in the color as a value in the interval [0, 1]. + Blue float32 `protobuf:"fixed32,3,opt,name=blue" json:"blue,omitempty"` +} + +func (m *Color) Reset() { *m = Color{} } +func (m *Color) String() string { return proto.CompactTextString(m) } +func (*Color) ProtoMessage() {} +func (*Color) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } + +func (m *Color) GetRed() float32 { + if m != nil { + return m.Red + } + return 0 +} + +func (m *Color) GetGreen() float32 { + if m != nil { + return m.Green + } + return 0 +} + +func (m *Color) GetBlue() float32 { + if m != nil { + return m.Blue + } + return 0 +} + +// Results of redacting an image. +type RedactImageResponse struct { + // The redacted image. The type will be the same as the original image. + RedactedImage []byte `protobuf:"bytes,1,opt,name=redacted_image,json=redactedImage,proto3" json:"redacted_image,omitempty"` + // If an image was being inspected and the InspectConfig's include_quote was + // set to true, then this field will include all text, if any, that was found + // in the image. + ExtractedText string `protobuf:"bytes,2,opt,name=extracted_text,json=extractedText" json:"extracted_text,omitempty"` +} + +func (m *RedactImageResponse) Reset() { *m = RedactImageResponse{} } +func (m *RedactImageResponse) String() string { return proto.CompactTextString(m) } +func (*RedactImageResponse) ProtoMessage() {} +func (*RedactImageResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } + +func (m *RedactImageResponse) GetRedactedImage() []byte { + if m != nil { + return m.RedactedImage + } + return nil +} + +func (m *RedactImageResponse) GetExtractedText() string { + if m != nil { + return m.ExtractedText + } + return "" +} + +// Request to de-identify a list of items. +type DeidentifyContentRequest struct { + // The parent resource name, for example projects/my-project-id. + Parent string `protobuf:"bytes,1,opt,name=parent" json:"parent,omitempty"` + // Configuration for the de-identification of the content item. + // Items specified here will override the template referenced by the + // deidentify_template_name argument. + DeidentifyConfig *DeidentifyConfig `protobuf:"bytes,2,opt,name=deidentify_config,json=deidentifyConfig" json:"deidentify_config,omitempty"` + // Configuration for the inspector. + // Items specified here will override the template referenced by the + // inspect_template_name argument. + InspectConfig *InspectConfig `protobuf:"bytes,3,opt,name=inspect_config,json=inspectConfig" json:"inspect_config,omitempty"` + // The item to de-identify. Will be treated as text. + Item *ContentItem `protobuf:"bytes,4,opt,name=item" json:"item,omitempty"` + // Optional template to use. Any configuration directly specified in + // inspect_config will override those set in the template. Singular fields + // that are set in this request will replace their corresponding fields in the + // template. Repeated fields are appended. Singular sub-messages and groups + // are recursively merged. + InspectTemplateName string `protobuf:"bytes,5,opt,name=inspect_template_name,json=inspectTemplateName" json:"inspect_template_name,omitempty"` + // Optional template to use. Any configuration directly specified in + // deidentify_config will override those set in the template. Singular fields + // that are set in this request will replace their corresponding fields in the + // template. Repeated fields are appended. Singular sub-messages and groups + // are recursively merged. + DeidentifyTemplateName string `protobuf:"bytes,6,opt,name=deidentify_template_name,json=deidentifyTemplateName" json:"deidentify_template_name,omitempty"` +} + +func (m *DeidentifyContentRequest) Reset() { *m = DeidentifyContentRequest{} } +func (m *DeidentifyContentRequest) String() string { return proto.CompactTextString(m) } +func (*DeidentifyContentRequest) ProtoMessage() {} +func (*DeidentifyContentRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } + +func (m *DeidentifyContentRequest) GetParent() string { + if m != nil { + return m.Parent + } + return "" +} + +func (m *DeidentifyContentRequest) GetDeidentifyConfig() *DeidentifyConfig { + if m != nil { + return m.DeidentifyConfig + } + return nil +} + +func (m *DeidentifyContentRequest) GetInspectConfig() *InspectConfig { + if m != nil { + return m.InspectConfig + } + return nil +} + +func (m *DeidentifyContentRequest) GetItem() *ContentItem { + if m != nil { + return m.Item + } + return nil +} + +func (m *DeidentifyContentRequest) GetInspectTemplateName() string { + if m != nil { + return m.InspectTemplateName + } + return "" +} + +func (m *DeidentifyContentRequest) GetDeidentifyTemplateName() string { + if m != nil { + return m.DeidentifyTemplateName + } + return "" +} + +// Results of de-identifying a ContentItem. +type DeidentifyContentResponse struct { + // The de-identified item. + Item *ContentItem `protobuf:"bytes,1,opt,name=item" json:"item,omitempty"` + // An overview of the changes that were made on the `item`. + Overview *TransformationOverview `protobuf:"bytes,2,opt,name=overview" json:"overview,omitempty"` +} + +func (m *DeidentifyContentResponse) Reset() { *m = DeidentifyContentResponse{} } +func (m *DeidentifyContentResponse) String() string { return proto.CompactTextString(m) } +func (*DeidentifyContentResponse) ProtoMessage() {} +func (*DeidentifyContentResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } + +func (m *DeidentifyContentResponse) GetItem() *ContentItem { + if m != nil { + return m.Item + } + return nil +} + +func (m *DeidentifyContentResponse) GetOverview() *TransformationOverview { + if m != nil { + return m.Overview + } + return nil +} + +// Request to re-identify an item. +type ReidentifyContentRequest struct { + // The parent resource name. + Parent string `protobuf:"bytes,1,opt,name=parent" json:"parent,omitempty"` + // Configuration for the re-identification of the content item. + // This field shares the same proto message type that is used for + // de-identification, however its usage here is for the reversal of the + // previous de-identification. Re-identification is performed by examining + // the transformations used to de-identify the items and executing the + // reverse. This requires that only reversible transformations + // be provided here. The reversible transformations are: + // + // - `CryptoReplaceFfxFpeConfig` + ReidentifyConfig *DeidentifyConfig `protobuf:"bytes,2,opt,name=reidentify_config,json=reidentifyConfig" json:"reidentify_config,omitempty"` + // Configuration for the inspector. + InspectConfig *InspectConfig `protobuf:"bytes,3,opt,name=inspect_config,json=inspectConfig" json:"inspect_config,omitempty"` + // The item to re-identify. Will be treated as text. + Item *ContentItem `protobuf:"bytes,4,opt,name=item" json:"item,omitempty"` + // Optional template to use. Any configuration directly specified in + // `inspect_config` will override those set in the template. Singular fields + // that are set in this request will replace their corresponding fields in the + // template. Repeated fields are appended. Singular sub-messages and groups + // are recursively merged. + InspectTemplateName string `protobuf:"bytes,5,opt,name=inspect_template_name,json=inspectTemplateName" json:"inspect_template_name,omitempty"` + // Optional template to use. References an instance of `DeidentifyTemplate`. + // Any configuration directly specified in `reidentify_config` or + // `inspect_config` will override those set in the template. Singular fields + // that are set in this request will replace their corresponding fields in the + // template. Repeated fields are appended. Singular sub-messages and groups + // are recursively merged. + ReidentifyTemplateName string `protobuf:"bytes,6,opt,name=reidentify_template_name,json=reidentifyTemplateName" json:"reidentify_template_name,omitempty"` +} + +func (m *ReidentifyContentRequest) Reset() { *m = ReidentifyContentRequest{} } +func (m *ReidentifyContentRequest) String() string { return proto.CompactTextString(m) } +func (*ReidentifyContentRequest) ProtoMessage() {} +func (*ReidentifyContentRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } + +func (m *ReidentifyContentRequest) GetParent() string { + if m != nil { + return m.Parent + } + return "" +} + +func (m *ReidentifyContentRequest) GetReidentifyConfig() *DeidentifyConfig { + if m != nil { + return m.ReidentifyConfig + } + return nil +} + +func (m *ReidentifyContentRequest) GetInspectConfig() *InspectConfig { + if m != nil { + return m.InspectConfig + } + return nil +} + +func (m *ReidentifyContentRequest) GetItem() *ContentItem { + if m != nil { + return m.Item + } + return nil +} + +func (m *ReidentifyContentRequest) GetInspectTemplateName() string { + if m != nil { + return m.InspectTemplateName + } + return "" +} + +func (m *ReidentifyContentRequest) GetReidentifyTemplateName() string { + if m != nil { + return m.ReidentifyTemplateName + } + return "" +} + +// Results of re-identifying a item. +type ReidentifyContentResponse struct { + // The re-identified item. + Item *ContentItem `protobuf:"bytes,1,opt,name=item" json:"item,omitempty"` + // An overview of the changes that were made to the `item`. + Overview *TransformationOverview `protobuf:"bytes,2,opt,name=overview" json:"overview,omitempty"` +} + +func (m *ReidentifyContentResponse) Reset() { *m = ReidentifyContentResponse{} } +func (m *ReidentifyContentResponse) String() string { return proto.CompactTextString(m) } +func (*ReidentifyContentResponse) ProtoMessage() {} +func (*ReidentifyContentResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } + +func (m *ReidentifyContentResponse) GetItem() *ContentItem { + if m != nil { + return m.Item + } + return nil +} + +func (m *ReidentifyContentResponse) GetOverview() *TransformationOverview { + if m != nil { + return m.Overview + } + return nil +} + +// Request to search for potentially sensitive info in a ContentItem. +type InspectContentRequest struct { + // The parent resource name, for example projects/my-project-id. + Parent string `protobuf:"bytes,1,opt,name=parent" json:"parent,omitempty"` + // Configuration for the inspector. What specified here will override + // the template referenced by the inspect_template_name argument. + InspectConfig *InspectConfig `protobuf:"bytes,2,opt,name=inspect_config,json=inspectConfig" json:"inspect_config,omitempty"` + // The item to inspect. + Item *ContentItem `protobuf:"bytes,3,opt,name=item" json:"item,omitempty"` + // Optional template to use. Any configuration directly specified in + // inspect_config will override those set in the template. Singular fields + // that are set in this request will replace their corresponding fields in the + // template. Repeated fields are appended. Singular sub-messages and groups + // are recursively merged. + InspectTemplateName string `protobuf:"bytes,4,opt,name=inspect_template_name,json=inspectTemplateName" json:"inspect_template_name,omitempty"` +} + +func (m *InspectContentRequest) Reset() { *m = InspectContentRequest{} } +func (m *InspectContentRequest) String() string { return proto.CompactTextString(m) } +func (*InspectContentRequest) ProtoMessage() {} +func (*InspectContentRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } + +func (m *InspectContentRequest) GetParent() string { + if m != nil { + return m.Parent + } + return "" +} + +func (m *InspectContentRequest) GetInspectConfig() *InspectConfig { + if m != nil { + return m.InspectConfig + } + return nil +} + +func (m *InspectContentRequest) GetItem() *ContentItem { + if m != nil { + return m.Item + } + return nil +} + +func (m *InspectContentRequest) GetInspectTemplateName() string { + if m != nil { + return m.InspectTemplateName + } + return "" +} + +// Results of inspecting an item. +type InspectContentResponse struct { + // The findings. + Result *InspectResult `protobuf:"bytes,1,opt,name=result" json:"result,omitempty"` +} + +func (m *InspectContentResponse) Reset() { *m = InspectContentResponse{} } +func (m *InspectContentResponse) String() string { return proto.CompactTextString(m) } +func (*InspectContentResponse) ProtoMessage() {} +func (*InspectContentResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } + +func (m *InspectContentResponse) GetResult() *InspectResult { + if m != nil { + return m.Result + } + return nil +} + +// Request for scheduling a scan of a data subset from a Google Platform data +// repository. +type InspectDataSourceRequest struct { + // The parent resource name, for example projects/my-project-id. + Parent string `protobuf:"bytes,1,opt,name=parent" json:"parent,omitempty"` + // A configuration for the job. + JobConfig *InspectJobConfig `protobuf:"bytes,2,opt,name=job_config,json=jobConfig" json:"job_config,omitempty"` +} + +func (m *InspectDataSourceRequest) Reset() { *m = InspectDataSourceRequest{} } +func (m *InspectDataSourceRequest) String() string { return proto.CompactTextString(m) } +func (*InspectDataSourceRequest) ProtoMessage() {} +func (*InspectDataSourceRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } + +func (m *InspectDataSourceRequest) GetParent() string { + if m != nil { + return m.Parent + } + return "" +} + +func (m *InspectDataSourceRequest) GetJobConfig() *InspectJobConfig { + if m != nil { + return m.JobConfig + } + return nil +} + +// Cloud repository for storing output. +type OutputStorageConfig struct { + // Types that are valid to be assigned to Type: + // *OutputStorageConfig_Table + Type isOutputStorageConfig_Type `protobuf_oneof:"type"` +} + +func (m *OutputStorageConfig) Reset() { *m = OutputStorageConfig{} } +func (m *OutputStorageConfig) String() string { return proto.CompactTextString(m) } +func (*OutputStorageConfig) ProtoMessage() {} +func (*OutputStorageConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} } + +type isOutputStorageConfig_Type interface { + isOutputStorageConfig_Type() +} + +type OutputStorageConfig_Table struct { + Table *BigQueryTable `protobuf:"bytes,1,opt,name=table,oneof"` +} + +func (*OutputStorageConfig_Table) isOutputStorageConfig_Type() {} + +func (m *OutputStorageConfig) GetType() isOutputStorageConfig_Type { + if m != nil { + return m.Type + } + return nil +} + +func (m *OutputStorageConfig) GetTable() *BigQueryTable { + if x, ok := m.GetType().(*OutputStorageConfig_Table); ok { + return x.Table + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*OutputStorageConfig) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _OutputStorageConfig_OneofMarshaler, _OutputStorageConfig_OneofUnmarshaler, _OutputStorageConfig_OneofSizer, []interface{}{ + (*OutputStorageConfig_Table)(nil), + } +} + +func _OutputStorageConfig_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*OutputStorageConfig) + // type + switch x := m.Type.(type) { + case *OutputStorageConfig_Table: + b.EncodeVarint(1<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Table); err != nil { + return err + } + case nil: + default: + return fmt.Errorf("OutputStorageConfig.Type has unexpected type %T", x) + } + return nil +} + +func _OutputStorageConfig_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*OutputStorageConfig) + switch tag { + case 1: // type.table + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(BigQueryTable) + err := b.DecodeMessage(msg) + m.Type = &OutputStorageConfig_Table{msg} + return true, err + default: + return false, nil + } +} + +func _OutputStorageConfig_OneofSizer(msg proto.Message) (n int) { + m := msg.(*OutputStorageConfig) + // type + switch x := m.Type.(type) { + case *OutputStorageConfig_Table: + s := proto.Size(x.Table) + n += proto.SizeVarint(1<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +// Statistics regarding a specific InfoType. +type InfoTypeStatistics struct { + // The type of finding this stat is for. + InfoType *InfoType `protobuf:"bytes,1,opt,name=info_type,json=infoType" json:"info_type,omitempty"` + // Number of findings for this infoType. + Count int64 `protobuf:"varint,2,opt,name=count" json:"count,omitempty"` +} + +func (m *InfoTypeStatistics) Reset() { *m = InfoTypeStatistics{} } +func (m *InfoTypeStatistics) String() string { return proto.CompactTextString(m) } +func (*InfoTypeStatistics) ProtoMessage() {} +func (*InfoTypeStatistics) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} } + +func (m *InfoTypeStatistics) GetInfoType() *InfoType { + if m != nil { + return m.InfoType + } + return nil +} + +func (m *InfoTypeStatistics) GetCount() int64 { + if m != nil { + return m.Count + } + return 0 +} + +// The results of an inspect DataSource job. +type InspectDataSourceDetails struct { + // The configuration used for this job. + RequestedOptions *InspectDataSourceDetails_RequestedOptions `protobuf:"bytes,2,opt,name=requested_options,json=requestedOptions" json:"requested_options,omitempty"` + // A summary of the outcome of this inspect job. + Result *InspectDataSourceDetails_Result `protobuf:"bytes,3,opt,name=result" json:"result,omitempty"` +} + +func (m *InspectDataSourceDetails) Reset() { *m = InspectDataSourceDetails{} } +func (m *InspectDataSourceDetails) String() string { return proto.CompactTextString(m) } +func (*InspectDataSourceDetails) ProtoMessage() {} +func (*InspectDataSourceDetails) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{21} } + +func (m *InspectDataSourceDetails) GetRequestedOptions() *InspectDataSourceDetails_RequestedOptions { + if m != nil { + return m.RequestedOptions + } + return nil +} + +func (m *InspectDataSourceDetails) GetResult() *InspectDataSourceDetails_Result { + if m != nil { + return m.Result + } + return nil +} + +type InspectDataSourceDetails_RequestedOptions struct { + // If run with an inspect template, a snapshot of it's state at the time of + // this run. + SnapshotInspectTemplate *InspectTemplate `protobuf:"bytes,1,opt,name=snapshot_inspect_template,json=snapshotInspectTemplate" json:"snapshot_inspect_template,omitempty"` + JobConfig *InspectJobConfig `protobuf:"bytes,3,opt,name=job_config,json=jobConfig" json:"job_config,omitempty"` +} + +func (m *InspectDataSourceDetails_RequestedOptions) Reset() { + *m = InspectDataSourceDetails_RequestedOptions{} +} +func (m *InspectDataSourceDetails_RequestedOptions) String() string { return proto.CompactTextString(m) } +func (*InspectDataSourceDetails_RequestedOptions) ProtoMessage() {} +func (*InspectDataSourceDetails_RequestedOptions) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{21, 0} +} + +func (m *InspectDataSourceDetails_RequestedOptions) GetSnapshotInspectTemplate() *InspectTemplate { + if m != nil { + return m.SnapshotInspectTemplate + } + return nil +} + +func (m *InspectDataSourceDetails_RequestedOptions) GetJobConfig() *InspectJobConfig { + if m != nil { + return m.JobConfig + } + return nil +} + +type InspectDataSourceDetails_Result struct { + // Total size in bytes that were processed. + ProcessedBytes int64 `protobuf:"varint,1,opt,name=processed_bytes,json=processedBytes" json:"processed_bytes,omitempty"` + // Estimate of the number of bytes to process. + TotalEstimatedBytes int64 `protobuf:"varint,2,opt,name=total_estimated_bytes,json=totalEstimatedBytes" json:"total_estimated_bytes,omitempty"` + // Statistics of how many instances of each info type were found during + // inspect job. + InfoTypeStats []*InfoTypeStatistics `protobuf:"bytes,3,rep,name=info_type_stats,json=infoTypeStats" json:"info_type_stats,omitempty"` +} + +func (m *InspectDataSourceDetails_Result) Reset() { *m = InspectDataSourceDetails_Result{} } +func (m *InspectDataSourceDetails_Result) String() string { return proto.CompactTextString(m) } +func (*InspectDataSourceDetails_Result) ProtoMessage() {} +func (*InspectDataSourceDetails_Result) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{21, 1} +} + +func (m *InspectDataSourceDetails_Result) GetProcessedBytes() int64 { + if m != nil { + return m.ProcessedBytes + } + return 0 +} + +func (m *InspectDataSourceDetails_Result) GetTotalEstimatedBytes() int64 { + if m != nil { + return m.TotalEstimatedBytes + } + return 0 +} + +func (m *InspectDataSourceDetails_Result) GetInfoTypeStats() []*InfoTypeStatistics { + if m != nil { + return m.InfoTypeStats + } + return nil +} + +// InfoType description. +type InfoTypeDescription struct { + // Internal name of the infoType. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // Human readable form of the infoType name. + DisplayName string `protobuf:"bytes,2,opt,name=display_name,json=displayName" json:"display_name,omitempty"` + // Which parts of the API supports this InfoType. + SupportedBy []InfoTypeSupportedBy `protobuf:"varint,3,rep,packed,name=supported_by,json=supportedBy,enum=google.privacy.dlp.v2beta2.InfoTypeSupportedBy" json:"supported_by,omitempty"` +} + +func (m *InfoTypeDescription) Reset() { *m = InfoTypeDescription{} } +func (m *InfoTypeDescription) String() string { return proto.CompactTextString(m) } +func (*InfoTypeDescription) ProtoMessage() {} +func (*InfoTypeDescription) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{22} } + +func (m *InfoTypeDescription) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *InfoTypeDescription) GetDisplayName() string { + if m != nil { + return m.DisplayName + } + return "" +} + +func (m *InfoTypeDescription) GetSupportedBy() []InfoTypeSupportedBy { + if m != nil { + return m.SupportedBy + } + return nil +} + +// Request for the list of infoTypes. +type ListInfoTypesRequest struct { + // Optional BCP-47 language code for localized infoType friendly + // names. If omitted, or if localized strings are not available, + // en-US strings will be returned. + LanguageCode string `protobuf:"bytes,1,opt,name=language_code,json=languageCode" json:"language_code,omitempty"` + // Optional filter to only return infoTypes supported by certain parts of the + // API. Defaults to supported_by=INSPECT. + Filter string `protobuf:"bytes,2,opt,name=filter" json:"filter,omitempty"` +} + +func (m *ListInfoTypesRequest) Reset() { *m = ListInfoTypesRequest{} } +func (m *ListInfoTypesRequest) String() string { return proto.CompactTextString(m) } +func (*ListInfoTypesRequest) ProtoMessage() {} +func (*ListInfoTypesRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{23} } + +func (m *ListInfoTypesRequest) GetLanguageCode() string { + if m != nil { + return m.LanguageCode + } + return "" +} + +func (m *ListInfoTypesRequest) GetFilter() string { + if m != nil { + return m.Filter + } + return "" +} + +// Response to the ListInfoTypes request. +type ListInfoTypesResponse struct { + // Set of sensitive infoTypes. + InfoTypes []*InfoTypeDescription `protobuf:"bytes,1,rep,name=info_types,json=infoTypes" json:"info_types,omitempty"` +} + +func (m *ListInfoTypesResponse) Reset() { *m = ListInfoTypesResponse{} } +func (m *ListInfoTypesResponse) String() string { return proto.CompactTextString(m) } +func (*ListInfoTypesResponse) ProtoMessage() {} +func (*ListInfoTypesResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{24} } + +func (m *ListInfoTypesResponse) GetInfoTypes() []*InfoTypeDescription { + if m != nil { + return m.InfoTypes + } + return nil +} + +// Request for creating a risk analysis DlpJob. +type AnalyzeDataSourceRiskRequest struct { + // The parent resource name, for example projects/my-project-id. + Parent string `protobuf:"bytes,1,opt,name=parent" json:"parent,omitempty"` + // Configuration for this risk analysis job. + JobConfig *RiskAnalysisJobConfig `protobuf:"bytes,2,opt,name=job_config,json=jobConfig" json:"job_config,omitempty"` +} + +func (m *AnalyzeDataSourceRiskRequest) Reset() { *m = AnalyzeDataSourceRiskRequest{} } +func (m *AnalyzeDataSourceRiskRequest) String() string { return proto.CompactTextString(m) } +func (*AnalyzeDataSourceRiskRequest) ProtoMessage() {} +func (*AnalyzeDataSourceRiskRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{25} } + +func (m *AnalyzeDataSourceRiskRequest) GetParent() string { + if m != nil { + return m.Parent + } + return "" +} + +func (m *AnalyzeDataSourceRiskRequest) GetJobConfig() *RiskAnalysisJobConfig { + if m != nil { + return m.JobConfig + } + return nil +} + +// Configuration for a risk analysis job. +type RiskAnalysisJobConfig struct { + // Privacy metric to compute. + PrivacyMetric *PrivacyMetric `protobuf:"bytes,1,opt,name=privacy_metric,json=privacyMetric" json:"privacy_metric,omitempty"` + // Input dataset to compute metrics over. + SourceTable *BigQueryTable `protobuf:"bytes,2,opt,name=source_table,json=sourceTable" json:"source_table,omitempty"` +} + +func (m *RiskAnalysisJobConfig) Reset() { *m = RiskAnalysisJobConfig{} } +func (m *RiskAnalysisJobConfig) String() string { return proto.CompactTextString(m) } +func (*RiskAnalysisJobConfig) ProtoMessage() {} +func (*RiskAnalysisJobConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{26} } + +func (m *RiskAnalysisJobConfig) GetPrivacyMetric() *PrivacyMetric { + if m != nil { + return m.PrivacyMetric + } + return nil +} + +func (m *RiskAnalysisJobConfig) GetSourceTable() *BigQueryTable { + if m != nil { + return m.SourceTable + } + return nil +} + +// Privacy metric to compute for reidentification risk analysis. +type PrivacyMetric struct { + // Types that are valid to be assigned to Type: + // *PrivacyMetric_NumericalStatsConfig_ + // *PrivacyMetric_CategoricalStatsConfig_ + // *PrivacyMetric_KAnonymityConfig_ + // *PrivacyMetric_LDiversityConfig_ + // *PrivacyMetric_KMapEstimationConfig_ + Type isPrivacyMetric_Type `protobuf_oneof:"type"` +} + +func (m *PrivacyMetric) Reset() { *m = PrivacyMetric{} } +func (m *PrivacyMetric) String() string { return proto.CompactTextString(m) } +func (*PrivacyMetric) ProtoMessage() {} +func (*PrivacyMetric) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{27} } + +type isPrivacyMetric_Type interface { + isPrivacyMetric_Type() +} + +type PrivacyMetric_NumericalStatsConfig_ struct { + NumericalStatsConfig *PrivacyMetric_NumericalStatsConfig `protobuf:"bytes,1,opt,name=numerical_stats_config,json=numericalStatsConfig,oneof"` +} +type PrivacyMetric_CategoricalStatsConfig_ struct { + CategoricalStatsConfig *PrivacyMetric_CategoricalStatsConfig `protobuf:"bytes,2,opt,name=categorical_stats_config,json=categoricalStatsConfig,oneof"` +} +type PrivacyMetric_KAnonymityConfig_ struct { + KAnonymityConfig *PrivacyMetric_KAnonymityConfig `protobuf:"bytes,3,opt,name=k_anonymity_config,json=kAnonymityConfig,oneof"` +} +type PrivacyMetric_LDiversityConfig_ struct { + LDiversityConfig *PrivacyMetric_LDiversityConfig `protobuf:"bytes,4,opt,name=l_diversity_config,json=lDiversityConfig,oneof"` +} +type PrivacyMetric_KMapEstimationConfig_ struct { + KMapEstimationConfig *PrivacyMetric_KMapEstimationConfig `protobuf:"bytes,5,opt,name=k_map_estimation_config,json=kMapEstimationConfig,oneof"` +} + +func (*PrivacyMetric_NumericalStatsConfig_) isPrivacyMetric_Type() {} +func (*PrivacyMetric_CategoricalStatsConfig_) isPrivacyMetric_Type() {} +func (*PrivacyMetric_KAnonymityConfig_) isPrivacyMetric_Type() {} +func (*PrivacyMetric_LDiversityConfig_) isPrivacyMetric_Type() {} +func (*PrivacyMetric_KMapEstimationConfig_) isPrivacyMetric_Type() {} + +func (m *PrivacyMetric) GetType() isPrivacyMetric_Type { + if m != nil { + return m.Type + } + return nil +} + +func (m *PrivacyMetric) GetNumericalStatsConfig() *PrivacyMetric_NumericalStatsConfig { + if x, ok := m.GetType().(*PrivacyMetric_NumericalStatsConfig_); ok { + return x.NumericalStatsConfig + } + return nil +} + +func (m *PrivacyMetric) GetCategoricalStatsConfig() *PrivacyMetric_CategoricalStatsConfig { + if x, ok := m.GetType().(*PrivacyMetric_CategoricalStatsConfig_); ok { + return x.CategoricalStatsConfig + } + return nil +} + +func (m *PrivacyMetric) GetKAnonymityConfig() *PrivacyMetric_KAnonymityConfig { + if x, ok := m.GetType().(*PrivacyMetric_KAnonymityConfig_); ok { + return x.KAnonymityConfig + } + return nil +} + +func (m *PrivacyMetric) GetLDiversityConfig() *PrivacyMetric_LDiversityConfig { + if x, ok := m.GetType().(*PrivacyMetric_LDiversityConfig_); ok { + return x.LDiversityConfig + } + return nil +} + +func (m *PrivacyMetric) GetKMapEstimationConfig() *PrivacyMetric_KMapEstimationConfig { + if x, ok := m.GetType().(*PrivacyMetric_KMapEstimationConfig_); ok { + return x.KMapEstimationConfig + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*PrivacyMetric) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _PrivacyMetric_OneofMarshaler, _PrivacyMetric_OneofUnmarshaler, _PrivacyMetric_OneofSizer, []interface{}{ + (*PrivacyMetric_NumericalStatsConfig_)(nil), + (*PrivacyMetric_CategoricalStatsConfig_)(nil), + (*PrivacyMetric_KAnonymityConfig_)(nil), + (*PrivacyMetric_LDiversityConfig_)(nil), + (*PrivacyMetric_KMapEstimationConfig_)(nil), + } +} + +func _PrivacyMetric_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*PrivacyMetric) + // type + switch x := m.Type.(type) { + case *PrivacyMetric_NumericalStatsConfig_: + b.EncodeVarint(1<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.NumericalStatsConfig); err != nil { + return err + } + case *PrivacyMetric_CategoricalStatsConfig_: + b.EncodeVarint(2<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.CategoricalStatsConfig); err != nil { + return err + } + case *PrivacyMetric_KAnonymityConfig_: + b.EncodeVarint(3<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.KAnonymityConfig); err != nil { + return err + } + case *PrivacyMetric_LDiversityConfig_: + b.EncodeVarint(4<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.LDiversityConfig); err != nil { + return err + } + case *PrivacyMetric_KMapEstimationConfig_: + b.EncodeVarint(5<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.KMapEstimationConfig); err != nil { + return err + } + case nil: + default: + return fmt.Errorf("PrivacyMetric.Type has unexpected type %T", x) + } + return nil +} + +func _PrivacyMetric_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*PrivacyMetric) + switch tag { + case 1: // type.numerical_stats_config + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(PrivacyMetric_NumericalStatsConfig) + err := b.DecodeMessage(msg) + m.Type = &PrivacyMetric_NumericalStatsConfig_{msg} + return true, err + case 2: // type.categorical_stats_config + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(PrivacyMetric_CategoricalStatsConfig) + err := b.DecodeMessage(msg) + m.Type = &PrivacyMetric_CategoricalStatsConfig_{msg} + return true, err + case 3: // type.k_anonymity_config + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(PrivacyMetric_KAnonymityConfig) + err := b.DecodeMessage(msg) + m.Type = &PrivacyMetric_KAnonymityConfig_{msg} + return true, err + case 4: // type.l_diversity_config + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(PrivacyMetric_LDiversityConfig) + err := b.DecodeMessage(msg) + m.Type = &PrivacyMetric_LDiversityConfig_{msg} + return true, err + case 5: // type.k_map_estimation_config + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(PrivacyMetric_KMapEstimationConfig) + err := b.DecodeMessage(msg) + m.Type = &PrivacyMetric_KMapEstimationConfig_{msg} + return true, err + default: + return false, nil + } +} + +func _PrivacyMetric_OneofSizer(msg proto.Message) (n int) { + m := msg.(*PrivacyMetric) + // type + switch x := m.Type.(type) { + case *PrivacyMetric_NumericalStatsConfig_: + s := proto.Size(x.NumericalStatsConfig) + n += proto.SizeVarint(1<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *PrivacyMetric_CategoricalStatsConfig_: + s := proto.Size(x.CategoricalStatsConfig) + n += proto.SizeVarint(2<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *PrivacyMetric_KAnonymityConfig_: + s := proto.Size(x.KAnonymityConfig) + n += proto.SizeVarint(3<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *PrivacyMetric_LDiversityConfig_: + s := proto.Size(x.LDiversityConfig) + n += proto.SizeVarint(4<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *PrivacyMetric_KMapEstimationConfig_: + s := proto.Size(x.KMapEstimationConfig) + n += proto.SizeVarint(5<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +// Compute numerical stats over an individual column, including +// min, max, and quantiles. +type PrivacyMetric_NumericalStatsConfig struct { + // Field to compute numerical stats on. Supported types are + // integer, float, date, datetime, timestamp, time. + Field *FieldId `protobuf:"bytes,1,opt,name=field" json:"field,omitempty"` +} + +func (m *PrivacyMetric_NumericalStatsConfig) Reset() { *m = PrivacyMetric_NumericalStatsConfig{} } +func (m *PrivacyMetric_NumericalStatsConfig) String() string { return proto.CompactTextString(m) } +func (*PrivacyMetric_NumericalStatsConfig) ProtoMessage() {} +func (*PrivacyMetric_NumericalStatsConfig) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{27, 0} +} + +func (m *PrivacyMetric_NumericalStatsConfig) GetField() *FieldId { + if m != nil { + return m.Field + } + return nil +} + +// Compute numerical stats over an individual column, including +// number of distinct values and value count distribution. +type PrivacyMetric_CategoricalStatsConfig struct { + // Field to compute categorical stats on. All column types are + // supported except for arrays and structs. However, it may be more + // informative to use NumericalStats when the field type is supported, + // depending on the data. + Field *FieldId `protobuf:"bytes,1,opt,name=field" json:"field,omitempty"` +} + +func (m *PrivacyMetric_CategoricalStatsConfig) Reset() { *m = PrivacyMetric_CategoricalStatsConfig{} } +func (m *PrivacyMetric_CategoricalStatsConfig) String() string { return proto.CompactTextString(m) } +func (*PrivacyMetric_CategoricalStatsConfig) ProtoMessage() {} +func (*PrivacyMetric_CategoricalStatsConfig) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{27, 1} +} + +func (m *PrivacyMetric_CategoricalStatsConfig) GetField() *FieldId { + if m != nil { + return m.Field + } + return nil +} + +// k-anonymity metric, used for analysis of reidentification risk. +type PrivacyMetric_KAnonymityConfig struct { + // Set of fields to compute k-anonymity over. When multiple fields are + // specified, they are considered a single composite key. Structs and + // repeated data types are not supported; however, nested fields are + // supported so long as they are not structs themselves or nested within + // a repeated field. + QuasiIds []*FieldId `protobuf:"bytes,1,rep,name=quasi_ids,json=quasiIds" json:"quasi_ids,omitempty"` + // Optional message indicating that each distinct entity_id should not + // contribute to the k-anonymity count more than once per equivalence class. + // If an entity_id appears on several rows with different quasi-identifier + // tuples, it will contribute to each count exactly once. + // + // This can lead to unexpected results. Consider a table where ID 1 is + // associated to quasi-identifier "foo", ID 2 to "bar", and ID 3 to *both* + // quasi-identifiers "foo" and "bar" (on separate rows), and where this ID + // is used as entity_id. Then, the anonymity value associated to ID 3 will + // be 2, even if it is the only ID to be associated to both values "foo" and + // "bar". + EntityId *EntityId `protobuf:"bytes,2,opt,name=entity_id,json=entityId" json:"entity_id,omitempty"` +} + +func (m *PrivacyMetric_KAnonymityConfig) Reset() { *m = PrivacyMetric_KAnonymityConfig{} } +func (m *PrivacyMetric_KAnonymityConfig) String() string { return proto.CompactTextString(m) } +func (*PrivacyMetric_KAnonymityConfig) ProtoMessage() {} +func (*PrivacyMetric_KAnonymityConfig) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{27, 2} +} + +func (m *PrivacyMetric_KAnonymityConfig) GetQuasiIds() []*FieldId { + if m != nil { + return m.QuasiIds + } + return nil +} + +func (m *PrivacyMetric_KAnonymityConfig) GetEntityId() *EntityId { + if m != nil { + return m.EntityId + } + return nil +} + +// l-diversity metric, used for analysis of reidentification risk. +type PrivacyMetric_LDiversityConfig struct { + // Set of quasi-identifiers indicating how equivalence classes are + // defined for the l-diversity computation. When multiple fields are + // specified, they are considered a single composite key. + QuasiIds []*FieldId `protobuf:"bytes,1,rep,name=quasi_ids,json=quasiIds" json:"quasi_ids,omitempty"` + // Sensitive field for computing the l-value. + SensitiveAttribute *FieldId `protobuf:"bytes,2,opt,name=sensitive_attribute,json=sensitiveAttribute" json:"sensitive_attribute,omitempty"` +} + +func (m *PrivacyMetric_LDiversityConfig) Reset() { *m = PrivacyMetric_LDiversityConfig{} } +func (m *PrivacyMetric_LDiversityConfig) String() string { return proto.CompactTextString(m) } +func (*PrivacyMetric_LDiversityConfig) ProtoMessage() {} +func (*PrivacyMetric_LDiversityConfig) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{27, 3} +} + +func (m *PrivacyMetric_LDiversityConfig) GetQuasiIds() []*FieldId { + if m != nil { + return m.QuasiIds + } + return nil +} + +func (m *PrivacyMetric_LDiversityConfig) GetSensitiveAttribute() *FieldId { + if m != nil { + return m.SensitiveAttribute + } + return nil +} + +// Reidentifiability metric. This corresponds to a risk model similar to what +// is called "journalist risk" in the literature, except the attack dataset is +// statistically modeled instead of being perfectly known. This can be done +// using publicly available data (like the US Census), or using a custom +// statistical model (indicated as one or several BigQuery tables), or by +// extrapolating from the distribution of values in the input dataset. +type PrivacyMetric_KMapEstimationConfig struct { + // Fields considered to be quasi-identifiers. No two columns can have the + // same tag. [required] + QuasiIds []*PrivacyMetric_KMapEstimationConfig_TaggedField `protobuf:"bytes,1,rep,name=quasi_ids,json=quasiIds" json:"quasi_ids,omitempty"` + // ISO 3166-1 alpha-2 region code to use in the statistical modeling. + // Required if no column is tagged with a region-specific InfoType (like + // US_ZIP_5) or a region code. + RegionCode string `protobuf:"bytes,2,opt,name=region_code,json=regionCode" json:"region_code,omitempty"` + // Several auxiliary tables can be used in the analysis. Each custom_tag + // used to tag a quasi-identifiers column must appear in exactly one column + // of one auxiliary table. + AuxiliaryTables []*PrivacyMetric_KMapEstimationConfig_AuxiliaryTable `protobuf:"bytes,3,rep,name=auxiliary_tables,json=auxiliaryTables" json:"auxiliary_tables,omitempty"` +} + +func (m *PrivacyMetric_KMapEstimationConfig) Reset() { *m = PrivacyMetric_KMapEstimationConfig{} } +func (m *PrivacyMetric_KMapEstimationConfig) String() string { return proto.CompactTextString(m) } +func (*PrivacyMetric_KMapEstimationConfig) ProtoMessage() {} +func (*PrivacyMetric_KMapEstimationConfig) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{27, 4} +} + +func (m *PrivacyMetric_KMapEstimationConfig) GetQuasiIds() []*PrivacyMetric_KMapEstimationConfig_TaggedField { + if m != nil { + return m.QuasiIds + } + return nil +} + +func (m *PrivacyMetric_KMapEstimationConfig) GetRegionCode() string { + if m != nil { + return m.RegionCode + } + return "" +} + +func (m *PrivacyMetric_KMapEstimationConfig) GetAuxiliaryTables() []*PrivacyMetric_KMapEstimationConfig_AuxiliaryTable { + if m != nil { + return m.AuxiliaryTables + } + return nil +} + +// A column with a semantic tag attached. +type PrivacyMetric_KMapEstimationConfig_TaggedField struct { + // Identifies the column. [required] + Field *FieldId `protobuf:"bytes,1,opt,name=field" json:"field,omitempty"` + // Semantic tag that identifies what a column contains, to determine which + // statistical model to use to estimate the reidentifiability of each + // value. [required] + // + // Types that are valid to be assigned to Tag: + // *PrivacyMetric_KMapEstimationConfig_TaggedField_InfoType + // *PrivacyMetric_KMapEstimationConfig_TaggedField_CustomTag + // *PrivacyMetric_KMapEstimationConfig_TaggedField_Inferred + Tag isPrivacyMetric_KMapEstimationConfig_TaggedField_Tag `protobuf_oneof:"tag"` +} + +func (m *PrivacyMetric_KMapEstimationConfig_TaggedField) Reset() { + *m = PrivacyMetric_KMapEstimationConfig_TaggedField{} +} +func (m *PrivacyMetric_KMapEstimationConfig_TaggedField) String() string { + return proto.CompactTextString(m) +} +func (*PrivacyMetric_KMapEstimationConfig_TaggedField) ProtoMessage() {} +func (*PrivacyMetric_KMapEstimationConfig_TaggedField) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{27, 4, 0} +} + +type isPrivacyMetric_KMapEstimationConfig_TaggedField_Tag interface { + isPrivacyMetric_KMapEstimationConfig_TaggedField_Tag() +} + +type PrivacyMetric_KMapEstimationConfig_TaggedField_InfoType struct { + InfoType *InfoType `protobuf:"bytes,2,opt,name=info_type,json=infoType,oneof"` +} +type PrivacyMetric_KMapEstimationConfig_TaggedField_CustomTag struct { + CustomTag string `protobuf:"bytes,3,opt,name=custom_tag,json=customTag,oneof"` +} +type PrivacyMetric_KMapEstimationConfig_TaggedField_Inferred struct { + Inferred *google_protobuf3.Empty `protobuf:"bytes,4,opt,name=inferred,oneof"` +} + +func (*PrivacyMetric_KMapEstimationConfig_TaggedField_InfoType) isPrivacyMetric_KMapEstimationConfig_TaggedField_Tag() { +} +func (*PrivacyMetric_KMapEstimationConfig_TaggedField_CustomTag) isPrivacyMetric_KMapEstimationConfig_TaggedField_Tag() { +} +func (*PrivacyMetric_KMapEstimationConfig_TaggedField_Inferred) isPrivacyMetric_KMapEstimationConfig_TaggedField_Tag() { +} + +func (m *PrivacyMetric_KMapEstimationConfig_TaggedField) GetTag() isPrivacyMetric_KMapEstimationConfig_TaggedField_Tag { + if m != nil { + return m.Tag + } + return nil +} + +func (m *PrivacyMetric_KMapEstimationConfig_TaggedField) GetField() *FieldId { + if m != nil { + return m.Field + } + return nil +} + +func (m *PrivacyMetric_KMapEstimationConfig_TaggedField) GetInfoType() *InfoType { + if x, ok := m.GetTag().(*PrivacyMetric_KMapEstimationConfig_TaggedField_InfoType); ok { + return x.InfoType + } + return nil +} + +func (m *PrivacyMetric_KMapEstimationConfig_TaggedField) GetCustomTag() string { + if x, ok := m.GetTag().(*PrivacyMetric_KMapEstimationConfig_TaggedField_CustomTag); ok { + return x.CustomTag + } + return "" +} + +func (m *PrivacyMetric_KMapEstimationConfig_TaggedField) GetInferred() *google_protobuf3.Empty { + if x, ok := m.GetTag().(*PrivacyMetric_KMapEstimationConfig_TaggedField_Inferred); ok { + return x.Inferred + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*PrivacyMetric_KMapEstimationConfig_TaggedField) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _PrivacyMetric_KMapEstimationConfig_TaggedField_OneofMarshaler, _PrivacyMetric_KMapEstimationConfig_TaggedField_OneofUnmarshaler, _PrivacyMetric_KMapEstimationConfig_TaggedField_OneofSizer, []interface{}{ + (*PrivacyMetric_KMapEstimationConfig_TaggedField_InfoType)(nil), + (*PrivacyMetric_KMapEstimationConfig_TaggedField_CustomTag)(nil), + (*PrivacyMetric_KMapEstimationConfig_TaggedField_Inferred)(nil), + } +} + +func _PrivacyMetric_KMapEstimationConfig_TaggedField_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*PrivacyMetric_KMapEstimationConfig_TaggedField) + // tag + switch x := m.Tag.(type) { + case *PrivacyMetric_KMapEstimationConfig_TaggedField_InfoType: + b.EncodeVarint(2<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.InfoType); err != nil { + return err + } + case *PrivacyMetric_KMapEstimationConfig_TaggedField_CustomTag: + b.EncodeVarint(3<<3 | proto.WireBytes) + b.EncodeStringBytes(x.CustomTag) + case *PrivacyMetric_KMapEstimationConfig_TaggedField_Inferred: + b.EncodeVarint(4<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Inferred); err != nil { + return err + } + case nil: + default: + return fmt.Errorf("PrivacyMetric_KMapEstimationConfig_TaggedField.Tag has unexpected type %T", x) + } + return nil +} + +func _PrivacyMetric_KMapEstimationConfig_TaggedField_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*PrivacyMetric_KMapEstimationConfig_TaggedField) + switch tag { + case 2: // tag.info_type + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(InfoType) + err := b.DecodeMessage(msg) + m.Tag = &PrivacyMetric_KMapEstimationConfig_TaggedField_InfoType{msg} + return true, err + case 3: // tag.custom_tag + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeStringBytes() + m.Tag = &PrivacyMetric_KMapEstimationConfig_TaggedField_CustomTag{x} + return true, err + case 4: // tag.inferred + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(google_protobuf3.Empty) + err := b.DecodeMessage(msg) + m.Tag = &PrivacyMetric_KMapEstimationConfig_TaggedField_Inferred{msg} + return true, err + default: + return false, nil + } +} + +func _PrivacyMetric_KMapEstimationConfig_TaggedField_OneofSizer(msg proto.Message) (n int) { + m := msg.(*PrivacyMetric_KMapEstimationConfig_TaggedField) + // tag + switch x := m.Tag.(type) { + case *PrivacyMetric_KMapEstimationConfig_TaggedField_InfoType: + s := proto.Size(x.InfoType) + n += proto.SizeVarint(2<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *PrivacyMetric_KMapEstimationConfig_TaggedField_CustomTag: + n += proto.SizeVarint(3<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.CustomTag))) + n += len(x.CustomTag) + case *PrivacyMetric_KMapEstimationConfig_TaggedField_Inferred: + s := proto.Size(x.Inferred) + n += proto.SizeVarint(4<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +// An auxiliary table contains statistical information on the relative +// frequency of different quasi-identifiers values. It has one or several +// quasi-identifiers columns, and one column that indicates the relative +// frequency of each quasi-identifier tuple. +// If a tuple is present in the data but not in the auxiliary table, the +// corresponding relative frequency is assumed to be zero (and thus, the +// tuple is highly reidentifiable). +type PrivacyMetric_KMapEstimationConfig_AuxiliaryTable struct { + // Auxiliary table location. [required] + Table *BigQueryTable `protobuf:"bytes,3,opt,name=table" json:"table,omitempty"` + // Quasi-identifier columns. [required] + QuasiIds []*PrivacyMetric_KMapEstimationConfig_AuxiliaryTable_QuasiIdField `protobuf:"bytes,1,rep,name=quasi_ids,json=quasiIds" json:"quasi_ids,omitempty"` + // The relative frequency column must contain a floating-point number + // between 0 and 1 (inclusive). Null values are assumed to be zero. + // [required] + RelativeFrequency *FieldId `protobuf:"bytes,2,opt,name=relative_frequency,json=relativeFrequency" json:"relative_frequency,omitempty"` +} + +func (m *PrivacyMetric_KMapEstimationConfig_AuxiliaryTable) Reset() { + *m = PrivacyMetric_KMapEstimationConfig_AuxiliaryTable{} +} +func (m *PrivacyMetric_KMapEstimationConfig_AuxiliaryTable) String() string { + return proto.CompactTextString(m) +} +func (*PrivacyMetric_KMapEstimationConfig_AuxiliaryTable) ProtoMessage() {} +func (*PrivacyMetric_KMapEstimationConfig_AuxiliaryTable) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{27, 4, 1} +} + +func (m *PrivacyMetric_KMapEstimationConfig_AuxiliaryTable) GetTable() *BigQueryTable { + if m != nil { + return m.Table + } + return nil +} + +func (m *PrivacyMetric_KMapEstimationConfig_AuxiliaryTable) GetQuasiIds() []*PrivacyMetric_KMapEstimationConfig_AuxiliaryTable_QuasiIdField { + if m != nil { + return m.QuasiIds + } + return nil +} + +func (m *PrivacyMetric_KMapEstimationConfig_AuxiliaryTable) GetRelativeFrequency() *FieldId { + if m != nil { + return m.RelativeFrequency + } + return nil +} + +// A quasi-identifier column has a custom_tag, used to know which column +// in the data corresponds to which column in the statistical model. +type PrivacyMetric_KMapEstimationConfig_AuxiliaryTable_QuasiIdField struct { + Field *FieldId `protobuf:"bytes,1,opt,name=field" json:"field,omitempty"` + CustomTag string `protobuf:"bytes,2,opt,name=custom_tag,json=customTag" json:"custom_tag,omitempty"` +} + +func (m *PrivacyMetric_KMapEstimationConfig_AuxiliaryTable_QuasiIdField) Reset() { + *m = PrivacyMetric_KMapEstimationConfig_AuxiliaryTable_QuasiIdField{} +} +func (m *PrivacyMetric_KMapEstimationConfig_AuxiliaryTable_QuasiIdField) String() string { + return proto.CompactTextString(m) +} +func (*PrivacyMetric_KMapEstimationConfig_AuxiliaryTable_QuasiIdField) ProtoMessage() {} +func (*PrivacyMetric_KMapEstimationConfig_AuxiliaryTable_QuasiIdField) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{27, 4, 1, 0} +} + +func (m *PrivacyMetric_KMapEstimationConfig_AuxiliaryTable_QuasiIdField) GetField() *FieldId { + if m != nil { + return m.Field + } + return nil +} + +func (m *PrivacyMetric_KMapEstimationConfig_AuxiliaryTable_QuasiIdField) GetCustomTag() string { + if m != nil { + return m.CustomTag + } + return "" +} + +// Result of a risk analysis operation request. +type AnalyzeDataSourceRiskDetails struct { + // Privacy metric to compute. + RequestedPrivacyMetric *PrivacyMetric `protobuf:"bytes,1,opt,name=requested_privacy_metric,json=requestedPrivacyMetric" json:"requested_privacy_metric,omitempty"` + // Input dataset to compute metrics over. + RequestedSourceTable *BigQueryTable `protobuf:"bytes,2,opt,name=requested_source_table,json=requestedSourceTable" json:"requested_source_table,omitempty"` + // Values associated with this metric. + // + // Types that are valid to be assigned to Result: + // *AnalyzeDataSourceRiskDetails_NumericalStatsResult_ + // *AnalyzeDataSourceRiskDetails_CategoricalStatsResult_ + // *AnalyzeDataSourceRiskDetails_KAnonymityResult_ + // *AnalyzeDataSourceRiskDetails_LDiversityResult_ + // *AnalyzeDataSourceRiskDetails_KMapEstimationResult_ + Result isAnalyzeDataSourceRiskDetails_Result `protobuf_oneof:"result"` +} + +func (m *AnalyzeDataSourceRiskDetails) Reset() { *m = AnalyzeDataSourceRiskDetails{} } +func (m *AnalyzeDataSourceRiskDetails) String() string { return proto.CompactTextString(m) } +func (*AnalyzeDataSourceRiskDetails) ProtoMessage() {} +func (*AnalyzeDataSourceRiskDetails) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{28} } + +type isAnalyzeDataSourceRiskDetails_Result interface { + isAnalyzeDataSourceRiskDetails_Result() +} + +type AnalyzeDataSourceRiskDetails_NumericalStatsResult_ struct { + NumericalStatsResult *AnalyzeDataSourceRiskDetails_NumericalStatsResult `protobuf:"bytes,3,opt,name=numerical_stats_result,json=numericalStatsResult,oneof"` +} +type AnalyzeDataSourceRiskDetails_CategoricalStatsResult_ struct { + CategoricalStatsResult *AnalyzeDataSourceRiskDetails_CategoricalStatsResult `protobuf:"bytes,4,opt,name=categorical_stats_result,json=categoricalStatsResult,oneof"` +} +type AnalyzeDataSourceRiskDetails_KAnonymityResult_ struct { + KAnonymityResult *AnalyzeDataSourceRiskDetails_KAnonymityResult `protobuf:"bytes,5,opt,name=k_anonymity_result,json=kAnonymityResult,oneof"` +} +type AnalyzeDataSourceRiskDetails_LDiversityResult_ struct { + LDiversityResult *AnalyzeDataSourceRiskDetails_LDiversityResult `protobuf:"bytes,6,opt,name=l_diversity_result,json=lDiversityResult,oneof"` +} +type AnalyzeDataSourceRiskDetails_KMapEstimationResult_ struct { + KMapEstimationResult *AnalyzeDataSourceRiskDetails_KMapEstimationResult `protobuf:"bytes,7,opt,name=k_map_estimation_result,json=kMapEstimationResult,oneof"` +} + +func (*AnalyzeDataSourceRiskDetails_NumericalStatsResult_) isAnalyzeDataSourceRiskDetails_Result() {} +func (*AnalyzeDataSourceRiskDetails_CategoricalStatsResult_) isAnalyzeDataSourceRiskDetails_Result() {} +func (*AnalyzeDataSourceRiskDetails_KAnonymityResult_) isAnalyzeDataSourceRiskDetails_Result() {} +func (*AnalyzeDataSourceRiskDetails_LDiversityResult_) isAnalyzeDataSourceRiskDetails_Result() {} +func (*AnalyzeDataSourceRiskDetails_KMapEstimationResult_) isAnalyzeDataSourceRiskDetails_Result() {} + +func (m *AnalyzeDataSourceRiskDetails) GetResult() isAnalyzeDataSourceRiskDetails_Result { + if m != nil { + return m.Result + } + return nil +} + +func (m *AnalyzeDataSourceRiskDetails) GetRequestedPrivacyMetric() *PrivacyMetric { + if m != nil { + return m.RequestedPrivacyMetric + } + return nil +} + +func (m *AnalyzeDataSourceRiskDetails) GetRequestedSourceTable() *BigQueryTable { + if m != nil { + return m.RequestedSourceTable + } + return nil +} + +func (m *AnalyzeDataSourceRiskDetails) GetNumericalStatsResult() *AnalyzeDataSourceRiskDetails_NumericalStatsResult { + if x, ok := m.GetResult().(*AnalyzeDataSourceRiskDetails_NumericalStatsResult_); ok { + return x.NumericalStatsResult + } + return nil +} + +func (m *AnalyzeDataSourceRiskDetails) GetCategoricalStatsResult() *AnalyzeDataSourceRiskDetails_CategoricalStatsResult { + if x, ok := m.GetResult().(*AnalyzeDataSourceRiskDetails_CategoricalStatsResult_); ok { + return x.CategoricalStatsResult + } + return nil +} + +func (m *AnalyzeDataSourceRiskDetails) GetKAnonymityResult() *AnalyzeDataSourceRiskDetails_KAnonymityResult { + if x, ok := m.GetResult().(*AnalyzeDataSourceRiskDetails_KAnonymityResult_); ok { + return x.KAnonymityResult + } + return nil +} + +func (m *AnalyzeDataSourceRiskDetails) GetLDiversityResult() *AnalyzeDataSourceRiskDetails_LDiversityResult { + if x, ok := m.GetResult().(*AnalyzeDataSourceRiskDetails_LDiversityResult_); ok { + return x.LDiversityResult + } + return nil +} + +func (m *AnalyzeDataSourceRiskDetails) GetKMapEstimationResult() *AnalyzeDataSourceRiskDetails_KMapEstimationResult { + if x, ok := m.GetResult().(*AnalyzeDataSourceRiskDetails_KMapEstimationResult_); ok { + return x.KMapEstimationResult + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*AnalyzeDataSourceRiskDetails) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _AnalyzeDataSourceRiskDetails_OneofMarshaler, _AnalyzeDataSourceRiskDetails_OneofUnmarshaler, _AnalyzeDataSourceRiskDetails_OneofSizer, []interface{}{ + (*AnalyzeDataSourceRiskDetails_NumericalStatsResult_)(nil), + (*AnalyzeDataSourceRiskDetails_CategoricalStatsResult_)(nil), + (*AnalyzeDataSourceRiskDetails_KAnonymityResult_)(nil), + (*AnalyzeDataSourceRiskDetails_LDiversityResult_)(nil), + (*AnalyzeDataSourceRiskDetails_KMapEstimationResult_)(nil), + } +} + +func _AnalyzeDataSourceRiskDetails_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*AnalyzeDataSourceRiskDetails) + // result + switch x := m.Result.(type) { + case *AnalyzeDataSourceRiskDetails_NumericalStatsResult_: + b.EncodeVarint(3<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.NumericalStatsResult); err != nil { + return err + } + case *AnalyzeDataSourceRiskDetails_CategoricalStatsResult_: + b.EncodeVarint(4<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.CategoricalStatsResult); err != nil { + return err + } + case *AnalyzeDataSourceRiskDetails_KAnonymityResult_: + b.EncodeVarint(5<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.KAnonymityResult); err != nil { + return err + } + case *AnalyzeDataSourceRiskDetails_LDiversityResult_: + b.EncodeVarint(6<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.LDiversityResult); err != nil { + return err + } + case *AnalyzeDataSourceRiskDetails_KMapEstimationResult_: + b.EncodeVarint(7<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.KMapEstimationResult); err != nil { + return err + } + case nil: + default: + return fmt.Errorf("AnalyzeDataSourceRiskDetails.Result has unexpected type %T", x) + } + return nil +} + +func _AnalyzeDataSourceRiskDetails_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*AnalyzeDataSourceRiskDetails) + switch tag { + case 3: // result.numerical_stats_result + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(AnalyzeDataSourceRiskDetails_NumericalStatsResult) + err := b.DecodeMessage(msg) + m.Result = &AnalyzeDataSourceRiskDetails_NumericalStatsResult_{msg} + return true, err + case 4: // result.categorical_stats_result + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(AnalyzeDataSourceRiskDetails_CategoricalStatsResult) + err := b.DecodeMessage(msg) + m.Result = &AnalyzeDataSourceRiskDetails_CategoricalStatsResult_{msg} + return true, err + case 5: // result.k_anonymity_result + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(AnalyzeDataSourceRiskDetails_KAnonymityResult) + err := b.DecodeMessage(msg) + m.Result = &AnalyzeDataSourceRiskDetails_KAnonymityResult_{msg} + return true, err + case 6: // result.l_diversity_result + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(AnalyzeDataSourceRiskDetails_LDiversityResult) + err := b.DecodeMessage(msg) + m.Result = &AnalyzeDataSourceRiskDetails_LDiversityResult_{msg} + return true, err + case 7: // result.k_map_estimation_result + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(AnalyzeDataSourceRiskDetails_KMapEstimationResult) + err := b.DecodeMessage(msg) + m.Result = &AnalyzeDataSourceRiskDetails_KMapEstimationResult_{msg} + return true, err + default: + return false, nil + } +} + +func _AnalyzeDataSourceRiskDetails_OneofSizer(msg proto.Message) (n int) { + m := msg.(*AnalyzeDataSourceRiskDetails) + // result + switch x := m.Result.(type) { + case *AnalyzeDataSourceRiskDetails_NumericalStatsResult_: + s := proto.Size(x.NumericalStatsResult) + n += proto.SizeVarint(3<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *AnalyzeDataSourceRiskDetails_CategoricalStatsResult_: + s := proto.Size(x.CategoricalStatsResult) + n += proto.SizeVarint(4<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *AnalyzeDataSourceRiskDetails_KAnonymityResult_: + s := proto.Size(x.KAnonymityResult) + n += proto.SizeVarint(5<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *AnalyzeDataSourceRiskDetails_LDiversityResult_: + s := proto.Size(x.LDiversityResult) + n += proto.SizeVarint(6<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *AnalyzeDataSourceRiskDetails_KMapEstimationResult_: + s := proto.Size(x.KMapEstimationResult) + n += proto.SizeVarint(7<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +// Result of the numerical stats computation. +type AnalyzeDataSourceRiskDetails_NumericalStatsResult struct { + // Minimum value appearing in the column. + MinValue *Value `protobuf:"bytes,1,opt,name=min_value,json=minValue" json:"min_value,omitempty"` + // Maximum value appearing in the column. + MaxValue *Value `protobuf:"bytes,2,opt,name=max_value,json=maxValue" json:"max_value,omitempty"` + // List of 99 values that partition the set of field values into 100 equal + // sized buckets. + QuantileValues []*Value `protobuf:"bytes,4,rep,name=quantile_values,json=quantileValues" json:"quantile_values,omitempty"` +} + +func (m *AnalyzeDataSourceRiskDetails_NumericalStatsResult) Reset() { + *m = AnalyzeDataSourceRiskDetails_NumericalStatsResult{} +} +func (m *AnalyzeDataSourceRiskDetails_NumericalStatsResult) String() string { + return proto.CompactTextString(m) +} +func (*AnalyzeDataSourceRiskDetails_NumericalStatsResult) ProtoMessage() {} +func (*AnalyzeDataSourceRiskDetails_NumericalStatsResult) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{28, 0} +} + +func (m *AnalyzeDataSourceRiskDetails_NumericalStatsResult) GetMinValue() *Value { + if m != nil { + return m.MinValue + } + return nil +} + +func (m *AnalyzeDataSourceRiskDetails_NumericalStatsResult) GetMaxValue() *Value { + if m != nil { + return m.MaxValue + } + return nil +} + +func (m *AnalyzeDataSourceRiskDetails_NumericalStatsResult) GetQuantileValues() []*Value { + if m != nil { + return m.QuantileValues + } + return nil +} + +// Result of the categorical stats computation. +type AnalyzeDataSourceRiskDetails_CategoricalStatsResult struct { + // Histogram of value frequencies in the column. + ValueFrequencyHistogramBuckets []*AnalyzeDataSourceRiskDetails_CategoricalStatsResult_CategoricalStatsHistogramBucket `protobuf:"bytes,5,rep,name=value_frequency_histogram_buckets,json=valueFrequencyHistogramBuckets" json:"value_frequency_histogram_buckets,omitempty"` +} + +func (m *AnalyzeDataSourceRiskDetails_CategoricalStatsResult) Reset() { + *m = AnalyzeDataSourceRiskDetails_CategoricalStatsResult{} +} +func (m *AnalyzeDataSourceRiskDetails_CategoricalStatsResult) String() string { + return proto.CompactTextString(m) +} +func (*AnalyzeDataSourceRiskDetails_CategoricalStatsResult) ProtoMessage() {} +func (*AnalyzeDataSourceRiskDetails_CategoricalStatsResult) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{28, 1} +} + +func (m *AnalyzeDataSourceRiskDetails_CategoricalStatsResult) GetValueFrequencyHistogramBuckets() []*AnalyzeDataSourceRiskDetails_CategoricalStatsResult_CategoricalStatsHistogramBucket { + if m != nil { + return m.ValueFrequencyHistogramBuckets + } + return nil +} + +type AnalyzeDataSourceRiskDetails_CategoricalStatsResult_CategoricalStatsHistogramBucket struct { + // Lower bound on the value frequency of the values in this bucket. + ValueFrequencyLowerBound int64 `protobuf:"varint,1,opt,name=value_frequency_lower_bound,json=valueFrequencyLowerBound" json:"value_frequency_lower_bound,omitempty"` + // Upper bound on the value frequency of the values in this bucket. + ValueFrequencyUpperBound int64 `protobuf:"varint,2,opt,name=value_frequency_upper_bound,json=valueFrequencyUpperBound" json:"value_frequency_upper_bound,omitempty"` + // Total number of values in this bucket. + BucketSize int64 `protobuf:"varint,3,opt,name=bucket_size,json=bucketSize" json:"bucket_size,omitempty"` + // Sample of value frequencies in this bucket. The total number of + // values returned per bucket is capped at 20. + BucketValues []*ValueFrequency `protobuf:"bytes,4,rep,name=bucket_values,json=bucketValues" json:"bucket_values,omitempty"` +} + +func (m *AnalyzeDataSourceRiskDetails_CategoricalStatsResult_CategoricalStatsHistogramBucket) Reset() { + *m = AnalyzeDataSourceRiskDetails_CategoricalStatsResult_CategoricalStatsHistogramBucket{} +} +func (m *AnalyzeDataSourceRiskDetails_CategoricalStatsResult_CategoricalStatsHistogramBucket) String() string { + return proto.CompactTextString(m) +} +func (*AnalyzeDataSourceRiskDetails_CategoricalStatsResult_CategoricalStatsHistogramBucket) ProtoMessage() { +} +func (*AnalyzeDataSourceRiskDetails_CategoricalStatsResult_CategoricalStatsHistogramBucket) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{28, 1, 0} +} + +func (m *AnalyzeDataSourceRiskDetails_CategoricalStatsResult_CategoricalStatsHistogramBucket) GetValueFrequencyLowerBound() int64 { + if m != nil { + return m.ValueFrequencyLowerBound + } + return 0 +} + +func (m *AnalyzeDataSourceRiskDetails_CategoricalStatsResult_CategoricalStatsHistogramBucket) GetValueFrequencyUpperBound() int64 { + if m != nil { + return m.ValueFrequencyUpperBound + } + return 0 +} + +func (m *AnalyzeDataSourceRiskDetails_CategoricalStatsResult_CategoricalStatsHistogramBucket) GetBucketSize() int64 { + if m != nil { + return m.BucketSize + } + return 0 +} + +func (m *AnalyzeDataSourceRiskDetails_CategoricalStatsResult_CategoricalStatsHistogramBucket) GetBucketValues() []*ValueFrequency { + if m != nil { + return m.BucketValues + } + return nil +} + +// Result of the k-anonymity computation. +type AnalyzeDataSourceRiskDetails_KAnonymityResult struct { + // Histogram of k-anonymity equivalence classes. + EquivalenceClassHistogramBuckets []*AnalyzeDataSourceRiskDetails_KAnonymityResult_KAnonymityHistogramBucket `protobuf:"bytes,5,rep,name=equivalence_class_histogram_buckets,json=equivalenceClassHistogramBuckets" json:"equivalence_class_histogram_buckets,omitempty"` +} + +func (m *AnalyzeDataSourceRiskDetails_KAnonymityResult) Reset() { + *m = AnalyzeDataSourceRiskDetails_KAnonymityResult{} +} +func (m *AnalyzeDataSourceRiskDetails_KAnonymityResult) String() string { + return proto.CompactTextString(m) +} +func (*AnalyzeDataSourceRiskDetails_KAnonymityResult) ProtoMessage() {} +func (*AnalyzeDataSourceRiskDetails_KAnonymityResult) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{28, 2} +} + +func (m *AnalyzeDataSourceRiskDetails_KAnonymityResult) GetEquivalenceClassHistogramBuckets() []*AnalyzeDataSourceRiskDetails_KAnonymityResult_KAnonymityHistogramBucket { + if m != nil { + return m.EquivalenceClassHistogramBuckets + } + return nil +} + +// The set of columns' values that share the same ldiversity value +type AnalyzeDataSourceRiskDetails_KAnonymityResult_KAnonymityEquivalenceClass struct { + // Set of values defining the equivalence class. One value per + // quasi-identifier column in the original KAnonymity metric message. + // The order is always the same as the original request. + QuasiIdsValues []*Value `protobuf:"bytes,1,rep,name=quasi_ids_values,json=quasiIdsValues" json:"quasi_ids_values,omitempty"` + // Size of the equivalence class, for example number of rows with the + // above set of values. + EquivalenceClassSize int64 `protobuf:"varint,2,opt,name=equivalence_class_size,json=equivalenceClassSize" json:"equivalence_class_size,omitempty"` +} + +func (m *AnalyzeDataSourceRiskDetails_KAnonymityResult_KAnonymityEquivalenceClass) Reset() { + *m = AnalyzeDataSourceRiskDetails_KAnonymityResult_KAnonymityEquivalenceClass{} +} +func (m *AnalyzeDataSourceRiskDetails_KAnonymityResult_KAnonymityEquivalenceClass) String() string { + return proto.CompactTextString(m) +} +func (*AnalyzeDataSourceRiskDetails_KAnonymityResult_KAnonymityEquivalenceClass) ProtoMessage() {} +func (*AnalyzeDataSourceRiskDetails_KAnonymityResult_KAnonymityEquivalenceClass) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{28, 2, 0} +} + +func (m *AnalyzeDataSourceRiskDetails_KAnonymityResult_KAnonymityEquivalenceClass) GetQuasiIdsValues() []*Value { + if m != nil { + return m.QuasiIdsValues + } + return nil +} + +func (m *AnalyzeDataSourceRiskDetails_KAnonymityResult_KAnonymityEquivalenceClass) GetEquivalenceClassSize() int64 { + if m != nil { + return m.EquivalenceClassSize + } + return 0 +} + +type AnalyzeDataSourceRiskDetails_KAnonymityResult_KAnonymityHistogramBucket struct { + // Lower bound on the size of the equivalence classes in this bucket. + EquivalenceClassSizeLowerBound int64 `protobuf:"varint,1,opt,name=equivalence_class_size_lower_bound,json=equivalenceClassSizeLowerBound" json:"equivalence_class_size_lower_bound,omitempty"` + // Upper bound on the size of the equivalence classes in this bucket. + EquivalenceClassSizeUpperBound int64 `protobuf:"varint,2,opt,name=equivalence_class_size_upper_bound,json=equivalenceClassSizeUpperBound" json:"equivalence_class_size_upper_bound,omitempty"` + // Total number of equivalence classes in this bucket. + BucketSize int64 `protobuf:"varint,3,opt,name=bucket_size,json=bucketSize" json:"bucket_size,omitempty"` + // Sample of equivalence classes in this bucket. The total number of + // classes returned per bucket is capped at 20. + BucketValues []*AnalyzeDataSourceRiskDetails_KAnonymityResult_KAnonymityEquivalenceClass `protobuf:"bytes,4,rep,name=bucket_values,json=bucketValues" json:"bucket_values,omitempty"` +} + +func (m *AnalyzeDataSourceRiskDetails_KAnonymityResult_KAnonymityHistogramBucket) Reset() { + *m = AnalyzeDataSourceRiskDetails_KAnonymityResult_KAnonymityHistogramBucket{} +} +func (m *AnalyzeDataSourceRiskDetails_KAnonymityResult_KAnonymityHistogramBucket) String() string { + return proto.CompactTextString(m) +} +func (*AnalyzeDataSourceRiskDetails_KAnonymityResult_KAnonymityHistogramBucket) ProtoMessage() {} +func (*AnalyzeDataSourceRiskDetails_KAnonymityResult_KAnonymityHistogramBucket) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{28, 2, 1} +} + +func (m *AnalyzeDataSourceRiskDetails_KAnonymityResult_KAnonymityHistogramBucket) GetEquivalenceClassSizeLowerBound() int64 { + if m != nil { + return m.EquivalenceClassSizeLowerBound + } + return 0 +} + +func (m *AnalyzeDataSourceRiskDetails_KAnonymityResult_KAnonymityHistogramBucket) GetEquivalenceClassSizeUpperBound() int64 { + if m != nil { + return m.EquivalenceClassSizeUpperBound + } + return 0 +} + +func (m *AnalyzeDataSourceRiskDetails_KAnonymityResult_KAnonymityHistogramBucket) GetBucketSize() int64 { + if m != nil { + return m.BucketSize + } + return 0 +} + +func (m *AnalyzeDataSourceRiskDetails_KAnonymityResult_KAnonymityHistogramBucket) GetBucketValues() []*AnalyzeDataSourceRiskDetails_KAnonymityResult_KAnonymityEquivalenceClass { + if m != nil { + return m.BucketValues + } + return nil +} + +// Result of the l-diversity computation. +type AnalyzeDataSourceRiskDetails_LDiversityResult struct { + // Histogram of l-diversity equivalence class sensitive value frequencies. + SensitiveValueFrequencyHistogramBuckets []*AnalyzeDataSourceRiskDetails_LDiversityResult_LDiversityHistogramBucket `protobuf:"bytes,5,rep,name=sensitive_value_frequency_histogram_buckets,json=sensitiveValueFrequencyHistogramBuckets" json:"sensitive_value_frequency_histogram_buckets,omitempty"` +} + +func (m *AnalyzeDataSourceRiskDetails_LDiversityResult) Reset() { + *m = AnalyzeDataSourceRiskDetails_LDiversityResult{} +} +func (m *AnalyzeDataSourceRiskDetails_LDiversityResult) String() string { + return proto.CompactTextString(m) +} +func (*AnalyzeDataSourceRiskDetails_LDiversityResult) ProtoMessage() {} +func (*AnalyzeDataSourceRiskDetails_LDiversityResult) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{28, 3} +} + +func (m *AnalyzeDataSourceRiskDetails_LDiversityResult) GetSensitiveValueFrequencyHistogramBuckets() []*AnalyzeDataSourceRiskDetails_LDiversityResult_LDiversityHistogramBucket { + if m != nil { + return m.SensitiveValueFrequencyHistogramBuckets + } + return nil +} + +// The set of columns' values that share the same ldiversity value. +type AnalyzeDataSourceRiskDetails_LDiversityResult_LDiversityEquivalenceClass struct { + // Quasi-identifier values defining the k-anonymity equivalence + // class. The order is always the same as the original request. + QuasiIdsValues []*Value `protobuf:"bytes,1,rep,name=quasi_ids_values,json=quasiIdsValues" json:"quasi_ids_values,omitempty"` + // Size of the k-anonymity equivalence class. + EquivalenceClassSize int64 `protobuf:"varint,2,opt,name=equivalence_class_size,json=equivalenceClassSize" json:"equivalence_class_size,omitempty"` + // Number of distinct sensitive values in this equivalence class. + NumDistinctSensitiveValues int64 `protobuf:"varint,3,opt,name=num_distinct_sensitive_values,json=numDistinctSensitiveValues" json:"num_distinct_sensitive_values,omitempty"` + // Estimated frequencies of top sensitive values. + TopSensitiveValues []*ValueFrequency `protobuf:"bytes,4,rep,name=top_sensitive_values,json=topSensitiveValues" json:"top_sensitive_values,omitempty"` +} + +func (m *AnalyzeDataSourceRiskDetails_LDiversityResult_LDiversityEquivalenceClass) Reset() { + *m = AnalyzeDataSourceRiskDetails_LDiversityResult_LDiversityEquivalenceClass{} +} +func (m *AnalyzeDataSourceRiskDetails_LDiversityResult_LDiversityEquivalenceClass) String() string { + return proto.CompactTextString(m) +} +func (*AnalyzeDataSourceRiskDetails_LDiversityResult_LDiversityEquivalenceClass) ProtoMessage() {} +func (*AnalyzeDataSourceRiskDetails_LDiversityResult_LDiversityEquivalenceClass) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{28, 3, 0} +} + +func (m *AnalyzeDataSourceRiskDetails_LDiversityResult_LDiversityEquivalenceClass) GetQuasiIdsValues() []*Value { + if m != nil { + return m.QuasiIdsValues + } + return nil +} + +func (m *AnalyzeDataSourceRiskDetails_LDiversityResult_LDiversityEquivalenceClass) GetEquivalenceClassSize() int64 { + if m != nil { + return m.EquivalenceClassSize + } + return 0 +} + +func (m *AnalyzeDataSourceRiskDetails_LDiversityResult_LDiversityEquivalenceClass) GetNumDistinctSensitiveValues() int64 { + if m != nil { + return m.NumDistinctSensitiveValues + } + return 0 +} + +func (m *AnalyzeDataSourceRiskDetails_LDiversityResult_LDiversityEquivalenceClass) GetTopSensitiveValues() []*ValueFrequency { + if m != nil { + return m.TopSensitiveValues + } + return nil +} + +type AnalyzeDataSourceRiskDetails_LDiversityResult_LDiversityHistogramBucket struct { + // Lower bound on the sensitive value frequencies of the equivalence + // classes in this bucket. + SensitiveValueFrequencyLowerBound int64 `protobuf:"varint,1,opt,name=sensitive_value_frequency_lower_bound,json=sensitiveValueFrequencyLowerBound" json:"sensitive_value_frequency_lower_bound,omitempty"` + // Upper bound on the sensitive value frequencies of the equivalence + // classes in this bucket. + SensitiveValueFrequencyUpperBound int64 `protobuf:"varint,2,opt,name=sensitive_value_frequency_upper_bound,json=sensitiveValueFrequencyUpperBound" json:"sensitive_value_frequency_upper_bound,omitempty"` + // Total number of equivalence classes in this bucket. + BucketSize int64 `protobuf:"varint,3,opt,name=bucket_size,json=bucketSize" json:"bucket_size,omitempty"` + // Sample of equivalence classes in this bucket. The total number of + // classes returned per bucket is capped at 20. + BucketValues []*AnalyzeDataSourceRiskDetails_LDiversityResult_LDiversityEquivalenceClass `protobuf:"bytes,4,rep,name=bucket_values,json=bucketValues" json:"bucket_values,omitempty"` +} + +func (m *AnalyzeDataSourceRiskDetails_LDiversityResult_LDiversityHistogramBucket) Reset() { + *m = AnalyzeDataSourceRiskDetails_LDiversityResult_LDiversityHistogramBucket{} +} +func (m *AnalyzeDataSourceRiskDetails_LDiversityResult_LDiversityHistogramBucket) String() string { + return proto.CompactTextString(m) +} +func (*AnalyzeDataSourceRiskDetails_LDiversityResult_LDiversityHistogramBucket) ProtoMessage() {} +func (*AnalyzeDataSourceRiskDetails_LDiversityResult_LDiversityHistogramBucket) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{28, 3, 1} +} + +func (m *AnalyzeDataSourceRiskDetails_LDiversityResult_LDiversityHistogramBucket) GetSensitiveValueFrequencyLowerBound() int64 { + if m != nil { + return m.SensitiveValueFrequencyLowerBound + } + return 0 +} + +func (m *AnalyzeDataSourceRiskDetails_LDiversityResult_LDiversityHistogramBucket) GetSensitiveValueFrequencyUpperBound() int64 { + if m != nil { + return m.SensitiveValueFrequencyUpperBound + } + return 0 +} + +func (m *AnalyzeDataSourceRiskDetails_LDiversityResult_LDiversityHistogramBucket) GetBucketSize() int64 { + if m != nil { + return m.BucketSize + } + return 0 +} + +func (m *AnalyzeDataSourceRiskDetails_LDiversityResult_LDiversityHistogramBucket) GetBucketValues() []*AnalyzeDataSourceRiskDetails_LDiversityResult_LDiversityEquivalenceClass { + if m != nil { + return m.BucketValues + } + return nil +} + +// Result of the reidentifiability analysis. Note that these results are an +// estimation, not exact values. +type AnalyzeDataSourceRiskDetails_KMapEstimationResult struct { + // The intervals [min_anonymity, max_anonymity] do not overlap. If a value + // doesn't correspond to any such interval, the associated frequency is + // zero. For example, the following records: + // {min_anonymity: 1, max_anonymity: 1, frequency: 17} + // {min_anonymity: 2, max_anonymity: 3, frequency: 42} + // {min_anonymity: 5, max_anonymity: 10, frequency: 99} + // mean that there are no record with an estimated anonymity of 4, 5, or + // larger than 10. + KMapEstimationHistogram []*AnalyzeDataSourceRiskDetails_KMapEstimationResult_KMapEstimationHistogramBucket `protobuf:"bytes,1,rep,name=k_map_estimation_histogram,json=kMapEstimationHistogram" json:"k_map_estimation_histogram,omitempty"` +} + +func (m *AnalyzeDataSourceRiskDetails_KMapEstimationResult) Reset() { + *m = AnalyzeDataSourceRiskDetails_KMapEstimationResult{} +} +func (m *AnalyzeDataSourceRiskDetails_KMapEstimationResult) String() string { + return proto.CompactTextString(m) +} +func (*AnalyzeDataSourceRiskDetails_KMapEstimationResult) ProtoMessage() {} +func (*AnalyzeDataSourceRiskDetails_KMapEstimationResult) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{28, 4} +} + +func (m *AnalyzeDataSourceRiskDetails_KMapEstimationResult) GetKMapEstimationHistogram() []*AnalyzeDataSourceRiskDetails_KMapEstimationResult_KMapEstimationHistogramBucket { + if m != nil { + return m.KMapEstimationHistogram + } + return nil +} + +// A tuple of values for the quasi-identifier columns. +type AnalyzeDataSourceRiskDetails_KMapEstimationResult_KMapEstimationQuasiIdValues struct { + // The quasi-identifier values. + QuasiIdsValues []*Value `protobuf:"bytes,1,rep,name=quasi_ids_values,json=quasiIdsValues" json:"quasi_ids_values,omitempty"` + // The estimated anonymity for these quasi-identifier values. + EstimatedAnonymity int64 `protobuf:"varint,2,opt,name=estimated_anonymity,json=estimatedAnonymity" json:"estimated_anonymity,omitempty"` +} + +func (m *AnalyzeDataSourceRiskDetails_KMapEstimationResult_KMapEstimationQuasiIdValues) Reset() { + *m = AnalyzeDataSourceRiskDetails_KMapEstimationResult_KMapEstimationQuasiIdValues{} +} +func (m *AnalyzeDataSourceRiskDetails_KMapEstimationResult_KMapEstimationQuasiIdValues) String() string { + return proto.CompactTextString(m) +} +func (*AnalyzeDataSourceRiskDetails_KMapEstimationResult_KMapEstimationQuasiIdValues) ProtoMessage() {} +func (*AnalyzeDataSourceRiskDetails_KMapEstimationResult_KMapEstimationQuasiIdValues) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{28, 4, 0} +} + +func (m *AnalyzeDataSourceRiskDetails_KMapEstimationResult_KMapEstimationQuasiIdValues) GetQuasiIdsValues() []*Value { + if m != nil { + return m.QuasiIdsValues + } + return nil +} + +func (m *AnalyzeDataSourceRiskDetails_KMapEstimationResult_KMapEstimationQuasiIdValues) GetEstimatedAnonymity() int64 { + if m != nil { + return m.EstimatedAnonymity + } + return 0 +} + +// A KMapEstimationHistogramBucket message with the following values: +// min_anonymity: 3 +// max_anonymity: 5 +// frequency: 42 +// means that there are 42 records whose quasi-identifier values correspond +// to 3, 4 or 5 people in the overlying population. An important particular +// case is when min_anonymity = max_anonymity = 1: the frequency field then +// corresponds to the number of uniquely identifiable records. +type AnalyzeDataSourceRiskDetails_KMapEstimationResult_KMapEstimationHistogramBucket struct { + // Always positive. + MinAnonymity int64 `protobuf:"varint,1,opt,name=min_anonymity,json=minAnonymity" json:"min_anonymity,omitempty"` + // Always greater than or equal to min_anonymity. + MaxAnonymity int64 `protobuf:"varint,2,opt,name=max_anonymity,json=maxAnonymity" json:"max_anonymity,omitempty"` + // Number of records within these anonymity bounds. + BucketSize int64 `protobuf:"varint,5,opt,name=bucket_size,json=bucketSize" json:"bucket_size,omitempty"` + // Sample of quasi-identifier tuple values in this bucket. The total + // number of classes returned per bucket is capped at 20. + BucketValues []*AnalyzeDataSourceRiskDetails_KMapEstimationResult_KMapEstimationQuasiIdValues `protobuf:"bytes,6,rep,name=bucket_values,json=bucketValues" json:"bucket_values,omitempty"` +} + +func (m *AnalyzeDataSourceRiskDetails_KMapEstimationResult_KMapEstimationHistogramBucket) Reset() { + *m = AnalyzeDataSourceRiskDetails_KMapEstimationResult_KMapEstimationHistogramBucket{} +} +func (m *AnalyzeDataSourceRiskDetails_KMapEstimationResult_KMapEstimationHistogramBucket) String() string { + return proto.CompactTextString(m) +} +func (*AnalyzeDataSourceRiskDetails_KMapEstimationResult_KMapEstimationHistogramBucket) ProtoMessage() { +} +func (*AnalyzeDataSourceRiskDetails_KMapEstimationResult_KMapEstimationHistogramBucket) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{28, 4, 1} +} + +func (m *AnalyzeDataSourceRiskDetails_KMapEstimationResult_KMapEstimationHistogramBucket) GetMinAnonymity() int64 { + if m != nil { + return m.MinAnonymity + } + return 0 +} + +func (m *AnalyzeDataSourceRiskDetails_KMapEstimationResult_KMapEstimationHistogramBucket) GetMaxAnonymity() int64 { + if m != nil { + return m.MaxAnonymity + } + return 0 +} + +func (m *AnalyzeDataSourceRiskDetails_KMapEstimationResult_KMapEstimationHistogramBucket) GetBucketSize() int64 { + if m != nil { + return m.BucketSize + } + return 0 +} + +func (m *AnalyzeDataSourceRiskDetails_KMapEstimationResult_KMapEstimationHistogramBucket) GetBucketValues() []*AnalyzeDataSourceRiskDetails_KMapEstimationResult_KMapEstimationQuasiIdValues { + if m != nil { + return m.BucketValues + } + return nil +} + +// A value of a field, including its frequency. +type ValueFrequency struct { + // A value contained in the field in question. + Value *Value `protobuf:"bytes,1,opt,name=value" json:"value,omitempty"` + // How many times the value is contained in the field. + Count int64 `protobuf:"varint,2,opt,name=count" json:"count,omitempty"` +} + +func (m *ValueFrequency) Reset() { *m = ValueFrequency{} } +func (m *ValueFrequency) String() string { return proto.CompactTextString(m) } +func (*ValueFrequency) ProtoMessage() {} +func (*ValueFrequency) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{29} } + +func (m *ValueFrequency) GetValue() *Value { + if m != nil { + return m.Value + } + return nil +} + +func (m *ValueFrequency) GetCount() int64 { + if m != nil { + return m.Count + } + return 0 +} + +// Set of primitive values supported by the system. +// Note that for the purposes of inspection or transformation, the number +// of bytes considered to comprise a 'Value' is based on its representation +// as a UTF-8 encoded string. For example, if 'integer_value' is set to +// 123456789, the number of bytes would be counted as 9, even though an +// int64 only holds up to 8 bytes of data. +type Value struct { + // Types that are valid to be assigned to Type: + // *Value_IntegerValue + // *Value_FloatValue + // *Value_StringValue + // *Value_BooleanValue + // *Value_TimestampValue + // *Value_TimeValue + // *Value_DateValue + Type isValue_Type `protobuf_oneof:"type"` +} + +func (m *Value) Reset() { *m = Value{} } +func (m *Value) String() string { return proto.CompactTextString(m) } +func (*Value) ProtoMessage() {} +func (*Value) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{30} } + +type isValue_Type interface { + isValue_Type() +} + +type Value_IntegerValue struct { + IntegerValue int64 `protobuf:"varint,1,opt,name=integer_value,json=integerValue,oneof"` +} +type Value_FloatValue struct { + FloatValue float64 `protobuf:"fixed64,2,opt,name=float_value,json=floatValue,oneof"` +} +type Value_StringValue struct { + StringValue string `protobuf:"bytes,3,opt,name=string_value,json=stringValue,oneof"` +} +type Value_BooleanValue struct { + BooleanValue bool `protobuf:"varint,4,opt,name=boolean_value,json=booleanValue,oneof"` +} +type Value_TimestampValue struct { + TimestampValue *google_protobuf1.Timestamp `protobuf:"bytes,5,opt,name=timestamp_value,json=timestampValue,oneof"` +} +type Value_TimeValue struct { + TimeValue *google_type2.TimeOfDay `protobuf:"bytes,6,opt,name=time_value,json=timeValue,oneof"` +} +type Value_DateValue struct { + DateValue *google_type.Date `protobuf:"bytes,7,opt,name=date_value,json=dateValue,oneof"` +} + +func (*Value_IntegerValue) isValue_Type() {} +func (*Value_FloatValue) isValue_Type() {} +func (*Value_StringValue) isValue_Type() {} +func (*Value_BooleanValue) isValue_Type() {} +func (*Value_TimestampValue) isValue_Type() {} +func (*Value_TimeValue) isValue_Type() {} +func (*Value_DateValue) isValue_Type() {} + +func (m *Value) GetType() isValue_Type { + if m != nil { + return m.Type + } + return nil +} + +func (m *Value) GetIntegerValue() int64 { + if x, ok := m.GetType().(*Value_IntegerValue); ok { + return x.IntegerValue + } + return 0 +} + +func (m *Value) GetFloatValue() float64 { + if x, ok := m.GetType().(*Value_FloatValue); ok { + return x.FloatValue + } + return 0 +} + +func (m *Value) GetStringValue() string { + if x, ok := m.GetType().(*Value_StringValue); ok { + return x.StringValue + } + return "" +} + +func (m *Value) GetBooleanValue() bool { + if x, ok := m.GetType().(*Value_BooleanValue); ok { + return x.BooleanValue + } + return false +} + +func (m *Value) GetTimestampValue() *google_protobuf1.Timestamp { + if x, ok := m.GetType().(*Value_TimestampValue); ok { + return x.TimestampValue + } + return nil +} + +func (m *Value) GetTimeValue() *google_type2.TimeOfDay { + if x, ok := m.GetType().(*Value_TimeValue); ok { + return x.TimeValue + } + return nil +} + +func (m *Value) GetDateValue() *google_type.Date { + if x, ok := m.GetType().(*Value_DateValue); ok { + return x.DateValue + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*Value) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _Value_OneofMarshaler, _Value_OneofUnmarshaler, _Value_OneofSizer, []interface{}{ + (*Value_IntegerValue)(nil), + (*Value_FloatValue)(nil), + (*Value_StringValue)(nil), + (*Value_BooleanValue)(nil), + (*Value_TimestampValue)(nil), + (*Value_TimeValue)(nil), + (*Value_DateValue)(nil), + } +} + +func _Value_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*Value) + // type + switch x := m.Type.(type) { + case *Value_IntegerValue: + b.EncodeVarint(1<<3 | proto.WireVarint) + b.EncodeVarint(uint64(x.IntegerValue)) + case *Value_FloatValue: + b.EncodeVarint(2<<3 | proto.WireFixed64) + b.EncodeFixed64(math.Float64bits(x.FloatValue)) + case *Value_StringValue: + b.EncodeVarint(3<<3 | proto.WireBytes) + b.EncodeStringBytes(x.StringValue) + case *Value_BooleanValue: + t := uint64(0) + if x.BooleanValue { + t = 1 + } + b.EncodeVarint(4<<3 | proto.WireVarint) + b.EncodeVarint(t) + case *Value_TimestampValue: + b.EncodeVarint(5<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.TimestampValue); err != nil { + return err + } + case *Value_TimeValue: + b.EncodeVarint(6<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.TimeValue); err != nil { + return err + } + case *Value_DateValue: + b.EncodeVarint(7<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.DateValue); err != nil { + return err + } + case nil: + default: + return fmt.Errorf("Value.Type has unexpected type %T", x) + } + return nil +} + +func _Value_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*Value) + switch tag { + case 1: // type.integer_value + if wire != proto.WireVarint { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeVarint() + m.Type = &Value_IntegerValue{int64(x)} + return true, err + case 2: // type.float_value + if wire != proto.WireFixed64 { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeFixed64() + m.Type = &Value_FloatValue{math.Float64frombits(x)} + return true, err + case 3: // type.string_value + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeStringBytes() + m.Type = &Value_StringValue{x} + return true, err + case 4: // type.boolean_value + if wire != proto.WireVarint { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeVarint() + m.Type = &Value_BooleanValue{x != 0} + return true, err + case 5: // type.timestamp_value + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(google_protobuf1.Timestamp) + err := b.DecodeMessage(msg) + m.Type = &Value_TimestampValue{msg} + return true, err + case 6: // type.time_value + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(google_type2.TimeOfDay) + err := b.DecodeMessage(msg) + m.Type = &Value_TimeValue{msg} + return true, err + case 7: // type.date_value + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(google_type.Date) + err := b.DecodeMessage(msg) + m.Type = &Value_DateValue{msg} + return true, err + default: + return false, nil + } +} + +func _Value_OneofSizer(msg proto.Message) (n int) { + m := msg.(*Value) + // type + switch x := m.Type.(type) { + case *Value_IntegerValue: + n += proto.SizeVarint(1<<3 | proto.WireVarint) + n += proto.SizeVarint(uint64(x.IntegerValue)) + case *Value_FloatValue: + n += proto.SizeVarint(2<<3 | proto.WireFixed64) + n += 8 + case *Value_StringValue: + n += proto.SizeVarint(3<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.StringValue))) + n += len(x.StringValue) + case *Value_BooleanValue: + n += proto.SizeVarint(4<<3 | proto.WireVarint) + n += 1 + case *Value_TimestampValue: + s := proto.Size(x.TimestampValue) + n += proto.SizeVarint(5<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Value_TimeValue: + s := proto.Size(x.TimeValue) + n += proto.SizeVarint(6<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Value_DateValue: + s := proto.Size(x.DateValue) + n += proto.SizeVarint(7<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +// The configuration that controls how the data will change. +type DeidentifyConfig struct { + // Types that are valid to be assigned to Transformation: + // *DeidentifyConfig_InfoTypeTransformations + // *DeidentifyConfig_RecordTransformations + Transformation isDeidentifyConfig_Transformation `protobuf_oneof:"transformation"` +} + +func (m *DeidentifyConfig) Reset() { *m = DeidentifyConfig{} } +func (m *DeidentifyConfig) String() string { return proto.CompactTextString(m) } +func (*DeidentifyConfig) ProtoMessage() {} +func (*DeidentifyConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{31} } + +type isDeidentifyConfig_Transformation interface { + isDeidentifyConfig_Transformation() +} + +type DeidentifyConfig_InfoTypeTransformations struct { + InfoTypeTransformations *InfoTypeTransformations `protobuf:"bytes,1,opt,name=info_type_transformations,json=infoTypeTransformations,oneof"` +} +type DeidentifyConfig_RecordTransformations struct { + RecordTransformations *RecordTransformations `protobuf:"bytes,2,opt,name=record_transformations,json=recordTransformations,oneof"` +} + +func (*DeidentifyConfig_InfoTypeTransformations) isDeidentifyConfig_Transformation() {} +func (*DeidentifyConfig_RecordTransformations) isDeidentifyConfig_Transformation() {} + +func (m *DeidentifyConfig) GetTransformation() isDeidentifyConfig_Transformation { + if m != nil { + return m.Transformation + } + return nil +} + +func (m *DeidentifyConfig) GetInfoTypeTransformations() *InfoTypeTransformations { + if x, ok := m.GetTransformation().(*DeidentifyConfig_InfoTypeTransformations); ok { + return x.InfoTypeTransformations + } + return nil +} + +func (m *DeidentifyConfig) GetRecordTransformations() *RecordTransformations { + if x, ok := m.GetTransformation().(*DeidentifyConfig_RecordTransformations); ok { + return x.RecordTransformations + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*DeidentifyConfig) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _DeidentifyConfig_OneofMarshaler, _DeidentifyConfig_OneofUnmarshaler, _DeidentifyConfig_OneofSizer, []interface{}{ + (*DeidentifyConfig_InfoTypeTransformations)(nil), + (*DeidentifyConfig_RecordTransformations)(nil), + } +} + +func _DeidentifyConfig_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*DeidentifyConfig) + // transformation + switch x := m.Transformation.(type) { + case *DeidentifyConfig_InfoTypeTransformations: + b.EncodeVarint(1<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.InfoTypeTransformations); err != nil { + return err + } + case *DeidentifyConfig_RecordTransformations: + b.EncodeVarint(2<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.RecordTransformations); err != nil { + return err + } + case nil: + default: + return fmt.Errorf("DeidentifyConfig.Transformation has unexpected type %T", x) + } + return nil +} + +func _DeidentifyConfig_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*DeidentifyConfig) + switch tag { + case 1: // transformation.info_type_transformations + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(InfoTypeTransformations) + err := b.DecodeMessage(msg) + m.Transformation = &DeidentifyConfig_InfoTypeTransformations{msg} + return true, err + case 2: // transformation.record_transformations + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(RecordTransformations) + err := b.DecodeMessage(msg) + m.Transformation = &DeidentifyConfig_RecordTransformations{msg} + return true, err + default: + return false, nil + } +} + +func _DeidentifyConfig_OneofSizer(msg proto.Message) (n int) { + m := msg.(*DeidentifyConfig) + // transformation + switch x := m.Transformation.(type) { + case *DeidentifyConfig_InfoTypeTransformations: + s := proto.Size(x.InfoTypeTransformations) + n += proto.SizeVarint(1<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *DeidentifyConfig_RecordTransformations: + s := proto.Size(x.RecordTransformations) + n += proto.SizeVarint(2<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +// A rule for transforming a value. +type PrimitiveTransformation struct { + // Types that are valid to be assigned to Transformation: + // *PrimitiveTransformation_ReplaceConfig + // *PrimitiveTransformation_RedactConfig + // *PrimitiveTransformation_CharacterMaskConfig + // *PrimitiveTransformation_CryptoReplaceFfxFpeConfig + // *PrimitiveTransformation_FixedSizeBucketingConfig + // *PrimitiveTransformation_BucketingConfig + // *PrimitiveTransformation_ReplaceWithInfoTypeConfig + // *PrimitiveTransformation_TimePartConfig + // *PrimitiveTransformation_CryptoHashConfig + Transformation isPrimitiveTransformation_Transformation `protobuf_oneof:"transformation"` +} + +func (m *PrimitiveTransformation) Reset() { *m = PrimitiveTransformation{} } +func (m *PrimitiveTransformation) String() string { return proto.CompactTextString(m) } +func (*PrimitiveTransformation) ProtoMessage() {} +func (*PrimitiveTransformation) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{32} } + +type isPrimitiveTransformation_Transformation interface { + isPrimitiveTransformation_Transformation() +} + +type PrimitiveTransformation_ReplaceConfig struct { + ReplaceConfig *ReplaceValueConfig `protobuf:"bytes,1,opt,name=replace_config,json=replaceConfig,oneof"` +} +type PrimitiveTransformation_RedactConfig struct { + RedactConfig *RedactConfig `protobuf:"bytes,2,opt,name=redact_config,json=redactConfig,oneof"` +} +type PrimitiveTransformation_CharacterMaskConfig struct { + CharacterMaskConfig *CharacterMaskConfig `protobuf:"bytes,3,opt,name=character_mask_config,json=characterMaskConfig,oneof"` +} +type PrimitiveTransformation_CryptoReplaceFfxFpeConfig struct { + CryptoReplaceFfxFpeConfig *CryptoReplaceFfxFpeConfig `protobuf:"bytes,4,opt,name=crypto_replace_ffx_fpe_config,json=cryptoReplaceFfxFpeConfig,oneof"` +} +type PrimitiveTransformation_FixedSizeBucketingConfig struct { + FixedSizeBucketingConfig *FixedSizeBucketingConfig `protobuf:"bytes,5,opt,name=fixed_size_bucketing_config,json=fixedSizeBucketingConfig,oneof"` +} +type PrimitiveTransformation_BucketingConfig struct { + BucketingConfig *BucketingConfig `protobuf:"bytes,6,opt,name=bucketing_config,json=bucketingConfig,oneof"` +} +type PrimitiveTransformation_ReplaceWithInfoTypeConfig struct { + ReplaceWithInfoTypeConfig *ReplaceWithInfoTypeConfig `protobuf:"bytes,7,opt,name=replace_with_info_type_config,json=replaceWithInfoTypeConfig,oneof"` +} +type PrimitiveTransformation_TimePartConfig struct { + TimePartConfig *TimePartConfig `protobuf:"bytes,8,opt,name=time_part_config,json=timePartConfig,oneof"` +} +type PrimitiveTransformation_CryptoHashConfig struct { + CryptoHashConfig *CryptoHashConfig `protobuf:"bytes,9,opt,name=crypto_hash_config,json=cryptoHashConfig,oneof"` +} + +func (*PrimitiveTransformation_ReplaceConfig) isPrimitiveTransformation_Transformation() {} +func (*PrimitiveTransformation_RedactConfig) isPrimitiveTransformation_Transformation() {} +func (*PrimitiveTransformation_CharacterMaskConfig) isPrimitiveTransformation_Transformation() {} +func (*PrimitiveTransformation_CryptoReplaceFfxFpeConfig) isPrimitiveTransformation_Transformation() {} +func (*PrimitiveTransformation_FixedSizeBucketingConfig) isPrimitiveTransformation_Transformation() {} +func (*PrimitiveTransformation_BucketingConfig) isPrimitiveTransformation_Transformation() {} +func (*PrimitiveTransformation_ReplaceWithInfoTypeConfig) isPrimitiveTransformation_Transformation() {} +func (*PrimitiveTransformation_TimePartConfig) isPrimitiveTransformation_Transformation() {} +func (*PrimitiveTransformation_CryptoHashConfig) isPrimitiveTransformation_Transformation() {} + +func (m *PrimitiveTransformation) GetTransformation() isPrimitiveTransformation_Transformation { + if m != nil { + return m.Transformation + } + return nil +} + +func (m *PrimitiveTransformation) GetReplaceConfig() *ReplaceValueConfig { + if x, ok := m.GetTransformation().(*PrimitiveTransformation_ReplaceConfig); ok { + return x.ReplaceConfig + } + return nil +} + +func (m *PrimitiveTransformation) GetRedactConfig() *RedactConfig { + if x, ok := m.GetTransformation().(*PrimitiveTransformation_RedactConfig); ok { + return x.RedactConfig + } + return nil +} + +func (m *PrimitiveTransformation) GetCharacterMaskConfig() *CharacterMaskConfig { + if x, ok := m.GetTransformation().(*PrimitiveTransformation_CharacterMaskConfig); ok { + return x.CharacterMaskConfig + } + return nil +} + +func (m *PrimitiveTransformation) GetCryptoReplaceFfxFpeConfig() *CryptoReplaceFfxFpeConfig { + if x, ok := m.GetTransformation().(*PrimitiveTransformation_CryptoReplaceFfxFpeConfig); ok { + return x.CryptoReplaceFfxFpeConfig + } + return nil +} + +func (m *PrimitiveTransformation) GetFixedSizeBucketingConfig() *FixedSizeBucketingConfig { + if x, ok := m.GetTransformation().(*PrimitiveTransformation_FixedSizeBucketingConfig); ok { + return x.FixedSizeBucketingConfig + } + return nil +} + +func (m *PrimitiveTransformation) GetBucketingConfig() *BucketingConfig { + if x, ok := m.GetTransformation().(*PrimitiveTransformation_BucketingConfig); ok { + return x.BucketingConfig + } + return nil +} + +func (m *PrimitiveTransformation) GetReplaceWithInfoTypeConfig() *ReplaceWithInfoTypeConfig { + if x, ok := m.GetTransformation().(*PrimitiveTransformation_ReplaceWithInfoTypeConfig); ok { + return x.ReplaceWithInfoTypeConfig + } + return nil +} + +func (m *PrimitiveTransformation) GetTimePartConfig() *TimePartConfig { + if x, ok := m.GetTransformation().(*PrimitiveTransformation_TimePartConfig); ok { + return x.TimePartConfig + } + return nil +} + +func (m *PrimitiveTransformation) GetCryptoHashConfig() *CryptoHashConfig { + if x, ok := m.GetTransformation().(*PrimitiveTransformation_CryptoHashConfig); ok { + return x.CryptoHashConfig + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*PrimitiveTransformation) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _PrimitiveTransformation_OneofMarshaler, _PrimitiveTransformation_OneofUnmarshaler, _PrimitiveTransformation_OneofSizer, []interface{}{ + (*PrimitiveTransformation_ReplaceConfig)(nil), + (*PrimitiveTransformation_RedactConfig)(nil), + (*PrimitiveTransformation_CharacterMaskConfig)(nil), + (*PrimitiveTransformation_CryptoReplaceFfxFpeConfig)(nil), + (*PrimitiveTransformation_FixedSizeBucketingConfig)(nil), + (*PrimitiveTransformation_BucketingConfig)(nil), + (*PrimitiveTransformation_ReplaceWithInfoTypeConfig)(nil), + (*PrimitiveTransformation_TimePartConfig)(nil), + (*PrimitiveTransformation_CryptoHashConfig)(nil), + } +} + +func _PrimitiveTransformation_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*PrimitiveTransformation) + // transformation + switch x := m.Transformation.(type) { + case *PrimitiveTransformation_ReplaceConfig: + b.EncodeVarint(1<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.ReplaceConfig); err != nil { + return err + } + case *PrimitiveTransformation_RedactConfig: + b.EncodeVarint(2<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.RedactConfig); err != nil { + return err + } + case *PrimitiveTransformation_CharacterMaskConfig: + b.EncodeVarint(3<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.CharacterMaskConfig); err != nil { + return err + } + case *PrimitiveTransformation_CryptoReplaceFfxFpeConfig: + b.EncodeVarint(4<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.CryptoReplaceFfxFpeConfig); err != nil { + return err + } + case *PrimitiveTransformation_FixedSizeBucketingConfig: + b.EncodeVarint(5<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.FixedSizeBucketingConfig); err != nil { + return err + } + case *PrimitiveTransformation_BucketingConfig: + b.EncodeVarint(6<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.BucketingConfig); err != nil { + return err + } + case *PrimitiveTransformation_ReplaceWithInfoTypeConfig: + b.EncodeVarint(7<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.ReplaceWithInfoTypeConfig); err != nil { + return err + } + case *PrimitiveTransformation_TimePartConfig: + b.EncodeVarint(8<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.TimePartConfig); err != nil { + return err + } + case *PrimitiveTransformation_CryptoHashConfig: + b.EncodeVarint(9<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.CryptoHashConfig); err != nil { + return err + } + case nil: + default: + return fmt.Errorf("PrimitiveTransformation.Transformation has unexpected type %T", x) + } + return nil +} + +func _PrimitiveTransformation_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*PrimitiveTransformation) + switch tag { + case 1: // transformation.replace_config + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(ReplaceValueConfig) + err := b.DecodeMessage(msg) + m.Transformation = &PrimitiveTransformation_ReplaceConfig{msg} + return true, err + case 2: // transformation.redact_config + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(RedactConfig) + err := b.DecodeMessage(msg) + m.Transformation = &PrimitiveTransformation_RedactConfig{msg} + return true, err + case 3: // transformation.character_mask_config + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(CharacterMaskConfig) + err := b.DecodeMessage(msg) + m.Transformation = &PrimitiveTransformation_CharacterMaskConfig{msg} + return true, err + case 4: // transformation.crypto_replace_ffx_fpe_config + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(CryptoReplaceFfxFpeConfig) + err := b.DecodeMessage(msg) + m.Transformation = &PrimitiveTransformation_CryptoReplaceFfxFpeConfig{msg} + return true, err + case 5: // transformation.fixed_size_bucketing_config + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(FixedSizeBucketingConfig) + err := b.DecodeMessage(msg) + m.Transformation = &PrimitiveTransformation_FixedSizeBucketingConfig{msg} + return true, err + case 6: // transformation.bucketing_config + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(BucketingConfig) + err := b.DecodeMessage(msg) + m.Transformation = &PrimitiveTransformation_BucketingConfig{msg} + return true, err + case 7: // transformation.replace_with_info_type_config + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(ReplaceWithInfoTypeConfig) + err := b.DecodeMessage(msg) + m.Transformation = &PrimitiveTransformation_ReplaceWithInfoTypeConfig{msg} + return true, err + case 8: // transformation.time_part_config + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(TimePartConfig) + err := b.DecodeMessage(msg) + m.Transformation = &PrimitiveTransformation_TimePartConfig{msg} + return true, err + case 9: // transformation.crypto_hash_config + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(CryptoHashConfig) + err := b.DecodeMessage(msg) + m.Transformation = &PrimitiveTransformation_CryptoHashConfig{msg} + return true, err + default: + return false, nil + } +} + +func _PrimitiveTransformation_OneofSizer(msg proto.Message) (n int) { + m := msg.(*PrimitiveTransformation) + // transformation + switch x := m.Transformation.(type) { + case *PrimitiveTransformation_ReplaceConfig: + s := proto.Size(x.ReplaceConfig) + n += proto.SizeVarint(1<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *PrimitiveTransformation_RedactConfig: + s := proto.Size(x.RedactConfig) + n += proto.SizeVarint(2<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *PrimitiveTransformation_CharacterMaskConfig: + s := proto.Size(x.CharacterMaskConfig) + n += proto.SizeVarint(3<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *PrimitiveTransformation_CryptoReplaceFfxFpeConfig: + s := proto.Size(x.CryptoReplaceFfxFpeConfig) + n += proto.SizeVarint(4<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *PrimitiveTransformation_FixedSizeBucketingConfig: + s := proto.Size(x.FixedSizeBucketingConfig) + n += proto.SizeVarint(5<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *PrimitiveTransformation_BucketingConfig: + s := proto.Size(x.BucketingConfig) + n += proto.SizeVarint(6<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *PrimitiveTransformation_ReplaceWithInfoTypeConfig: + s := proto.Size(x.ReplaceWithInfoTypeConfig) + n += proto.SizeVarint(7<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *PrimitiveTransformation_TimePartConfig: + s := proto.Size(x.TimePartConfig) + n += proto.SizeVarint(8<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *PrimitiveTransformation_CryptoHashConfig: + s := proto.Size(x.CryptoHashConfig) + n += proto.SizeVarint(9<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +// For use with `Date`, `Timestamp`, and `TimeOfDay`, extract or preserve a +// portion of the value. +type TimePartConfig struct { + PartToExtract TimePartConfig_TimePart `protobuf:"varint,1,opt,name=part_to_extract,json=partToExtract,enum=google.privacy.dlp.v2beta2.TimePartConfig_TimePart" json:"part_to_extract,omitempty"` +} + +func (m *TimePartConfig) Reset() { *m = TimePartConfig{} } +func (m *TimePartConfig) String() string { return proto.CompactTextString(m) } +func (*TimePartConfig) ProtoMessage() {} +func (*TimePartConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{33} } + +func (m *TimePartConfig) GetPartToExtract() TimePartConfig_TimePart { + if m != nil { + return m.PartToExtract + } + return TimePartConfig_TIME_PART_UNSPECIFIED +} + +// Pseudonymization method that generates surrogates via cryptographic hashing. +// Uses SHA-256. +// The key size must be either 32 or 64 bytes. +// Outputs a 32 byte digest as an uppercase hex string +// (for example, 41D1567F7F99F1DC2A5FAB886DEE5BEE). +// Currently, only string and integer values can be hashed. +type CryptoHashConfig struct { + // The key used by the hash function. + CryptoKey *CryptoKey `protobuf:"bytes,1,opt,name=crypto_key,json=cryptoKey" json:"crypto_key,omitempty"` +} + +func (m *CryptoHashConfig) Reset() { *m = CryptoHashConfig{} } +func (m *CryptoHashConfig) String() string { return proto.CompactTextString(m) } +func (*CryptoHashConfig) ProtoMessage() {} +func (*CryptoHashConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{34} } + +func (m *CryptoHashConfig) GetCryptoKey() *CryptoKey { + if m != nil { + return m.CryptoKey + } + return nil +} + +// Replace each input value with a given `Value`. +type ReplaceValueConfig struct { + // Value to replace it with. + NewValue *Value `protobuf:"bytes,1,opt,name=new_value,json=newValue" json:"new_value,omitempty"` +} + +func (m *ReplaceValueConfig) Reset() { *m = ReplaceValueConfig{} } +func (m *ReplaceValueConfig) String() string { return proto.CompactTextString(m) } +func (*ReplaceValueConfig) ProtoMessage() {} +func (*ReplaceValueConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{35} } + +func (m *ReplaceValueConfig) GetNewValue() *Value { + if m != nil { + return m.NewValue + } + return nil +} + +// Replace each matching finding with the name of the info_type. +type ReplaceWithInfoTypeConfig struct { +} + +func (m *ReplaceWithInfoTypeConfig) Reset() { *m = ReplaceWithInfoTypeConfig{} } +func (m *ReplaceWithInfoTypeConfig) String() string { return proto.CompactTextString(m) } +func (*ReplaceWithInfoTypeConfig) ProtoMessage() {} +func (*ReplaceWithInfoTypeConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{36} } + +// Redact a given value. For example, if used with an `InfoTypeTransformation` +// transforming PHONE_NUMBER, and input 'My phone number is 206-555-0123', the +// output would be 'My phone number is '. +type RedactConfig struct { +} + +func (m *RedactConfig) Reset() { *m = RedactConfig{} } +func (m *RedactConfig) String() string { return proto.CompactTextString(m) } +func (*RedactConfig) ProtoMessage() {} +func (*RedactConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{37} } + +// Characters to skip when doing deidentification of a value. These will be left +// alone and skipped. +type CharsToIgnore struct { + // Types that are valid to be assigned to Characters: + // *CharsToIgnore_CharactersToSkip + // *CharsToIgnore_CommonCharactersToIgnore + Characters isCharsToIgnore_Characters `protobuf_oneof:"characters"` +} + +func (m *CharsToIgnore) Reset() { *m = CharsToIgnore{} } +func (m *CharsToIgnore) String() string { return proto.CompactTextString(m) } +func (*CharsToIgnore) ProtoMessage() {} +func (*CharsToIgnore) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{38} } + +type isCharsToIgnore_Characters interface { + isCharsToIgnore_Characters() +} + +type CharsToIgnore_CharactersToSkip struct { + CharactersToSkip string `protobuf:"bytes,1,opt,name=characters_to_skip,json=charactersToSkip,oneof"` +} +type CharsToIgnore_CommonCharactersToIgnore struct { + CommonCharactersToIgnore CharsToIgnore_CommonCharsToIgnore `protobuf:"varint,2,opt,name=common_characters_to_ignore,json=commonCharactersToIgnore,enum=google.privacy.dlp.v2beta2.CharsToIgnore_CommonCharsToIgnore,oneof"` +} + +func (*CharsToIgnore_CharactersToSkip) isCharsToIgnore_Characters() {} +func (*CharsToIgnore_CommonCharactersToIgnore) isCharsToIgnore_Characters() {} + +func (m *CharsToIgnore) GetCharacters() isCharsToIgnore_Characters { + if m != nil { + return m.Characters + } + return nil +} + +func (m *CharsToIgnore) GetCharactersToSkip() string { + if x, ok := m.GetCharacters().(*CharsToIgnore_CharactersToSkip); ok { + return x.CharactersToSkip + } + return "" +} + +func (m *CharsToIgnore) GetCommonCharactersToIgnore() CharsToIgnore_CommonCharsToIgnore { + if x, ok := m.GetCharacters().(*CharsToIgnore_CommonCharactersToIgnore); ok { + return x.CommonCharactersToIgnore + } + return CharsToIgnore_COMMON_CHARS_TO_IGNORE_UNSPECIFIED +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*CharsToIgnore) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _CharsToIgnore_OneofMarshaler, _CharsToIgnore_OneofUnmarshaler, _CharsToIgnore_OneofSizer, []interface{}{ + (*CharsToIgnore_CharactersToSkip)(nil), + (*CharsToIgnore_CommonCharactersToIgnore)(nil), + } +} + +func _CharsToIgnore_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*CharsToIgnore) + // characters + switch x := m.Characters.(type) { + case *CharsToIgnore_CharactersToSkip: + b.EncodeVarint(1<<3 | proto.WireBytes) + b.EncodeStringBytes(x.CharactersToSkip) + case *CharsToIgnore_CommonCharactersToIgnore: + b.EncodeVarint(2<<3 | proto.WireVarint) + b.EncodeVarint(uint64(x.CommonCharactersToIgnore)) + case nil: + default: + return fmt.Errorf("CharsToIgnore.Characters has unexpected type %T", x) + } + return nil +} + +func _CharsToIgnore_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*CharsToIgnore) + switch tag { + case 1: // characters.characters_to_skip + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeStringBytes() + m.Characters = &CharsToIgnore_CharactersToSkip{x} + return true, err + case 2: // characters.common_characters_to_ignore + if wire != proto.WireVarint { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeVarint() + m.Characters = &CharsToIgnore_CommonCharactersToIgnore{CharsToIgnore_CommonCharsToIgnore(x)} + return true, err + default: + return false, nil + } +} + +func _CharsToIgnore_OneofSizer(msg proto.Message) (n int) { + m := msg.(*CharsToIgnore) + // characters + switch x := m.Characters.(type) { + case *CharsToIgnore_CharactersToSkip: + n += proto.SizeVarint(1<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.CharactersToSkip))) + n += len(x.CharactersToSkip) + case *CharsToIgnore_CommonCharactersToIgnore: + n += proto.SizeVarint(2<<3 | proto.WireVarint) + n += proto.SizeVarint(uint64(x.CommonCharactersToIgnore)) + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +// Partially mask a string by replacing a given number of characters with a +// fixed character. Masking can start from the beginning or end of the string. +// This can be used on data of any type (numbers, longs, and so on) and when +// de-identifying structured data we'll attempt to preserve the original data's +// type. (This allows you to take a long like 123 and modify it to a string like +// **3. +type CharacterMaskConfig struct { + // Character to mask the sensitive values—for example, "*" for an + // alphabetic string such as name, or "0" for a numeric string such as ZIP + // code or credit card number. String must have length 1. If not supplied, we + // will default to "*" for strings, 0 for digits. + MaskingCharacter string `protobuf:"bytes,1,opt,name=masking_character,json=maskingCharacter" json:"masking_character,omitempty"` + // Number of characters to mask. If not set, all matching chars will be + // masked. Skipped characters do not count towards this tally. + NumberToMask int32 `protobuf:"varint,2,opt,name=number_to_mask,json=numberToMask" json:"number_to_mask,omitempty"` + // Mask characters in reverse order. For example, if `masking_character` is + // '0', number_to_mask is 14, and `reverse_order` is false, then + // 1234-5678-9012-3456 -> 00000000000000-3456 + // If `masking_character` is '*', `number_to_mask` is 3, and `reverse_order` + // is true, then 12345 -> 12*** + ReverseOrder bool `protobuf:"varint,3,opt,name=reverse_order,json=reverseOrder" json:"reverse_order,omitempty"` + // When masking a string, items in this list will be skipped when replacing. + // For example, if your string is 555-555-5555 and you ask us to skip `-` and + // mask 5 chars with * we would produce ***-*55-5555. + CharactersToIgnore []*CharsToIgnore `protobuf:"bytes,4,rep,name=characters_to_ignore,json=charactersToIgnore" json:"characters_to_ignore,omitempty"` +} + +func (m *CharacterMaskConfig) Reset() { *m = CharacterMaskConfig{} } +func (m *CharacterMaskConfig) String() string { return proto.CompactTextString(m) } +func (*CharacterMaskConfig) ProtoMessage() {} +func (*CharacterMaskConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{39} } + +func (m *CharacterMaskConfig) GetMaskingCharacter() string { + if m != nil { + return m.MaskingCharacter + } + return "" +} + +func (m *CharacterMaskConfig) GetNumberToMask() int32 { + if m != nil { + return m.NumberToMask + } + return 0 +} + +func (m *CharacterMaskConfig) GetReverseOrder() bool { + if m != nil { + return m.ReverseOrder + } + return false +} + +func (m *CharacterMaskConfig) GetCharactersToIgnore() []*CharsToIgnore { + if m != nil { + return m.CharactersToIgnore + } + return nil +} + +// Buckets values based on fixed size ranges. The +// Bucketing transformation can provide all of this functionality, +// but requires more configuration. This message is provided as a convenience to +// the user for simple bucketing strategies. +// +// The transformed value will be a hyphenated string of +// -, i.e if lower_bound = 10 and upper_bound = 20 +// all values that are within this bucket will be replaced with "10-20". +// +// This can be used on data of type: double, long. +// +// If the bound Value type differs from the type of data +// being transformed, we will first attempt converting the type of the data to +// be transformed to match the type of the bound before comparing. +type FixedSizeBucketingConfig struct { + // Lower bound value of buckets. All values less than `lower_bound` are + // grouped together into a single bucket; for example if `lower_bound` = 10, + // then all values less than 10 are replaced with the value “-10â€. [Required]. + LowerBound *Value `protobuf:"bytes,1,opt,name=lower_bound,json=lowerBound" json:"lower_bound,omitempty"` + // Upper bound value of buckets. All values greater than upper_bound are + // grouped together into a single bucket; for example if `upper_bound` = 89, + // then all values greater than 89 are replaced with the value “89+â€. + // [Required]. + UpperBound *Value `protobuf:"bytes,2,opt,name=upper_bound,json=upperBound" json:"upper_bound,omitempty"` + // Size of each bucket (except for minimum and maximum buckets). So if + // `lower_bound` = 10, `upper_bound` = 89, and `bucket_size` = 10, then the + // following buckets would be used: -10, 10-20, 20-30, 30-40, 40-50, 50-60, + // 60-70, 70-80, 80-89, 89+. Precision up to 2 decimals works. [Required]. + BucketSize float64 `protobuf:"fixed64,3,opt,name=bucket_size,json=bucketSize" json:"bucket_size,omitempty"` +} + +func (m *FixedSizeBucketingConfig) Reset() { *m = FixedSizeBucketingConfig{} } +func (m *FixedSizeBucketingConfig) String() string { return proto.CompactTextString(m) } +func (*FixedSizeBucketingConfig) ProtoMessage() {} +func (*FixedSizeBucketingConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{40} } + +func (m *FixedSizeBucketingConfig) GetLowerBound() *Value { + if m != nil { + return m.LowerBound + } + return nil +} + +func (m *FixedSizeBucketingConfig) GetUpperBound() *Value { + if m != nil { + return m.UpperBound + } + return nil +} + +func (m *FixedSizeBucketingConfig) GetBucketSize() float64 { + if m != nil { + return m.BucketSize + } + return 0 +} + +// Generalization function that buckets values based on ranges. The ranges and +// replacement values are dynamically provided by the user for custom behavior, +// such as 1-30 -> LOW 31-65 -> MEDIUM 66-100 -> HIGH +// This can be used on +// data of type: number, long, string, timestamp. +// If the bound `Value` type differs from the type of data being transformed, we +// will first attempt converting the type of the data to be transformed to match +// the type of the bound before comparing. +type BucketingConfig struct { + // Set of buckets. Ranges must be non-overlapping. + Buckets []*BucketingConfig_Bucket `protobuf:"bytes,1,rep,name=buckets" json:"buckets,omitempty"` +} + +func (m *BucketingConfig) Reset() { *m = BucketingConfig{} } +func (m *BucketingConfig) String() string { return proto.CompactTextString(m) } +func (*BucketingConfig) ProtoMessage() {} +func (*BucketingConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{41} } + +func (m *BucketingConfig) GetBuckets() []*BucketingConfig_Bucket { + if m != nil { + return m.Buckets + } + return nil +} + +// Bucket is represented as a range, along with replacement values. +type BucketingConfig_Bucket struct { + // Lower bound of the range, inclusive. Type should be the same as max if + // used. + Min *Value `protobuf:"bytes,1,opt,name=min" json:"min,omitempty"` + // Upper bound of the range, exclusive; type must match min. + Max *Value `protobuf:"bytes,2,opt,name=max" json:"max,omitempty"` + // Replacement value for this bucket. If not provided + // the default behavior will be to hyphenate the min-max range. + ReplacementValue *Value `protobuf:"bytes,3,opt,name=replacement_value,json=replacementValue" json:"replacement_value,omitempty"` +} + +func (m *BucketingConfig_Bucket) Reset() { *m = BucketingConfig_Bucket{} } +func (m *BucketingConfig_Bucket) String() string { return proto.CompactTextString(m) } +func (*BucketingConfig_Bucket) ProtoMessage() {} +func (*BucketingConfig_Bucket) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{41, 0} } + +func (m *BucketingConfig_Bucket) GetMin() *Value { + if m != nil { + return m.Min + } + return nil +} + +func (m *BucketingConfig_Bucket) GetMax() *Value { + if m != nil { + return m.Max + } + return nil +} + +func (m *BucketingConfig_Bucket) GetReplacementValue() *Value { + if m != nil { + return m.ReplacementValue + } + return nil +} + +// Replaces an identifier with a surrogate using FPE with the FFX +// mode of operation; however when used in the `ReidentifyContent` API method, +// it serves the opposite function by reversing the surrogate back into +// the original identifier. +// The identifier must be encoded as ASCII. +// For a given crypto key and context, the same identifier will be +// replaced with the same surrogate. +// Identifiers must be at least two characters long. +// In the case that the identifier is the empty string, it will be skipped. +type CryptoReplaceFfxFpeConfig struct { + // The key used by the encryption algorithm. [required] + CryptoKey *CryptoKey `protobuf:"bytes,1,opt,name=crypto_key,json=cryptoKey" json:"crypto_key,omitempty"` + // The 'tweak', a context may be used for higher security since the same + // identifier in two different contexts won't be given the same surrogate. If + // the context is not set, a default tweak will be used. + // + // If the context is set but: + // + // 1. there is no record present when transforming a given value or + // 1. the field is not present when transforming a given value, + // + // a default tweak will be used. + // + // Note that case (1) is expected when an `InfoTypeTransformation` is + // applied to both structured and non-structured `ContentItem`s. + // Currently, the referenced field may be of value type integer or string. + // + // The tweak is constructed as a sequence of bytes in big endian byte order + // such that: + // + // - a 64 bit integer is encoded followed by a single byte of value 1 + // - a string is encoded in UTF-8 format followed by a single byte of value + // Ã¥ 2 + Context *FieldId `protobuf:"bytes,2,opt,name=context" json:"context,omitempty"` + // Types that are valid to be assigned to Alphabet: + // *CryptoReplaceFfxFpeConfig_CommonAlphabet + // *CryptoReplaceFfxFpeConfig_CustomAlphabet + // *CryptoReplaceFfxFpeConfig_Radix + Alphabet isCryptoReplaceFfxFpeConfig_Alphabet `protobuf_oneof:"alphabet"` + // The custom infoType to annotate the surrogate with. + // This annotation will be applied to the surrogate by prefixing it with + // the name of the custom infoType followed by the number of + // characters comprising the surrogate. The following scheme defines the + // format: info_type_name(surrogate_character_count):surrogate + // + // For example, if the name of custom infoType is 'MY_TOKEN_INFO_TYPE' and + // the surrogate is 'abc', the full replacement value + // will be: 'MY_TOKEN_INFO_TYPE(3):abc' + // + // This annotation identifies the surrogate when inspecting content using the + // custom infoType + // [`SurrogateType`](/dlp/docs/reference/rest/v2beta2/InspectConfig#surrogatetype). + // This facilitates reversal of the surrogate when it occurs in free text. + // + // In order for inspection to work properly, the name of this infoType must + // not occur naturally anywhere in your data; otherwise, inspection may + // find a surrogate that does not correspond to an actual identifier. + // Therefore, choose your custom infoType name carefully after considering + // what your data looks like. One way to select a name that has a high chance + // of yielding reliable detection is to include one or more unicode characters + // that are highly improbable to exist in your data. + // For example, assuming your data is entered from a regular ASCII keyboard, + // the symbol with the hex code point 29DD might be used like so: + // â§MY_TOKEN_TYPE + SurrogateInfoType *InfoType `protobuf:"bytes,8,opt,name=surrogate_info_type,json=surrogateInfoType" json:"surrogate_info_type,omitempty"` +} + +func (m *CryptoReplaceFfxFpeConfig) Reset() { *m = CryptoReplaceFfxFpeConfig{} } +func (m *CryptoReplaceFfxFpeConfig) String() string { return proto.CompactTextString(m) } +func (*CryptoReplaceFfxFpeConfig) ProtoMessage() {} +func (*CryptoReplaceFfxFpeConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{42} } + +type isCryptoReplaceFfxFpeConfig_Alphabet interface { + isCryptoReplaceFfxFpeConfig_Alphabet() +} + +type CryptoReplaceFfxFpeConfig_CommonAlphabet struct { + CommonAlphabet CryptoReplaceFfxFpeConfig_FfxCommonNativeAlphabet `protobuf:"varint,4,opt,name=common_alphabet,json=commonAlphabet,enum=google.privacy.dlp.v2beta2.CryptoReplaceFfxFpeConfig_FfxCommonNativeAlphabet,oneof"` +} +type CryptoReplaceFfxFpeConfig_CustomAlphabet struct { + CustomAlphabet string `protobuf:"bytes,5,opt,name=custom_alphabet,json=customAlphabet,oneof"` +} +type CryptoReplaceFfxFpeConfig_Radix struct { + Radix int32 `protobuf:"varint,6,opt,name=radix,oneof"` +} + +func (*CryptoReplaceFfxFpeConfig_CommonAlphabet) isCryptoReplaceFfxFpeConfig_Alphabet() {} +func (*CryptoReplaceFfxFpeConfig_CustomAlphabet) isCryptoReplaceFfxFpeConfig_Alphabet() {} +func (*CryptoReplaceFfxFpeConfig_Radix) isCryptoReplaceFfxFpeConfig_Alphabet() {} + +func (m *CryptoReplaceFfxFpeConfig) GetAlphabet() isCryptoReplaceFfxFpeConfig_Alphabet { + if m != nil { + return m.Alphabet + } + return nil +} + +func (m *CryptoReplaceFfxFpeConfig) GetCryptoKey() *CryptoKey { + if m != nil { + return m.CryptoKey + } + return nil +} + +func (m *CryptoReplaceFfxFpeConfig) GetContext() *FieldId { + if m != nil { + return m.Context + } + return nil +} + +func (m *CryptoReplaceFfxFpeConfig) GetCommonAlphabet() CryptoReplaceFfxFpeConfig_FfxCommonNativeAlphabet { + if x, ok := m.GetAlphabet().(*CryptoReplaceFfxFpeConfig_CommonAlphabet); ok { + return x.CommonAlphabet + } + return CryptoReplaceFfxFpeConfig_FFX_COMMON_NATIVE_ALPHABET_UNSPECIFIED +} + +func (m *CryptoReplaceFfxFpeConfig) GetCustomAlphabet() string { + if x, ok := m.GetAlphabet().(*CryptoReplaceFfxFpeConfig_CustomAlphabet); ok { + return x.CustomAlphabet + } + return "" +} + +func (m *CryptoReplaceFfxFpeConfig) GetRadix() int32 { + if x, ok := m.GetAlphabet().(*CryptoReplaceFfxFpeConfig_Radix); ok { + return x.Radix + } + return 0 +} + +func (m *CryptoReplaceFfxFpeConfig) GetSurrogateInfoType() *InfoType { + if m != nil { + return m.SurrogateInfoType + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*CryptoReplaceFfxFpeConfig) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _CryptoReplaceFfxFpeConfig_OneofMarshaler, _CryptoReplaceFfxFpeConfig_OneofUnmarshaler, _CryptoReplaceFfxFpeConfig_OneofSizer, []interface{}{ + (*CryptoReplaceFfxFpeConfig_CommonAlphabet)(nil), + (*CryptoReplaceFfxFpeConfig_CustomAlphabet)(nil), + (*CryptoReplaceFfxFpeConfig_Radix)(nil), + } +} + +func _CryptoReplaceFfxFpeConfig_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*CryptoReplaceFfxFpeConfig) + // alphabet + switch x := m.Alphabet.(type) { + case *CryptoReplaceFfxFpeConfig_CommonAlphabet: + b.EncodeVarint(4<<3 | proto.WireVarint) + b.EncodeVarint(uint64(x.CommonAlphabet)) + case *CryptoReplaceFfxFpeConfig_CustomAlphabet: + b.EncodeVarint(5<<3 | proto.WireBytes) + b.EncodeStringBytes(x.CustomAlphabet) + case *CryptoReplaceFfxFpeConfig_Radix: + b.EncodeVarint(6<<3 | proto.WireVarint) + b.EncodeVarint(uint64(x.Radix)) + case nil: + default: + return fmt.Errorf("CryptoReplaceFfxFpeConfig.Alphabet has unexpected type %T", x) + } + return nil +} + +func _CryptoReplaceFfxFpeConfig_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*CryptoReplaceFfxFpeConfig) + switch tag { + case 4: // alphabet.common_alphabet + if wire != proto.WireVarint { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeVarint() + m.Alphabet = &CryptoReplaceFfxFpeConfig_CommonAlphabet{CryptoReplaceFfxFpeConfig_FfxCommonNativeAlphabet(x)} + return true, err + case 5: // alphabet.custom_alphabet + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeStringBytes() + m.Alphabet = &CryptoReplaceFfxFpeConfig_CustomAlphabet{x} + return true, err + case 6: // alphabet.radix + if wire != proto.WireVarint { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeVarint() + m.Alphabet = &CryptoReplaceFfxFpeConfig_Radix{int32(x)} + return true, err + default: + return false, nil + } +} + +func _CryptoReplaceFfxFpeConfig_OneofSizer(msg proto.Message) (n int) { + m := msg.(*CryptoReplaceFfxFpeConfig) + // alphabet + switch x := m.Alphabet.(type) { + case *CryptoReplaceFfxFpeConfig_CommonAlphabet: + n += proto.SizeVarint(4<<3 | proto.WireVarint) + n += proto.SizeVarint(uint64(x.CommonAlphabet)) + case *CryptoReplaceFfxFpeConfig_CustomAlphabet: + n += proto.SizeVarint(5<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.CustomAlphabet))) + n += len(x.CustomAlphabet) + case *CryptoReplaceFfxFpeConfig_Radix: + n += proto.SizeVarint(6<<3 | proto.WireVarint) + n += proto.SizeVarint(uint64(x.Radix)) + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +// This is a data encryption key (DEK) (as opposed to +// a key encryption key (KEK) stored by KMS). +// When using KMS to wrap/unwrap DEKs, be sure to set an appropriate +// IAM policy on the KMS CryptoKey (KEK) to ensure an attacker cannot +// unwrap the data crypto key. +type CryptoKey struct { + // Types that are valid to be assigned to Source: + // *CryptoKey_Transient + // *CryptoKey_Unwrapped + // *CryptoKey_KmsWrapped + Source isCryptoKey_Source `protobuf_oneof:"source"` +} + +func (m *CryptoKey) Reset() { *m = CryptoKey{} } +func (m *CryptoKey) String() string { return proto.CompactTextString(m) } +func (*CryptoKey) ProtoMessage() {} +func (*CryptoKey) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{43} } + +type isCryptoKey_Source interface { + isCryptoKey_Source() +} + +type CryptoKey_Transient struct { + Transient *TransientCryptoKey `protobuf:"bytes,1,opt,name=transient,oneof"` +} +type CryptoKey_Unwrapped struct { + Unwrapped *UnwrappedCryptoKey `protobuf:"bytes,2,opt,name=unwrapped,oneof"` +} +type CryptoKey_KmsWrapped struct { + KmsWrapped *KmsWrappedCryptoKey `protobuf:"bytes,3,opt,name=kms_wrapped,json=kmsWrapped,oneof"` +} + +func (*CryptoKey_Transient) isCryptoKey_Source() {} +func (*CryptoKey_Unwrapped) isCryptoKey_Source() {} +func (*CryptoKey_KmsWrapped) isCryptoKey_Source() {} + +func (m *CryptoKey) GetSource() isCryptoKey_Source { + if m != nil { + return m.Source + } + return nil +} + +func (m *CryptoKey) GetTransient() *TransientCryptoKey { + if x, ok := m.GetSource().(*CryptoKey_Transient); ok { + return x.Transient + } + return nil +} + +func (m *CryptoKey) GetUnwrapped() *UnwrappedCryptoKey { + if x, ok := m.GetSource().(*CryptoKey_Unwrapped); ok { + return x.Unwrapped + } + return nil +} + +func (m *CryptoKey) GetKmsWrapped() *KmsWrappedCryptoKey { + if x, ok := m.GetSource().(*CryptoKey_KmsWrapped); ok { + return x.KmsWrapped + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*CryptoKey) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _CryptoKey_OneofMarshaler, _CryptoKey_OneofUnmarshaler, _CryptoKey_OneofSizer, []interface{}{ + (*CryptoKey_Transient)(nil), + (*CryptoKey_Unwrapped)(nil), + (*CryptoKey_KmsWrapped)(nil), + } +} + +func _CryptoKey_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*CryptoKey) + // source + switch x := m.Source.(type) { + case *CryptoKey_Transient: + b.EncodeVarint(1<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Transient); err != nil { + return err + } + case *CryptoKey_Unwrapped: + b.EncodeVarint(2<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Unwrapped); err != nil { + return err + } + case *CryptoKey_KmsWrapped: + b.EncodeVarint(3<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.KmsWrapped); err != nil { + return err + } + case nil: + default: + return fmt.Errorf("CryptoKey.Source has unexpected type %T", x) + } + return nil +} + +func _CryptoKey_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*CryptoKey) + switch tag { + case 1: // source.transient + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(TransientCryptoKey) + err := b.DecodeMessage(msg) + m.Source = &CryptoKey_Transient{msg} + return true, err + case 2: // source.unwrapped + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(UnwrappedCryptoKey) + err := b.DecodeMessage(msg) + m.Source = &CryptoKey_Unwrapped{msg} + return true, err + case 3: // source.kms_wrapped + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(KmsWrappedCryptoKey) + err := b.DecodeMessage(msg) + m.Source = &CryptoKey_KmsWrapped{msg} + return true, err + default: + return false, nil + } +} + +func _CryptoKey_OneofSizer(msg proto.Message) (n int) { + m := msg.(*CryptoKey) + // source + switch x := m.Source.(type) { + case *CryptoKey_Transient: + s := proto.Size(x.Transient) + n += proto.SizeVarint(1<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *CryptoKey_Unwrapped: + s := proto.Size(x.Unwrapped) + n += proto.SizeVarint(2<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *CryptoKey_KmsWrapped: + s := proto.Size(x.KmsWrapped) + n += proto.SizeVarint(3<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +// Use this to have a random data crypto key generated. +// It will be discarded after the request finishes. +type TransientCryptoKey struct { + // Name of the key. [required] + // This is an arbitrary string used to differentiate different keys. + // A unique key is generated per name: two separate `TransientCryptoKey` + // protos share the same generated key if their names are the same. + // When the data crypto key is generated, this name is not used in any way + // (repeating the api call will result in a different key being generated). + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` +} + +func (m *TransientCryptoKey) Reset() { *m = TransientCryptoKey{} } +func (m *TransientCryptoKey) String() string { return proto.CompactTextString(m) } +func (*TransientCryptoKey) ProtoMessage() {} +func (*TransientCryptoKey) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{44} } + +func (m *TransientCryptoKey) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +// Using raw keys is prone to security risks due to accidentally +// leaking the key. Choose another type of key if possible. +type UnwrappedCryptoKey struct { + // The AES 128/192/256 bit key. [required] + Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` +} + +func (m *UnwrappedCryptoKey) Reset() { *m = UnwrappedCryptoKey{} } +func (m *UnwrappedCryptoKey) String() string { return proto.CompactTextString(m) } +func (*UnwrappedCryptoKey) ProtoMessage() {} +func (*UnwrappedCryptoKey) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{45} } + +func (m *UnwrappedCryptoKey) GetKey() []byte { + if m != nil { + return m.Key + } + return nil +} + +// Include to use an existing data crypto key wrapped by KMS. +// Authorization requires the following IAM permissions when sending a request +// to perform a crypto transformation using a kms-wrapped crypto key: +// dlp.kms.encrypt +type KmsWrappedCryptoKey struct { + // The wrapped data crypto key. [required] + WrappedKey []byte `protobuf:"bytes,1,opt,name=wrapped_key,json=wrappedKey,proto3" json:"wrapped_key,omitempty"` + // The resource name of the KMS CryptoKey to use for unwrapping. [required] + CryptoKeyName string `protobuf:"bytes,2,opt,name=crypto_key_name,json=cryptoKeyName" json:"crypto_key_name,omitempty"` +} + +func (m *KmsWrappedCryptoKey) Reset() { *m = KmsWrappedCryptoKey{} } +func (m *KmsWrappedCryptoKey) String() string { return proto.CompactTextString(m) } +func (*KmsWrappedCryptoKey) ProtoMessage() {} +func (*KmsWrappedCryptoKey) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{46} } + +func (m *KmsWrappedCryptoKey) GetWrappedKey() []byte { + if m != nil { + return m.WrappedKey + } + return nil +} + +func (m *KmsWrappedCryptoKey) GetCryptoKeyName() string { + if m != nil { + return m.CryptoKeyName + } + return "" +} + +// A type of transformation that will scan unstructured text and +// apply various `PrimitiveTransformation`s to each finding, where the +// transformation is applied to only values that were identified as a specific +// info_type. +type InfoTypeTransformations struct { + // Transformation for each infoType. Cannot specify more than one + // for a given infoType. [required] + Transformations []*InfoTypeTransformations_InfoTypeTransformation `protobuf:"bytes,1,rep,name=transformations" json:"transformations,omitempty"` +} + +func (m *InfoTypeTransformations) Reset() { *m = InfoTypeTransformations{} } +func (m *InfoTypeTransformations) String() string { return proto.CompactTextString(m) } +func (*InfoTypeTransformations) ProtoMessage() {} +func (*InfoTypeTransformations) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{47} } + +func (m *InfoTypeTransformations) GetTransformations() []*InfoTypeTransformations_InfoTypeTransformation { + if m != nil { + return m.Transformations + } + return nil +} + +// A transformation to apply to text that is identified as a specific +// info_type. +type InfoTypeTransformations_InfoTypeTransformation struct { + // InfoTypes to apply the transformation to. Empty list will match all + // available infoTypes for this transformation. + InfoTypes []*InfoType `protobuf:"bytes,1,rep,name=info_types,json=infoTypes" json:"info_types,omitempty"` + // Primitive transformation to apply to the infoType. [required] + PrimitiveTransformation *PrimitiveTransformation `protobuf:"bytes,2,opt,name=primitive_transformation,json=primitiveTransformation" json:"primitive_transformation,omitempty"` +} + +func (m *InfoTypeTransformations_InfoTypeTransformation) Reset() { + *m = InfoTypeTransformations_InfoTypeTransformation{} +} +func (m *InfoTypeTransformations_InfoTypeTransformation) String() string { + return proto.CompactTextString(m) +} +func (*InfoTypeTransformations_InfoTypeTransformation) ProtoMessage() {} +func (*InfoTypeTransformations_InfoTypeTransformation) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{47, 0} +} + +func (m *InfoTypeTransformations_InfoTypeTransformation) GetInfoTypes() []*InfoType { + if m != nil { + return m.InfoTypes + } + return nil +} + +func (m *InfoTypeTransformations_InfoTypeTransformation) GetPrimitiveTransformation() *PrimitiveTransformation { + if m != nil { + return m.PrimitiveTransformation + } + return nil +} + +// The transformation to apply to the field. +type FieldTransformation struct { + // Input field(s) to apply the transformation to. [required] + Fields []*FieldId `protobuf:"bytes,1,rep,name=fields" json:"fields,omitempty"` + // Only apply the transformation if the condition evaluates to true for the + // given `RecordCondition`. The conditions are allowed to reference fields + // that are not used in the actual transformation. [optional] + // + // Example Use Cases: + // + // - Apply a different bucket transformation to an age column if the zip code + // column for the same record is within a specific range. + // - Redact a field if the date of birth field is greater than 85. + Condition *RecordCondition `protobuf:"bytes,3,opt,name=condition" json:"condition,omitempty"` + // Transformation to apply. [required] + // + // Types that are valid to be assigned to Transformation: + // *FieldTransformation_PrimitiveTransformation + // *FieldTransformation_InfoTypeTransformations + Transformation isFieldTransformation_Transformation `protobuf_oneof:"transformation"` +} + +func (m *FieldTransformation) Reset() { *m = FieldTransformation{} } +func (m *FieldTransformation) String() string { return proto.CompactTextString(m) } +func (*FieldTransformation) ProtoMessage() {} +func (*FieldTransformation) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{48} } + +type isFieldTransformation_Transformation interface { + isFieldTransformation_Transformation() +} + +type FieldTransformation_PrimitiveTransformation struct { + PrimitiveTransformation *PrimitiveTransformation `protobuf:"bytes,4,opt,name=primitive_transformation,json=primitiveTransformation,oneof"` +} +type FieldTransformation_InfoTypeTransformations struct { + InfoTypeTransformations *InfoTypeTransformations `protobuf:"bytes,5,opt,name=info_type_transformations,json=infoTypeTransformations,oneof"` +} + +func (*FieldTransformation_PrimitiveTransformation) isFieldTransformation_Transformation() {} +func (*FieldTransformation_InfoTypeTransformations) isFieldTransformation_Transformation() {} + +func (m *FieldTransformation) GetTransformation() isFieldTransformation_Transformation { + if m != nil { + return m.Transformation + } + return nil +} + +func (m *FieldTransformation) GetFields() []*FieldId { + if m != nil { + return m.Fields + } + return nil +} + +func (m *FieldTransformation) GetCondition() *RecordCondition { + if m != nil { + return m.Condition + } + return nil +} + +func (m *FieldTransformation) GetPrimitiveTransformation() *PrimitiveTransformation { + if x, ok := m.GetTransformation().(*FieldTransformation_PrimitiveTransformation); ok { + return x.PrimitiveTransformation + } + return nil +} + +func (m *FieldTransformation) GetInfoTypeTransformations() *InfoTypeTransformations { + if x, ok := m.GetTransformation().(*FieldTransformation_InfoTypeTransformations); ok { + return x.InfoTypeTransformations + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*FieldTransformation) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _FieldTransformation_OneofMarshaler, _FieldTransformation_OneofUnmarshaler, _FieldTransformation_OneofSizer, []interface{}{ + (*FieldTransformation_PrimitiveTransformation)(nil), + (*FieldTransformation_InfoTypeTransformations)(nil), + } +} + +func _FieldTransformation_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*FieldTransformation) + // transformation + switch x := m.Transformation.(type) { + case *FieldTransformation_PrimitiveTransformation: + b.EncodeVarint(4<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.PrimitiveTransformation); err != nil { + return err + } + case *FieldTransformation_InfoTypeTransformations: + b.EncodeVarint(5<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.InfoTypeTransformations); err != nil { + return err + } + case nil: + default: + return fmt.Errorf("FieldTransformation.Transformation has unexpected type %T", x) + } + return nil +} + +func _FieldTransformation_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*FieldTransformation) + switch tag { + case 4: // transformation.primitive_transformation + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(PrimitiveTransformation) + err := b.DecodeMessage(msg) + m.Transformation = &FieldTransformation_PrimitiveTransformation{msg} + return true, err + case 5: // transformation.info_type_transformations + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(InfoTypeTransformations) + err := b.DecodeMessage(msg) + m.Transformation = &FieldTransformation_InfoTypeTransformations{msg} + return true, err + default: + return false, nil + } +} + +func _FieldTransformation_OneofSizer(msg proto.Message) (n int) { + m := msg.(*FieldTransformation) + // transformation + switch x := m.Transformation.(type) { + case *FieldTransformation_PrimitiveTransformation: + s := proto.Size(x.PrimitiveTransformation) + n += proto.SizeVarint(4<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *FieldTransformation_InfoTypeTransformations: + s := proto.Size(x.InfoTypeTransformations) + n += proto.SizeVarint(5<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +// A type of transformation that is applied over structured data such as a +// table. +type RecordTransformations struct { + // Transform the record by applying various field transformations. + FieldTransformations []*FieldTransformation `protobuf:"bytes,1,rep,name=field_transformations,json=fieldTransformations" json:"field_transformations,omitempty"` + // Configuration defining which records get suppressed entirely. Records that + // match any suppression rule are omitted from the output [optional]. + RecordSuppressions []*RecordSuppression `protobuf:"bytes,2,rep,name=record_suppressions,json=recordSuppressions" json:"record_suppressions,omitempty"` +} + +func (m *RecordTransformations) Reset() { *m = RecordTransformations{} } +func (m *RecordTransformations) String() string { return proto.CompactTextString(m) } +func (*RecordTransformations) ProtoMessage() {} +func (*RecordTransformations) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{49} } + +func (m *RecordTransformations) GetFieldTransformations() []*FieldTransformation { + if m != nil { + return m.FieldTransformations + } + return nil +} + +func (m *RecordTransformations) GetRecordSuppressions() []*RecordSuppression { + if m != nil { + return m.RecordSuppressions + } + return nil +} + +// Configuration to suppress records whose suppression conditions evaluate to +// true. +type RecordSuppression struct { + // A condition that when it evaluates to true will result in the record being + // evaluated to be suppressed from the transformed content. + Condition *RecordCondition `protobuf:"bytes,1,opt,name=condition" json:"condition,omitempty"` +} + +func (m *RecordSuppression) Reset() { *m = RecordSuppression{} } +func (m *RecordSuppression) String() string { return proto.CompactTextString(m) } +func (*RecordSuppression) ProtoMessage() {} +func (*RecordSuppression) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{50} } + +func (m *RecordSuppression) GetCondition() *RecordCondition { + if m != nil { + return m.Condition + } + return nil +} + +// A condition for determining whether a transformation should be applied to +// a field. +type RecordCondition struct { + // An expression. + Expressions *RecordCondition_Expressions `protobuf:"bytes,3,opt,name=expressions" json:"expressions,omitempty"` +} + +func (m *RecordCondition) Reset() { *m = RecordCondition{} } +func (m *RecordCondition) String() string { return proto.CompactTextString(m) } +func (*RecordCondition) ProtoMessage() {} +func (*RecordCondition) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{51} } + +func (m *RecordCondition) GetExpressions() *RecordCondition_Expressions { + if m != nil { + return m.Expressions + } + return nil +} + +// The field type of `value` and `field` do not need to match to be +// considered equal, but not all comparisons are possible. +// +// A `value` of type: +// +// - `string` can be compared against all other types +// - `boolean` can only be compared against other booleans +// - `integer` can be compared against doubles or a string if the string value +// can be parsed as an integer. +// - `double` can be compared against integers or a string if the string can +// be parsed as a double. +// - `Timestamp` can be compared against strings in RFC 3339 date string +// format. +// - `TimeOfDay` can be compared against timestamps and strings in the format +// of 'HH:mm:ss'. +// +// If we fail to compare do to type mismatch, a warning will be given and +// the condition will evaluate to false. +type RecordCondition_Condition struct { + // Field within the record this condition is evaluated against. [required] + Field *FieldId `protobuf:"bytes,1,opt,name=field" json:"field,omitempty"` + // Operator used to compare the field or infoType to the value. [required] + Operator RelationalOperator `protobuf:"varint,3,opt,name=operator,enum=google.privacy.dlp.v2beta2.RelationalOperator" json:"operator,omitempty"` + // Value to compare against. [Required, except for `EXISTS` tests.] + Value *Value `protobuf:"bytes,4,opt,name=value" json:"value,omitempty"` +} + +func (m *RecordCondition_Condition) Reset() { *m = RecordCondition_Condition{} } +func (m *RecordCondition_Condition) String() string { return proto.CompactTextString(m) } +func (*RecordCondition_Condition) ProtoMessage() {} +func (*RecordCondition_Condition) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{51, 0} } + +func (m *RecordCondition_Condition) GetField() *FieldId { + if m != nil { + return m.Field + } + return nil +} + +func (m *RecordCondition_Condition) GetOperator() RelationalOperator { + if m != nil { + return m.Operator + } + return RelationalOperator_RELATIONAL_OPERATOR_UNSPECIFIED +} + +func (m *RecordCondition_Condition) GetValue() *Value { + if m != nil { + return m.Value + } + return nil +} + +// A collection of conditions. +type RecordCondition_Conditions struct { + Conditions []*RecordCondition_Condition `protobuf:"bytes,1,rep,name=conditions" json:"conditions,omitempty"` +} + +func (m *RecordCondition_Conditions) Reset() { *m = RecordCondition_Conditions{} } +func (m *RecordCondition_Conditions) String() string { return proto.CompactTextString(m) } +func (*RecordCondition_Conditions) ProtoMessage() {} +func (*RecordCondition_Conditions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{51, 1} } + +func (m *RecordCondition_Conditions) GetConditions() []*RecordCondition_Condition { + if m != nil { + return m.Conditions + } + return nil +} + +// An expression, consisting or an operator and conditions. +type RecordCondition_Expressions struct { + // The operator to apply to the result of conditions. Default and currently + // only supported value is `AND`. + LogicalOperator RecordCondition_Expressions_LogicalOperator `protobuf:"varint,1,opt,name=logical_operator,json=logicalOperator,enum=google.privacy.dlp.v2beta2.RecordCondition_Expressions_LogicalOperator" json:"logical_operator,omitempty"` + // Types that are valid to be assigned to Type: + // *RecordCondition_Expressions_Conditions + Type isRecordCondition_Expressions_Type `protobuf_oneof:"type"` +} + +func (m *RecordCondition_Expressions) Reset() { *m = RecordCondition_Expressions{} } +func (m *RecordCondition_Expressions) String() string { return proto.CompactTextString(m) } +func (*RecordCondition_Expressions) ProtoMessage() {} +func (*RecordCondition_Expressions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{51, 2} } + +type isRecordCondition_Expressions_Type interface { + isRecordCondition_Expressions_Type() +} + +type RecordCondition_Expressions_Conditions struct { + Conditions *RecordCondition_Conditions `protobuf:"bytes,3,opt,name=conditions,oneof"` +} + +func (*RecordCondition_Expressions_Conditions) isRecordCondition_Expressions_Type() {} + +func (m *RecordCondition_Expressions) GetType() isRecordCondition_Expressions_Type { + if m != nil { + return m.Type + } + return nil +} + +func (m *RecordCondition_Expressions) GetLogicalOperator() RecordCondition_Expressions_LogicalOperator { + if m != nil { + return m.LogicalOperator + } + return RecordCondition_Expressions_LOGICAL_OPERATOR_UNSPECIFIED +} + +func (m *RecordCondition_Expressions) GetConditions() *RecordCondition_Conditions { + if x, ok := m.GetType().(*RecordCondition_Expressions_Conditions); ok { + return x.Conditions + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*RecordCondition_Expressions) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _RecordCondition_Expressions_OneofMarshaler, _RecordCondition_Expressions_OneofUnmarshaler, _RecordCondition_Expressions_OneofSizer, []interface{}{ + (*RecordCondition_Expressions_Conditions)(nil), + } +} + +func _RecordCondition_Expressions_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*RecordCondition_Expressions) + // type + switch x := m.Type.(type) { + case *RecordCondition_Expressions_Conditions: + b.EncodeVarint(3<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Conditions); err != nil { + return err + } + case nil: + default: + return fmt.Errorf("RecordCondition_Expressions.Type has unexpected type %T", x) + } + return nil +} + +func _RecordCondition_Expressions_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*RecordCondition_Expressions) + switch tag { + case 3: // type.conditions + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(RecordCondition_Conditions) + err := b.DecodeMessage(msg) + m.Type = &RecordCondition_Expressions_Conditions{msg} + return true, err + default: + return false, nil + } +} + +func _RecordCondition_Expressions_OneofSizer(msg proto.Message) (n int) { + m := msg.(*RecordCondition_Expressions) + // type + switch x := m.Type.(type) { + case *RecordCondition_Expressions_Conditions: + s := proto.Size(x.Conditions) + n += proto.SizeVarint(3<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +// Overview of the modifications that occurred. +type TransformationOverview struct { + // Total size in bytes that were transformed in some way. + TransformedBytes int64 `protobuf:"varint,2,opt,name=transformed_bytes,json=transformedBytes" json:"transformed_bytes,omitempty"` + // Transformations applied to the dataset. + TransformationSummaries []*TransformationSummary `protobuf:"bytes,3,rep,name=transformation_summaries,json=transformationSummaries" json:"transformation_summaries,omitempty"` +} + +func (m *TransformationOverview) Reset() { *m = TransformationOverview{} } +func (m *TransformationOverview) String() string { return proto.CompactTextString(m) } +func (*TransformationOverview) ProtoMessage() {} +func (*TransformationOverview) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{52} } + +func (m *TransformationOverview) GetTransformedBytes() int64 { + if m != nil { + return m.TransformedBytes + } + return 0 +} + +func (m *TransformationOverview) GetTransformationSummaries() []*TransformationSummary { + if m != nil { + return m.TransformationSummaries + } + return nil +} + +// Summary of a single tranformation. +// Only one of 'transformation', 'field_transformation', or 'record_suppress' +// will be set. +type TransformationSummary struct { + // Set if the transformation was limited to a specific info_type. + InfoType *InfoType `protobuf:"bytes,1,opt,name=info_type,json=infoType" json:"info_type,omitempty"` + // Set if the transformation was limited to a specific FieldId. + Field *FieldId `protobuf:"bytes,2,opt,name=field" json:"field,omitempty"` + // The specific transformation these stats apply to. + Transformation *PrimitiveTransformation `protobuf:"bytes,3,opt,name=transformation" json:"transformation,omitempty"` + // The field transformation that was applied. + // If multiple field transformations are requested for a single field, + // this list will contain all of them; otherwise, only one is supplied. + FieldTransformations []*FieldTransformation `protobuf:"bytes,5,rep,name=field_transformations,json=fieldTransformations" json:"field_transformations,omitempty"` + // The specific suppression option these stats apply to. + RecordSuppress *RecordSuppression `protobuf:"bytes,6,opt,name=record_suppress,json=recordSuppress" json:"record_suppress,omitempty"` + Results []*TransformationSummary_SummaryResult `protobuf:"bytes,4,rep,name=results" json:"results,omitempty"` + // Total size in bytes that were transformed in some way. + TransformedBytes int64 `protobuf:"varint,7,opt,name=transformed_bytes,json=transformedBytes" json:"transformed_bytes,omitempty"` +} + +func (m *TransformationSummary) Reset() { *m = TransformationSummary{} } +func (m *TransformationSummary) String() string { return proto.CompactTextString(m) } +func (*TransformationSummary) ProtoMessage() {} +func (*TransformationSummary) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{53} } + +func (m *TransformationSummary) GetInfoType() *InfoType { + if m != nil { + return m.InfoType + } + return nil +} + +func (m *TransformationSummary) GetField() *FieldId { + if m != nil { + return m.Field + } + return nil +} + +func (m *TransformationSummary) GetTransformation() *PrimitiveTransformation { + if m != nil { + return m.Transformation + } + return nil +} + +func (m *TransformationSummary) GetFieldTransformations() []*FieldTransformation { + if m != nil { + return m.FieldTransformations + } + return nil +} + +func (m *TransformationSummary) GetRecordSuppress() *RecordSuppression { + if m != nil { + return m.RecordSuppress + } + return nil +} + +func (m *TransformationSummary) GetResults() []*TransformationSummary_SummaryResult { + if m != nil { + return m.Results + } + return nil +} + +func (m *TransformationSummary) GetTransformedBytes() int64 { + if m != nil { + return m.TransformedBytes + } + return 0 +} + +// A collection that informs the user the number of times a particular +// `TransformationResultCode` and error details occurred. +type TransformationSummary_SummaryResult struct { + Count int64 `protobuf:"varint,1,opt,name=count" json:"count,omitempty"` + Code TransformationSummary_TransformationResultCode `protobuf:"varint,2,opt,name=code,enum=google.privacy.dlp.v2beta2.TransformationSummary_TransformationResultCode" json:"code,omitempty"` + // A place for warnings or errors to show up if a transformation didn't + // work as expected. + Details string `protobuf:"bytes,3,opt,name=details" json:"details,omitempty"` +} + +func (m *TransformationSummary_SummaryResult) Reset() { *m = TransformationSummary_SummaryResult{} } +func (m *TransformationSummary_SummaryResult) String() string { return proto.CompactTextString(m) } +func (*TransformationSummary_SummaryResult) ProtoMessage() {} +func (*TransformationSummary_SummaryResult) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{53, 0} +} + +func (m *TransformationSummary_SummaryResult) GetCount() int64 { + if m != nil { + return m.Count + } + return 0 +} + +func (m *TransformationSummary_SummaryResult) GetCode() TransformationSummary_TransformationResultCode { + if m != nil { + return m.Code + } + return TransformationSummary_TRANSFORMATION_RESULT_CODE_UNSPECIFIED +} + +func (m *TransformationSummary_SummaryResult) GetDetails() string { + if m != nil { + return m.Details + } + return "" +} + +// The inspectTemplate contains a configuration (set of types of sensitive data +// to be detected) to be used anywhere you otherwise would normally specify +// InspectConfig. +type InspectTemplate struct { + // The template name. Output only. + // + // The template will have one of the following formats: + // `projects/PROJECT_ID/inspectTemplates/TEMPLATE_ID` OR + // `organizations/ORGANIZATION_ID/inspectTemplates/TEMPLATE_ID` + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // Display name (max 256 chars). + DisplayName string `protobuf:"bytes,2,opt,name=display_name,json=displayName" json:"display_name,omitempty"` + // Short description (max 256 chars). + Description string `protobuf:"bytes,3,opt,name=description" json:"description,omitempty"` + // The creation timestamp of a inspectTemplate, output only field. + CreateTime *google_protobuf1.Timestamp `protobuf:"bytes,4,opt,name=create_time,json=createTime" json:"create_time,omitempty"` + // The last update timestamp of a inspectTemplate, output only field. + UpdateTime *google_protobuf1.Timestamp `protobuf:"bytes,5,opt,name=update_time,json=updateTime" json:"update_time,omitempty"` + // The core content of the template. Configuration of the scanning process. + InspectConfig *InspectConfig `protobuf:"bytes,6,opt,name=inspect_config,json=inspectConfig" json:"inspect_config,omitempty"` +} + +func (m *InspectTemplate) Reset() { *m = InspectTemplate{} } +func (m *InspectTemplate) String() string { return proto.CompactTextString(m) } +func (*InspectTemplate) ProtoMessage() {} +func (*InspectTemplate) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{54} } + +func (m *InspectTemplate) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *InspectTemplate) GetDisplayName() string { + if m != nil { + return m.DisplayName + } + return "" +} + +func (m *InspectTemplate) GetDescription() string { + if m != nil { + return m.Description + } + return "" +} + +func (m *InspectTemplate) GetCreateTime() *google_protobuf1.Timestamp { + if m != nil { + return m.CreateTime + } + return nil +} + +func (m *InspectTemplate) GetUpdateTime() *google_protobuf1.Timestamp { + if m != nil { + return m.UpdateTime + } + return nil +} + +func (m *InspectTemplate) GetInspectConfig() *InspectConfig { + if m != nil { + return m.InspectConfig + } + return nil +} + +// The DeidentifyTemplates contains instructions on how to deidentify content. +type DeidentifyTemplate struct { + // The template name. Output only. + // + // The template will have one of the following formats: + // `projects/PROJECT_ID/deidentifyTemplates/TEMPLATE_ID` OR + // `organizations/ORGANIZATION_ID/deidentifyTemplates/TEMPLATE_ID` + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // Display name (max 256 chars). + DisplayName string `protobuf:"bytes,2,opt,name=display_name,json=displayName" json:"display_name,omitempty"` + // Short description (max 256 chars). + Description string `protobuf:"bytes,3,opt,name=description" json:"description,omitempty"` + // The creation timestamp of a inspectTemplate, output only field. + CreateTime *google_protobuf1.Timestamp `protobuf:"bytes,4,opt,name=create_time,json=createTime" json:"create_time,omitempty"` + // The last update timestamp of a inspectTemplate, output only field. + UpdateTime *google_protobuf1.Timestamp `protobuf:"bytes,5,opt,name=update_time,json=updateTime" json:"update_time,omitempty"` + // ///////////// // The core content of the template // /////////////// + DeidentifyConfig *DeidentifyConfig `protobuf:"bytes,6,opt,name=deidentify_config,json=deidentifyConfig" json:"deidentify_config,omitempty"` +} + +func (m *DeidentifyTemplate) Reset() { *m = DeidentifyTemplate{} } +func (m *DeidentifyTemplate) String() string { return proto.CompactTextString(m) } +func (*DeidentifyTemplate) ProtoMessage() {} +func (*DeidentifyTemplate) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{55} } + +func (m *DeidentifyTemplate) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *DeidentifyTemplate) GetDisplayName() string { + if m != nil { + return m.DisplayName + } + return "" +} + +func (m *DeidentifyTemplate) GetDescription() string { + if m != nil { + return m.Description + } + return "" +} + +func (m *DeidentifyTemplate) GetCreateTime() *google_protobuf1.Timestamp { + if m != nil { + return m.CreateTime + } + return nil +} + +func (m *DeidentifyTemplate) GetUpdateTime() *google_protobuf1.Timestamp { + if m != nil { + return m.UpdateTime + } + return nil +} + +func (m *DeidentifyTemplate) GetDeidentifyConfig() *DeidentifyConfig { + if m != nil { + return m.DeidentifyConfig + } + return nil +} + +// Request message for CreateInspectTemplate. +type CreateInspectTemplateRequest struct { + // The parent resource name, for example projects/my-project-id or + // organizations/my-org-id. + Parent string `protobuf:"bytes,1,opt,name=parent" json:"parent,omitempty"` + // The InspectTemplate to create. + InspectTemplate *InspectTemplate `protobuf:"bytes,2,opt,name=inspect_template,json=inspectTemplate" json:"inspect_template,omitempty"` + // The template id can contain uppercase and lowercase letters, + // numbers, and hyphens; that is, it must match the regular + // expression: `[a-zA-Z\\d-]+`. The maximum length is 100 + // characters. Can be empty to allow the system to generate one. + TemplateId string `protobuf:"bytes,3,opt,name=template_id,json=templateId" json:"template_id,omitempty"` +} + +func (m *CreateInspectTemplateRequest) Reset() { *m = CreateInspectTemplateRequest{} } +func (m *CreateInspectTemplateRequest) String() string { return proto.CompactTextString(m) } +func (*CreateInspectTemplateRequest) ProtoMessage() {} +func (*CreateInspectTemplateRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{56} } + +func (m *CreateInspectTemplateRequest) GetParent() string { + if m != nil { + return m.Parent + } + return "" +} + +func (m *CreateInspectTemplateRequest) GetInspectTemplate() *InspectTemplate { + if m != nil { + return m.InspectTemplate + } + return nil +} + +func (m *CreateInspectTemplateRequest) GetTemplateId() string { + if m != nil { + return m.TemplateId + } + return "" +} + +// Request message for UpdateInspectTemplate. +type UpdateInspectTemplateRequest struct { + // Resource name of organization and inspectTemplate to be updated, for + // example `organizations/433245324/inspectTemplates/432452342`. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // New InspectTemplate value. + InspectTemplate *InspectTemplate `protobuf:"bytes,2,opt,name=inspect_template,json=inspectTemplate" json:"inspect_template,omitempty"` + // Mask to control which fields get updated. + UpdateMask *google_protobuf4.FieldMask `protobuf:"bytes,3,opt,name=update_mask,json=updateMask" json:"update_mask,omitempty"` +} + +func (m *UpdateInspectTemplateRequest) Reset() { *m = UpdateInspectTemplateRequest{} } +func (m *UpdateInspectTemplateRequest) String() string { return proto.CompactTextString(m) } +func (*UpdateInspectTemplateRequest) ProtoMessage() {} +func (*UpdateInspectTemplateRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{57} } + +func (m *UpdateInspectTemplateRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *UpdateInspectTemplateRequest) GetInspectTemplate() *InspectTemplate { + if m != nil { + return m.InspectTemplate + } + return nil +} + +func (m *UpdateInspectTemplateRequest) GetUpdateMask() *google_protobuf4.FieldMask { + if m != nil { + return m.UpdateMask + } + return nil +} + +// Request message for GetInspectTemplate. +type GetInspectTemplateRequest struct { + // Resource name of the organization and inspectTemplate to be read, for + // example `organizations/433245324/inspectTemplates/432452342`. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` +} + +func (m *GetInspectTemplateRequest) Reset() { *m = GetInspectTemplateRequest{} } +func (m *GetInspectTemplateRequest) String() string { return proto.CompactTextString(m) } +func (*GetInspectTemplateRequest) ProtoMessage() {} +func (*GetInspectTemplateRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{58} } + +func (m *GetInspectTemplateRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +// Request message for ListInspectTemplates. +type ListInspectTemplatesRequest struct { + // The parent resource name, for example projects/my-project-id or + // organizations/my-org-id. + Parent string `protobuf:"bytes,1,opt,name=parent" json:"parent,omitempty"` + // Optional page token to continue retrieval. Comes from previous call + // to `ListInspectTemplates`. + PageToken string `protobuf:"bytes,2,opt,name=page_token,json=pageToken" json:"page_token,omitempty"` + // Optional size of the page, can be limited by server. If zero server returns + // a page of max size 100. + PageSize int32 `protobuf:"varint,3,opt,name=page_size,json=pageSize" json:"page_size,omitempty"` +} + +func (m *ListInspectTemplatesRequest) Reset() { *m = ListInspectTemplatesRequest{} } +func (m *ListInspectTemplatesRequest) String() string { return proto.CompactTextString(m) } +func (*ListInspectTemplatesRequest) ProtoMessage() {} +func (*ListInspectTemplatesRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{59} } + +func (m *ListInspectTemplatesRequest) GetParent() string { + if m != nil { + return m.Parent + } + return "" +} + +func (m *ListInspectTemplatesRequest) GetPageToken() string { + if m != nil { + return m.PageToken + } + return "" +} + +func (m *ListInspectTemplatesRequest) GetPageSize() int32 { + if m != nil { + return m.PageSize + } + return 0 +} + +// Response message for ListInspectTemplates. +type ListInspectTemplatesResponse struct { + // List of inspectTemplates, up to page_size in ListInspectTemplatesRequest. + InspectTemplates []*InspectTemplate `protobuf:"bytes,1,rep,name=inspect_templates,json=inspectTemplates" json:"inspect_templates,omitempty"` + // If the next page is available then the next page token to be used + // in following ListInspectTemplates request. + NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken" json:"next_page_token,omitempty"` +} + +func (m *ListInspectTemplatesResponse) Reset() { *m = ListInspectTemplatesResponse{} } +func (m *ListInspectTemplatesResponse) String() string { return proto.CompactTextString(m) } +func (*ListInspectTemplatesResponse) ProtoMessage() {} +func (*ListInspectTemplatesResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{60} } + +func (m *ListInspectTemplatesResponse) GetInspectTemplates() []*InspectTemplate { + if m != nil { + return m.InspectTemplates + } + return nil +} + +func (m *ListInspectTemplatesResponse) GetNextPageToken() string { + if m != nil { + return m.NextPageToken + } + return "" +} + +// Request message for DeleteInspectTemplate. +type DeleteInspectTemplateRequest struct { + // Resource name of the organization and inspectTemplate to be deleted, for + // example `organizations/433245324/inspectTemplates/432452342`. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` +} + +func (m *DeleteInspectTemplateRequest) Reset() { *m = DeleteInspectTemplateRequest{} } +func (m *DeleteInspectTemplateRequest) String() string { return proto.CompactTextString(m) } +func (*DeleteInspectTemplateRequest) ProtoMessage() {} +func (*DeleteInspectTemplateRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{61} } + +func (m *DeleteInspectTemplateRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +type InspectJobConfig struct { + // The data to scan. + StorageConfig *StorageConfig `protobuf:"bytes,1,opt,name=storage_config,json=storageConfig" json:"storage_config,omitempty"` + // Where to put the findings. + OutputConfig *OutputStorageConfig `protobuf:"bytes,2,opt,name=output_config,json=outputConfig" json:"output_config,omitempty"` + // How and what to scan for. + InspectConfig *InspectConfig `protobuf:"bytes,3,opt,name=inspect_config,json=inspectConfig" json:"inspect_config,omitempty"` + // If provided, will be used as the default for all values in InspectConfig. + // `inspect_config` will be merged into the values persisted as part of the + // template. + InspectTemplateName string `protobuf:"bytes,4,opt,name=inspect_template_name,json=inspectTemplateName" json:"inspect_template_name,omitempty"` +} + +func (m *InspectJobConfig) Reset() { *m = InspectJobConfig{} } +func (m *InspectJobConfig) String() string { return proto.CompactTextString(m) } +func (*InspectJobConfig) ProtoMessage() {} +func (*InspectJobConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{62} } + +func (m *InspectJobConfig) GetStorageConfig() *StorageConfig { + if m != nil { + return m.StorageConfig + } + return nil +} + +func (m *InspectJobConfig) GetOutputConfig() *OutputStorageConfig { + if m != nil { + return m.OutputConfig + } + return nil +} + +func (m *InspectJobConfig) GetInspectConfig() *InspectConfig { + if m != nil { + return m.InspectConfig + } + return nil +} + +func (m *InspectJobConfig) GetInspectTemplateName() string { + if m != nil { + return m.InspectTemplateName + } + return "" +} + +// Combines all of the information about a DLP job. +type DlpJob struct { + // The server-assigned name. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // The type of job. + Type DlpJobType `protobuf:"varint,2,opt,name=type,enum=google.privacy.dlp.v2beta2.DlpJobType" json:"type,omitempty"` + // State of a job. + State DlpJob_JobState `protobuf:"varint,3,opt,name=state,enum=google.privacy.dlp.v2beta2.DlpJob_JobState" json:"state,omitempty"` + // Types that are valid to be assigned to Details: + // *DlpJob_RiskDetails + // *DlpJob_InspectDetails + Details isDlpJob_Details `protobuf_oneof:"details"` + // Time when the job was created. + CreateTime *google_protobuf1.Timestamp `protobuf:"bytes,6,opt,name=create_time,json=createTime" json:"create_time,omitempty"` + // Time when the job started. + StartTime *google_protobuf1.Timestamp `protobuf:"bytes,7,opt,name=start_time,json=startTime" json:"start_time,omitempty"` + // Time when the job finished. + EndTime *google_protobuf1.Timestamp `protobuf:"bytes,8,opt,name=end_time,json=endTime" json:"end_time,omitempty"` + // A stream of errors encountered running the job. + ErrorResults []*google_rpc.Status `protobuf:"bytes,9,rep,name=error_results,json=errorResults" json:"error_results,omitempty"` +} + +func (m *DlpJob) Reset() { *m = DlpJob{} } +func (m *DlpJob) String() string { return proto.CompactTextString(m) } +func (*DlpJob) ProtoMessage() {} +func (*DlpJob) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{63} } + +type isDlpJob_Details interface { + isDlpJob_Details() +} + +type DlpJob_RiskDetails struct { + RiskDetails *AnalyzeDataSourceRiskDetails `protobuf:"bytes,4,opt,name=risk_details,json=riskDetails,oneof"` +} +type DlpJob_InspectDetails struct { + InspectDetails *InspectDataSourceDetails `protobuf:"bytes,5,opt,name=inspect_details,json=inspectDetails,oneof"` +} + +func (*DlpJob_RiskDetails) isDlpJob_Details() {} +func (*DlpJob_InspectDetails) isDlpJob_Details() {} + +func (m *DlpJob) GetDetails() isDlpJob_Details { + if m != nil { + return m.Details + } + return nil +} + +func (m *DlpJob) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *DlpJob) GetType() DlpJobType { + if m != nil { + return m.Type + } + return DlpJobType_DLP_JOB_TYPE_UNSPECIFIED +} + +func (m *DlpJob) GetState() DlpJob_JobState { + if m != nil { + return m.State + } + return DlpJob_JOB_STATE_UNSPECIFIED +} + +func (m *DlpJob) GetRiskDetails() *AnalyzeDataSourceRiskDetails { + if x, ok := m.GetDetails().(*DlpJob_RiskDetails); ok { + return x.RiskDetails + } + return nil +} + +func (m *DlpJob) GetInspectDetails() *InspectDataSourceDetails { + if x, ok := m.GetDetails().(*DlpJob_InspectDetails); ok { + return x.InspectDetails + } + return nil +} + +func (m *DlpJob) GetCreateTime() *google_protobuf1.Timestamp { + if m != nil { + return m.CreateTime + } + return nil +} + +func (m *DlpJob) GetStartTime() *google_protobuf1.Timestamp { + if m != nil { + return m.StartTime + } + return nil +} + +func (m *DlpJob) GetEndTime() *google_protobuf1.Timestamp { + if m != nil { + return m.EndTime + } + return nil +} + +func (m *DlpJob) GetErrorResults() []*google_rpc.Status { + if m != nil { + return m.ErrorResults + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*DlpJob) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _DlpJob_OneofMarshaler, _DlpJob_OneofUnmarshaler, _DlpJob_OneofSizer, []interface{}{ + (*DlpJob_RiskDetails)(nil), + (*DlpJob_InspectDetails)(nil), + } +} + +func _DlpJob_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*DlpJob) + // details + switch x := m.Details.(type) { + case *DlpJob_RiskDetails: + b.EncodeVarint(4<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.RiskDetails); err != nil { + return err + } + case *DlpJob_InspectDetails: + b.EncodeVarint(5<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.InspectDetails); err != nil { + return err + } + case nil: + default: + return fmt.Errorf("DlpJob.Details has unexpected type %T", x) + } + return nil +} + +func _DlpJob_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*DlpJob) + switch tag { + case 4: // details.risk_details + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(AnalyzeDataSourceRiskDetails) + err := b.DecodeMessage(msg) + m.Details = &DlpJob_RiskDetails{msg} + return true, err + case 5: // details.inspect_details + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(InspectDataSourceDetails) + err := b.DecodeMessage(msg) + m.Details = &DlpJob_InspectDetails{msg} + return true, err + default: + return false, nil + } +} + +func _DlpJob_OneofSizer(msg proto.Message) (n int) { + m := msg.(*DlpJob) + // details + switch x := m.Details.(type) { + case *DlpJob_RiskDetails: + s := proto.Size(x.RiskDetails) + n += proto.SizeVarint(4<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *DlpJob_InspectDetails: + s := proto.Size(x.InspectDetails) + n += proto.SizeVarint(5<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +// The request message for [DlpJobs.GetDlpJob][]. +type GetDlpJobRequest struct { + // The name of the DlpJob resource. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` +} + +func (m *GetDlpJobRequest) Reset() { *m = GetDlpJobRequest{} } +func (m *GetDlpJobRequest) String() string { return proto.CompactTextString(m) } +func (*GetDlpJobRequest) ProtoMessage() {} +func (*GetDlpJobRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{64} } + +func (m *GetDlpJobRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +// The request message for listing DLP jobs. +type ListDlpJobsRequest struct { + // The parent resource name, for example projects/my-project-id. + Parent string `protobuf:"bytes,4,opt,name=parent" json:"parent,omitempty"` + // Optional. Allows filtering. + // + // Supported syntax: + // + // * Filter expressions are made up of one or more restrictions. + // * Restrictions can be combined by `AND` or `OR` logical operators. A + // sequence of restrictions implicitly uses `AND`. + // * A restriction has the form of ` `. + // * Supported fields/values for inspect jobs: + // - `state` - PENDING|RUNNING|CANCELED|FINISHED|FAILED + // - `inspected_storage` - DATASTORE|CLOUD_STORAGE|BIGQUERY + // * Supported fields for risk analysis jobs: + // - `state` - RUNNING|CANCELED|FINISHED|FAILED + // * The operator must be `=` or `!=`. + // + // Examples: + // + // * inspected_storage = cloud_storage AND state = done + // * inspected_storage = cloud_storage OR inspected_storage = bigquery + // * inspected_storage = cloud_storage AND (state = done OR state = canceled) + // + // The length of this field should be no more than 500 characters. + Filter string `protobuf:"bytes,1,opt,name=filter" json:"filter,omitempty"` + // The standard list page size. + PageSize int32 `protobuf:"varint,2,opt,name=page_size,json=pageSize" json:"page_size,omitempty"` + // The standard list page token. + PageToken string `protobuf:"bytes,3,opt,name=page_token,json=pageToken" json:"page_token,omitempty"` + // The type of job. Defaults to `DlpJobType.INSPECT` + Type DlpJobType `protobuf:"varint,5,opt,name=type,enum=google.privacy.dlp.v2beta2.DlpJobType" json:"type,omitempty"` +} + +func (m *ListDlpJobsRequest) Reset() { *m = ListDlpJobsRequest{} } +func (m *ListDlpJobsRequest) String() string { return proto.CompactTextString(m) } +func (*ListDlpJobsRequest) ProtoMessage() {} +func (*ListDlpJobsRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{65} } + +func (m *ListDlpJobsRequest) GetParent() string { + if m != nil { + return m.Parent + } + return "" +} + +func (m *ListDlpJobsRequest) GetFilter() string { + if m != nil { + return m.Filter + } + return "" +} + +func (m *ListDlpJobsRequest) GetPageSize() int32 { + if m != nil { + return m.PageSize + } + return 0 +} + +func (m *ListDlpJobsRequest) GetPageToken() string { + if m != nil { + return m.PageToken + } + return "" +} + +func (m *ListDlpJobsRequest) GetType() DlpJobType { + if m != nil { + return m.Type + } + return DlpJobType_DLP_JOB_TYPE_UNSPECIFIED +} + +// The response message for listing DLP jobs. +type ListDlpJobsResponse struct { + // A list of DlpJobs that matches the specified filter in the request. + Jobs []*DlpJob `protobuf:"bytes,1,rep,name=jobs" json:"jobs,omitempty"` + // The standard List next-page token. + NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken" json:"next_page_token,omitempty"` +} + +func (m *ListDlpJobsResponse) Reset() { *m = ListDlpJobsResponse{} } +func (m *ListDlpJobsResponse) String() string { return proto.CompactTextString(m) } +func (*ListDlpJobsResponse) ProtoMessage() {} +func (*ListDlpJobsResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{66} } + +func (m *ListDlpJobsResponse) GetJobs() []*DlpJob { + if m != nil { + return m.Jobs + } + return nil +} + +func (m *ListDlpJobsResponse) GetNextPageToken() string { + if m != nil { + return m.NextPageToken + } + return "" +} + +// The request message for canceling a DLP job. +type CancelDlpJobRequest struct { + // The name of the DlpJob resource to be cancelled. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` +} + +func (m *CancelDlpJobRequest) Reset() { *m = CancelDlpJobRequest{} } +func (m *CancelDlpJobRequest) String() string { return proto.CompactTextString(m) } +func (*CancelDlpJobRequest) ProtoMessage() {} +func (*CancelDlpJobRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{67} } + +func (m *CancelDlpJobRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +// The request message for deleting a DLP job. +type DeleteDlpJobRequest struct { + // The name of the DlpJob resource to be deleted. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` +} + +func (m *DeleteDlpJobRequest) Reset() { *m = DeleteDlpJobRequest{} } +func (m *DeleteDlpJobRequest) String() string { return proto.CompactTextString(m) } +func (*DeleteDlpJobRequest) ProtoMessage() {} +func (*DeleteDlpJobRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{68} } + +func (m *DeleteDlpJobRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +// Request message for CreateDeidentifyTemplate. +type CreateDeidentifyTemplateRequest struct { + // The parent resource name, for example projects/my-project-id or + // organizations/my-org-id. + Parent string `protobuf:"bytes,1,opt,name=parent" json:"parent,omitempty"` + // The DeidentifyTemplate to create. + DeidentifyTemplate *DeidentifyTemplate `protobuf:"bytes,2,opt,name=deidentify_template,json=deidentifyTemplate" json:"deidentify_template,omitempty"` + // The template id can contain uppercase and lowercase letters, + // numbers, and hyphens; that is, it must match the regular + // expression: `[a-zA-Z\\d-]+`. The maximum length is 100 + // characters. Can be empty to allow the system to generate one. + TemplateId string `protobuf:"bytes,3,opt,name=template_id,json=templateId" json:"template_id,omitempty"` +} + +func (m *CreateDeidentifyTemplateRequest) Reset() { *m = CreateDeidentifyTemplateRequest{} } +func (m *CreateDeidentifyTemplateRequest) String() string { return proto.CompactTextString(m) } +func (*CreateDeidentifyTemplateRequest) ProtoMessage() {} +func (*CreateDeidentifyTemplateRequest) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{69} +} + +func (m *CreateDeidentifyTemplateRequest) GetParent() string { + if m != nil { + return m.Parent + } + return "" +} + +func (m *CreateDeidentifyTemplateRequest) GetDeidentifyTemplate() *DeidentifyTemplate { + if m != nil { + return m.DeidentifyTemplate + } + return nil +} + +func (m *CreateDeidentifyTemplateRequest) GetTemplateId() string { + if m != nil { + return m.TemplateId + } + return "" +} + +// Request message for UpdateDeidentifyTemplate. +type UpdateDeidentifyTemplateRequest struct { + // Resource name of organization and deidentify template to be updated, for + // example `organizations/433245324/deidentifyTemplates/432452342`. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // New DeidentifyTemplate value. + DeidentifyTemplate *DeidentifyTemplate `protobuf:"bytes,2,opt,name=deidentify_template,json=deidentifyTemplate" json:"deidentify_template,omitempty"` + // Mask to control which fields get updated. + UpdateMask *google_protobuf4.FieldMask `protobuf:"bytes,3,opt,name=update_mask,json=updateMask" json:"update_mask,omitempty"` +} + +func (m *UpdateDeidentifyTemplateRequest) Reset() { *m = UpdateDeidentifyTemplateRequest{} } +func (m *UpdateDeidentifyTemplateRequest) String() string { return proto.CompactTextString(m) } +func (*UpdateDeidentifyTemplateRequest) ProtoMessage() {} +func (*UpdateDeidentifyTemplateRequest) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{70} +} + +func (m *UpdateDeidentifyTemplateRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *UpdateDeidentifyTemplateRequest) GetDeidentifyTemplate() *DeidentifyTemplate { + if m != nil { + return m.DeidentifyTemplate + } + return nil +} + +func (m *UpdateDeidentifyTemplateRequest) GetUpdateMask() *google_protobuf4.FieldMask { + if m != nil { + return m.UpdateMask + } + return nil +} + +// Request message for GetDeidentifyTemplate. +type GetDeidentifyTemplateRequest struct { + // Resource name of the organization and deidentify template to be read, for + // example `organizations/433245324/deidentifyTemplates/432452342`. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` +} + +func (m *GetDeidentifyTemplateRequest) Reset() { *m = GetDeidentifyTemplateRequest{} } +func (m *GetDeidentifyTemplateRequest) String() string { return proto.CompactTextString(m) } +func (*GetDeidentifyTemplateRequest) ProtoMessage() {} +func (*GetDeidentifyTemplateRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{71} } + +func (m *GetDeidentifyTemplateRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +// Request message for ListDeidentifyTemplates. +type ListDeidentifyTemplatesRequest struct { + // The parent resource name, for example projects/my-project-id or + // organizations/my-org-id. + Parent string `protobuf:"bytes,1,opt,name=parent" json:"parent,omitempty"` + // Optional page token to continue retrieval. Comes from previous call + // to `ListDeidentifyTemplates`. + PageToken string `protobuf:"bytes,2,opt,name=page_token,json=pageToken" json:"page_token,omitempty"` + // Optional size of the page, can be limited by server. If zero server returns + // a page of max size 100. + PageSize int32 `protobuf:"varint,3,opt,name=page_size,json=pageSize" json:"page_size,omitempty"` +} + +func (m *ListDeidentifyTemplatesRequest) Reset() { *m = ListDeidentifyTemplatesRequest{} } +func (m *ListDeidentifyTemplatesRequest) String() string { return proto.CompactTextString(m) } +func (*ListDeidentifyTemplatesRequest) ProtoMessage() {} +func (*ListDeidentifyTemplatesRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{72} } + +func (m *ListDeidentifyTemplatesRequest) GetParent() string { + if m != nil { + return m.Parent + } + return "" +} + +func (m *ListDeidentifyTemplatesRequest) GetPageToken() string { + if m != nil { + return m.PageToken + } + return "" +} + +func (m *ListDeidentifyTemplatesRequest) GetPageSize() int32 { + if m != nil { + return m.PageSize + } + return 0 +} + +// Response message for ListDeidentifyTemplates. +type ListDeidentifyTemplatesResponse struct { + // List of deidentify templates, up to page_size in + // ListDeidentifyTemplatesRequest. + DeidentifyTemplates []*DeidentifyTemplate `protobuf:"bytes,1,rep,name=deidentify_templates,json=deidentifyTemplates" json:"deidentify_templates,omitempty"` + // If the next page is available then the next page token to be used + // in following ListDeidentifyTemplates request. + NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken" json:"next_page_token,omitempty"` +} + +func (m *ListDeidentifyTemplatesResponse) Reset() { *m = ListDeidentifyTemplatesResponse{} } +func (m *ListDeidentifyTemplatesResponse) String() string { return proto.CompactTextString(m) } +func (*ListDeidentifyTemplatesResponse) ProtoMessage() {} +func (*ListDeidentifyTemplatesResponse) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{73} +} + +func (m *ListDeidentifyTemplatesResponse) GetDeidentifyTemplates() []*DeidentifyTemplate { + if m != nil { + return m.DeidentifyTemplates + } + return nil +} + +func (m *ListDeidentifyTemplatesResponse) GetNextPageToken() string { + if m != nil { + return m.NextPageToken + } + return "" +} + +// Request message for DeleteDeidentifyTemplate. +type DeleteDeidentifyTemplateRequest struct { + // Resource name of the organization and deidentify template to be deleted, + // for example `organizations/433245324/deidentifyTemplates/432452342`. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` +} + +func (m *DeleteDeidentifyTemplateRequest) Reset() { *m = DeleteDeidentifyTemplateRequest{} } +func (m *DeleteDeidentifyTemplateRequest) String() string { return proto.CompactTextString(m) } +func (*DeleteDeidentifyTemplateRequest) ProtoMessage() {} +func (*DeleteDeidentifyTemplateRequest) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{74} +} + +func (m *DeleteDeidentifyTemplateRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func init() { + proto.RegisterType((*InspectConfig)(nil), "google.privacy.dlp.v2beta2.InspectConfig") + proto.RegisterType((*InspectConfig_FindingLimits)(nil), "google.privacy.dlp.v2beta2.InspectConfig.FindingLimits") + proto.RegisterType((*InspectConfig_FindingLimits_InfoTypeLimit)(nil), "google.privacy.dlp.v2beta2.InspectConfig.FindingLimits.InfoTypeLimit") + proto.RegisterType((*ContentItem)(nil), "google.privacy.dlp.v2beta2.ContentItem") + proto.RegisterType((*Table)(nil), "google.privacy.dlp.v2beta2.Table") + proto.RegisterType((*Table_Row)(nil), "google.privacy.dlp.v2beta2.Table.Row") + proto.RegisterType((*InspectResult)(nil), "google.privacy.dlp.v2beta2.InspectResult") + proto.RegisterType((*Finding)(nil), "google.privacy.dlp.v2beta2.Finding") + proto.RegisterType((*Location)(nil), "google.privacy.dlp.v2beta2.Location") + proto.RegisterType((*TableLocation)(nil), "google.privacy.dlp.v2beta2.TableLocation") + proto.RegisterType((*Range)(nil), "google.privacy.dlp.v2beta2.Range") + proto.RegisterType((*ImageLocation)(nil), "google.privacy.dlp.v2beta2.ImageLocation") + proto.RegisterType((*RedactImageRequest)(nil), "google.privacy.dlp.v2beta2.RedactImageRequest") + proto.RegisterType((*RedactImageRequest_ImageRedactionConfig)(nil), "google.privacy.dlp.v2beta2.RedactImageRequest.ImageRedactionConfig") + proto.RegisterType((*Color)(nil), "google.privacy.dlp.v2beta2.Color") + proto.RegisterType((*RedactImageResponse)(nil), "google.privacy.dlp.v2beta2.RedactImageResponse") + proto.RegisterType((*DeidentifyContentRequest)(nil), "google.privacy.dlp.v2beta2.DeidentifyContentRequest") + proto.RegisterType((*DeidentifyContentResponse)(nil), "google.privacy.dlp.v2beta2.DeidentifyContentResponse") + proto.RegisterType((*ReidentifyContentRequest)(nil), "google.privacy.dlp.v2beta2.ReidentifyContentRequest") + proto.RegisterType((*ReidentifyContentResponse)(nil), "google.privacy.dlp.v2beta2.ReidentifyContentResponse") + proto.RegisterType((*InspectContentRequest)(nil), "google.privacy.dlp.v2beta2.InspectContentRequest") + proto.RegisterType((*InspectContentResponse)(nil), "google.privacy.dlp.v2beta2.InspectContentResponse") + proto.RegisterType((*InspectDataSourceRequest)(nil), "google.privacy.dlp.v2beta2.InspectDataSourceRequest") + proto.RegisterType((*OutputStorageConfig)(nil), "google.privacy.dlp.v2beta2.OutputStorageConfig") + proto.RegisterType((*InfoTypeStatistics)(nil), "google.privacy.dlp.v2beta2.InfoTypeStatistics") + proto.RegisterType((*InspectDataSourceDetails)(nil), "google.privacy.dlp.v2beta2.InspectDataSourceDetails") + proto.RegisterType((*InspectDataSourceDetails_RequestedOptions)(nil), "google.privacy.dlp.v2beta2.InspectDataSourceDetails.RequestedOptions") + proto.RegisterType((*InspectDataSourceDetails_Result)(nil), "google.privacy.dlp.v2beta2.InspectDataSourceDetails.Result") + proto.RegisterType((*InfoTypeDescription)(nil), "google.privacy.dlp.v2beta2.InfoTypeDescription") + proto.RegisterType((*ListInfoTypesRequest)(nil), "google.privacy.dlp.v2beta2.ListInfoTypesRequest") + proto.RegisterType((*ListInfoTypesResponse)(nil), "google.privacy.dlp.v2beta2.ListInfoTypesResponse") + proto.RegisterType((*AnalyzeDataSourceRiskRequest)(nil), "google.privacy.dlp.v2beta2.AnalyzeDataSourceRiskRequest") + proto.RegisterType((*RiskAnalysisJobConfig)(nil), "google.privacy.dlp.v2beta2.RiskAnalysisJobConfig") + proto.RegisterType((*PrivacyMetric)(nil), "google.privacy.dlp.v2beta2.PrivacyMetric") + proto.RegisterType((*PrivacyMetric_NumericalStatsConfig)(nil), "google.privacy.dlp.v2beta2.PrivacyMetric.NumericalStatsConfig") + proto.RegisterType((*PrivacyMetric_CategoricalStatsConfig)(nil), "google.privacy.dlp.v2beta2.PrivacyMetric.CategoricalStatsConfig") + proto.RegisterType((*PrivacyMetric_KAnonymityConfig)(nil), "google.privacy.dlp.v2beta2.PrivacyMetric.KAnonymityConfig") + proto.RegisterType((*PrivacyMetric_LDiversityConfig)(nil), "google.privacy.dlp.v2beta2.PrivacyMetric.LDiversityConfig") + proto.RegisterType((*PrivacyMetric_KMapEstimationConfig)(nil), "google.privacy.dlp.v2beta2.PrivacyMetric.KMapEstimationConfig") + proto.RegisterType((*PrivacyMetric_KMapEstimationConfig_TaggedField)(nil), "google.privacy.dlp.v2beta2.PrivacyMetric.KMapEstimationConfig.TaggedField") + proto.RegisterType((*PrivacyMetric_KMapEstimationConfig_AuxiliaryTable)(nil), "google.privacy.dlp.v2beta2.PrivacyMetric.KMapEstimationConfig.AuxiliaryTable") + proto.RegisterType((*PrivacyMetric_KMapEstimationConfig_AuxiliaryTable_QuasiIdField)(nil), "google.privacy.dlp.v2beta2.PrivacyMetric.KMapEstimationConfig.AuxiliaryTable.QuasiIdField") + proto.RegisterType((*AnalyzeDataSourceRiskDetails)(nil), "google.privacy.dlp.v2beta2.AnalyzeDataSourceRiskDetails") + proto.RegisterType((*AnalyzeDataSourceRiskDetails_NumericalStatsResult)(nil), "google.privacy.dlp.v2beta2.AnalyzeDataSourceRiskDetails.NumericalStatsResult") + proto.RegisterType((*AnalyzeDataSourceRiskDetails_CategoricalStatsResult)(nil), "google.privacy.dlp.v2beta2.AnalyzeDataSourceRiskDetails.CategoricalStatsResult") + proto.RegisterType((*AnalyzeDataSourceRiskDetails_CategoricalStatsResult_CategoricalStatsHistogramBucket)(nil), "google.privacy.dlp.v2beta2.AnalyzeDataSourceRiskDetails.CategoricalStatsResult.CategoricalStatsHistogramBucket") + proto.RegisterType((*AnalyzeDataSourceRiskDetails_KAnonymityResult)(nil), "google.privacy.dlp.v2beta2.AnalyzeDataSourceRiskDetails.KAnonymityResult") + proto.RegisterType((*AnalyzeDataSourceRiskDetails_KAnonymityResult_KAnonymityEquivalenceClass)(nil), "google.privacy.dlp.v2beta2.AnalyzeDataSourceRiskDetails.KAnonymityResult.KAnonymityEquivalenceClass") + proto.RegisterType((*AnalyzeDataSourceRiskDetails_KAnonymityResult_KAnonymityHistogramBucket)(nil), "google.privacy.dlp.v2beta2.AnalyzeDataSourceRiskDetails.KAnonymityResult.KAnonymityHistogramBucket") + proto.RegisterType((*AnalyzeDataSourceRiskDetails_LDiversityResult)(nil), "google.privacy.dlp.v2beta2.AnalyzeDataSourceRiskDetails.LDiversityResult") + proto.RegisterType((*AnalyzeDataSourceRiskDetails_LDiversityResult_LDiversityEquivalenceClass)(nil), "google.privacy.dlp.v2beta2.AnalyzeDataSourceRiskDetails.LDiversityResult.LDiversityEquivalenceClass") + proto.RegisterType((*AnalyzeDataSourceRiskDetails_LDiversityResult_LDiversityHistogramBucket)(nil), "google.privacy.dlp.v2beta2.AnalyzeDataSourceRiskDetails.LDiversityResult.LDiversityHistogramBucket") + proto.RegisterType((*AnalyzeDataSourceRiskDetails_KMapEstimationResult)(nil), "google.privacy.dlp.v2beta2.AnalyzeDataSourceRiskDetails.KMapEstimationResult") + proto.RegisterType((*AnalyzeDataSourceRiskDetails_KMapEstimationResult_KMapEstimationQuasiIdValues)(nil), "google.privacy.dlp.v2beta2.AnalyzeDataSourceRiskDetails.KMapEstimationResult.KMapEstimationQuasiIdValues") + proto.RegisterType((*AnalyzeDataSourceRiskDetails_KMapEstimationResult_KMapEstimationHistogramBucket)(nil), "google.privacy.dlp.v2beta2.AnalyzeDataSourceRiskDetails.KMapEstimationResult.KMapEstimationHistogramBucket") + proto.RegisterType((*ValueFrequency)(nil), "google.privacy.dlp.v2beta2.ValueFrequency") + proto.RegisterType((*Value)(nil), "google.privacy.dlp.v2beta2.Value") + proto.RegisterType((*DeidentifyConfig)(nil), "google.privacy.dlp.v2beta2.DeidentifyConfig") + proto.RegisterType((*PrimitiveTransformation)(nil), "google.privacy.dlp.v2beta2.PrimitiveTransformation") + proto.RegisterType((*TimePartConfig)(nil), "google.privacy.dlp.v2beta2.TimePartConfig") + proto.RegisterType((*CryptoHashConfig)(nil), "google.privacy.dlp.v2beta2.CryptoHashConfig") + proto.RegisterType((*ReplaceValueConfig)(nil), "google.privacy.dlp.v2beta2.ReplaceValueConfig") + proto.RegisterType((*ReplaceWithInfoTypeConfig)(nil), "google.privacy.dlp.v2beta2.ReplaceWithInfoTypeConfig") + proto.RegisterType((*RedactConfig)(nil), "google.privacy.dlp.v2beta2.RedactConfig") + proto.RegisterType((*CharsToIgnore)(nil), "google.privacy.dlp.v2beta2.CharsToIgnore") + proto.RegisterType((*CharacterMaskConfig)(nil), "google.privacy.dlp.v2beta2.CharacterMaskConfig") + proto.RegisterType((*FixedSizeBucketingConfig)(nil), "google.privacy.dlp.v2beta2.FixedSizeBucketingConfig") + proto.RegisterType((*BucketingConfig)(nil), "google.privacy.dlp.v2beta2.BucketingConfig") + proto.RegisterType((*BucketingConfig_Bucket)(nil), "google.privacy.dlp.v2beta2.BucketingConfig.Bucket") + proto.RegisterType((*CryptoReplaceFfxFpeConfig)(nil), "google.privacy.dlp.v2beta2.CryptoReplaceFfxFpeConfig") + proto.RegisterType((*CryptoKey)(nil), "google.privacy.dlp.v2beta2.CryptoKey") + proto.RegisterType((*TransientCryptoKey)(nil), "google.privacy.dlp.v2beta2.TransientCryptoKey") + proto.RegisterType((*UnwrappedCryptoKey)(nil), "google.privacy.dlp.v2beta2.UnwrappedCryptoKey") + proto.RegisterType((*KmsWrappedCryptoKey)(nil), "google.privacy.dlp.v2beta2.KmsWrappedCryptoKey") + proto.RegisterType((*InfoTypeTransformations)(nil), "google.privacy.dlp.v2beta2.InfoTypeTransformations") + proto.RegisterType((*InfoTypeTransformations_InfoTypeTransformation)(nil), "google.privacy.dlp.v2beta2.InfoTypeTransformations.InfoTypeTransformation") + proto.RegisterType((*FieldTransformation)(nil), "google.privacy.dlp.v2beta2.FieldTransformation") + proto.RegisterType((*RecordTransformations)(nil), "google.privacy.dlp.v2beta2.RecordTransformations") + proto.RegisterType((*RecordSuppression)(nil), "google.privacy.dlp.v2beta2.RecordSuppression") + proto.RegisterType((*RecordCondition)(nil), "google.privacy.dlp.v2beta2.RecordCondition") + proto.RegisterType((*RecordCondition_Condition)(nil), "google.privacy.dlp.v2beta2.RecordCondition.Condition") + proto.RegisterType((*RecordCondition_Conditions)(nil), "google.privacy.dlp.v2beta2.RecordCondition.Conditions") + proto.RegisterType((*RecordCondition_Expressions)(nil), "google.privacy.dlp.v2beta2.RecordCondition.Expressions") + proto.RegisterType((*TransformationOverview)(nil), "google.privacy.dlp.v2beta2.TransformationOverview") + proto.RegisterType((*TransformationSummary)(nil), "google.privacy.dlp.v2beta2.TransformationSummary") + proto.RegisterType((*TransformationSummary_SummaryResult)(nil), "google.privacy.dlp.v2beta2.TransformationSummary.SummaryResult") + proto.RegisterType((*InspectTemplate)(nil), "google.privacy.dlp.v2beta2.InspectTemplate") + proto.RegisterType((*DeidentifyTemplate)(nil), "google.privacy.dlp.v2beta2.DeidentifyTemplate") + proto.RegisterType((*CreateInspectTemplateRequest)(nil), "google.privacy.dlp.v2beta2.CreateInspectTemplateRequest") + proto.RegisterType((*UpdateInspectTemplateRequest)(nil), "google.privacy.dlp.v2beta2.UpdateInspectTemplateRequest") + proto.RegisterType((*GetInspectTemplateRequest)(nil), "google.privacy.dlp.v2beta2.GetInspectTemplateRequest") + proto.RegisterType((*ListInspectTemplatesRequest)(nil), "google.privacy.dlp.v2beta2.ListInspectTemplatesRequest") + proto.RegisterType((*ListInspectTemplatesResponse)(nil), "google.privacy.dlp.v2beta2.ListInspectTemplatesResponse") + proto.RegisterType((*DeleteInspectTemplateRequest)(nil), "google.privacy.dlp.v2beta2.DeleteInspectTemplateRequest") + proto.RegisterType((*InspectJobConfig)(nil), "google.privacy.dlp.v2beta2.InspectJobConfig") + proto.RegisterType((*DlpJob)(nil), "google.privacy.dlp.v2beta2.DlpJob") + proto.RegisterType((*GetDlpJobRequest)(nil), "google.privacy.dlp.v2beta2.GetDlpJobRequest") + proto.RegisterType((*ListDlpJobsRequest)(nil), "google.privacy.dlp.v2beta2.ListDlpJobsRequest") + proto.RegisterType((*ListDlpJobsResponse)(nil), "google.privacy.dlp.v2beta2.ListDlpJobsResponse") + proto.RegisterType((*CancelDlpJobRequest)(nil), "google.privacy.dlp.v2beta2.CancelDlpJobRequest") + proto.RegisterType((*DeleteDlpJobRequest)(nil), "google.privacy.dlp.v2beta2.DeleteDlpJobRequest") + proto.RegisterType((*CreateDeidentifyTemplateRequest)(nil), "google.privacy.dlp.v2beta2.CreateDeidentifyTemplateRequest") + proto.RegisterType((*UpdateDeidentifyTemplateRequest)(nil), "google.privacy.dlp.v2beta2.UpdateDeidentifyTemplateRequest") + proto.RegisterType((*GetDeidentifyTemplateRequest)(nil), "google.privacy.dlp.v2beta2.GetDeidentifyTemplateRequest") + proto.RegisterType((*ListDeidentifyTemplatesRequest)(nil), "google.privacy.dlp.v2beta2.ListDeidentifyTemplatesRequest") + proto.RegisterType((*ListDeidentifyTemplatesResponse)(nil), "google.privacy.dlp.v2beta2.ListDeidentifyTemplatesResponse") + proto.RegisterType((*DeleteDeidentifyTemplateRequest)(nil), "google.privacy.dlp.v2beta2.DeleteDeidentifyTemplateRequest") + proto.RegisterEnum("google.privacy.dlp.v2beta2.InfoTypeSupportedBy", InfoTypeSupportedBy_name, InfoTypeSupportedBy_value) + proto.RegisterEnum("google.privacy.dlp.v2beta2.RelationalOperator", RelationalOperator_name, RelationalOperator_value) + proto.RegisterEnum("google.privacy.dlp.v2beta2.DlpJobType", DlpJobType_name, DlpJobType_value) + proto.RegisterEnum("google.privacy.dlp.v2beta2.TimePartConfig_TimePart", TimePartConfig_TimePart_name, TimePartConfig_TimePart_value) + proto.RegisterEnum("google.privacy.dlp.v2beta2.CharsToIgnore_CommonCharsToIgnore", CharsToIgnore_CommonCharsToIgnore_name, CharsToIgnore_CommonCharsToIgnore_value) + proto.RegisterEnum("google.privacy.dlp.v2beta2.CryptoReplaceFfxFpeConfig_FfxCommonNativeAlphabet", CryptoReplaceFfxFpeConfig_FfxCommonNativeAlphabet_name, CryptoReplaceFfxFpeConfig_FfxCommonNativeAlphabet_value) + proto.RegisterEnum("google.privacy.dlp.v2beta2.RecordCondition_Expressions_LogicalOperator", RecordCondition_Expressions_LogicalOperator_name, RecordCondition_Expressions_LogicalOperator_value) + proto.RegisterEnum("google.privacy.dlp.v2beta2.TransformationSummary_TransformationResultCode", TransformationSummary_TransformationResultCode_name, TransformationSummary_TransformationResultCode_value) + proto.RegisterEnum("google.privacy.dlp.v2beta2.DlpJob_JobState", DlpJob_JobState_name, DlpJob_JobState_value) +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// Client API for DlpService service + +type DlpServiceClient interface { + // Finds potentially sensitive info in content. + // This method has limits on input size, processing time, and output size. + // [How-to guide for text](/dlp/docs/inspecting-text), [How-to guide for + // images](/dlp/docs/inspecting-images) + InspectContent(ctx context.Context, in *InspectContentRequest, opts ...grpc.CallOption) (*InspectContentResponse, error) + // Redacts potentially sensitive info from an image. + // This method has limits on input size, processing time, and output size. + // [How-to guide](/dlp/docs/redacting-sensitive-data-images) + RedactImage(ctx context.Context, in *RedactImageRequest, opts ...grpc.CallOption) (*RedactImageResponse, error) + // De-identifies potentially sensitive info from a ContentItem. + // This method has limits on input size and output size. + // [How-to guide](/dlp/docs/deidentify-sensitive-data) + DeidentifyContent(ctx context.Context, in *DeidentifyContentRequest, opts ...grpc.CallOption) (*DeidentifyContentResponse, error) + // Re-identify content that has been de-identified. + ReidentifyContent(ctx context.Context, in *ReidentifyContentRequest, opts ...grpc.CallOption) (*ReidentifyContentResponse, error) + // Schedules a job scanning content in a Google Cloud Platform data + // repository. [How-to guide](/dlp/docs/inspecting-storage) + InspectDataSource(ctx context.Context, in *InspectDataSourceRequest, opts ...grpc.CallOption) (*DlpJob, error) + // Schedules a job to compute risk analysis metrics over content in a Google + // Cloud Platform repository. [How-to guide}(/dlp/docs/compute-risk-analysis) + AnalyzeDataSourceRisk(ctx context.Context, in *AnalyzeDataSourceRiskRequest, opts ...grpc.CallOption) (*DlpJob, error) + // Returns sensitive information types DLP supports. + ListInfoTypes(ctx context.Context, in *ListInfoTypesRequest, opts ...grpc.CallOption) (*ListInfoTypesResponse, error) + // Creates an inspect template for re-using frequently used configuration + // for inspecting content, images, and storage. + CreateInspectTemplate(ctx context.Context, in *CreateInspectTemplateRequest, opts ...grpc.CallOption) (*InspectTemplate, error) + // Updates the inspect template. + UpdateInspectTemplate(ctx context.Context, in *UpdateInspectTemplateRequest, opts ...grpc.CallOption) (*InspectTemplate, error) + // Gets an inspect template. + GetInspectTemplate(ctx context.Context, in *GetInspectTemplateRequest, opts ...grpc.CallOption) (*InspectTemplate, error) + // Lists inspect templates. + ListInspectTemplates(ctx context.Context, in *ListInspectTemplatesRequest, opts ...grpc.CallOption) (*ListInspectTemplatesResponse, error) + // Deletes inspect templates. + DeleteInspectTemplate(ctx context.Context, in *DeleteInspectTemplateRequest, opts ...grpc.CallOption) (*google_protobuf3.Empty, error) + // Creates an Deidentify template for re-using frequently used configuration + // for Deidentifying content, images, and storage. + CreateDeidentifyTemplate(ctx context.Context, in *CreateDeidentifyTemplateRequest, opts ...grpc.CallOption) (*DeidentifyTemplate, error) + // Updates the inspect template. + UpdateDeidentifyTemplate(ctx context.Context, in *UpdateDeidentifyTemplateRequest, opts ...grpc.CallOption) (*DeidentifyTemplate, error) + // Gets an inspect template. + GetDeidentifyTemplate(ctx context.Context, in *GetDeidentifyTemplateRequest, opts ...grpc.CallOption) (*DeidentifyTemplate, error) + // Lists inspect templates. + ListDeidentifyTemplates(ctx context.Context, in *ListDeidentifyTemplatesRequest, opts ...grpc.CallOption) (*ListDeidentifyTemplatesResponse, error) + // Deletes inspect templates. + DeleteDeidentifyTemplate(ctx context.Context, in *DeleteDeidentifyTemplateRequest, opts ...grpc.CallOption) (*google_protobuf3.Empty, error) + // Lists DlpJobs that match the specified filter in the request. + ListDlpJobs(ctx context.Context, in *ListDlpJobsRequest, opts ...grpc.CallOption) (*ListDlpJobsResponse, error) + // Gets the latest state of a long-running DlpJob. + GetDlpJob(ctx context.Context, in *GetDlpJobRequest, opts ...grpc.CallOption) (*DlpJob, error) + // Deletes a long-running DlpJob. This method indicates that the client is + // no longer interested in the DlpJob result. The job will be cancelled if + // possible. + DeleteDlpJob(ctx context.Context, in *DeleteDlpJobRequest, opts ...grpc.CallOption) (*google_protobuf3.Empty, error) + // Starts asynchronous cancellation on a long-running DlpJob. The server + // makes a best effort to cancel the DlpJob, but success is not + // guaranteed. + CancelDlpJob(ctx context.Context, in *CancelDlpJobRequest, opts ...grpc.CallOption) (*google_protobuf3.Empty, error) +} + +type dlpServiceClient struct { + cc *grpc.ClientConn +} + +func NewDlpServiceClient(cc *grpc.ClientConn) DlpServiceClient { + return &dlpServiceClient{cc} +} + +func (c *dlpServiceClient) InspectContent(ctx context.Context, in *InspectContentRequest, opts ...grpc.CallOption) (*InspectContentResponse, error) { + out := new(InspectContentResponse) + err := grpc.Invoke(ctx, "/google.privacy.dlp.v2beta2.DlpService/InspectContent", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *dlpServiceClient) RedactImage(ctx context.Context, in *RedactImageRequest, opts ...grpc.CallOption) (*RedactImageResponse, error) { + out := new(RedactImageResponse) + err := grpc.Invoke(ctx, "/google.privacy.dlp.v2beta2.DlpService/RedactImage", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *dlpServiceClient) DeidentifyContent(ctx context.Context, in *DeidentifyContentRequest, opts ...grpc.CallOption) (*DeidentifyContentResponse, error) { + out := new(DeidentifyContentResponse) + err := grpc.Invoke(ctx, "/google.privacy.dlp.v2beta2.DlpService/DeidentifyContent", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *dlpServiceClient) ReidentifyContent(ctx context.Context, in *ReidentifyContentRequest, opts ...grpc.CallOption) (*ReidentifyContentResponse, error) { + out := new(ReidentifyContentResponse) + err := grpc.Invoke(ctx, "/google.privacy.dlp.v2beta2.DlpService/ReidentifyContent", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *dlpServiceClient) InspectDataSource(ctx context.Context, in *InspectDataSourceRequest, opts ...grpc.CallOption) (*DlpJob, error) { + out := new(DlpJob) + err := grpc.Invoke(ctx, "/google.privacy.dlp.v2beta2.DlpService/InspectDataSource", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *dlpServiceClient) AnalyzeDataSourceRisk(ctx context.Context, in *AnalyzeDataSourceRiskRequest, opts ...grpc.CallOption) (*DlpJob, error) { + out := new(DlpJob) + err := grpc.Invoke(ctx, "/google.privacy.dlp.v2beta2.DlpService/AnalyzeDataSourceRisk", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *dlpServiceClient) ListInfoTypes(ctx context.Context, in *ListInfoTypesRequest, opts ...grpc.CallOption) (*ListInfoTypesResponse, error) { + out := new(ListInfoTypesResponse) + err := grpc.Invoke(ctx, "/google.privacy.dlp.v2beta2.DlpService/ListInfoTypes", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *dlpServiceClient) CreateInspectTemplate(ctx context.Context, in *CreateInspectTemplateRequest, opts ...grpc.CallOption) (*InspectTemplate, error) { + out := new(InspectTemplate) + err := grpc.Invoke(ctx, "/google.privacy.dlp.v2beta2.DlpService/CreateInspectTemplate", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *dlpServiceClient) UpdateInspectTemplate(ctx context.Context, in *UpdateInspectTemplateRequest, opts ...grpc.CallOption) (*InspectTemplate, error) { + out := new(InspectTemplate) + err := grpc.Invoke(ctx, "/google.privacy.dlp.v2beta2.DlpService/UpdateInspectTemplate", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *dlpServiceClient) GetInspectTemplate(ctx context.Context, in *GetInspectTemplateRequest, opts ...grpc.CallOption) (*InspectTemplate, error) { + out := new(InspectTemplate) + err := grpc.Invoke(ctx, "/google.privacy.dlp.v2beta2.DlpService/GetInspectTemplate", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *dlpServiceClient) ListInspectTemplates(ctx context.Context, in *ListInspectTemplatesRequest, opts ...grpc.CallOption) (*ListInspectTemplatesResponse, error) { + out := new(ListInspectTemplatesResponse) + err := grpc.Invoke(ctx, "/google.privacy.dlp.v2beta2.DlpService/ListInspectTemplates", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *dlpServiceClient) DeleteInspectTemplate(ctx context.Context, in *DeleteInspectTemplateRequest, opts ...grpc.CallOption) (*google_protobuf3.Empty, error) { + out := new(google_protobuf3.Empty) + err := grpc.Invoke(ctx, "/google.privacy.dlp.v2beta2.DlpService/DeleteInspectTemplate", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *dlpServiceClient) CreateDeidentifyTemplate(ctx context.Context, in *CreateDeidentifyTemplateRequest, opts ...grpc.CallOption) (*DeidentifyTemplate, error) { + out := new(DeidentifyTemplate) + err := grpc.Invoke(ctx, "/google.privacy.dlp.v2beta2.DlpService/CreateDeidentifyTemplate", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *dlpServiceClient) UpdateDeidentifyTemplate(ctx context.Context, in *UpdateDeidentifyTemplateRequest, opts ...grpc.CallOption) (*DeidentifyTemplate, error) { + out := new(DeidentifyTemplate) + err := grpc.Invoke(ctx, "/google.privacy.dlp.v2beta2.DlpService/UpdateDeidentifyTemplate", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *dlpServiceClient) GetDeidentifyTemplate(ctx context.Context, in *GetDeidentifyTemplateRequest, opts ...grpc.CallOption) (*DeidentifyTemplate, error) { + out := new(DeidentifyTemplate) + err := grpc.Invoke(ctx, "/google.privacy.dlp.v2beta2.DlpService/GetDeidentifyTemplate", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *dlpServiceClient) ListDeidentifyTemplates(ctx context.Context, in *ListDeidentifyTemplatesRequest, opts ...grpc.CallOption) (*ListDeidentifyTemplatesResponse, error) { + out := new(ListDeidentifyTemplatesResponse) + err := grpc.Invoke(ctx, "/google.privacy.dlp.v2beta2.DlpService/ListDeidentifyTemplates", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *dlpServiceClient) DeleteDeidentifyTemplate(ctx context.Context, in *DeleteDeidentifyTemplateRequest, opts ...grpc.CallOption) (*google_protobuf3.Empty, error) { + out := new(google_protobuf3.Empty) + err := grpc.Invoke(ctx, "/google.privacy.dlp.v2beta2.DlpService/DeleteDeidentifyTemplate", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *dlpServiceClient) ListDlpJobs(ctx context.Context, in *ListDlpJobsRequest, opts ...grpc.CallOption) (*ListDlpJobsResponse, error) { + out := new(ListDlpJobsResponse) + err := grpc.Invoke(ctx, "/google.privacy.dlp.v2beta2.DlpService/ListDlpJobs", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *dlpServiceClient) GetDlpJob(ctx context.Context, in *GetDlpJobRequest, opts ...grpc.CallOption) (*DlpJob, error) { + out := new(DlpJob) + err := grpc.Invoke(ctx, "/google.privacy.dlp.v2beta2.DlpService/GetDlpJob", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *dlpServiceClient) DeleteDlpJob(ctx context.Context, in *DeleteDlpJobRequest, opts ...grpc.CallOption) (*google_protobuf3.Empty, error) { + out := new(google_protobuf3.Empty) + err := grpc.Invoke(ctx, "/google.privacy.dlp.v2beta2.DlpService/DeleteDlpJob", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *dlpServiceClient) CancelDlpJob(ctx context.Context, in *CancelDlpJobRequest, opts ...grpc.CallOption) (*google_protobuf3.Empty, error) { + out := new(google_protobuf3.Empty) + err := grpc.Invoke(ctx, "/google.privacy.dlp.v2beta2.DlpService/CancelDlpJob", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for DlpService service + +type DlpServiceServer interface { + // Finds potentially sensitive info in content. + // This method has limits on input size, processing time, and output size. + // [How-to guide for text](/dlp/docs/inspecting-text), [How-to guide for + // images](/dlp/docs/inspecting-images) + InspectContent(context.Context, *InspectContentRequest) (*InspectContentResponse, error) + // Redacts potentially sensitive info from an image. + // This method has limits on input size, processing time, and output size. + // [How-to guide](/dlp/docs/redacting-sensitive-data-images) + RedactImage(context.Context, *RedactImageRequest) (*RedactImageResponse, error) + // De-identifies potentially sensitive info from a ContentItem. + // This method has limits on input size and output size. + // [How-to guide](/dlp/docs/deidentify-sensitive-data) + DeidentifyContent(context.Context, *DeidentifyContentRequest) (*DeidentifyContentResponse, error) + // Re-identify content that has been de-identified. + ReidentifyContent(context.Context, *ReidentifyContentRequest) (*ReidentifyContentResponse, error) + // Schedules a job scanning content in a Google Cloud Platform data + // repository. [How-to guide](/dlp/docs/inspecting-storage) + InspectDataSource(context.Context, *InspectDataSourceRequest) (*DlpJob, error) + // Schedules a job to compute risk analysis metrics over content in a Google + // Cloud Platform repository. [How-to guide}(/dlp/docs/compute-risk-analysis) + AnalyzeDataSourceRisk(context.Context, *AnalyzeDataSourceRiskRequest) (*DlpJob, error) + // Returns sensitive information types DLP supports. + ListInfoTypes(context.Context, *ListInfoTypesRequest) (*ListInfoTypesResponse, error) + // Creates an inspect template for re-using frequently used configuration + // for inspecting content, images, and storage. + CreateInspectTemplate(context.Context, *CreateInspectTemplateRequest) (*InspectTemplate, error) + // Updates the inspect template. + UpdateInspectTemplate(context.Context, *UpdateInspectTemplateRequest) (*InspectTemplate, error) + // Gets an inspect template. + GetInspectTemplate(context.Context, *GetInspectTemplateRequest) (*InspectTemplate, error) + // Lists inspect templates. + ListInspectTemplates(context.Context, *ListInspectTemplatesRequest) (*ListInspectTemplatesResponse, error) + // Deletes inspect templates. + DeleteInspectTemplate(context.Context, *DeleteInspectTemplateRequest) (*google_protobuf3.Empty, error) + // Creates an Deidentify template for re-using frequently used configuration + // for Deidentifying content, images, and storage. + CreateDeidentifyTemplate(context.Context, *CreateDeidentifyTemplateRequest) (*DeidentifyTemplate, error) + // Updates the inspect template. + UpdateDeidentifyTemplate(context.Context, *UpdateDeidentifyTemplateRequest) (*DeidentifyTemplate, error) + // Gets an inspect template. + GetDeidentifyTemplate(context.Context, *GetDeidentifyTemplateRequest) (*DeidentifyTemplate, error) + // Lists inspect templates. + ListDeidentifyTemplates(context.Context, *ListDeidentifyTemplatesRequest) (*ListDeidentifyTemplatesResponse, error) + // Deletes inspect templates. + DeleteDeidentifyTemplate(context.Context, *DeleteDeidentifyTemplateRequest) (*google_protobuf3.Empty, error) + // Lists DlpJobs that match the specified filter in the request. + ListDlpJobs(context.Context, *ListDlpJobsRequest) (*ListDlpJobsResponse, error) + // Gets the latest state of a long-running DlpJob. + GetDlpJob(context.Context, *GetDlpJobRequest) (*DlpJob, error) + // Deletes a long-running DlpJob. This method indicates that the client is + // no longer interested in the DlpJob result. The job will be cancelled if + // possible. + DeleteDlpJob(context.Context, *DeleteDlpJobRequest) (*google_protobuf3.Empty, error) + // Starts asynchronous cancellation on a long-running DlpJob. The server + // makes a best effort to cancel the DlpJob, but success is not + // guaranteed. + CancelDlpJob(context.Context, *CancelDlpJobRequest) (*google_protobuf3.Empty, error) +} + +func RegisterDlpServiceServer(s *grpc.Server, srv DlpServiceServer) { + s.RegisterService(&_DlpService_serviceDesc, srv) +} + +func _DlpService_InspectContent_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(InspectContentRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DlpServiceServer).InspectContent(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.privacy.dlp.v2beta2.DlpService/InspectContent", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DlpServiceServer).InspectContent(ctx, req.(*InspectContentRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _DlpService_RedactImage_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RedactImageRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DlpServiceServer).RedactImage(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.privacy.dlp.v2beta2.DlpService/RedactImage", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DlpServiceServer).RedactImage(ctx, req.(*RedactImageRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _DlpService_DeidentifyContent_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeidentifyContentRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DlpServiceServer).DeidentifyContent(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.privacy.dlp.v2beta2.DlpService/DeidentifyContent", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DlpServiceServer).DeidentifyContent(ctx, req.(*DeidentifyContentRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _DlpService_ReidentifyContent_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ReidentifyContentRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DlpServiceServer).ReidentifyContent(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.privacy.dlp.v2beta2.DlpService/ReidentifyContent", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DlpServiceServer).ReidentifyContent(ctx, req.(*ReidentifyContentRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _DlpService_InspectDataSource_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(InspectDataSourceRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DlpServiceServer).InspectDataSource(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.privacy.dlp.v2beta2.DlpService/InspectDataSource", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DlpServiceServer).InspectDataSource(ctx, req.(*InspectDataSourceRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _DlpService_AnalyzeDataSourceRisk_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AnalyzeDataSourceRiskRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DlpServiceServer).AnalyzeDataSourceRisk(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.privacy.dlp.v2beta2.DlpService/AnalyzeDataSourceRisk", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DlpServiceServer).AnalyzeDataSourceRisk(ctx, req.(*AnalyzeDataSourceRiskRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _DlpService_ListInfoTypes_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListInfoTypesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DlpServiceServer).ListInfoTypes(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.privacy.dlp.v2beta2.DlpService/ListInfoTypes", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DlpServiceServer).ListInfoTypes(ctx, req.(*ListInfoTypesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _DlpService_CreateInspectTemplate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateInspectTemplateRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DlpServiceServer).CreateInspectTemplate(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.privacy.dlp.v2beta2.DlpService/CreateInspectTemplate", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DlpServiceServer).CreateInspectTemplate(ctx, req.(*CreateInspectTemplateRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _DlpService_UpdateInspectTemplate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdateInspectTemplateRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DlpServiceServer).UpdateInspectTemplate(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.privacy.dlp.v2beta2.DlpService/UpdateInspectTemplate", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DlpServiceServer).UpdateInspectTemplate(ctx, req.(*UpdateInspectTemplateRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _DlpService_GetInspectTemplate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetInspectTemplateRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DlpServiceServer).GetInspectTemplate(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.privacy.dlp.v2beta2.DlpService/GetInspectTemplate", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DlpServiceServer).GetInspectTemplate(ctx, req.(*GetInspectTemplateRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _DlpService_ListInspectTemplates_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListInspectTemplatesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DlpServiceServer).ListInspectTemplates(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.privacy.dlp.v2beta2.DlpService/ListInspectTemplates", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DlpServiceServer).ListInspectTemplates(ctx, req.(*ListInspectTemplatesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _DlpService_DeleteInspectTemplate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteInspectTemplateRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DlpServiceServer).DeleteInspectTemplate(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.privacy.dlp.v2beta2.DlpService/DeleteInspectTemplate", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DlpServiceServer).DeleteInspectTemplate(ctx, req.(*DeleteInspectTemplateRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _DlpService_CreateDeidentifyTemplate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateDeidentifyTemplateRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DlpServiceServer).CreateDeidentifyTemplate(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.privacy.dlp.v2beta2.DlpService/CreateDeidentifyTemplate", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DlpServiceServer).CreateDeidentifyTemplate(ctx, req.(*CreateDeidentifyTemplateRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _DlpService_UpdateDeidentifyTemplate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdateDeidentifyTemplateRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DlpServiceServer).UpdateDeidentifyTemplate(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.privacy.dlp.v2beta2.DlpService/UpdateDeidentifyTemplate", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DlpServiceServer).UpdateDeidentifyTemplate(ctx, req.(*UpdateDeidentifyTemplateRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _DlpService_GetDeidentifyTemplate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetDeidentifyTemplateRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DlpServiceServer).GetDeidentifyTemplate(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.privacy.dlp.v2beta2.DlpService/GetDeidentifyTemplate", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DlpServiceServer).GetDeidentifyTemplate(ctx, req.(*GetDeidentifyTemplateRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _DlpService_ListDeidentifyTemplates_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListDeidentifyTemplatesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DlpServiceServer).ListDeidentifyTemplates(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.privacy.dlp.v2beta2.DlpService/ListDeidentifyTemplates", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DlpServiceServer).ListDeidentifyTemplates(ctx, req.(*ListDeidentifyTemplatesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _DlpService_DeleteDeidentifyTemplate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteDeidentifyTemplateRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DlpServiceServer).DeleteDeidentifyTemplate(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.privacy.dlp.v2beta2.DlpService/DeleteDeidentifyTemplate", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DlpServiceServer).DeleteDeidentifyTemplate(ctx, req.(*DeleteDeidentifyTemplateRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _DlpService_ListDlpJobs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListDlpJobsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DlpServiceServer).ListDlpJobs(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.privacy.dlp.v2beta2.DlpService/ListDlpJobs", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DlpServiceServer).ListDlpJobs(ctx, req.(*ListDlpJobsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _DlpService_GetDlpJob_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetDlpJobRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DlpServiceServer).GetDlpJob(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.privacy.dlp.v2beta2.DlpService/GetDlpJob", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DlpServiceServer).GetDlpJob(ctx, req.(*GetDlpJobRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _DlpService_DeleteDlpJob_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteDlpJobRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DlpServiceServer).DeleteDlpJob(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.privacy.dlp.v2beta2.DlpService/DeleteDlpJob", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DlpServiceServer).DeleteDlpJob(ctx, req.(*DeleteDlpJobRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _DlpService_CancelDlpJob_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CancelDlpJobRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DlpServiceServer).CancelDlpJob(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/google.privacy.dlp.v2beta2.DlpService/CancelDlpJob", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DlpServiceServer).CancelDlpJob(ctx, req.(*CancelDlpJobRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _DlpService_serviceDesc = grpc.ServiceDesc{ + ServiceName: "google.privacy.dlp.v2beta2.DlpService", + HandlerType: (*DlpServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "InspectContent", + Handler: _DlpService_InspectContent_Handler, + }, + { + MethodName: "RedactImage", + Handler: _DlpService_RedactImage_Handler, + }, + { + MethodName: "DeidentifyContent", + Handler: _DlpService_DeidentifyContent_Handler, + }, + { + MethodName: "ReidentifyContent", + Handler: _DlpService_ReidentifyContent_Handler, + }, + { + MethodName: "InspectDataSource", + Handler: _DlpService_InspectDataSource_Handler, + }, + { + MethodName: "AnalyzeDataSourceRisk", + Handler: _DlpService_AnalyzeDataSourceRisk_Handler, + }, + { + MethodName: "ListInfoTypes", + Handler: _DlpService_ListInfoTypes_Handler, + }, + { + MethodName: "CreateInspectTemplate", + Handler: _DlpService_CreateInspectTemplate_Handler, + }, + { + MethodName: "UpdateInspectTemplate", + Handler: _DlpService_UpdateInspectTemplate_Handler, + }, + { + MethodName: "GetInspectTemplate", + Handler: _DlpService_GetInspectTemplate_Handler, + }, + { + MethodName: "ListInspectTemplates", + Handler: _DlpService_ListInspectTemplates_Handler, + }, + { + MethodName: "DeleteInspectTemplate", + Handler: _DlpService_DeleteInspectTemplate_Handler, + }, + { + MethodName: "CreateDeidentifyTemplate", + Handler: _DlpService_CreateDeidentifyTemplate_Handler, + }, + { + MethodName: "UpdateDeidentifyTemplate", + Handler: _DlpService_UpdateDeidentifyTemplate_Handler, + }, + { + MethodName: "GetDeidentifyTemplate", + Handler: _DlpService_GetDeidentifyTemplate_Handler, + }, + { + MethodName: "ListDeidentifyTemplates", + Handler: _DlpService_ListDeidentifyTemplates_Handler, + }, + { + MethodName: "DeleteDeidentifyTemplate", + Handler: _DlpService_DeleteDeidentifyTemplate_Handler, + }, + { + MethodName: "ListDlpJobs", + Handler: _DlpService_ListDlpJobs_Handler, + }, + { + MethodName: "GetDlpJob", + Handler: _DlpService_GetDlpJob_Handler, + }, + { + MethodName: "DeleteDlpJob", + Handler: _DlpService_DeleteDlpJob_Handler, + }, + { + MethodName: "CancelDlpJob", + Handler: _DlpService_CancelDlpJob_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "google/privacy/dlp/v2beta2/dlp.proto", +} + +func init() { proto.RegisterFile("google/privacy/dlp/v2beta2/dlp.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 6587 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x7d, 0x6b, 0x6c, 0x1b, 0xd9, + 0x75, 0xb0, 0x86, 0x14, 0x25, 0xf2, 0x90, 0x94, 0xa8, 0xab, 0x87, 0x65, 0xda, 0x5e, 0x7b, 0x67, + 0x77, 0x1d, 0xaf, 0x77, 0x23, 0x65, 0xb5, 0xeb, 0x38, 0x6b, 0x7f, 0xde, 0x2c, 0x45, 0xd1, 0x96, + 0x6c, 0x49, 0xd4, 0x0e, 0x29, 0xaf, 0x9d, 0xdd, 0x6f, 0xe7, 0x1b, 0x91, 0x57, 0xd4, 0xac, 0xc8, + 0x19, 0x7a, 0x66, 0x68, 0x49, 0x9b, 0x2f, 0x5f, 0xbe, 0xb6, 0x48, 0x91, 0x34, 0x40, 0x1f, 0x48, + 0x80, 0x2d, 0x90, 0x02, 0x49, 0x80, 0x04, 0x48, 0x82, 0x22, 0x7d, 0xa4, 0x68, 0xd1, 0x3c, 0x80, + 0x34, 0x41, 0xd1, 0xf7, 0x8f, 0x22, 0x40, 0x81, 0xa2, 0x28, 0x5a, 0xb4, 0x05, 0x8a, 0x3e, 0x50, + 0x14, 0xfd, 0xd1, 0x7f, 0x05, 0x8a, 0xfb, 0x98, 0x27, 0x87, 0x43, 0x52, 0x92, 0xd1, 0x36, 0xff, + 0x38, 0xe7, 0x9e, 0x73, 0xee, 0xb9, 0xe7, 0x9e, 0x7b, 0xee, 0xb9, 0xe7, 0x3e, 0x08, 0xcf, 0x36, + 0x74, 0xbd, 0xd1, 0xc4, 0x8b, 0x6d, 0x43, 0x7d, 0xac, 0xd4, 0x8e, 0x16, 0xeb, 0xcd, 0xf6, 0xe2, + 0xe3, 0xa5, 0x1d, 0x6c, 0x29, 0x4b, 0xe4, 0xf7, 0x42, 0xdb, 0xd0, 0x2d, 0x1d, 0xe5, 0x19, 0xd6, + 0x02, 0xc7, 0x5a, 0x20, 0x25, 0x1c, 0x2b, 0x7f, 0x9e, 0x73, 0x50, 0xda, 0xea, 0xa2, 0xa2, 0x69, + 0xba, 0xa5, 0x58, 0xaa, 0xae, 0x99, 0x8c, 0x32, 0x7f, 0x25, 0x82, 0xbf, 0x69, 0xe9, 0x86, 0xd2, + 0xc0, 0x1c, 0xf3, 0x29, 0x07, 0x53, 0xb7, 0xf4, 0x9d, 0xce, 0xee, 0x62, 0xbd, 0x63, 0x50, 0x56, + 0xbc, 0xfc, 0x5c, 0xb0, 0x1c, 0xb7, 0xda, 0xd6, 0x11, 0x2f, 0xbc, 0x14, 0x2c, 0xdc, 0x55, 0x71, + 0xb3, 0x2e, 0xb7, 0x14, 0x73, 0x9f, 0x63, 0x5c, 0x0c, 0x62, 0x58, 0x6a, 0x0b, 0x9b, 0x96, 0xd2, + 0xe2, 0x6d, 0xcc, 0x9f, 0xe1, 0x08, 0x46, 0xbb, 0xb6, 0x68, 0x5a, 0x8a, 0xd5, 0xb1, 0x9b, 0x30, + 0xc7, 0x0b, 0xac, 0xa3, 0x36, 0x5e, 0xac, 0x2b, 0x16, 0x0e, 0x08, 0xc4, 0xe1, 0x47, 0xfa, 0xee, + 0x01, 0xc6, 0xfb, 0x61, 0x85, 0xa4, 0x2a, 0x7d, 0xb7, 0xae, 0x70, 0x69, 0xc5, 0x5f, 0x1c, 0x83, + 0xec, 0x9a, 0x66, 0xb6, 0x71, 0xcd, 0x2a, 0xea, 0xda, 0xae, 0xda, 0x40, 0x45, 0x00, 0x55, 0xdb, + 0xd5, 0x65, 0x82, 0x6e, 0xce, 0x0b, 0x97, 0xe2, 0x57, 0xd2, 0x4b, 0xcf, 0x2e, 0xf4, 0xd6, 0xfa, + 0xc2, 0x9a, 0xb6, 0xab, 0x57, 0x8f, 0xda, 0x58, 0x4a, 0xa9, 0xfc, 0x97, 0x89, 0x36, 0x60, 0xa2, + 0xa5, 0x6a, 0x72, 0x53, 0xdd, 0xc7, 0x4d, 0x75, 0x4f, 0xd7, 0xeb, 0xf3, 0xb1, 0x4b, 0xc2, 0x95, + 0x89, 0xa5, 0xcb, 0x51, 0x8c, 0xd6, 0x1d, 0x6c, 0x29, 0xdb, 0x52, 0x35, 0xf7, 0x13, 0x95, 0x61, + 0xac, 0xa9, 0xb6, 0x54, 0xcb, 0x9c, 0x8f, 0x5f, 0x12, 0xae, 0xa4, 0x97, 0xae, 0x47, 0xcb, 0xe3, + 0x69, 0xce, 0xc2, 0x6d, 0x55, 0xab, 0xab, 0x5a, 0x63, 0x9d, 0x92, 0x4b, 0x9c, 0x0d, 0x7a, 0x06, + 0xb2, 0xaa, 0x56, 0x6b, 0x76, 0xea, 0x58, 0x7e, 0xd4, 0xd1, 0x2d, 0x3c, 0x3f, 0x7a, 0x49, 0xb8, + 0x92, 0x94, 0x32, 0x1c, 0xf8, 0x06, 0x81, 0xa1, 0x17, 0x01, 0xe1, 0x43, 0x86, 0xe4, 0xd1, 0x48, + 0x82, 0x62, 0xe6, 0x78, 0xc9, 0x9a, 0xd3, 0xe4, 0xfb, 0x30, 0x55, 0xeb, 0x98, 0x96, 0xde, 0xf2, + 0x22, 0x8f, 0x51, 0xf5, 0x5d, 0x8d, 0x12, 0xb7, 0x48, 0x89, 0x1c, 0x25, 0x4e, 0xd6, 0x7c, 0xdf, + 0x66, 0xfe, 0xdf, 0x63, 0x90, 0xf5, 0x35, 0x02, 0xbd, 0x04, 0xb3, 0x2d, 0xe5, 0x50, 0xde, 0x65, + 0x40, 0x53, 0x6e, 0x63, 0x43, 0x56, 0x2d, 0xdc, 0x9a, 0x17, 0x2e, 0x09, 0x57, 0x12, 0x12, 0x6a, + 0x29, 0x87, 0x9c, 0xc0, 0xdc, 0xc2, 0xc6, 0x9a, 0x85, 0x5b, 0xe8, 0x3a, 0xcc, 0x77, 0x91, 0x18, + 0xf8, 0x51, 0x07, 0x9b, 0x16, 0xed, 0x99, 0x84, 0x34, 0xeb, 0xa7, 0x92, 0x58, 0x21, 0xfa, 0x09, + 0x01, 0xf2, 0xdd, 0x95, 0xd9, 0x0d, 0x9c, 0x8f, 0xd3, 0xf6, 0x95, 0x8e, 0xd9, 0x1d, 0x8e, 0xe9, + 0xd0, 0x4f, 0x69, 0x2e, 0x20, 0x38, 0x2f, 0xcc, 0x77, 0x88, 0x89, 0x7a, 0x10, 0x51, 0x01, 0x52, + 0xae, 0x08, 0x02, 0xb5, 0x88, 0xc1, 0x2c, 0x34, 0x69, 0x5b, 0x28, 0x7a, 0x1a, 0x32, 0xde, 0x66, + 0x71, 0x25, 0xa4, 0x3d, 0x12, 0x88, 0xef, 0x0b, 0x90, 0x2e, 0xea, 0x9a, 0x85, 0x35, 0x8b, 0xea, + 0x10, 0xc1, 0xa8, 0x53, 0x61, 0x4a, 0xa2, 0xbf, 0xd1, 0x0c, 0x8c, 0xd6, 0x15, 0x4b, 0xa1, 0xe4, + 0x99, 0xd5, 0x11, 0x89, 0x7e, 0xa1, 0x39, 0x48, 0x3c, 0x56, 0x9a, 0x1d, 0x4c, 0xad, 0x35, 0xb5, + 0x3a, 0x22, 0xb1, 0x4f, 0xf4, 0x2a, 0x24, 0x2c, 0x65, 0xa7, 0xc9, 0xac, 0x2d, 0xbd, 0xf4, 0x74, + 0x94, 0xcc, 0x55, 0x82, 0x48, 0x48, 0x29, 0xc5, 0x72, 0x1a, 0x52, 0x84, 0x35, 0xed, 0x67, 0xf1, + 0x87, 0x02, 0x24, 0x68, 0x39, 0xba, 0x05, 0xe3, 0x7b, 0x58, 0xa9, 0x63, 0xc3, 0x1e, 0xa9, 0xcf, + 0x44, 0xf1, 0xbc, 0x4d, 0x3c, 0xd1, 0x5a, 0x5d, 0xb2, 0x69, 0xd0, 0xab, 0x30, 0x6a, 0xe8, 0x07, + 0xa4, 0xf5, 0x84, 0xf6, 0xb9, 0xbe, 0xf2, 0x2c, 0x48, 0xfa, 0x81, 0x44, 0x49, 0xf2, 0xaf, 0x43, + 0x5c, 0xd2, 0x0f, 0xd0, 0xab, 0x30, 0x46, 0xdb, 0x66, 0xd7, 0x1f, 0xd9, 0xa6, 0xfb, 0x04, 0x53, + 0xe2, 0x04, 0xe2, 0x27, 0x1d, 0xcf, 0x23, 0x61, 0xb3, 0xd3, 0xb4, 0xd0, 0x47, 0x21, 0xe9, 0xf4, + 0xc7, 0x40, 0xad, 0xa1, 0xb8, 0x92, 0x43, 0x84, 0x3e, 0x08, 0xc8, 0xb1, 0x53, 0xcb, 0xe8, 0x68, + 0x35, 0xc5, 0xc2, 0xcc, 0xf3, 0x24, 0xa5, 0x29, 0xbb, 0xa4, 0x6a, 0x17, 0x88, 0x5f, 0x8f, 0xc1, + 0x38, 0x67, 0x82, 0x66, 0x20, 0xc1, 0x1c, 0x01, 0xeb, 0x5d, 0xf6, 0xe1, 0x37, 0xb4, 0xd8, 0xb1, + 0x0c, 0xed, 0x36, 0x80, 0xc7, 0x0b, 0xc6, 0x87, 0xf2, 0x82, 0x1e, 0x4a, 0xf4, 0x3a, 0x24, 0x9b, + 0x7a, 0x8d, 0xce, 0x42, 0xdc, 0x7c, 0x22, 0x25, 0x59, 0xe7, 0xb8, 0x92, 0x43, 0x85, 0x6e, 0x42, + 0xba, 0x66, 0x60, 0xc5, 0xc2, 0x32, 0x99, 0x04, 0xe6, 0xc7, 0x28, 0x93, 0xbc, 0xcb, 0x84, 0x4d, + 0x46, 0x0b, 0x55, 0x7b, 0x32, 0x92, 0x80, 0xa1, 0x13, 0x80, 0xf8, 0xdd, 0x38, 0x24, 0x6d, 0x9e, + 0xe8, 0x75, 0x80, 0x9d, 0x23, 0x0b, 0xcb, 0x86, 0xa2, 0x35, 0xec, 0x01, 0x18, 0xd9, 0xf1, 0x12, + 0x41, 0x94, 0x52, 0x84, 0x88, 0xfe, 0x44, 0x77, 0x61, 0xb2, 0xa6, 0xd7, 0x71, 0x5b, 0x57, 0x35, + 0x8b, 0xb3, 0x89, 0x0d, 0xca, 0x66, 0xc2, 0xa1, 0xb4, 0x79, 0xa5, 0xd5, 0x96, 0xd2, 0xc0, 0xf2, + 0x8e, 0x7e, 0x88, 0x4d, 0xee, 0x92, 0x9e, 0x8f, 0xec, 0x26, 0x82, 0xee, 0x68, 0x08, 0x28, 0xf5, + 0x32, 0x21, 0x46, 0x2b, 0x00, 0x06, 0xae, 0xe9, 0x46, 0x5d, 0xde, 0xc7, 0x47, 0x5c, 0xcf, 0x91, + 0xc3, 0x42, 0xa2, 0xd8, 0xf7, 0xf0, 0x91, 0x94, 0x32, 0xec, 0x9f, 0xe8, 0x35, 0x62, 0xc8, 0x64, + 0xd2, 0x57, 0xeb, 0x74, 0xba, 0x18, 0x74, 0x58, 0xee, 0xb2, 0x1f, 0x68, 0x0b, 0x26, 0xe8, 0xa8, + 0x97, 0x9d, 0x1e, 0x67, 0x9d, 0xf5, 0x7c, 0xdf, 0x01, 0xea, 0x34, 0x2a, 0x6b, 0x79, 0x3f, 0xc5, + 0x17, 0x21, 0xeb, 0x2b, 0x47, 0xe7, 0x20, 0x65, 0xe8, 0x07, 0xb2, 0xaa, 0xd5, 0xf1, 0x21, 0xed, + 0xc1, 0xb8, 0x94, 0x34, 0xf4, 0x83, 0x35, 0xf2, 0x2d, 0x2e, 0x42, 0x82, 0xa9, 0x76, 0x06, 0x12, + 0xa6, 0xa5, 0x18, 0x16, 0xc7, 0x60, 0x1f, 0x28, 0x07, 0x71, 0xac, 0xb1, 0x71, 0x15, 0x97, 0xc8, + 0x4f, 0xb1, 0x06, 0x59, 0x9f, 0x4e, 0x09, 0x8a, 0xa5, 0xb7, 0xf9, 0x84, 0x44, 0x7e, 0x12, 0xef, + 0xd9, 0xc4, 0xbb, 0xf6, 0x6c, 0x43, 0x7f, 0x13, 0xf6, 0x07, 0x6a, 0xdd, 0xda, 0xa3, 0xc3, 0x22, + 0x21, 0xb1, 0x0f, 0x34, 0x07, 0x63, 0x7b, 0x58, 0x6d, 0xec, 0x59, 0x54, 0xff, 0x09, 0x89, 0x7f, + 0x89, 0xef, 0x8f, 0x02, 0x92, 0x70, 0x5d, 0xa9, 0x59, 0xb4, 0x2e, 0x7b, 0x86, 0x9a, 0x83, 0xb1, + 0xb6, 0x62, 0x60, 0xcd, 0xe2, 0x43, 0x97, 0x7f, 0x11, 0x25, 0xaa, 0xcc, 0xbd, 0xc8, 0x35, 0x3a, + 0xf7, 0x70, 0x0b, 0x7b, 0x7e, 0xe0, 0xc9, 0x4a, 0xca, 0xaa, 0xbe, 0xc8, 0xe8, 0x02, 0x30, 0x53, + 0xb1, 0xa7, 0x3e, 0x52, 0x5b, 0x8a, 0x42, 0xe8, 0x48, 0x77, 0x8a, 0xe9, 0x8c, 0x40, 0x64, 0xcf, + 0xf0, 0xe2, 0x15, 0x32, 0x29, 0x7c, 0x1c, 0xce, 0xb0, 0x62, 0x83, 0xb6, 0x41, 0xd5, 0x35, 0x2e, + 0x17, 0x09, 0x29, 0x88, 0xc9, 0x16, 0xa3, 0xed, 0x2c, 0xd8, 0xf0, 0x05, 0xfe, 0xc1, 0x99, 0x71, + 0x91, 0x67, 0xd5, 0x10, 0xa8, 0x99, 0xff, 0x0b, 0x01, 0x66, 0xc2, 0xf0, 0x51, 0xf1, 0x98, 0x53, + 0xe9, 0xea, 0x88, 0xc7, 0xc7, 0x5d, 0x81, 0x49, 0xd6, 0x28, 0x59, 0x69, 0x36, 0x65, 0x0b, 0x1f, + 0xb2, 0x6e, 0x4e, 0xae, 0x8e, 0x48, 0x59, 0x56, 0x50, 0x68, 0x36, 0xab, 0xf8, 0xd0, 0x22, 0xe3, + 0xde, 0xdb, 0xfc, 0xa6, 0x6e, 0xf0, 0x88, 0x2e, 0x72, 0xdc, 0x17, 0x09, 0xa2, 0x34, 0x61, 0xb8, + 0xb2, 0x37, 0x75, 0x63, 0x39, 0x09, 0x63, 0x96, 0x62, 0x34, 0xb0, 0x25, 0x16, 0x21, 0x41, 0x41, + 0xc4, 0xec, 0x0c, 0x5c, 0xa7, 0xed, 0x88, 0x49, 0xe4, 0x27, 0x31, 0xb1, 0x86, 0x81, 0xb1, 0x46, + 0x05, 0x8a, 0x49, 0xec, 0x83, 0x18, 0xe3, 0x8e, 0x3d, 0x3f, 0xc7, 0x24, 0xfa, 0x5b, 0xac, 0xc1, + 0xb4, 0x4f, 0xc9, 0x66, 0x5b, 0xd7, 0x4c, 0x8c, 0x9e, 0x03, 0x5e, 0x2f, 0xae, 0xcb, 0x54, 0xb7, + 0x94, 0x7b, 0xc6, 0x6e, 0x18, 0xae, 0x53, 0x74, 0x82, 0x86, 0x0f, 0x2d, 0x83, 0xe1, 0x39, 0x1a, + 0x48, 0x49, 0x59, 0x07, 0x4a, 0xda, 0x2f, 0xfe, 0x4c, 0x1c, 0xe6, 0x57, 0xb0, 0x5a, 0xc7, 0x9a, + 0xa5, 0xee, 0x1e, 0xf1, 0xe8, 0xa2, 0x9f, 0x25, 0x3f, 0x84, 0xa9, 0xba, 0x43, 0xe3, 0x37, 0xe6, + 0x17, 0xa3, 0xd4, 0xe6, 0xab, 0x88, 0x18, 0x47, 0xae, 0x1e, 0x80, 0x84, 0x0c, 0x92, 0xf8, 0x09, + 0x07, 0xc9, 0x4d, 0x18, 0xa5, 0xb1, 0x28, 0xf3, 0x9d, 0x1f, 0x88, 0xee, 0x56, 0x27, 0xb8, 0x92, + 0x28, 0x11, 0x5a, 0x82, 0x59, 0x5b, 0x1c, 0x0b, 0xb7, 0xda, 0x4d, 0x32, 0x59, 0x69, 0x4a, 0x0b, + 0x53, 0x2f, 0x9a, 0x92, 0xa6, 0x79, 0x61, 0x95, 0x97, 0x6d, 0x2a, 0x2d, 0x8c, 0x3e, 0x02, 0xf3, + 0x1e, 0xed, 0xf8, 0xc9, 0xc6, 0x28, 0xd9, 0x9c, 0x5b, 0xee, 0xa5, 0x14, 0xbf, 0x26, 0xc0, 0xd9, + 0x90, 0xce, 0xe0, 0x1d, 0x6f, 0x37, 0x44, 0x38, 0x4e, 0x43, 0x36, 0x21, 0xa9, 0x3f, 0xc6, 0xc6, + 0x63, 0x15, 0x1f, 0xf0, 0x9e, 0x5a, 0x8a, 0xf4, 0xdd, 0x86, 0xa2, 0x99, 0xbb, 0xba, 0xd1, 0xa2, + 0xde, 0xb3, 0xcc, 0x29, 0x25, 0x87, 0x07, 0xb5, 0x1b, 0xe9, 0x18, 0x76, 0x63, 0x9c, 0x8e, 0xdd, + 0x18, 0x3f, 0x9e, 0x76, 0x63, 0xf4, 0xb1, 0x1b, 0xa3, 0xb7, 0xdd, 0x48, 0xff, 0x33, 0xec, 0xe6, + 0xdf, 0x04, 0x98, 0x75, 0xd5, 0x3e, 0x88, 0xd1, 0x9c, 0xfe, 0xb4, 0x69, 0x2b, 0x24, 0x7e, 0xaa, + 0x3d, 0x3b, 0xda, 0xb3, 0x67, 0xc5, 0xb7, 0x60, 0x2e, 0xd8, 0x66, 0xde, 0x37, 0x05, 0x18, 0x33, + 0xe8, 0x5a, 0x83, 0xf7, 0xce, 0x20, 0x8d, 0x62, 0x8b, 0x13, 0x89, 0x13, 0x8a, 0x9f, 0x84, 0x79, + 0x5e, 0x40, 0x66, 0xf5, 0x8a, 0xde, 0x31, 0x6a, 0x7d, 0x43, 0x91, 0x7b, 0x00, 0xef, 0xea, 0x3b, + 0x43, 0x8c, 0x40, 0x5e, 0xc3, 0x5d, 0x7d, 0x87, 0xab, 0x34, 0xf5, 0xae, 0xfd, 0x53, 0xfc, 0x3f, + 0x30, 0x5d, 0xee, 0x58, 0xed, 0x8e, 0x55, 0x61, 0x39, 0x2b, 0xae, 0xe5, 0x82, 0xbd, 0xb6, 0x1c, + 0xa0, 0x65, 0xcb, 0x6a, 0xe3, 0x8d, 0x0e, 0x36, 0x8e, 0x02, 0x6b, 0xcc, 0x31, 0xb6, 0xc0, 0x15, + 0x5b, 0x80, 0xec, 0x69, 0xbe, 0x62, 0x29, 0x96, 0x6a, 0x5a, 0x6a, 0xcd, 0x3c, 0x8d, 0x45, 0xf7, + 0x0c, 0x24, 0x6a, 0x7a, 0x47, 0xb3, 0x78, 0xe8, 0xc8, 0x3e, 0xc4, 0x7f, 0x19, 0x0d, 0x51, 0xe9, + 0x0a, 0xb6, 0x14, 0xb5, 0x69, 0x22, 0x83, 0xf8, 0x30, 0xaa, 0x5d, 0x5c, 0x97, 0xf5, 0x36, 0xcd, + 0xe7, 0x71, 0x0d, 0x0e, 0x92, 0x75, 0xe8, 0x62, 0xb8, 0x20, 0xd9, 0xdc, 0xca, 0x8c, 0x19, 0x71, + 0x6e, 0x7e, 0x08, 0xaa, 0x38, 0x56, 0xc2, 0x4c, 0xf6, 0xe6, 0x31, 0x2b, 0xf2, 0xda, 0x4d, 0xfe, + 0xf7, 0x05, 0xc8, 0x05, 0xeb, 0x46, 0x0d, 0x38, 0x6b, 0x6a, 0x4a, 0xdb, 0xdc, 0xd3, 0x2d, 0x39, + 0x68, 0xe6, 0x5c, 0xc7, 0x2f, 0x0c, 0x50, 0xb9, 0x6d, 0xfd, 0xd2, 0x19, 0x9b, 0x5b, 0xa0, 0x20, + 0x60, 0x81, 0xf1, 0x13, 0x59, 0x60, 0xfe, 0x7b, 0x02, 0x8c, 0xf1, 0x25, 0xfb, 0x07, 0x60, 0xb2, + 0x6d, 0xe8, 0x35, 0x6c, 0x9a, 0xb8, 0x2e, 0x93, 0xe5, 0x9d, 0xc9, 0x97, 0x0a, 0x13, 0x0e, 0x78, + 0x99, 0x40, 0xc9, 0x38, 0xb6, 0x74, 0x4b, 0x69, 0xca, 0xd8, 0xb4, 0xd4, 0x16, 0x59, 0x7e, 0x73, + 0x74, 0x66, 0x0a, 0xd3, 0xb4, 0xb0, 0x64, 0x97, 0x31, 0x9a, 0xfb, 0x30, 0xe9, 0x58, 0x9c, 0x6c, + 0x5a, 0x8a, 0x65, 0x2f, 0xee, 0x16, 0x06, 0xb1, 0x3b, 0xd7, 0x74, 0x89, 0x43, 0x72, 0x61, 0xa6, + 0xf8, 0x25, 0x01, 0xa6, 0x6d, 0xac, 0x15, 0x6c, 0xd6, 0x0c, 0x95, 0x76, 0x07, 0x89, 0x0a, 0xa9, + 0x6b, 0xe1, 0x09, 0x1e, 0xf2, 0x1b, 0x3d, 0x0d, 0x99, 0xba, 0x6a, 0xb6, 0x9b, 0xca, 0x11, 0x73, + 0x3b, 0x2c, 0xaa, 0x4b, 0x73, 0x18, 0x9d, 0x48, 0x24, 0xc8, 0x98, 0x9d, 0x76, 0x5b, 0x37, 0x58, + 0xa3, 0xa8, 0x8c, 0x13, 0x4b, 0x8b, 0x03, 0xc9, 0x68, 0xd3, 0x2d, 0x1f, 0x49, 0x69, 0xd3, 0xfd, + 0x10, 0x2b, 0x30, 0xb3, 0xae, 0x9a, 0x96, 0x93, 0x05, 0xb4, 0x3d, 0xcc, 0x33, 0x90, 0x6d, 0x2a, + 0x5a, 0xa3, 0x43, 0xd6, 0x11, 0x64, 0x19, 0xcc, 0x65, 0xcd, 0xd8, 0xc0, 0xa2, 0x5e, 0xc7, 0xc4, + 0x0d, 0xed, 0xaa, 0x4d, 0x0b, 0x1b, 0x5c, 0x5a, 0xfe, 0x25, 0x36, 0x60, 0x36, 0xc0, 0x94, 0xbb, + 0xc5, 0xcd, 0x90, 0x94, 0xef, 0x40, 0xf2, 0x7b, 0xb4, 0xe7, 0xc9, 0xfe, 0x8a, 0x9f, 0x16, 0xe0, + 0x7c, 0x41, 0x53, 0x9a, 0x47, 0xef, 0x61, 0x8f, 0x93, 0x54, 0xcd, 0xfd, 0xfe, 0x93, 0x4f, 0xb7, + 0xa3, 0x7c, 0x29, 0x72, 0x59, 0xa4, 0x9a, 0xfb, 0xb4, 0x26, 0x53, 0x35, 0x43, 0xbd, 0xe5, 0x6f, + 0x09, 0x30, 0x1b, 0x8a, 0x44, 0x26, 0x3a, 0xce, 0x51, 0x6e, 0x61, 0xcb, 0x50, 0x6b, 0x83, 0x78, + 0xce, 0x2d, 0x06, 0xdb, 0xa0, 0x04, 0x52, 0xb6, 0xed, 0xfd, 0x44, 0xeb, 0x90, 0x31, 0x69, 0x53, + 0x65, 0xe6, 0x89, 0x63, 0x43, 0x7a, 0x62, 0x29, 0xcd, 0xc8, 0xe9, 0x87, 0xf8, 0xb7, 0x93, 0x90, + 0xf5, 0x55, 0x87, 0x1e, 0xc3, 0x9c, 0xd6, 0x69, 0x61, 0x43, 0xad, 0x29, 0x4d, 0x36, 0x1e, 0x6c, + 0x4d, 0x31, 0xc9, 0x5f, 0x1b, 0x58, 0xf2, 0x85, 0x4d, 0x9b, 0x0f, 0x1d, 0x11, 0x4c, 0x23, 0xab, + 0x23, 0xd2, 0x8c, 0x16, 0x02, 0x47, 0xff, 0x17, 0xe6, 0x6b, 0x8a, 0x85, 0x1b, 0x7a, 0x48, 0xcd, + 0xac, 0x8d, 0xaf, 0x0f, 0x5e, 0x73, 0xd1, 0xe5, 0xe4, 0xaf, 0x7b, 0xae, 0x16, 0x5a, 0x82, 0xde, + 0x05, 0xb4, 0x2f, 0x2b, 0x9a, 0xae, 0x1d, 0xb5, 0x54, 0xeb, 0xc8, 0xef, 0xc2, 0x6e, 0x0c, 0x5e, + 0xef, 0xbd, 0x82, 0xcd, 0xc2, 0xa9, 0x31, 0xb7, 0x1f, 0x80, 0x91, 0xba, 0x9a, 0x72, 0x5d, 0x7d, + 0x8c, 0x0d, 0xd3, 0x53, 0xd7, 0xe8, 0xb0, 0x75, 0xad, 0xaf, 0xd8, 0x2c, 0xdc, 0xba, 0x9a, 0x01, + 0x18, 0x3a, 0x80, 0x33, 0xfb, 0x72, 0x4b, 0x69, 0xdb, 0x1e, 0xd1, 0x4d, 0x08, 0xf0, 0x9c, 0xd1, + 0x10, 0xdd, 0x79, 0x6f, 0x43, 0x69, 0x97, 0x1c, 0x36, 0x6e, 0x77, 0xee, 0x87, 0xc0, 0xf3, 0x6f, + 0xc0, 0x4c, 0x58, 0xf7, 0xa3, 0x57, 0x21, 0x41, 0x13, 0x50, 0xdc, 0x9a, 0x06, 0x4a, 0x59, 0x31, + 0x8a, 0x7c, 0x05, 0xe6, 0xc2, 0xfb, 0xf5, 0x24, 0x4c, 0xdf, 0x17, 0x20, 0x17, 0xec, 0x35, 0xf4, + 0x3a, 0xa4, 0x1e, 0x75, 0x14, 0x53, 0x95, 0xd5, 0xfa, 0x50, 0x29, 0xef, 0x24, 0xa5, 0x5a, 0xab, + 0xd3, 0x38, 0x86, 0x04, 0xee, 0xd6, 0x91, 0xac, 0xd6, 0x07, 0xc9, 0xe9, 0x96, 0x28, 0x32, 0x61, + 0x81, 0xf9, 0xaf, 0xfc, 0x37, 0x04, 0xc8, 0x05, 0xfb, 0xf8, 0x14, 0x24, 0xab, 0xc2, 0xb4, 0x89, + 0x35, 0x53, 0xb5, 0xd4, 0xc7, 0x58, 0x56, 0x2c, 0xcb, 0x50, 0x77, 0x3a, 0x96, 0xed, 0x46, 0x06, + 0xe2, 0x85, 0x1c, 0xfa, 0x82, 0x4d, 0x9e, 0xff, 0xdc, 0x38, 0xcc, 0x84, 0xd9, 0x07, 0x6a, 0x74, + 0x0b, 0x7c, 0xf7, 0x64, 0x26, 0xb7, 0x50, 0x55, 0x1a, 0x0d, 0x5c, 0xa7, 0xd2, 0x78, 0xda, 0x75, + 0x11, 0xd2, 0x06, 0x6e, 0x30, 0xfb, 0xae, 0xdb, 0x53, 0x28, 0x30, 0x10, 0x9d, 0xb0, 0x0e, 0x21, + 0xa7, 0x74, 0x0e, 0xd5, 0xa6, 0xaa, 0x18, 0x47, 0xcc, 0x77, 0xda, 0x33, 0xfd, 0xc6, 0x09, 0x05, + 0x2a, 0xd8, 0x6c, 0x99, 0x83, 0x9d, 0x54, 0x7c, 0xdf, 0x66, 0xfe, 0x9f, 0x04, 0x48, 0x7b, 0x84, + 0x3e, 0x81, 0xb9, 0xfa, 0x33, 0x69, 0xb1, 0x63, 0x66, 0xd2, 0x2e, 0x02, 0xf0, 0x4d, 0x44, 0x4b, + 0x69, 0x38, 0xdb, 0x47, 0x29, 0x06, 0xab, 0x2a, 0x0d, 0xf4, 0x0a, 0x10, 0x64, 0x6c, 0x18, 0xb8, + 0xce, 0xfd, 0xd2, 0x5c, 0x57, 0x06, 0xbf, 0xd4, 0x6a, 0x5b, 0x47, 0x9c, 0x2d, 0xc5, 0x5c, 0x4e, + 0x40, 0xdc, 0x52, 0x1a, 0xf9, 0x4f, 0xc7, 0x61, 0xc2, 0xaf, 0x11, 0xf4, 0x51, 0x7b, 0xd9, 0x10, + 0x1f, 0x76, 0xb2, 0x62, 0x74, 0xe8, 0xa0, 0xdb, 0x8a, 0x3e, 0x76, 0xaa, 0x9d, 0xb6, 0xf0, 0x06, + 0xb3, 0xa3, 0xa0, 0x55, 0x49, 0x80, 0x0c, 0xdc, 0x54, 0xe8, 0x60, 0xd9, 0xa5, 0x31, 0xbc, 0x56, + 0x3b, 0x1a, 0x66, 0xb0, 0x4c, 0xd9, 0xe4, 0xb7, 0x6d, 0xea, 0xfc, 0x1e, 0x64, 0xbc, 0xb5, 0x9d, + 0xc4, 0x1c, 0x2e, 0xf8, 0x7a, 0x92, 0xd9, 0xbc, 0xdb, 0x8f, 0xce, 0x5a, 0xeb, 0x9b, 0x4f, 0xf5, + 0x08, 0x95, 0xec, 0x05, 0x50, 0x0d, 0xe6, 0xdd, 0x05, 0xd0, 0x49, 0x03, 0x96, 0x39, 0x87, 0x95, + 0x3f, 0xb2, 0x90, 0xc1, 0x2d, 0x91, 0x4f, 0x16, 0xc3, 0xcc, 0x38, 0x8c, 0x2a, 0x6e, 0x30, 0x83, + 0x3e, 0x25, 0x74, 0xc7, 0x2e, 0xbe, 0x35, 0x56, 0xe4, 0x40, 0x8f, 0x52, 0x50, 0x20, 0x94, 0x61, + 0xeb, 0x92, 0xee, 0x50, 0x86, 0xaf, 0x57, 0x3e, 0x2b, 0x84, 0xc5, 0x32, 0x5c, 0x12, 0x36, 0x9e, + 0xca, 0xc7, 0x96, 0x24, 0x38, 0x05, 0x3a, 0xb2, 0x74, 0x85, 0x36, 0x5c, 0x9a, 0x23, 0x7f, 0x68, + 0xc3, 0xc5, 0x60, 0xb3, 0xff, 0xda, 0xb1, 0xc5, 0x70, 0xe7, 0x4c, 0x47, 0x00, 0x4f, 0xa4, 0xe3, + 0x56, 0xed, 0x8d, 0x74, 0x78, 0xd5, 0x63, 0x27, 0xac, 0xda, 0x9d, 0x14, 0xdd, 0xaa, 0x9b, 0x01, + 0x18, 0xfa, 0x69, 0x21, 0x24, 0xf2, 0xe1, 0x02, 0x8c, 0x9f, 0xd0, 0x18, 0xfc, 0xfe, 0xc4, 0x35, + 0x86, 0xfd, 0x10, 0x78, 0xfe, 0x6f, 0x84, 0x60, 0x24, 0xc4, 0x25, 0x7c, 0x0d, 0x52, 0x2d, 0x55, + 0x93, 0xd9, 0x1e, 0xfe, 0x00, 0xdb, 0x9b, 0x6c, 0x5f, 0x3b, 0xd9, 0x52, 0x35, 0xfa, 0x8b, 0xd2, + 0x2b, 0x87, 0x9c, 0x3e, 0x36, 0x38, 0xbd, 0x72, 0xc8, 0xe8, 0xef, 0xc2, 0xe4, 0xa3, 0x8e, 0xa2, + 0x59, 0x6a, 0x13, 0xcb, 0x7c, 0x77, 0x7d, 0x74, 0xd0, 0xdd, 0xf5, 0x09, 0x9b, 0x92, 0x7e, 0x9a, + 0xf9, 0x7f, 0x88, 0x77, 0xc7, 0x66, 0xbc, 0x99, 0xdf, 0x16, 0xe0, 0x69, 0xca, 0xde, 0xf5, 0x9f, + 0xf2, 0x9e, 0x6a, 0x5a, 0x7a, 0xc3, 0x50, 0x5a, 0xf2, 0x4e, 0xa7, 0xb6, 0x8f, 0x2d, 0x7b, 0x73, + 0x4a, 0x3f, 0xe5, 0x51, 0xd1, 0x05, 0x5e, 0xb5, 0x2b, 0x5e, 0xa6, 0xf5, 0x4a, 0x4f, 0x51, 0xc9, + 0x1c, 0xd7, 0x1c, 0x28, 0x36, 0xf3, 0xbf, 0x10, 0x83, 0x8b, 0x7d, 0x78, 0xa0, 0x5b, 0x70, 0x2e, + 0xd8, 0xbe, 0xa6, 0x7e, 0x80, 0x0d, 0x79, 0x47, 0xef, 0x68, 0x75, 0x9e, 0xa9, 0x98, 0xf7, 0x57, + 0xb4, 0x4e, 0x10, 0x96, 0x49, 0x79, 0x18, 0x79, 0xa7, 0xdd, 0x76, 0xc8, 0x63, 0x61, 0xe4, 0xdb, + 0x04, 0x81, 0x91, 0x5f, 0x84, 0x34, 0xd3, 0xa1, 0x6c, 0xaa, 0xef, 0xb1, 0x09, 0x36, 0x2e, 0x01, + 0x03, 0x55, 0xd4, 0xf7, 0x30, 0x2a, 0x43, 0x96, 0x23, 0xf8, 0x3a, 0xf9, 0x6a, 0xdf, 0x4e, 0x76, + 0x6a, 0x93, 0x32, 0x8c, 0x01, 0xef, 0xeb, 0x3f, 0x4e, 0x78, 0x23, 0x66, 0xde, 0xcb, 0xbf, 0x2e, + 0xc0, 0x33, 0xf8, 0x51, 0x47, 0x7d, 0xac, 0x34, 0xb1, 0x56, 0xc3, 0x72, 0xad, 0xa9, 0x98, 0x66, + 0xcf, 0x7e, 0xae, 0x9d, 0x9a, 0xdb, 0xf1, 0x00, 0x82, 0x7d, 0x7b, 0xc9, 0x23, 0x4f, 0x91, 0x88, + 0xd3, 0xd5, 0xbb, 0x5f, 0x14, 0x20, 0xef, 0xd2, 0x97, 0x02, 0xe8, 0xe8, 0x1e, 0xe4, 0x9c, 0xa0, + 0x43, 0x1e, 0xf6, 0xfc, 0xc9, 0x84, 0x1d, 0x42, 0x30, 0xad, 0xa1, 0x57, 0x60, 0xae, 0x5b, 0x3f, + 0xb4, 0xcb, 0x58, 0x0f, 0xcf, 0x04, 0xa5, 0x25, 0x9d, 0x97, 0xff, 0xeb, 0x18, 0x9c, 0xed, 0xd9, + 0x42, 0x74, 0x17, 0xc4, 0x70, 0x9e, 0x21, 0x06, 0xf8, 0x54, 0x18, 0x7f, 0x8f, 0x19, 0xf6, 0xe6, + 0xd5, 0x6d, 0x8d, 0xa1, 0xbc, 0x86, 0xb1, 0xc9, 0xcf, 0x08, 0xe1, 0x46, 0x59, 0x7f, 0x12, 0x76, + 0x11, 0xec, 0xd7, 0x80, 0x39, 0x7f, 0x7a, 0xdc, 0xbb, 0xcc, 0xe2, 0xe6, 0xfc, 0x3b, 0x02, 0xbc, + 0xe0, 0xae, 0x92, 0x06, 0x75, 0x5f, 0xb5, 0x53, 0x9b, 0xd2, 0x3c, 0x80, 0xa0, 0x59, 0x7f, 0xc0, + 0x91, 0xeb, 0x7e, 0xb4, 0xef, 0xfa, 0x7e, 0x0c, 0xf2, 0x2e, 0x9b, 0xff, 0x86, 0xd6, 0x8d, 0x0a, + 0x70, 0x41, 0xeb, 0xb4, 0xe4, 0xba, 0x6a, 0x5a, 0xaa, 0x56, 0xb3, 0xe4, 0x80, 0xc6, 0x4d, 0x6e, + 0x39, 0x79, 0xad, 0xd3, 0x5a, 0xe1, 0x38, 0x15, 0x5f, 0xe3, 0x4d, 0xf4, 0x36, 0xcc, 0x58, 0x7a, + 0xbb, 0x9b, 0x72, 0x78, 0x27, 0x87, 0x2c, 0xbd, 0x1d, 0xe0, 0x9e, 0xff, 0xe7, 0x18, 0x9c, 0xed, + 0xd9, 0x13, 0x68, 0x0b, 0x9e, 0xeb, 0x6d, 0x23, 0xdd, 0x23, 0xf0, 0xe9, 0x1e, 0x1d, 0xe7, 0x19, + 0x84, 0x91, 0x1c, 0xbb, 0xc7, 0x61, 0x2f, 0x8e, 0xff, 0xb5, 0x43, 0x31, 0xc2, 0x96, 0xfb, 0x0c, + 0xc5, 0xff, 0x18, 0x0d, 0x26, 0x11, 0xf8, 0x70, 0xfc, 0x9a, 0x00, 0xf9, 0xae, 0x60, 0xce, 0x19, + 0x85, 0xdc, 0x6c, 0xf7, 0x4f, 0x35, 0x9e, 0x0b, 0x00, 0x83, 0xa3, 0xf0, 0xcc, 0x7e, 0x78, 0x71, + 0xfe, 0x0b, 0x02, 0x9c, 0xf3, 0x93, 0xf2, 0xb5, 0x1e, 0x37, 0xd8, 0x53, 0x1d, 0x76, 0x8b, 0x30, + 0xed, 0xee, 0x74, 0x38, 0x21, 0x3e, 0xb7, 0x0e, 0xe4, 0x14, 0x39, 0xae, 0x30, 0xff, 0x85, 0x18, + 0x5c, 0x88, 0x6c, 0x18, 0x7a, 0x06, 0xb2, 0x24, 0x2a, 0x75, 0x99, 0x31, 0xe3, 0xcd, 0xb4, 0x54, + 0xcd, 0x61, 0x43, 0x91, 0x94, 0xc3, 0xae, 0x1a, 0x33, 0x2d, 0xe5, 0xd0, 0x45, 0x0a, 0x98, 0x5e, + 0xa2, 0xcb, 0xf4, 0x7e, 0xb6, 0xcb, 0xf4, 0xd8, 0x41, 0x66, 0xf5, 0x49, 0x76, 0xa4, 0xaf, 0x37, + 0xfc, 0xf6, 0xb7, 0x9c, 0xb4, 0xb7, 0xe4, 0x44, 0x19, 0x26, 0xfc, 0x43, 0x0a, 0x5d, 0xb7, 0x4f, + 0xdb, 0x0e, 0x1c, 0xa9, 0xf3, 0xe3, 0xb8, 0xe1, 0xdb, 0x91, 0x7f, 0x1e, 0x83, 0x04, 0x0b, 0xc3, + 0x9f, 0x83, 0xac, 0xaa, 0x59, 0xb8, 0x81, 0x0d, 0xcf, 0x52, 0x20, 0xbe, 0x3a, 0x22, 0x65, 0x38, + 0x98, 0xa1, 0x3d, 0x0d, 0xe9, 0xdd, 0xa6, 0xae, 0x58, 0x9e, 0x78, 0x5f, 0x58, 0x1d, 0x91, 0x80, + 0x02, 0x19, 0xca, 0x33, 0x90, 0x31, 0x2d, 0x43, 0xd5, 0x1a, 0xb2, 0xff, 0x5c, 0x70, 0x9a, 0x41, + 0x9d, 0xea, 0x76, 0x74, 0xbd, 0x89, 0x15, 0x7b, 0xe5, 0x31, 0xca, 0xcf, 0x50, 0x65, 0x38, 0x98, + 0xa1, 0x95, 0x60, 0xd2, 0xb9, 0x2f, 0xc0, 0x11, 0x13, 0xfd, 0x8e, 0x72, 0xae, 0x8e, 0x48, 0x13, + 0x0e, 0x11, 0x63, 0x73, 0x1d, 0x80, 0x40, 0x38, 0x87, 0x31, 0x7f, 0x2a, 0xc9, 0x3a, 0x6a, 0x63, + 0x4a, 0x5d, 0xde, 0x5d, 0x51, 0x8e, 0x56, 0x47, 0xa4, 0x14, 0xc1, 0x65, 0x84, 0x4b, 0x00, 0x75, + 0xc5, 0xb2, 0x09, 0xd9, 0x82, 0x6d, 0xca, 0x47, 0xb8, 0xa2, 0x58, 0x98, 0xd0, 0x10, 0x34, 0x4a, + 0xe3, 0x64, 0x3b, 0x7e, 0x2a, 0x06, 0xb9, 0xe0, 0xe9, 0x12, 0xf4, 0x08, 0xce, 0xba, 0xdb, 0x7c, + 0x96, 0xef, 0x44, 0x83, 0xc9, 0xfb, 0xf4, 0xe5, 0x41, 0x12, 0x69, 0xfe, 0xc3, 0x10, 0xe6, 0xea, + 0x88, 0x74, 0x46, 0x0d, 0x2f, 0x42, 0xef, 0xc2, 0x1c, 0x3f, 0xe6, 0x19, 0xac, 0x6f, 0x90, 0x3d, + 0x27, 0x4a, 0xd9, 0x5d, 0xdb, 0xac, 0x11, 0x56, 0xb0, 0x9c, 0x83, 0x09, 0x7f, 0x25, 0xe2, 0x6f, + 0x8f, 0xc3, 0x99, 0x2d, 0x43, 0x6d, 0xd1, 0xf9, 0xc1, 0x8f, 0x8e, 0xde, 0x84, 0x09, 0x03, 0xb7, + 0x9b, 0x0a, 0x99, 0xaa, 0xbd, 0x7b, 0x3b, 0x0b, 0xd1, 0x12, 0x51, 0x0a, 0xaa, 0x6b, 0x27, 0xf9, + 0x9f, 0xe5, 0x7c, 0xb8, 0x96, 0xcb, 0xc0, 0x4f, 0xac, 0xf9, 0x77, 0x6e, 0xae, 0xf4, 0x3f, 0x74, + 0xe8, 0x70, 0xcc, 0x18, 0x9e, 0x6f, 0x84, 0x61, 0xb6, 0xb6, 0xa7, 0xd0, 0xb3, 0x6d, 0x06, 0xbd, + 0xdd, 0xe2, 0xdf, 0x9a, 0x89, 0xdc, 0x3f, 0x2c, 0xda, 0x84, 0x1b, 0x8a, 0xb9, 0xef, 0xf0, 0x9f, + 0xae, 0x75, 0x83, 0xd1, 0x11, 0x5c, 0xa8, 0x19, 0x47, 0x6d, 0x4b, 0x97, 0x6d, 0xbd, 0xec, 0xee, + 0x1e, 0xca, 0xbb, 0x6d, 0xec, 0xdf, 0x9d, 0xb9, 0x16, 0x59, 0x1d, 0x65, 0xc0, 0xb5, 0x74, 0x7b, + 0xf7, 0xf0, 0x76, 0xdb, 0x55, 0xd3, 0xd9, 0x5a, 0xaf, 0x42, 0xd4, 0x81, 0x73, 0xbb, 0xea, 0x21, + 0xae, 0xb3, 0x60, 0x9b, 0xf9, 0x23, 0x32, 0x86, 0x7d, 0xbb, 0x34, 0xaf, 0x44, 0xe7, 0x04, 0x0f, + 0x71, 0x9d, 0x78, 0xd4, 0x65, 0x9b, 0xd8, 0xa9, 0x77, 0x7e, 0xb7, 0x47, 0x19, 0x7a, 0x00, 0xb9, + 0xae, 0xba, 0xc6, 0xfa, 0x9f, 0x05, 0xe8, 0xae, 0x62, 0x72, 0x27, 0xc0, 0xf9, 0x08, 0x2e, 0xd8, + 0x4a, 0x3c, 0x50, 0xad, 0x3d, 0xf7, 0x1e, 0x87, 0x5d, 0xcd, 0x78, 0x7f, 0x5d, 0x72, 0x45, 0xbd, + 0xa9, 0x5a, 0x7b, 0xf6, 0xc0, 0x73, 0x75, 0x69, 0xf4, 0x2a, 0x44, 0xf7, 0x21, 0x47, 0xdd, 0x4d, + 0x5b, 0x31, 0x1c, 0x0b, 0x4c, 0xd2, 0xda, 0x22, 0x23, 0x41, 0xe2, 0x83, 0xb6, 0x14, 0xc3, 0xb5, + 0x41, 0xea, 0xc6, 0x5c, 0x08, 0x7a, 0x1b, 0x10, 0x37, 0x8f, 0x3d, 0xc5, 0xdc, 0xb3, 0x39, 0xa7, + 0xfa, 0x1f, 0x70, 0x60, 0x36, 0xb1, 0xaa, 0x98, 0x7b, 0xee, 0x1e, 0x5d, 0x2d, 0x00, 0x0b, 0x19, + 0xbb, 0xff, 0x2a, 0xc0, 0x84, 0x5f, 0x28, 0xf4, 0x16, 0x4c, 0xd2, 0x56, 0x59, 0xba, 0xcc, 0x0f, + 0x7b, 0xd2, 0x31, 0x3b, 0x11, 0xed, 0xb5, 0xfc, 0x4c, 0x9c, 0x4f, 0x29, 0x4b, 0x78, 0x55, 0xf5, + 0x12, 0xe3, 0x24, 0xfe, 0x7f, 0x01, 0x92, 0x76, 0x19, 0x3a, 0x0b, 0xb3, 0xd5, 0xb5, 0x8d, 0x92, + 0xbc, 0x55, 0x90, 0xaa, 0xf2, 0xf6, 0x66, 0x65, 0xab, 0x54, 0x5c, 0xbb, 0xbd, 0x56, 0x5a, 0xc9, + 0x8d, 0xa0, 0x24, 0x8c, 0x3e, 0x2c, 0x15, 0xa4, 0x9c, 0x80, 0x52, 0x90, 0xd8, 0x28, 0x6f, 0x56, + 0x57, 0x73, 0x31, 0x94, 0x83, 0xcc, 0x4a, 0xe1, 0xa1, 0x5c, 0xbe, 0x2d, 0x33, 0x48, 0x1c, 0x4d, + 0x42, 0x9a, 0x43, 0xde, 0x2c, 0x95, 0xee, 0xe5, 0x46, 0x09, 0x0a, 0xf9, 0x45, 0x20, 0x94, 0x3e, + 0x41, 0x50, 0x56, 0xcb, 0xdb, 0x12, 0x81, 0xac, 0x14, 0x1e, 0xe6, 0xc6, 0xc4, 0x07, 0x90, 0x0b, + 0x2a, 0x0b, 0xad, 0x00, 0x70, 0xb5, 0xef, 0xe3, 0x23, 0xee, 0xa2, 0x9e, 0xeb, 0xaf, 0x6e, 0x7a, + 0x4e, 0xbe, 0x66, 0xff, 0x14, 0xab, 0x80, 0xba, 0x5d, 0x17, 0x7a, 0x0d, 0x52, 0x1a, 0x3e, 0x18, + 0x3a, 0xfb, 0xa6, 0xe1, 0x03, 0xfa, 0x4b, 0x3c, 0x07, 0x67, 0x7b, 0x1a, 0xa9, 0x38, 0x01, 0x19, + 0xaf, 0x57, 0x13, 0xff, 0x3e, 0x06, 0x59, 0xe2, 0x8d, 0xcc, 0xaa, 0xbe, 0xd6, 0xd0, 0x74, 0x03, + 0xa3, 0x05, 0x40, 0x8e, 0x1f, 0x32, 0x49, 0xa7, 0x9a, 0xfb, 0x2a, 0x3b, 0xc9, 0x9e, 0xa2, 0x36, + 0xe2, 0x94, 0x55, 0xf5, 0xca, 0xbe, 0xda, 0x46, 0xff, 0x0f, 0xce, 0xd5, 0xf4, 0x56, 0x4b, 0xd7, + 0x64, 0x3f, 0x99, 0x4a, 0xd9, 0xf1, 0x7b, 0x6f, 0xb7, 0xfa, 0x79, 0x43, 0xa7, 0xfe, 0x85, 0x22, + 0x65, 0xe6, 0x83, 0x11, 0x77, 0x51, 0x73, 0xc0, 0x76, 0xed, 0xac, 0x4c, 0x7c, 0x5f, 0x80, 0xe9, + 0x10, 0x1a, 0x74, 0x19, 0xc4, 0x62, 0x79, 0x63, 0xa3, 0xbc, 0x29, 0x17, 0x57, 0x0b, 0x52, 0x45, + 0xae, 0x96, 0xe5, 0xb5, 0x3b, 0x9b, 0x65, 0xa9, 0x14, 0xb0, 0x9c, 0x34, 0x8c, 0x6f, 0x6e, 0x6f, + 0x94, 0xa4, 0xb5, 0x62, 0x4e, 0x40, 0x33, 0x90, 0x2b, 0xac, 0x6f, 0xad, 0x16, 0xe4, 0xed, 0xad, + 0xad, 0x92, 0x24, 0x17, 0x0b, 0x95, 0x52, 0x2e, 0xe6, 0x42, 0xd7, 0xcb, 0x6f, 0xda, 0x50, 0x6a, + 0x4b, 0x5b, 0xdb, 0x9b, 0xc5, 0xea, 0x76, 0xa1, 0xba, 0x56, 0xde, 0xcc, 0x8d, 0xa2, 0x09, 0x80, + 0x37, 0x57, 0xd7, 0xaa, 0xa5, 0xca, 0x56, 0xa1, 0x58, 0xca, 0x25, 0x96, 0x33, 0x00, 0xae, 0x4a, + 0xc4, 0x7f, 0x24, 0x72, 0x86, 0x38, 0xf8, 0x17, 0x60, 0x8a, 0xcc, 0x1e, 0xd4, 0xd9, 0xd9, 0xc5, + 0xfc, 0x58, 0x48, 0x8e, 0x17, 0x38, 0x64, 0xe8, 0x59, 0x98, 0xd0, 0x3a, 0xad, 0x1d, 0x6c, 0x10, + 0x0d, 0x93, 0x52, 0x7e, 0x9f, 0x20, 0xc3, 0xa0, 0x55, 0x9d, 0x30, 0x26, 0x41, 0xb0, 0x81, 0xc9, + 0xc2, 0x06, 0xcb, 0xba, 0x51, 0xc7, 0xec, 0x8c, 0x79, 0x92, 0xcc, 0x5f, 0x14, 0x58, 0x26, 0x30, + 0xf4, 0x16, 0xcc, 0x84, 0x76, 0xd8, 0x68, 0xff, 0xfb, 0x23, 0x3e, 0x45, 0x4b, 0xa8, 0xd6, 0xdd, + 0x29, 0x3f, 0x14, 0x60, 0xbe, 0x97, 0xf3, 0x47, 0xcb, 0x90, 0x0e, 0xae, 0x41, 0x07, 0x32, 0x71, + 0x68, 0xba, 0xeb, 0xd1, 0x65, 0x48, 0x07, 0x57, 0x9d, 0x83, 0xf1, 0xe8, 0x44, 0xae, 0x40, 0x05, + 0xef, 0x32, 0x40, 0xfc, 0x4a, 0x0c, 0x26, 0x83, 0xc2, 0xaf, 0xc3, 0xb8, 0x9d, 0x5a, 0x61, 0x8b, + 0xa3, 0xa5, 0x21, 0x26, 0x25, 0xfe, 0x2d, 0xd9, 0x2c, 0xf2, 0x3f, 0x10, 0x60, 0x8c, 0x2f, 0x6f, + 0x5e, 0x86, 0x78, 0x4b, 0xd5, 0x06, 0xd7, 0x06, 0xc1, 0xa6, 0x44, 0xca, 0xe1, 0xe0, 0xcd, 0x27, + 0xd8, 0x68, 0x13, 0xa6, 0xf8, 0x44, 0xd5, 0xc2, 0x9a, 0xe5, 0x09, 0xc9, 0x07, 0x62, 0x91, 0xf3, + 0xd0, 0x32, 0x87, 0xf3, 0x67, 0xa3, 0x70, 0xb6, 0x67, 0x88, 0x71, 0x3a, 0xae, 0x12, 0xdd, 0x82, + 0xf1, 0x9a, 0xae, 0x39, 0x17, 0x0b, 0x06, 0xbd, 0x51, 0xc4, 0x69, 0xd0, 0x21, 0x4c, 0x72, 0x27, + 0xa5, 0x34, 0xdb, 0x7b, 0xca, 0x0e, 0x66, 0xbb, 0x5d, 0x13, 0xd1, 0x5b, 0x2d, 0x3d, 0x1b, 0xb5, + 0x70, 0x7b, 0xf7, 0x90, 0xf9, 0x9c, 0x4d, 0xba, 0x83, 0x5a, 0xe0, 0x4c, 0xc9, 0x04, 0xcd, 0xea, + 0xb1, 0x21, 0xe8, 0x79, 0xe0, 0x37, 0x5a, 0xdd, 0x9a, 0x13, 0xdc, 0x97, 0x4e, 0xb0, 0x02, 0x07, + 0x75, 0x0e, 0x12, 0x86, 0x52, 0x57, 0x0f, 0x69, 0xb4, 0x93, 0x58, 0x1d, 0x91, 0xd8, 0x27, 0x3d, + 0x17, 0xd1, 0x31, 0x0c, 0xbd, 0x41, 0x96, 0x1d, 0xee, 0x1e, 0x7b, 0x72, 0x88, 0x33, 0xa8, 0x53, + 0x0e, 0x03, 0x1b, 0x24, 0x7e, 0x5e, 0x80, 0x33, 0x3d, 0x9a, 0x81, 0xae, 0xc2, 0xe5, 0xdb, 0xb7, + 0x1f, 0xc8, 0xdc, 0x7f, 0x6e, 0x16, 0xaa, 0x6b, 0xf7, 0x4b, 0x32, 0x75, 0x81, 0xcb, 0xa5, 0x6a, + 0x94, 0xff, 0x24, 0x93, 0x67, 0xe9, 0x41, 0x61, 0xa5, 0x54, 0x5c, 0xdb, 0x28, 0xac, 0xe7, 0x62, + 0xe8, 0x3c, 0xcc, 0xbb, 0xae, 0x94, 0xb1, 0x90, 0x6d, 0xf4, 0x38, 0x9a, 0x82, 0xac, 0x1f, 0x34, + 0xba, 0x0c, 0x90, 0xb4, 0x15, 0x25, 0x7e, 0x26, 0x06, 0x29, 0xc7, 0x1a, 0xd0, 0x26, 0xa4, 0x68, + 0x30, 0xa2, 0xda, 0xe7, 0xe6, 0xfa, 0xac, 0x0a, 0xaa, 0x36, 0xb2, 0xc3, 0x82, 0x2e, 0xe4, 0x6c, + 0x28, 0xe1, 0xd7, 0xd1, 0x0e, 0x0c, 0xa5, 0xdd, 0xc6, 0xb6, 0x03, 0x89, 0xe4, 0xb7, 0x6d, 0x23, + 0xfb, 0xf8, 0x39, 0x2c, 0x90, 0x04, 0xe9, 0xfd, 0x96, 0x29, 0xdb, 0x1c, 0x07, 0x58, 0x06, 0xdc, + 0x6b, 0x99, 0x6f, 0x76, 0xb3, 0x84, 0x7d, 0x07, 0x4c, 0xd6, 0xfd, 0x6c, 0x3b, 0x5a, 0xbc, 0x02, + 0xa8, 0xbb, 0x41, 0x61, 0x47, 0x36, 0xc5, 0xcb, 0x80, 0xba, 0x45, 0x45, 0x39, 0x88, 0xdb, 0xe3, + 0x2f, 0x23, 0x91, 0x9f, 0xe2, 0x3b, 0x30, 0x1d, 0x22, 0x00, 0xf1, 0x8a, 0x9c, 0x58, 0x76, 0x09, + 0x80, 0x83, 0x08, 0xc2, 0x65, 0x98, 0x74, 0x07, 0xb4, 0xf7, 0x54, 0x68, 0xd6, 0x19, 0xae, 0xf4, + 0x18, 0xfa, 0x5f, 0xc5, 0xe0, 0x4c, 0x8f, 0xb5, 0x29, 0xb2, 0x60, 0xb2, 0x7b, 0xa5, 0xdb, 0xf7, + 0x04, 0x4e, 0x0f, 0x6e, 0x3d, 0xe0, 0x52, 0xb0, 0x8a, 0xfc, 0x9f, 0x08, 0x30, 0x17, 0x8e, 0x7b, + 0x3a, 0xb7, 0xfe, 0x35, 0x98, 0x6f, 0xdb, 0xeb, 0xda, 0xc0, 0xca, 0x9a, 0x1b, 0xd8, 0xcb, 0x7d, + 0xce, 0x2a, 0x84, 0xad, 0x89, 0xa5, 0x33, 0xed, 0xf0, 0x02, 0xf1, 0xf3, 0x71, 0x98, 0xa6, 0xae, + 0x2e, 0xd0, 0x98, 0x9b, 0x30, 0x46, 0x0f, 0x61, 0x0c, 0x75, 0x0e, 0x8b, 0x93, 0xa0, 0x35, 0x48, + 0xd5, 0x74, 0xad, 0xae, 0x52, 0xa9, 0xe3, 0xfd, 0xd7, 0x5d, 0x2c, 0x1d, 0x50, 0xb4, 0x49, 0x24, + 0x97, 0x1a, 0xb5, 0x23, 0xf4, 0x31, 0x7a, 0x6c, 0x7d, 0xac, 0x8e, 0xf4, 0xd4, 0x48, 0x74, 0x2e, + 0x25, 0xf1, 0x24, 0x72, 0x29, 0x21, 0x6b, 0xa4, 0xbf, 0x14, 0x60, 0x36, 0x34, 0x49, 0x82, 0xea, + 0x30, 0xcb, 0x2e, 0xc6, 0x86, 0x1b, 0xff, 0x62, 0xdf, 0x7e, 0x0a, 0x58, 0xc6, 0xcc, 0x6e, 0x37, + 0xd0, 0x44, 0xef, 0xc0, 0x34, 0xcf, 0xee, 0x98, 0x9d, 0x76, 0xdb, 0xc0, 0xa6, 0xc9, 0x53, 0x3b, + 0xa4, 0x8e, 0x0f, 0xf6, 0xef, 0xcb, 0x8a, 0x4b, 0x25, 0x21, 0x23, 0x08, 0x32, 0xc5, 0x77, 0x60, + 0xaa, 0x0b, 0xd1, 0x6f, 0x36, 0xc2, 0x49, 0xcc, 0x46, 0xfc, 0x61, 0x02, 0x26, 0x03, 0xc5, 0xe8, + 0x21, 0xa4, 0xf1, 0xa1, 0xdb, 0x96, 0x01, 0x9e, 0xc1, 0x08, 0x70, 0x58, 0x28, 0xb9, 0xe4, 0x92, + 0x97, 0x57, 0xfe, 0x8f, 0x04, 0x48, 0xb9, 0x15, 0x9d, 0xe0, 0xc8, 0xd3, 0x5d, 0x48, 0xea, 0x6d, + 0x6c, 0x28, 0x16, 0xbf, 0xd5, 0x39, 0xd1, 0x2f, 0x6b, 0xd5, 0xa4, 0x1d, 0xa6, 0x34, 0xcb, 0x9c, + 0x4a, 0x72, 0xe8, 0xdd, 0xa4, 0xee, 0xe8, 0x70, 0x49, 0xdd, 0x7c, 0x0d, 0xc0, 0x69, 0x8c, 0x89, + 0xb6, 0x01, 0x1c, 0xbd, 0xda, 0x56, 0x76, 0x6d, 0x18, 0xad, 0xb9, 0x1d, 0xe4, 0x61, 0x94, 0xff, + 0x72, 0x0c, 0xd2, 0x1e, 0x7d, 0x22, 0x03, 0x72, 0x4d, 0xbd, 0x41, 0x4f, 0x14, 0x39, 0x1a, 0x60, + 0x39, 0x80, 0x3b, 0xc7, 0xec, 0xa2, 0x85, 0x75, 0xc6, 0xcf, 0x51, 0xcd, 0x64, 0xd3, 0x0f, 0x40, + 0x0f, 0x7c, 0x4d, 0x63, 0x06, 0xf1, 0xe1, 0x63, 0x35, 0x8d, 0x0c, 0x6f, 0x0f, 0x2f, 0xf1, 0x7f, + 0xc1, 0x64, 0xa0, 0x76, 0x74, 0x09, 0xce, 0xaf, 0x97, 0xef, 0xac, 0x15, 0x0b, 0xeb, 0x72, 0x79, + 0xab, 0x24, 0x15, 0xaa, 0x65, 0x29, 0x10, 0x06, 0x8d, 0x43, 0xbc, 0xb0, 0xb9, 0x92, 0x13, 0x9c, + 0x5c, 0xef, 0xb7, 0x04, 0x98, 0x0b, 0xbf, 0x9f, 0x46, 0x96, 0x7c, 0x8e, 0x03, 0x08, 0x5c, 0x04, + 0xc9, 0x79, 0x0a, 0xd8, 0x2d, 0x90, 0x26, 0xcc, 0xfb, 0xbd, 0x85, 0x6c, 0x76, 0x5a, 0x2d, 0xc5, + 0x50, 0x9d, 0x43, 0xa2, 0x2f, 0x0d, 0x7e, 0x45, 0xae, 0x42, 0x49, 0x8f, 0xa4, 0x33, 0x56, 0x08, + 0x58, 0xc5, 0xa6, 0xf8, 0xed, 0x31, 0x98, 0x0d, 0x25, 0x39, 0x8d, 0xfb, 0x4f, 0xce, 0xd8, 0x8a, + 0x0d, 0x3d, 0xb6, 0xde, 0x0a, 0x7a, 0x59, 0xde, 0xe3, 0xc7, 0x9a, 0x50, 0x03, 0xac, 0x7a, 0xbb, + 0xe5, 0xc4, 0x69, 0xba, 0xe5, 0xfb, 0x30, 0x19, 0x70, 0xcb, 0x3c, 0xad, 0x39, 0xa4, 0x4b, 0x9e, + 0xf0, 0xbb, 0x64, 0xf4, 0x10, 0xc6, 0xd9, 0xde, 0x90, 0xbd, 0x41, 0xfa, 0xd1, 0xa1, 0xed, 0x61, + 0xc1, 0xb6, 0x0b, 0x76, 0x67, 0xcb, 0xe6, 0x17, 0x6e, 0xa8, 0xe3, 0xe1, 0x86, 0x9a, 0xff, 0xa2, + 0x00, 0x59, 0x1f, 0x1f, 0x77, 0x83, 0x49, 0xf0, 0x6c, 0x30, 0xa1, 0x77, 0x60, 0xd4, 0x39, 0x07, + 0x3d, 0x11, 0x1d, 0xf0, 0x85, 0x0b, 0x1b, 0xd0, 0x36, 0xad, 0xab, 0xa8, 0xd7, 0xb1, 0x44, 0xf9, + 0xa2, 0x79, 0x18, 0xaf, 0xb3, 0x5d, 0x37, 0xfe, 0x46, 0x81, 0xfd, 0x29, 0xbe, 0x03, 0xf3, 0xbd, + 0x68, 0xc9, 0x92, 0xa7, 0x2a, 0x15, 0x36, 0x2b, 0xb7, 0xcb, 0xd2, 0x06, 0x4d, 0xe8, 0xc8, 0x52, + 0xa9, 0xb2, 0xbd, 0x5e, 0x95, 0x8b, 0xe5, 0x95, 0x90, 0x94, 0x51, 0x65, 0xbb, 0x58, 0x2c, 0x55, + 0x2a, 0x2c, 0xdf, 0x58, 0x92, 0xa4, 0xb2, 0x94, 0x8b, 0x89, 0xbf, 0x19, 0x83, 0xc9, 0xe0, 0xcd, + 0xb3, 0x63, 0x5e, 0xaa, 0xba, 0x04, 0xe9, 0xba, 0x7b, 0xb9, 0x88, 0x37, 0xc4, 0x0b, 0x0a, 0x3e, + 0x67, 0x32, 0x3a, 0xcc, 0x73, 0x26, 0x84, 0xb8, 0xd3, 0xae, 0x3b, 0xc4, 0x89, 0xfe, 0xc4, 0x0c, + 0x9d, 0x12, 0x77, 0x5f, 0x91, 0x1d, 0x3b, 0xd9, 0x15, 0x59, 0xf1, 0x07, 0x31, 0x40, 0x2b, 0x5d, + 0x97, 0x8d, 0x7f, 0x1c, 0x75, 0x17, 0xfa, 0x96, 0xc1, 0xd8, 0x69, 0xbc, 0x65, 0x20, 0xfe, 0x8a, + 0x00, 0xe7, 0x8b, 0x54, 0xcc, 0xe0, 0xb5, 0xc8, 0x3e, 0xb7, 0xce, 0xee, 0x43, 0xae, 0xeb, 0xf2, + 0x65, 0x6c, 0xf8, 0xcb, 0x97, 0x93, 0x81, 0xbb, 0xc8, 0x64, 0x25, 0xe9, 0xdc, 0x59, 0x56, 0xeb, + 0xbc, 0x1f, 0xc0, 0x06, 0xad, 0xd5, 0xc5, 0xdf, 0x13, 0xe0, 0xfc, 0x36, 0xd5, 0x4d, 0x0f, 0x89, + 0xc3, 0x0c, 0xe0, 0x49, 0x49, 0xeb, 0x76, 0x2b, 0xcd, 0xab, 0xc6, 0x7b, 0x74, 0x2b, 0xf5, 0xf7, + 0x1b, 0x8a, 0xb9, 0x6f, 0x77, 0x2b, 0xf9, 0x2d, 0x2e, 0xc2, 0xd9, 0x3b, 0xd8, 0x1a, 0xbc, 0x15, + 0xe2, 0x23, 0x38, 0xc7, 0xee, 0x22, 0xfa, 0x28, 0xcc, 0x7e, 0x5d, 0x75, 0x01, 0xa0, 0x4d, 0x5f, + 0x60, 0xd1, 0xf7, 0xf9, 0x9b, 0x1e, 0x29, 0x29, 0x45, 0x20, 0x55, 0x02, 0x40, 0xe7, 0x80, 0x7e, + 0xb8, 0xf9, 0xcc, 0x84, 0x94, 0x24, 0x00, 0x9a, 0xcd, 0xfc, 0x92, 0x00, 0xe7, 0xc3, 0xeb, 0xe4, + 0xd7, 0x20, 0x1f, 0xc0, 0x54, 0x50, 0xb3, 0x76, 0xcc, 0x38, 0x94, 0x6a, 0x73, 0x01, 0xd5, 0x9a, + 0xe8, 0x32, 0x4c, 0x6a, 0xf8, 0xd0, 0x92, 0xbb, 0x64, 0xcf, 0x12, 0xf0, 0x96, 0x2d, 0xbf, 0xb8, + 0x04, 0xe7, 0x57, 0x70, 0x13, 0x0f, 0x63, 0x0f, 0xe2, 0xf7, 0x63, 0x90, 0x0b, 0xde, 0xd6, 0x25, + 0x2e, 0x8a, 0x3f, 0x69, 0xe8, 0xdf, 0x46, 0x8e, 0x74, 0x51, 0xbe, 0x0b, 0xe5, 0x52, 0xd6, 0xf4, + 0xdd, 0x2f, 0xaf, 0x42, 0x56, 0xa7, 0xd7, 0xce, 0xfd, 0xfb, 0xc7, 0x91, 0xb1, 0x41, 0xc8, 0x3d, + 0x75, 0x29, 0xc3, 0xb8, 0x3c, 0xb1, 0x77, 0x24, 0x8e, 0xf3, 0x60, 0xc0, 0xb7, 0x12, 0x30, 0xb6, + 0xd2, 0x6c, 0xdf, 0xd5, 0x77, 0x42, 0x47, 0xdc, 0x0d, 0xfe, 0xf0, 0xdb, 0x00, 0x4f, 0x18, 0x32, + 0x2e, 0x34, 0xec, 0x63, 0x0f, 0xc4, 0x15, 0xe8, 0x0b, 0x4a, 0x16, 0xe6, 0x0b, 0xa2, 0x17, 0xfa, + 0x13, 0x2f, 0xdc, 0xd5, 0x77, 0x2a, 0x84, 0x44, 0x62, 0x94, 0xe8, 0x7f, 0x43, 0xc6, 0x50, 0xcd, + 0x7d, 0xd9, 0x9e, 0xd4, 0x99, 0xb7, 0xfe, 0xc8, 0x71, 0x8f, 0xe2, 0xac, 0x8e, 0x48, 0x69, 0xc3, + 0x73, 0xc1, 0x44, 0x06, 0xdb, 0x15, 0x38, 0x35, 0x0c, 0xb0, 0xb3, 0xdd, 0xeb, 0xda, 0xfb, 0xea, + 0x88, 0x64, 0xf7, 0xa8, 0x5d, 0xc1, 0x49, 0xde, 0x1d, 0x43, 0xaf, 0x02, 0xd0, 0x47, 0xa7, 0x18, + 0xed, 0x78, 0x5f, 0xda, 0x14, 0xc5, 0xa6, 0xa4, 0xd7, 0x20, 0x89, 0xb5, 0x3a, 0x23, 0x4c, 0xf6, + 0x25, 0x1c, 0xc7, 0x5a, 0x9d, 0x92, 0x5d, 0x87, 0x2c, 0x36, 0x0c, 0xdd, 0x90, 0xed, 0xa0, 0x32, + 0x45, 0x3d, 0x00, 0xb2, 0x69, 0x8d, 0x76, 0x6d, 0xa1, 0x42, 0x1f, 0xe5, 0x94, 0x32, 0x14, 0x91, + 0x05, 0x51, 0xa6, 0x58, 0x83, 0xa4, 0xdd, 0x75, 0xe8, 0x2c, 0xcc, 0xde, 0x2d, 0x2f, 0xcb, 0x95, + 0x6a, 0xa1, 0x1a, 0x12, 0x3c, 0x6d, 0x95, 0x36, 0x57, 0xd6, 0x36, 0xef, 0xe4, 0x04, 0xf2, 0x21, + 0x6d, 0x6f, 0x6e, 0x92, 0x8f, 0x18, 0x4a, 0xc2, 0xe8, 0x4a, 0x79, 0xb3, 0x94, 0x8b, 0xa3, 0x0c, + 0x24, 0x8b, 0x85, 0xcd, 0x62, 0x69, 0xbd, 0xb4, 0x92, 0x1b, 0x45, 0x00, 0x63, 0xb7, 0x0b, 0x6b, + 0xe4, 0x77, 0x62, 0x39, 0xe5, 0x04, 0x77, 0xe2, 0x65, 0xc8, 0xdd, 0xc1, 0x16, 0x33, 0x9a, 0x28, + 0x07, 0xf1, 0x5d, 0x01, 0x10, 0xf1, 0x7b, 0x0c, 0x33, 0xc4, 0xc5, 0x8e, 0xfa, 0x5c, 0xac, 0x7b, + 0x7b, 0x5c, 0xf0, 0xde, 0x1e, 0xf7, 0xfb, 0xd6, 0x98, 0xdf, 0xb7, 0x06, 0xfc, 0x72, 0x3c, 0xe8, + 0x97, 0xed, 0x11, 0x94, 0x18, 0x7e, 0x04, 0x89, 0x1d, 0x98, 0xf6, 0x49, 0xcf, 0x9d, 0xf5, 0x87, + 0x61, 0xf4, 0x5d, 0x7d, 0xc7, 0xf6, 0xcf, 0x62, 0x7f, 0x96, 0x12, 0xc5, 0x1f, 0xd8, 0x15, 0x3f, + 0x0f, 0xd3, 0x45, 0x45, 0xab, 0xe1, 0x66, 0x7f, 0x05, 0x3f, 0x0f, 0xd3, 0xcc, 0x6b, 0xf7, 0x47, + 0xfd, 0x8e, 0x00, 0x17, 0x59, 0x8c, 0xd2, 0x1d, 0xee, 0xf5, 0x9b, 0xfb, 0x64, 0x98, 0x0e, 0x79, + 0xe8, 0x68, 0x90, 0xcc, 0x7d, 0x48, 0x5d, 0xa8, 0xfb, 0x4d, 0xa4, 0xfe, 0xf1, 0xca, 0x8f, 0x04, + 0xb8, 0xc8, 0xe2, 0x95, 0xde, 0xd2, 0x87, 0x39, 0xd0, 0x27, 0x2e, 0xf9, 0x89, 0x62, 0x97, 0x25, + 0x38, 0x4f, 0xc6, 0xd1, 0x30, 0x2d, 0x12, 0x2d, 0x78, 0x8a, 0x1a, 0x65, 0x17, 0xd1, 0x13, 0x8d, + 0x60, 0x7e, 0x59, 0x80, 0x8b, 0x3d, 0xab, 0xe5, 0xe3, 0x42, 0x81, 0x99, 0x10, 0x5d, 0xdb, 0xe3, + 0x64, 0x58, 0x65, 0x4f, 0x77, 0x2b, 0x7b, 0xf0, 0x21, 0x74, 0x0d, 0x2e, 0xf2, 0x71, 0x31, 0x8c, + 0x6e, 0xaf, 0x6e, 0xb9, 0xaf, 0x73, 0x78, 0xde, 0xc7, 0x20, 0x2e, 0xb5, 0xb4, 0xb9, 0xbd, 0x21, + 0x57, 0x1f, 0x6e, 0x85, 0xb8, 0xd4, 0x35, 0x0a, 0xa8, 0xe6, 0x04, 0x34, 0x05, 0x59, 0x69, 0xad, + 0x72, 0x4f, 0x2e, 0x6c, 0x16, 0xd6, 0x1f, 0x56, 0xd6, 0x2a, 0xb9, 0xd8, 0xd5, 0xef, 0x08, 0x80, + 0xba, 0xb3, 0x8d, 0xe8, 0x19, 0xb8, 0x28, 0x95, 0xd6, 0xe9, 0x62, 0xb7, 0x77, 0x5e, 0x2b, 0x03, + 0xc9, 0xd2, 0x1b, 0xdb, 0x85, 0x75, 0xb9, 0x5a, 0xce, 0x09, 0x28, 0x07, 0x99, 0xcd, 0x72, 0x55, + 0x76, 0x20, 0xf4, 0x8c, 0xcd, 0x1d, 0xa9, 0x54, 0xa8, 0x96, 0x24, 0xb9, 0xba, 0x5a, 0xd8, 0xcc, + 0xc5, 0x51, 0x16, 0x52, 0xeb, 0xa5, 0x4a, 0x85, 0x7d, 0x8e, 0xa2, 0x3c, 0xcc, 0x79, 0x11, 0xe4, + 0xb2, 0xc4, 0xc8, 0x2b, 0xb9, 0x04, 0x3a, 0x03, 0xd3, 0x0e, 0xaa, 0xa7, 0x60, 0x8c, 0xb8, 0xfc, + 0xd2, 0x83, 0xb5, 0x4a, 0xb5, 0x92, 0x1b, 0xbf, 0x2a, 0x01, 0xb8, 0x4e, 0x11, 0x9d, 0x87, 0xf9, + 0x95, 0xf5, 0x2d, 0x99, 0xcc, 0x2e, 0x21, 0x9a, 0x98, 0x84, 0x34, 0xd7, 0x04, 0xc1, 0xc8, 0x09, + 0x68, 0x16, 0xa6, 0x7c, 0xda, 0xa0, 0xe0, 0xd8, 0xd2, 0x57, 0x2f, 0x50, 0xa6, 0x15, 0x6c, 0x3c, + 0x56, 0x6b, 0x18, 0xfd, 0xaa, 0x00, 0x13, 0xfe, 0x27, 0x93, 0xd0, 0x4b, 0x83, 0x45, 0x60, 0x9e, + 0x27, 0xa5, 0xf2, 0x4b, 0xc3, 0x90, 0x30, 0x73, 0x15, 0xaf, 0xff, 0xe4, 0x8f, 0xfe, 0xee, 0x73, + 0xb1, 0x97, 0xc4, 0x17, 0x9d, 0xa7, 0xb8, 0x3f, 0xce, 0x06, 0xca, 0xad, 0xb6, 0xa1, 0xbf, 0x8b, + 0x6b, 0x96, 0xb9, 0x78, 0xf5, 0x13, 0x8b, 0x35, 0x46, 0x75, 0x83, 0x47, 0x16, 0x37, 0x84, 0xab, + 0xe8, 0x2b, 0x02, 0xa4, 0x3d, 0xef, 0xf5, 0xa1, 0x85, 0xe1, 0x5e, 0x4f, 0xcc, 0x2f, 0x0e, 0x8c, + 0xcf, 0x25, 0x7d, 0x85, 0x4a, 0xba, 0x20, 0x3e, 0x1f, 0x29, 0x29, 0x7d, 0x22, 0xf0, 0x06, 0x3b, + 0x28, 0x49, 0xc4, 0xfc, 0xae, 0x00, 0x53, 0x5d, 0x6f, 0xcc, 0xa1, 0x57, 0x06, 0x5e, 0xea, 0x7a, + 0xf5, 0x7b, 0x6d, 0x48, 0x2a, 0x2e, 0xf8, 0x0d, 0x2a, 0xf8, 0x2b, 0xe2, 0xe2, 0x40, 0x2a, 0x76, + 0x07, 0xbc, 0x2d, 0xbe, 0x34, 0x9c, 0xf8, 0xd2, 0xb1, 0xc4, 0x97, 0x4e, 0x49, 0x7c, 0xc3, 0x27, + 0xfe, 0xd7, 0x05, 0x98, 0xea, 0x8a, 0x54, 0xd1, 0x70, 0x81, 0xad, 0x2d, 0xfe, 0x00, 0x21, 0xc6, + 0x80, 0xb2, 0xd6, 0x1d, 0xde, 0x5e, 0x83, 0xfe, 0x35, 0x01, 0x66, 0x43, 0xe3, 0x76, 0x34, 0x7c, + 0xa8, 0xff, 0x44, 0x65, 0x56, 0x58, 0x8d, 0x44, 0xe6, 0x9f, 0x17, 0x20, 0xeb, 0x7b, 0x52, 0x08, + 0x7d, 0x28, 0xfa, 0x69, 0xe3, 0xee, 0x27, 0x8d, 0xf2, 0x2f, 0x0d, 0x41, 0xc1, 0x4d, 0x22, 0x4f, + 0x45, 0x9e, 0x41, 0xc8, 0x11, 0xd9, 0xdd, 0x83, 0xfe, 0x9e, 0x00, 0xb3, 0xa1, 0x59, 0xa0, 0x68, + 0x35, 0x46, 0x25, 0x8e, 0xf2, 0xc3, 0xac, 0xfe, 0xc5, 0x5b, 0x54, 0xb8, 0xeb, 0xe2, 0x52, 0x97, + 0x3e, 0x75, 0xa3, 0xa1, 0x68, 0xea, 0x7b, 0x2c, 0x1d, 0x4e, 0x9d, 0x45, 0x20, 0x4f, 0x40, 0x54, + 0x4a, 0xe4, 0x0f, 0xcd, 0x09, 0x45, 0xcb, 0x1f, 0x95, 0x46, 0x3a, 0x96, 0xfc, 0x4b, 0x1e, 0xf9, + 0xc9, 0xb4, 0x1c, 0x94, 0xbe, 0x4b, 0xf8, 0xc5, 0xab, 0x9f, 0x20, 0xf2, 0xff, 0x86, 0x00, 0xa8, + 0x3b, 0x15, 0x84, 0x22, 0x07, 0x7f, 0xcf, 0xd4, 0xd1, 0x70, 0x92, 0x73, 0x4b, 0x46, 0xc7, 0x90, + 0x1c, 0xfd, 0xae, 0x60, 0xbf, 0xb8, 0x15, 0x48, 0xdd, 0x5c, 0xef, 0x6f, 0x9e, 0xa1, 0x29, 0xac, + 0xfc, 0x47, 0x86, 0x27, 0xf4, 0x7b, 0x3c, 0x74, 0x0c, 0x0b, 0x42, 0x5f, 0x15, 0x60, 0x36, 0x34, + 0x85, 0x14, 0x6d, 0x3e, 0x51, 0x59, 0xa7, 0x7c, 0x8f, 0x17, 0x46, 0x6c, 0x39, 0xaf, 0x1e, 0x47, + 0xdf, 0x7f, 0x20, 0xc0, 0x7c, 0xaf, 0x85, 0x10, 0xba, 0xd9, 0x7f, 0xa4, 0xf6, 0x0c, 0x29, 0xf3, + 0x43, 0x86, 0xb8, 0xe2, 0xeb, 0xb4, 0x15, 0x37, 0xc4, 0x6b, 0xfd, 0xb5, 0x1d, 0x12, 0x0c, 0x13, + 0x93, 0x27, 0x6d, 0xe9, 0xb5, 0x2c, 0x8a, 0x6e, 0x4b, 0x9f, 0xc5, 0xd4, 0x71, 0xdb, 0xb2, 0x74, + 0xad, 0x4f, 0x8f, 0x84, 0x34, 0x84, 0x0f, 0xdf, 0xef, 0x0b, 0x30, 0x1b, 0xba, 0x1a, 0x8a, 0xb6, + 0x9f, 0xa8, 0x05, 0xd4, 0xd0, 0xad, 0xe0, 0x1e, 0x08, 0x1d, 0xaf, 0x15, 0xe8, 0x4f, 0x05, 0x38, + 0xd3, 0x63, 0x95, 0x84, 0x6e, 0xf4, 0x1b, 0x94, 0xbd, 0x57, 0x74, 0xf9, 0x9b, 0xc7, 0xa2, 0xe5, + 0x63, 0x3a, 0xa4, 0x4d, 0x43, 0x58, 0x19, 0xfa, 0xa6, 0x00, 0xf3, 0xbd, 0xd6, 0x52, 0xd1, 0x26, + 0xd6, 0x67, 0x05, 0xd6, 0x73, 0x70, 0x73, 0x81, 0xaf, 0x1e, 0xb3, 0x13, 0x7e, 0x49, 0x80, 0xb4, + 0x27, 0x6d, 0x13, 0x1d, 0x9e, 0x77, 0x67, 0xa7, 0xa2, 0xc3, 0xf3, 0x90, 0x7c, 0x90, 0xf8, 0x22, + 0x95, 0xf7, 0x32, 0x7a, 0x36, 0x3a, 0x8c, 0xe1, 0xe2, 0x7c, 0x56, 0x80, 0x94, 0x93, 0x3c, 0x43, + 0x2f, 0xf6, 0x33, 0x6d, 0x6f, 0x5e, 0x67, 0xa0, 0xa0, 0x2a, 0x44, 0x1a, 0xaa, 0x3d, 0x57, 0x16, + 0x5b, 0x14, 0xa2, 0xac, 0x4f, 0x09, 0x90, 0xf1, 0x66, 0x90, 0xd0, 0xe2, 0x00, 0x3d, 0xea, 0x93, + 0xa9, 0x57, 0x2f, 0x72, 0x39, 0xae, 0x0e, 0x26, 0xc7, 0xcf, 0x09, 0x90, 0xf1, 0x26, 0xbd, 0xa2, + 0xe5, 0x08, 0x49, 0x8f, 0xf5, 0x94, 0xe3, 0xc3, 0x54, 0x8e, 0x0f, 0x89, 0x2f, 0x0c, 0x22, 0xc7, + 0x8d, 0x1a, 0xe5, 0x7c, 0x43, 0xb8, 0xba, 0xfc, 0x65, 0x01, 0x9e, 0xaa, 0xe9, 0xad, 0x08, 0x31, + 0x96, 0x93, 0x2b, 0xcd, 0xf6, 0x16, 0xa9, 0x6d, 0x4b, 0xf8, 0xd8, 0x2d, 0x8e, 0xd7, 0xd0, 0x9b, + 0x8a, 0xd6, 0x58, 0xd0, 0x8d, 0xc6, 0x62, 0x03, 0x6b, 0x54, 0x96, 0x45, 0x56, 0xa4, 0xb4, 0x55, + 0x33, 0xec, 0x1f, 0xa0, 0x6e, 0xd6, 0x9b, 0xed, 0x6f, 0xc4, 0xe6, 0xef, 0x30, 0xfa, 0x62, 0x53, + 0xef, 0xd4, 0x49, 0x5f, 0x2e, 0xdc, 0x5f, 0x5a, 0x26, 0xc5, 0x7f, 0x68, 0x17, 0xbd, 0x4d, 0x8b, + 0xde, 0x5e, 0x69, 0xb6, 0xdf, 0xbe, 0xcf, 0x28, 0x77, 0xc6, 0x28, 0xff, 0x97, 0xff, 0x33, 0x00, + 0x00, 0xff, 0xff, 0x78, 0xae, 0x10, 0x67, 0xc0, 0x6a, 0x00, 0x00, +} diff --git a/vendor/google.golang.org/genproto/googleapis/privacy/dlp/v2beta2/storage.pb.go b/vendor/google.golang.org/genproto/googleapis/privacy/dlp/v2beta2/storage.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..ab4fdec5750a0a245aaeba88bca8a25549e9c76d --- /dev/null +++ b/vendor/google.golang.org/genproto/googleapis/privacy/dlp/v2beta2/storage.pb.go @@ -0,0 +1,1165 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: google/privacy/dlp/v2beta2/storage.proto + +package dlp + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import _ "google.golang.org/genproto/googleapis/api/annotations" +import _ "github.com/golang/protobuf/ptypes/timestamp" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// Categorization of results based on how likely they are to represent a match, +// based on the number of elements they contain which imply a match. +type Likelihood int32 + +const ( + // Default value; information with all likelihoods is included. + Likelihood_LIKELIHOOD_UNSPECIFIED Likelihood = 0 + // Few matching elements. + Likelihood_VERY_UNLIKELY Likelihood = 1 + Likelihood_UNLIKELY Likelihood = 2 + // Some matching elements. + Likelihood_POSSIBLE Likelihood = 3 + Likelihood_LIKELY Likelihood = 4 + // Many matching elements. + Likelihood_VERY_LIKELY Likelihood = 5 +) + +var Likelihood_name = map[int32]string{ + 0: "LIKELIHOOD_UNSPECIFIED", + 1: "VERY_UNLIKELY", + 2: "UNLIKELY", + 3: "POSSIBLE", + 4: "LIKELY", + 5: "VERY_LIKELY", +} +var Likelihood_value = map[string]int32{ + "LIKELIHOOD_UNSPECIFIED": 0, + "VERY_UNLIKELY": 1, + "UNLIKELY": 2, + "POSSIBLE": 3, + "LIKELY": 4, + "VERY_LIKELY": 5, +} + +func (x Likelihood) String() string { + return proto.EnumName(Likelihood_name, int32(x)) +} +func (Likelihood) EnumDescriptor() ([]byte, []int) { return fileDescriptor1, []int{0} } + +// Type of information detected by the API. +type InfoType struct { + // Name of the information type. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` +} + +func (m *InfoType) Reset() { *m = InfoType{} } +func (m *InfoType) String() string { return proto.CompactTextString(m) } +func (*InfoType) ProtoMessage() {} +func (*InfoType) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} } + +func (m *InfoType) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +// Custom information type provided by the user. Used to find domain-specific +// sensitive information configurable to the data in question. +type CustomInfoType struct { + // Info type configuration. All custom info types must have configurations + // that do not conflict with built-in info types or other custom info types. + InfoType *InfoType `protobuf:"bytes,1,opt,name=info_type,json=infoType" json:"info_type,omitempty"` + // Types that are valid to be assigned to Type: + // *CustomInfoType_Dictionary_ + // *CustomInfoType_SurrogateType_ + Type isCustomInfoType_Type `protobuf_oneof:"type"` +} + +func (m *CustomInfoType) Reset() { *m = CustomInfoType{} } +func (m *CustomInfoType) String() string { return proto.CompactTextString(m) } +func (*CustomInfoType) ProtoMessage() {} +func (*CustomInfoType) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{1} } + +type isCustomInfoType_Type interface { + isCustomInfoType_Type() +} + +type CustomInfoType_Dictionary_ struct { + Dictionary *CustomInfoType_Dictionary `protobuf:"bytes,2,opt,name=dictionary,oneof"` +} +type CustomInfoType_SurrogateType_ struct { + SurrogateType *CustomInfoType_SurrogateType `protobuf:"bytes,4,opt,name=surrogate_type,json=surrogateType,oneof"` +} + +func (*CustomInfoType_Dictionary_) isCustomInfoType_Type() {} +func (*CustomInfoType_SurrogateType_) isCustomInfoType_Type() {} + +func (m *CustomInfoType) GetType() isCustomInfoType_Type { + if m != nil { + return m.Type + } + return nil +} + +func (m *CustomInfoType) GetInfoType() *InfoType { + if m != nil { + return m.InfoType + } + return nil +} + +func (m *CustomInfoType) GetDictionary() *CustomInfoType_Dictionary { + if x, ok := m.GetType().(*CustomInfoType_Dictionary_); ok { + return x.Dictionary + } + return nil +} + +func (m *CustomInfoType) GetSurrogateType() *CustomInfoType_SurrogateType { + if x, ok := m.GetType().(*CustomInfoType_SurrogateType_); ok { + return x.SurrogateType + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*CustomInfoType) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _CustomInfoType_OneofMarshaler, _CustomInfoType_OneofUnmarshaler, _CustomInfoType_OneofSizer, []interface{}{ + (*CustomInfoType_Dictionary_)(nil), + (*CustomInfoType_SurrogateType_)(nil), + } +} + +func _CustomInfoType_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*CustomInfoType) + // type + switch x := m.Type.(type) { + case *CustomInfoType_Dictionary_: + b.EncodeVarint(2<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Dictionary); err != nil { + return err + } + case *CustomInfoType_SurrogateType_: + b.EncodeVarint(4<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.SurrogateType); err != nil { + return err + } + case nil: + default: + return fmt.Errorf("CustomInfoType.Type has unexpected type %T", x) + } + return nil +} + +func _CustomInfoType_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*CustomInfoType) + switch tag { + case 2: // type.dictionary + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(CustomInfoType_Dictionary) + err := b.DecodeMessage(msg) + m.Type = &CustomInfoType_Dictionary_{msg} + return true, err + case 4: // type.surrogate_type + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(CustomInfoType_SurrogateType) + err := b.DecodeMessage(msg) + m.Type = &CustomInfoType_SurrogateType_{msg} + return true, err + default: + return false, nil + } +} + +func _CustomInfoType_OneofSizer(msg proto.Message) (n int) { + m := msg.(*CustomInfoType) + // type + switch x := m.Type.(type) { + case *CustomInfoType_Dictionary_: + s := proto.Size(x.Dictionary) + n += proto.SizeVarint(2<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *CustomInfoType_SurrogateType_: + s := proto.Size(x.SurrogateType) + n += proto.SizeVarint(4<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +// Custom information type based on a dictionary of words or phrases. This can +// be used to match sensitive information specific to the data, such as a list +// of employee IDs or job titles. +// +// Dictionary words are case-insensitive and all characters other than letters +// and digits in the unicode [Basic Multilingual +// Plane](https://en.wikipedia.org/wiki/Plane_%28Unicode%29#Basic_Multilingual_Plane) +// will be replaced with whitespace when scanning for matches, so the +// dictionary phrase "Sam Johnson" will match all three phrases "sam johnson", +// "Sam, Johnson", and "Sam (Johnson)". Additionally, the characters +// surrounding any match must be of a different type than the adjacent +// characters within the word, so letters must be next to non-letters and +// digits next to non-digits. For example, the dictionary word "jen" will +// match the first three letters of the text "jen123" but will return no +// matches for "jennifer". +// +// Dictionary words containing a large number of characters that are not +// letters or digits may result in unexpected findings because such characters +// are treated as whitespace. +type CustomInfoType_Dictionary struct { + // Types that are valid to be assigned to Source: + // *CustomInfoType_Dictionary_WordList_ + Source isCustomInfoType_Dictionary_Source `protobuf_oneof:"source"` +} + +func (m *CustomInfoType_Dictionary) Reset() { *m = CustomInfoType_Dictionary{} } +func (m *CustomInfoType_Dictionary) String() string { return proto.CompactTextString(m) } +func (*CustomInfoType_Dictionary) ProtoMessage() {} +func (*CustomInfoType_Dictionary) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{1, 0} } + +type isCustomInfoType_Dictionary_Source interface { + isCustomInfoType_Dictionary_Source() +} + +type CustomInfoType_Dictionary_WordList_ struct { + WordList *CustomInfoType_Dictionary_WordList `protobuf:"bytes,1,opt,name=word_list,json=wordList,oneof"` +} + +func (*CustomInfoType_Dictionary_WordList_) isCustomInfoType_Dictionary_Source() {} + +func (m *CustomInfoType_Dictionary) GetSource() isCustomInfoType_Dictionary_Source { + if m != nil { + return m.Source + } + return nil +} + +func (m *CustomInfoType_Dictionary) GetWordList() *CustomInfoType_Dictionary_WordList { + if x, ok := m.GetSource().(*CustomInfoType_Dictionary_WordList_); ok { + return x.WordList + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*CustomInfoType_Dictionary) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _CustomInfoType_Dictionary_OneofMarshaler, _CustomInfoType_Dictionary_OneofUnmarshaler, _CustomInfoType_Dictionary_OneofSizer, []interface{}{ + (*CustomInfoType_Dictionary_WordList_)(nil), + } +} + +func _CustomInfoType_Dictionary_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*CustomInfoType_Dictionary) + // source + switch x := m.Source.(type) { + case *CustomInfoType_Dictionary_WordList_: + b.EncodeVarint(1<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.WordList); err != nil { + return err + } + case nil: + default: + return fmt.Errorf("CustomInfoType_Dictionary.Source has unexpected type %T", x) + } + return nil +} + +func _CustomInfoType_Dictionary_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*CustomInfoType_Dictionary) + switch tag { + case 1: // source.word_list + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(CustomInfoType_Dictionary_WordList) + err := b.DecodeMessage(msg) + m.Source = &CustomInfoType_Dictionary_WordList_{msg} + return true, err + default: + return false, nil + } +} + +func _CustomInfoType_Dictionary_OneofSizer(msg proto.Message) (n int) { + m := msg.(*CustomInfoType_Dictionary) + // source + switch x := m.Source.(type) { + case *CustomInfoType_Dictionary_WordList_: + s := proto.Size(x.WordList) + n += proto.SizeVarint(1<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +// Message defining a list of words or phrases to search for in the data. +type CustomInfoType_Dictionary_WordList struct { + // Words or phrases defining the dictionary. The dictionary must contain + // at least one phrase and every phrase must contain at least 2 characters + // that are letters or digits. [required] + Words []string `protobuf:"bytes,1,rep,name=words" json:"words,omitempty"` +} + +func (m *CustomInfoType_Dictionary_WordList) Reset() { *m = CustomInfoType_Dictionary_WordList{} } +func (m *CustomInfoType_Dictionary_WordList) String() string { return proto.CompactTextString(m) } +func (*CustomInfoType_Dictionary_WordList) ProtoMessage() {} +func (*CustomInfoType_Dictionary_WordList) Descriptor() ([]byte, []int) { + return fileDescriptor1, []int{1, 0, 0} +} + +func (m *CustomInfoType_Dictionary_WordList) GetWords() []string { + if m != nil { + return m.Words + } + return nil +} + +// Message for detecting output from deidentification transformations +// such as +// [`CryptoReplaceFfxFpeConfig`](/dlp/docs/reference/rest/v2beta1/content/deidentify#CryptoReplaceFfxFpeConfig). +// These types of transformations are +// those that perform pseudonymization, thereby producing a "surrogate" as +// output. This should be used in conjunction with a field on the +// transformation such as `surrogate_info_type`. This custom info type does +// not support the use of `detection_rules`. +type CustomInfoType_SurrogateType struct { +} + +func (m *CustomInfoType_SurrogateType) Reset() { *m = CustomInfoType_SurrogateType{} } +func (m *CustomInfoType_SurrogateType) String() string { return proto.CompactTextString(m) } +func (*CustomInfoType_SurrogateType) ProtoMessage() {} +func (*CustomInfoType_SurrogateType) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{1, 1} } + +// General identifier of a data field in a storage service. +type FieldId struct { + // Name describing the field. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` +} + +func (m *FieldId) Reset() { *m = FieldId{} } +func (m *FieldId) String() string { return proto.CompactTextString(m) } +func (*FieldId) ProtoMessage() {} +func (*FieldId) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{2} } + +func (m *FieldId) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +// Datastore partition ID. +// A partition ID identifies a grouping of entities. The grouping is always +// by project and namespace, however the namespace ID may be empty. +// +// A partition ID contains several dimensions: +// project ID and namespace ID. +type PartitionId struct { + // The ID of the project to which the entities belong. + ProjectId string `protobuf:"bytes,2,opt,name=project_id,json=projectId" json:"project_id,omitempty"` + // If not empty, the ID of the namespace to which the entities belong. + NamespaceId string `protobuf:"bytes,4,opt,name=namespace_id,json=namespaceId" json:"namespace_id,omitempty"` +} + +func (m *PartitionId) Reset() { *m = PartitionId{} } +func (m *PartitionId) String() string { return proto.CompactTextString(m) } +func (*PartitionId) ProtoMessage() {} +func (*PartitionId) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{3} } + +func (m *PartitionId) GetProjectId() string { + if m != nil { + return m.ProjectId + } + return "" +} + +func (m *PartitionId) GetNamespaceId() string { + if m != nil { + return m.NamespaceId + } + return "" +} + +// A representation of a Datastore kind. +type KindExpression struct { + // The name of the kind. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` +} + +func (m *KindExpression) Reset() { *m = KindExpression{} } +func (m *KindExpression) String() string { return proto.CompactTextString(m) } +func (*KindExpression) ProtoMessage() {} +func (*KindExpression) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{4} } + +func (m *KindExpression) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +// Options defining a data set within Google Cloud Datastore. +type DatastoreOptions struct { + // A partition ID identifies a grouping of entities. The grouping is always + // by project and namespace, however the namespace ID may be empty. + PartitionId *PartitionId `protobuf:"bytes,1,opt,name=partition_id,json=partitionId" json:"partition_id,omitempty"` + // The kind to process. + Kind *KindExpression `protobuf:"bytes,2,opt,name=kind" json:"kind,omitempty"` +} + +func (m *DatastoreOptions) Reset() { *m = DatastoreOptions{} } +func (m *DatastoreOptions) String() string { return proto.CompactTextString(m) } +func (*DatastoreOptions) ProtoMessage() {} +func (*DatastoreOptions) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{5} } + +func (m *DatastoreOptions) GetPartitionId() *PartitionId { + if m != nil { + return m.PartitionId + } + return nil +} + +func (m *DatastoreOptions) GetKind() *KindExpression { + if m != nil { + return m.Kind + } + return nil +} + +// Options defining a file or a set of files (path ending with *) within +// a Google Cloud Storage bucket. +type CloudStorageOptions struct { + FileSet *CloudStorageOptions_FileSet `protobuf:"bytes,1,opt,name=file_set,json=fileSet" json:"file_set,omitempty"` +} + +func (m *CloudStorageOptions) Reset() { *m = CloudStorageOptions{} } +func (m *CloudStorageOptions) String() string { return proto.CompactTextString(m) } +func (*CloudStorageOptions) ProtoMessage() {} +func (*CloudStorageOptions) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{6} } + +func (m *CloudStorageOptions) GetFileSet() *CloudStorageOptions_FileSet { + if m != nil { + return m.FileSet + } + return nil +} + +// Set of files to scan. +type CloudStorageOptions_FileSet struct { + // The url, in the format `gs:///`. Trailing wildcard in the + // path is allowed. + Url string `protobuf:"bytes,1,opt,name=url" json:"url,omitempty"` +} + +func (m *CloudStorageOptions_FileSet) Reset() { *m = CloudStorageOptions_FileSet{} } +func (m *CloudStorageOptions_FileSet) String() string { return proto.CompactTextString(m) } +func (*CloudStorageOptions_FileSet) ProtoMessage() {} +func (*CloudStorageOptions_FileSet) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{6, 0} } + +func (m *CloudStorageOptions_FileSet) GetUrl() string { + if m != nil { + return m.Url + } + return "" +} + +// Options defining BigQuery table and row identifiers. +type BigQueryOptions struct { + // Complete BigQuery table reference. + TableReference *BigQueryTable `protobuf:"bytes,1,opt,name=table_reference,json=tableReference" json:"table_reference,omitempty"` + // References to fields uniquely identifying rows within the table. + // Nested fields in the format, like `person.birthdate.year`, are allowed. + IdentifyingFields []*FieldId `protobuf:"bytes,2,rep,name=identifying_fields,json=identifyingFields" json:"identifying_fields,omitempty"` +} + +func (m *BigQueryOptions) Reset() { *m = BigQueryOptions{} } +func (m *BigQueryOptions) String() string { return proto.CompactTextString(m) } +func (*BigQueryOptions) ProtoMessage() {} +func (*BigQueryOptions) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{7} } + +func (m *BigQueryOptions) GetTableReference() *BigQueryTable { + if m != nil { + return m.TableReference + } + return nil +} + +func (m *BigQueryOptions) GetIdentifyingFields() []*FieldId { + if m != nil { + return m.IdentifyingFields + } + return nil +} + +// Shared message indicating Cloud storage type. +type StorageConfig struct { + // Types that are valid to be assigned to Type: + // *StorageConfig_DatastoreOptions + // *StorageConfig_CloudStorageOptions + // *StorageConfig_BigQueryOptions + Type isStorageConfig_Type `protobuf_oneof:"type"` +} + +func (m *StorageConfig) Reset() { *m = StorageConfig{} } +func (m *StorageConfig) String() string { return proto.CompactTextString(m) } +func (*StorageConfig) ProtoMessage() {} +func (*StorageConfig) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{8} } + +type isStorageConfig_Type interface { + isStorageConfig_Type() +} + +type StorageConfig_DatastoreOptions struct { + DatastoreOptions *DatastoreOptions `protobuf:"bytes,2,opt,name=datastore_options,json=datastoreOptions,oneof"` +} +type StorageConfig_CloudStorageOptions struct { + CloudStorageOptions *CloudStorageOptions `protobuf:"bytes,3,opt,name=cloud_storage_options,json=cloudStorageOptions,oneof"` +} +type StorageConfig_BigQueryOptions struct { + BigQueryOptions *BigQueryOptions `protobuf:"bytes,4,opt,name=big_query_options,json=bigQueryOptions,oneof"` +} + +func (*StorageConfig_DatastoreOptions) isStorageConfig_Type() {} +func (*StorageConfig_CloudStorageOptions) isStorageConfig_Type() {} +func (*StorageConfig_BigQueryOptions) isStorageConfig_Type() {} + +func (m *StorageConfig) GetType() isStorageConfig_Type { + if m != nil { + return m.Type + } + return nil +} + +func (m *StorageConfig) GetDatastoreOptions() *DatastoreOptions { + if x, ok := m.GetType().(*StorageConfig_DatastoreOptions); ok { + return x.DatastoreOptions + } + return nil +} + +func (m *StorageConfig) GetCloudStorageOptions() *CloudStorageOptions { + if x, ok := m.GetType().(*StorageConfig_CloudStorageOptions); ok { + return x.CloudStorageOptions + } + return nil +} + +func (m *StorageConfig) GetBigQueryOptions() *BigQueryOptions { + if x, ok := m.GetType().(*StorageConfig_BigQueryOptions); ok { + return x.BigQueryOptions + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*StorageConfig) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _StorageConfig_OneofMarshaler, _StorageConfig_OneofUnmarshaler, _StorageConfig_OneofSizer, []interface{}{ + (*StorageConfig_DatastoreOptions)(nil), + (*StorageConfig_CloudStorageOptions)(nil), + (*StorageConfig_BigQueryOptions)(nil), + } +} + +func _StorageConfig_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*StorageConfig) + // type + switch x := m.Type.(type) { + case *StorageConfig_DatastoreOptions: + b.EncodeVarint(2<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.DatastoreOptions); err != nil { + return err + } + case *StorageConfig_CloudStorageOptions: + b.EncodeVarint(3<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.CloudStorageOptions); err != nil { + return err + } + case *StorageConfig_BigQueryOptions: + b.EncodeVarint(4<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.BigQueryOptions); err != nil { + return err + } + case nil: + default: + return fmt.Errorf("StorageConfig.Type has unexpected type %T", x) + } + return nil +} + +func _StorageConfig_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*StorageConfig) + switch tag { + case 2: // type.datastore_options + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(DatastoreOptions) + err := b.DecodeMessage(msg) + m.Type = &StorageConfig_DatastoreOptions{msg} + return true, err + case 3: // type.cloud_storage_options + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(CloudStorageOptions) + err := b.DecodeMessage(msg) + m.Type = &StorageConfig_CloudStorageOptions{msg} + return true, err + case 4: // type.big_query_options + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(BigQueryOptions) + err := b.DecodeMessage(msg) + m.Type = &StorageConfig_BigQueryOptions{msg} + return true, err + default: + return false, nil + } +} + +func _StorageConfig_OneofSizer(msg proto.Message) (n int) { + m := msg.(*StorageConfig) + // type + switch x := m.Type.(type) { + case *StorageConfig_DatastoreOptions: + s := proto.Size(x.DatastoreOptions) + n += proto.SizeVarint(2<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *StorageConfig_CloudStorageOptions: + s := proto.Size(x.CloudStorageOptions) + n += proto.SizeVarint(3<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *StorageConfig_BigQueryOptions: + s := proto.Size(x.BigQueryOptions) + n += proto.SizeVarint(4<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +// Record key for a finding in a Cloud Storage file. +type CloudStorageKey struct { + // Path to the file. + FilePath string `protobuf:"bytes,1,opt,name=file_path,json=filePath" json:"file_path,omitempty"` + // Byte offset of the referenced data in the file. + StartOffset int64 `protobuf:"varint,2,opt,name=start_offset,json=startOffset" json:"start_offset,omitempty"` +} + +func (m *CloudStorageKey) Reset() { *m = CloudStorageKey{} } +func (m *CloudStorageKey) String() string { return proto.CompactTextString(m) } +func (*CloudStorageKey) ProtoMessage() {} +func (*CloudStorageKey) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{9} } + +func (m *CloudStorageKey) GetFilePath() string { + if m != nil { + return m.FilePath + } + return "" +} + +func (m *CloudStorageKey) GetStartOffset() int64 { + if m != nil { + return m.StartOffset + } + return 0 +} + +// Record key for a finding in Cloud Datastore. +type DatastoreKey struct { + // Datastore entity key. + EntityKey *Key `protobuf:"bytes,1,opt,name=entity_key,json=entityKey" json:"entity_key,omitempty"` +} + +func (m *DatastoreKey) Reset() { *m = DatastoreKey{} } +func (m *DatastoreKey) String() string { return proto.CompactTextString(m) } +func (*DatastoreKey) ProtoMessage() {} +func (*DatastoreKey) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{10} } + +func (m *DatastoreKey) GetEntityKey() *Key { + if m != nil { + return m.EntityKey + } + return nil +} + +// A unique identifier for a Datastore entity. +// If a key's partition ID or any of its path kinds or names are +// reserved/read-only, the key is reserved/read-only. +// A reserved/read-only key is forbidden in certain documented contexts. +type Key struct { + // Entities are partitioned into subsets, currently identified by a project + // ID and namespace ID. + // Queries are scoped to a single partition. + PartitionId *PartitionId `protobuf:"bytes,1,opt,name=partition_id,json=partitionId" json:"partition_id,omitempty"` + // The entity path. + // An entity path consists of one or more elements composed of a kind and a + // string or numerical identifier, which identify entities. The first + // element identifies a _root entity_, the second element identifies + // a _child_ of the root entity, the third element identifies a child of the + // second entity, and so forth. The entities identified by all prefixes of + // the path are called the element's _ancestors_. + // + // A path can never be empty, and a path can have at most 100 elements. + Path []*Key_PathElement `protobuf:"bytes,2,rep,name=path" json:"path,omitempty"` +} + +func (m *Key) Reset() { *m = Key{} } +func (m *Key) String() string { return proto.CompactTextString(m) } +func (*Key) ProtoMessage() {} +func (*Key) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{11} } + +func (m *Key) GetPartitionId() *PartitionId { + if m != nil { + return m.PartitionId + } + return nil +} + +func (m *Key) GetPath() []*Key_PathElement { + if m != nil { + return m.Path + } + return nil +} + +// A (kind, ID/name) pair used to construct a key path. +// +// If either name or ID is set, the element is complete. +// If neither is set, the element is incomplete. +type Key_PathElement struct { + // The kind of the entity. + // A kind matching regex `__.*__` is reserved/read-only. + // A kind must not contain more than 1500 bytes when UTF-8 encoded. + // Cannot be `""`. + Kind string `protobuf:"bytes,1,opt,name=kind" json:"kind,omitempty"` + // The type of ID. + // + // Types that are valid to be assigned to IdType: + // *Key_PathElement_Id + // *Key_PathElement_Name + IdType isKey_PathElement_IdType `protobuf_oneof:"id_type"` +} + +func (m *Key_PathElement) Reset() { *m = Key_PathElement{} } +func (m *Key_PathElement) String() string { return proto.CompactTextString(m) } +func (*Key_PathElement) ProtoMessage() {} +func (*Key_PathElement) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{11, 0} } + +type isKey_PathElement_IdType interface { + isKey_PathElement_IdType() +} + +type Key_PathElement_Id struct { + Id int64 `protobuf:"varint,2,opt,name=id,oneof"` +} +type Key_PathElement_Name struct { + Name string `protobuf:"bytes,3,opt,name=name,oneof"` +} + +func (*Key_PathElement_Id) isKey_PathElement_IdType() {} +func (*Key_PathElement_Name) isKey_PathElement_IdType() {} + +func (m *Key_PathElement) GetIdType() isKey_PathElement_IdType { + if m != nil { + return m.IdType + } + return nil +} + +func (m *Key_PathElement) GetKind() string { + if m != nil { + return m.Kind + } + return "" +} + +func (m *Key_PathElement) GetId() int64 { + if x, ok := m.GetIdType().(*Key_PathElement_Id); ok { + return x.Id + } + return 0 +} + +func (m *Key_PathElement) GetName() string { + if x, ok := m.GetIdType().(*Key_PathElement_Name); ok { + return x.Name + } + return "" +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*Key_PathElement) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _Key_PathElement_OneofMarshaler, _Key_PathElement_OneofUnmarshaler, _Key_PathElement_OneofSizer, []interface{}{ + (*Key_PathElement_Id)(nil), + (*Key_PathElement_Name)(nil), + } +} + +func _Key_PathElement_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*Key_PathElement) + // id_type + switch x := m.IdType.(type) { + case *Key_PathElement_Id: + b.EncodeVarint(2<<3 | proto.WireVarint) + b.EncodeVarint(uint64(x.Id)) + case *Key_PathElement_Name: + b.EncodeVarint(3<<3 | proto.WireBytes) + b.EncodeStringBytes(x.Name) + case nil: + default: + return fmt.Errorf("Key_PathElement.IdType has unexpected type %T", x) + } + return nil +} + +func _Key_PathElement_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*Key_PathElement) + switch tag { + case 2: // id_type.id + if wire != proto.WireVarint { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeVarint() + m.IdType = &Key_PathElement_Id{int64(x)} + return true, err + case 3: // id_type.name + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeStringBytes() + m.IdType = &Key_PathElement_Name{x} + return true, err + default: + return false, nil + } +} + +func _Key_PathElement_OneofSizer(msg proto.Message) (n int) { + m := msg.(*Key_PathElement) + // id_type + switch x := m.IdType.(type) { + case *Key_PathElement_Id: + n += proto.SizeVarint(2<<3 | proto.WireVarint) + n += proto.SizeVarint(uint64(x.Id)) + case *Key_PathElement_Name: + n += proto.SizeVarint(3<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.Name))) + n += len(x.Name) + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +// Message for a unique key indicating a record that contains a finding. +type RecordKey struct { + // Types that are valid to be assigned to Type: + // *RecordKey_CloudStorageKey + // *RecordKey_DatastoreKey + Type isRecordKey_Type `protobuf_oneof:"type"` +} + +func (m *RecordKey) Reset() { *m = RecordKey{} } +func (m *RecordKey) String() string { return proto.CompactTextString(m) } +func (*RecordKey) ProtoMessage() {} +func (*RecordKey) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{12} } + +type isRecordKey_Type interface { + isRecordKey_Type() +} + +type RecordKey_CloudStorageKey struct { + CloudStorageKey *CloudStorageKey `protobuf:"bytes,1,opt,name=cloud_storage_key,json=cloudStorageKey,oneof"` +} +type RecordKey_DatastoreKey struct { + DatastoreKey *DatastoreKey `protobuf:"bytes,2,opt,name=datastore_key,json=datastoreKey,oneof"` +} + +func (*RecordKey_CloudStorageKey) isRecordKey_Type() {} +func (*RecordKey_DatastoreKey) isRecordKey_Type() {} + +func (m *RecordKey) GetType() isRecordKey_Type { + if m != nil { + return m.Type + } + return nil +} + +func (m *RecordKey) GetCloudStorageKey() *CloudStorageKey { + if x, ok := m.GetType().(*RecordKey_CloudStorageKey); ok { + return x.CloudStorageKey + } + return nil +} + +func (m *RecordKey) GetDatastoreKey() *DatastoreKey { + if x, ok := m.GetType().(*RecordKey_DatastoreKey); ok { + return x.DatastoreKey + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*RecordKey) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _RecordKey_OneofMarshaler, _RecordKey_OneofUnmarshaler, _RecordKey_OneofSizer, []interface{}{ + (*RecordKey_CloudStorageKey)(nil), + (*RecordKey_DatastoreKey)(nil), + } +} + +func _RecordKey_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*RecordKey) + // type + switch x := m.Type.(type) { + case *RecordKey_CloudStorageKey: + b.EncodeVarint(1<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.CloudStorageKey); err != nil { + return err + } + case *RecordKey_DatastoreKey: + b.EncodeVarint(2<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.DatastoreKey); err != nil { + return err + } + case nil: + default: + return fmt.Errorf("RecordKey.Type has unexpected type %T", x) + } + return nil +} + +func _RecordKey_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*RecordKey) + switch tag { + case 1: // type.cloud_storage_key + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(CloudStorageKey) + err := b.DecodeMessage(msg) + m.Type = &RecordKey_CloudStorageKey{msg} + return true, err + case 2: // type.datastore_key + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(DatastoreKey) + err := b.DecodeMessage(msg) + m.Type = &RecordKey_DatastoreKey{msg} + return true, err + default: + return false, nil + } +} + +func _RecordKey_OneofSizer(msg proto.Message) (n int) { + m := msg.(*RecordKey) + // type + switch x := m.Type.(type) { + case *RecordKey_CloudStorageKey: + s := proto.Size(x.CloudStorageKey) + n += proto.SizeVarint(1<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *RecordKey_DatastoreKey: + s := proto.Size(x.DatastoreKey) + n += proto.SizeVarint(2<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +// Message defining the location of a BigQuery table. A table is uniquely +// identified by its project_id, dataset_id, and table_name. Within a query +// a table is often referenced with a string in the format of: +// `:.` or +// `..`. +type BigQueryTable struct { + // The Google Cloud Platform project ID of the project containing the table. + // If omitted, project ID is inferred from the API call. + ProjectId string `protobuf:"bytes,1,opt,name=project_id,json=projectId" json:"project_id,omitempty"` + // Dataset ID of the table. + DatasetId string `protobuf:"bytes,2,opt,name=dataset_id,json=datasetId" json:"dataset_id,omitempty"` + // Name of the table. + TableId string `protobuf:"bytes,3,opt,name=table_id,json=tableId" json:"table_id,omitempty"` +} + +func (m *BigQueryTable) Reset() { *m = BigQueryTable{} } +func (m *BigQueryTable) String() string { return proto.CompactTextString(m) } +func (*BigQueryTable) ProtoMessage() {} +func (*BigQueryTable) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{13} } + +func (m *BigQueryTable) GetProjectId() string { + if m != nil { + return m.ProjectId + } + return "" +} + +func (m *BigQueryTable) GetDatasetId() string { + if m != nil { + return m.DatasetId + } + return "" +} + +func (m *BigQueryTable) GetTableId() string { + if m != nil { + return m.TableId + } + return "" +} + +// An entity in a dataset is a field or set of fields that correspond to a +// single person. For example, in medical records the `EntityId` might be +// a patient identifier, or for financial records it might be an account +// identifier. This message is used when generalizations or analysis must be +// consistent across multiple rows pertaining to the same entity. +type EntityId struct { + // Composite key indicating which field contains the entity identifier. + Field *FieldId `protobuf:"bytes,1,opt,name=field" json:"field,omitempty"` +} + +func (m *EntityId) Reset() { *m = EntityId{} } +func (m *EntityId) String() string { return proto.CompactTextString(m) } +func (*EntityId) ProtoMessage() {} +func (*EntityId) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{14} } + +func (m *EntityId) GetField() *FieldId { + if m != nil { + return m.Field + } + return nil +} + +func init() { + proto.RegisterType((*InfoType)(nil), "google.privacy.dlp.v2beta2.InfoType") + proto.RegisterType((*CustomInfoType)(nil), "google.privacy.dlp.v2beta2.CustomInfoType") + proto.RegisterType((*CustomInfoType_Dictionary)(nil), "google.privacy.dlp.v2beta2.CustomInfoType.Dictionary") + proto.RegisterType((*CustomInfoType_Dictionary_WordList)(nil), "google.privacy.dlp.v2beta2.CustomInfoType.Dictionary.WordList") + proto.RegisterType((*CustomInfoType_SurrogateType)(nil), "google.privacy.dlp.v2beta2.CustomInfoType.SurrogateType") + proto.RegisterType((*FieldId)(nil), "google.privacy.dlp.v2beta2.FieldId") + proto.RegisterType((*PartitionId)(nil), "google.privacy.dlp.v2beta2.PartitionId") + proto.RegisterType((*KindExpression)(nil), "google.privacy.dlp.v2beta2.KindExpression") + proto.RegisterType((*DatastoreOptions)(nil), "google.privacy.dlp.v2beta2.DatastoreOptions") + proto.RegisterType((*CloudStorageOptions)(nil), "google.privacy.dlp.v2beta2.CloudStorageOptions") + proto.RegisterType((*CloudStorageOptions_FileSet)(nil), "google.privacy.dlp.v2beta2.CloudStorageOptions.FileSet") + proto.RegisterType((*BigQueryOptions)(nil), "google.privacy.dlp.v2beta2.BigQueryOptions") + proto.RegisterType((*StorageConfig)(nil), "google.privacy.dlp.v2beta2.StorageConfig") + proto.RegisterType((*CloudStorageKey)(nil), "google.privacy.dlp.v2beta2.CloudStorageKey") + proto.RegisterType((*DatastoreKey)(nil), "google.privacy.dlp.v2beta2.DatastoreKey") + proto.RegisterType((*Key)(nil), "google.privacy.dlp.v2beta2.Key") + proto.RegisterType((*Key_PathElement)(nil), "google.privacy.dlp.v2beta2.Key.PathElement") + proto.RegisterType((*RecordKey)(nil), "google.privacy.dlp.v2beta2.RecordKey") + proto.RegisterType((*BigQueryTable)(nil), "google.privacy.dlp.v2beta2.BigQueryTable") + proto.RegisterType((*EntityId)(nil), "google.privacy.dlp.v2beta2.EntityId") + proto.RegisterEnum("google.privacy.dlp.v2beta2.Likelihood", Likelihood_name, Likelihood_value) +} + +func init() { proto.RegisterFile("google/privacy/dlp/v2beta2/storage.proto", fileDescriptor1) } + +var fileDescriptor1 = []byte{ + // 1100 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0xdf, 0x6e, 0xe3, 0xc4, + 0x17, 0x8e, 0x93, 0xb4, 0x4d, 0x4e, 0x9a, 0x26, 0x9d, 0xdd, 0xdf, 0x4f, 0x25, 0x4b, 0x77, 0x4b, + 0x58, 0x89, 0xb2, 0x45, 0x8e, 0x54, 0x84, 0x00, 0x21, 0x8a, 0x48, 0x93, 0x12, 0xd3, 0xaa, 0xe9, + 0x4e, 0xba, 0x5d, 0x15, 0x8a, 0x2c, 0x27, 0x33, 0x71, 0x87, 0x3a, 0x1e, 0x63, 0x4f, 0x76, 0xc9, + 0x0b, 0xf0, 0x0a, 0xdc, 0x71, 0xc3, 0x1d, 0x0f, 0x80, 0xc4, 0x15, 0x12, 0x97, 0x3c, 0x09, 0x8f, + 0x81, 0xe6, 0x8f, 0xd3, 0xa4, 0x94, 0xd0, 0x45, 0xdc, 0xcd, 0x9c, 0x39, 0xe7, 0x9b, 0x6f, 0xce, + 0xf9, 0xce, 0xb1, 0x61, 0xdb, 0xe7, 0xdc, 0x0f, 0x68, 0x23, 0x8a, 0xd9, 0x0b, 0x6f, 0x30, 0x69, + 0x90, 0x20, 0x6a, 0xbc, 0xd8, 0xed, 0x53, 0xe1, 0xed, 0x36, 0x12, 0xc1, 0x63, 0xcf, 0xa7, 0x76, + 0x14, 0x73, 0xc1, 0x51, 0x4d, 0x7b, 0xda, 0xc6, 0xd3, 0x26, 0x41, 0x64, 0x1b, 0xcf, 0xda, 0xeb, + 0x06, 0xc5, 0x8b, 0x58, 0xc3, 0x0b, 0x43, 0x2e, 0x3c, 0xc1, 0x78, 0x98, 0xe8, 0xc8, 0xda, 0xa3, + 0xe9, 0x1d, 0x5c, 0xf0, 0xfe, 0x78, 0xd8, 0x10, 0x6c, 0x44, 0x13, 0xe1, 0x8d, 0x22, 0xed, 0x50, + 0x7f, 0x08, 0x05, 0x27, 0x1c, 0xf2, 0xd3, 0x49, 0x44, 0x11, 0x82, 0x7c, 0xe8, 0x8d, 0xe8, 0x86, + 0xb5, 0x65, 0x6d, 0x17, 0xb1, 0x5a, 0xd7, 0x7f, 0xcb, 0xc1, 0xda, 0xfe, 0x38, 0x11, 0x7c, 0x34, + 0x75, 0xfb, 0x14, 0x8a, 0x2c, 0x1c, 0x72, 0x57, 0x4c, 0x22, 0xed, 0x5b, 0xda, 0x7d, 0x6c, 0xff, + 0x3d, 0x43, 0x3b, 0x0d, 0xc4, 0x05, 0x96, 0x42, 0x3c, 0x07, 0x20, 0x6c, 0x20, 0x89, 0x7a, 0xf1, + 0x64, 0x23, 0xab, 0x30, 0xde, 0x5b, 0x84, 0x31, 0x4f, 0xc1, 0x6e, 0x4d, 0x83, 0x3b, 0x19, 0x3c, + 0x03, 0x85, 0x3c, 0x58, 0x4b, 0xc6, 0x71, 0xcc, 0x7d, 0x4f, 0x50, 0x4d, 0x30, 0xaf, 0xc0, 0x3f, + 0x78, 0x05, 0xf0, 0x5e, 0x0a, 0x20, 0x77, 0x9d, 0x0c, 0x2e, 0x27, 0xb3, 0x86, 0xda, 0xf7, 0x16, + 0xc0, 0xf5, 0xfd, 0xe8, 0x2b, 0x28, 0xbe, 0xe4, 0x31, 0x71, 0x03, 0x96, 0x08, 0x93, 0x8d, 0xbd, + 0x7f, 0xf5, 0x12, 0xfb, 0x39, 0x8f, 0xc9, 0x11, 0x4b, 0x44, 0x27, 0x83, 0x0b, 0x2f, 0xcd, 0xba, + 0xb6, 0x05, 0x85, 0xd4, 0x8e, 0xee, 0xc3, 0x92, 0xb4, 0x27, 0x1b, 0xd6, 0x56, 0x6e, 0xbb, 0x88, + 0xf5, 0xa6, 0x59, 0x80, 0xe5, 0x84, 0x8f, 0xe3, 0x01, 0xad, 0x55, 0xa0, 0x3c, 0xc7, 0xbd, 0xb9, + 0x0c, 0x79, 0x99, 0x83, 0xfa, 0x26, 0xac, 0x1c, 0x30, 0x1a, 0x10, 0x87, 0xdc, 0x5a, 0xe3, 0x2e, + 0x94, 0x4e, 0xbc, 0x58, 0x30, 0x49, 0xc4, 0x21, 0x68, 0x13, 0x20, 0x8a, 0xf9, 0xd7, 0x74, 0x20, + 0x5c, 0x46, 0x54, 0x71, 0x8a, 0xb8, 0x68, 0x2c, 0x0e, 0x41, 0x6f, 0xc0, 0xaa, 0x8c, 0x4a, 0x22, + 0x6f, 0x40, 0xa5, 0x43, 0x5e, 0x39, 0x94, 0xa6, 0x36, 0x87, 0xd4, 0x1f, 0xc3, 0xda, 0x21, 0x0b, + 0x49, 0xfb, 0xdb, 0x28, 0xa6, 0x49, 0xc2, 0x78, 0x78, 0xeb, 0xb5, 0x3f, 0x58, 0x50, 0x6d, 0x79, + 0xc2, 0x93, 0x5a, 0xa7, 0xdd, 0x48, 0xc9, 0x16, 0x7d, 0x0e, 0xab, 0x51, 0xca, 0x45, 0xa2, 0xeb, + 0x8c, 0xbe, 0xb5, 0x28, 0xa3, 0x33, 0xdc, 0x71, 0x29, 0x9a, 0x79, 0xc8, 0x1e, 0xe4, 0xaf, 0x58, + 0x48, 0x8c, 0xbe, 0x9e, 0x2c, 0xc2, 0x98, 0xa7, 0x8b, 0x55, 0x5c, 0xfd, 0x3b, 0x0b, 0xee, 0xed, + 0x07, 0x7c, 0x4c, 0x7a, 0xba, 0x1b, 0x53, 0x8e, 0x18, 0x0a, 0x43, 0x16, 0x50, 0x37, 0xa1, 0x69, + 0xc5, 0xdf, 0x5f, 0x58, 0xf1, 0xbf, 0x42, 0xd8, 0x07, 0x2c, 0xa0, 0x3d, 0x2a, 0xf0, 0xca, 0x50, + 0x2f, 0x6a, 0x0f, 0x64, 0x89, 0xd4, 0x12, 0x55, 0x21, 0x37, 0x8e, 0x03, 0x93, 0x2a, 0xb9, 0xac, + 0xff, 0x62, 0x41, 0xa5, 0xc9, 0xfc, 0xa7, 0x63, 0x1a, 0x4f, 0xae, 0x49, 0x54, 0x84, 0xd7, 0x0f, + 0xa8, 0x1b, 0xd3, 0x21, 0x8d, 0x69, 0x38, 0x48, 0x7b, 0xf1, 0xed, 0x45, 0x5c, 0x52, 0x94, 0x53, + 0x19, 0x8a, 0xd7, 0x14, 0x02, 0x4e, 0x01, 0x10, 0x06, 0xc4, 0x08, 0x0d, 0x05, 0x1b, 0x4e, 0x58, + 0xe8, 0xbb, 0x43, 0xa9, 0x99, 0x64, 0x23, 0xbb, 0x95, 0xdb, 0x2e, 0xed, 0xbe, 0xb9, 0x08, 0xd6, + 0xa8, 0x0b, 0xaf, 0xcf, 0x84, 0x2b, 0x5b, 0x52, 0xff, 0x39, 0x0b, 0x65, 0xf3, 0xf8, 0x7d, 0x1e, + 0x0e, 0x99, 0x8f, 0xbe, 0x84, 0x75, 0x92, 0x96, 0xdd, 0xe5, 0xfa, 0x39, 0xa6, 0x46, 0xef, 0x2c, + 0xba, 0xe4, 0xa6, 0x56, 0x3a, 0x19, 0x5c, 0x25, 0x37, 0xf5, 0x43, 0xe1, 0x7f, 0x03, 0x99, 0x6f, + 0xd7, 0x4c, 0xd0, 0xe9, 0x05, 0x39, 0x75, 0x41, 0xe3, 0x15, 0x0b, 0xd5, 0xc9, 0xe0, 0x7b, 0x83, + 0x5b, 0x24, 0x70, 0x0e, 0xeb, 0x7d, 0xe6, 0xbb, 0xdf, 0xc8, 0x5c, 0x4e, 0xaf, 0xd0, 0xa3, 0x66, + 0xe7, 0x2e, 0xf9, 0xbf, 0x86, 0xaf, 0xf4, 0xe7, 0x4d, 0xd3, 0xa6, 0x7d, 0x0a, 0x95, 0x59, 0x42, + 0x87, 0x74, 0x82, 0x1e, 0x40, 0x51, 0x09, 0x2f, 0xf2, 0xc4, 0xa5, 0xd1, 0x87, 0x52, 0xe2, 0x89, + 0x27, 0x2e, 0x65, 0x5f, 0x26, 0xc2, 0x8b, 0x85, 0xcb, 0x87, 0x43, 0xa9, 0x4c, 0x99, 0xd1, 0x1c, + 0x2e, 0x29, 0x5b, 0x57, 0x99, 0xea, 0xc7, 0xb0, 0x3a, 0x4d, 0xa2, 0xc4, 0xdb, 0x03, 0x90, 0xe5, + 0x12, 0x13, 0xf7, 0x8a, 0x4e, 0x8c, 0x7c, 0x1e, 0x2d, 0x6c, 0x13, 0x3a, 0xc1, 0x45, 0x1d, 0x72, + 0x48, 0x27, 0xf5, 0x3f, 0x2c, 0xc8, 0x49, 0x9c, 0xff, 0xb2, 0x69, 0x3f, 0x81, 0xbc, 0x7a, 0x9e, + 0x56, 0xdd, 0xce, 0x3f, 0xb0, 0xb1, 0xe5, 0xd3, 0xdb, 0x01, 0x1d, 0xd1, 0x50, 0x60, 0x15, 0x58, + 0x3b, 0x95, 0xd3, 0x6c, 0x6a, 0x94, 0x93, 0x47, 0x0d, 0x01, 0x33, 0x79, 0xe4, 0x1a, 0x55, 0x21, + 0x6b, 0x26, 0x5b, 0xae, 0x93, 0xc1, 0x59, 0x46, 0xd0, 0x7d, 0x33, 0x9f, 0xa4, 0x4a, 0x8a, 0x9d, + 0x8c, 0x9e, 0x50, 0xcd, 0x22, 0xac, 0x30, 0xa2, 0x3e, 0x23, 0xf5, 0x5f, 0x2d, 0x28, 0x62, 0x3a, + 0xe0, 0x31, 0x91, 0x0f, 0x3e, 0x87, 0xf5, 0x79, 0x95, 0x5d, 0xe7, 0x6f, 0xe7, 0xae, 0x0a, 0x3b, + 0xa4, 0xf2, 0xe3, 0x55, 0x19, 0xdc, 0xa8, 0x71, 0x17, 0xca, 0xd7, 0xdd, 0x21, 0x61, 0x75, 0x67, + 0x6c, 0xdf, 0xa9, 0x33, 0x34, 0xe6, 0x2a, 0x99, 0xd9, 0x4f, 0xf5, 0x74, 0x09, 0xe5, 0xb9, 0xee, + 0xbf, 0x31, 0xe7, 0xad, 0x9b, 0x73, 0x7e, 0x13, 0x40, 0xe1, 0xd0, 0xd9, 0xcf, 0x80, 0xb1, 0x38, + 0x04, 0xbd, 0x06, 0x05, 0x3d, 0x7f, 0x18, 0xd1, 0x59, 0xc3, 0x2b, 0x6a, 0xef, 0x90, 0x7a, 0x1b, + 0x0a, 0x6d, 0xa5, 0x11, 0x87, 0xa0, 0x0f, 0x61, 0x49, 0x8d, 0x11, 0x93, 0x9d, 0x3b, 0x4d, 0x11, + 0x1d, 0xf1, 0x44, 0x00, 0x1c, 0xb1, 0x2b, 0x1a, 0xb0, 0x4b, 0xce, 0x09, 0xaa, 0xc1, 0xff, 0x8f, + 0x9c, 0xc3, 0xf6, 0x91, 0xd3, 0xe9, 0x76, 0x5b, 0xee, 0xb3, 0xe3, 0xde, 0x49, 0x7b, 0xdf, 0x39, + 0x70, 0xda, 0xad, 0x6a, 0x06, 0xad, 0x43, 0xf9, 0xac, 0x8d, 0xcf, 0xdd, 0x67, 0xc7, 0xca, 0xe5, + 0xbc, 0x6a, 0xa1, 0x55, 0x28, 0x4c, 0x77, 0x59, 0xb9, 0x3b, 0xe9, 0xf6, 0x7a, 0x4e, 0xf3, 0xa8, + 0x5d, 0xcd, 0x21, 0x80, 0x65, 0x73, 0x92, 0x47, 0x15, 0x28, 0xa9, 0x50, 0x63, 0x58, 0x6a, 0xfe, + 0x68, 0xc1, 0xc3, 0x01, 0x1f, 0x2d, 0xe0, 0xd9, 0x84, 0x56, 0x10, 0x99, 0x8a, 0x9d, 0x58, 0x5f, + 0x7c, 0x6c, 0x3c, 0x7d, 0x1e, 0x78, 0xa1, 0x6f, 0xf3, 0xd8, 0x6f, 0xf8, 0x34, 0x54, 0x7f, 0x57, + 0x0d, 0x7d, 0xe4, 0x45, 0x2c, 0xb9, 0xed, 0x2f, 0xef, 0x23, 0x12, 0x44, 0x3f, 0x65, 0x37, 0x3e, + 0xd3, 0xf1, 0x4a, 0x1b, 0x76, 0x2b, 0x88, 0xec, 0xb3, 0xdd, 0xa6, 0x3c, 0xfe, 0x3d, 0x3d, 0xba, + 0x50, 0x47, 0x17, 0xad, 0x20, 0xba, 0x38, 0xd3, 0x91, 0xfd, 0x65, 0x85, 0xff, 0xee, 0x9f, 0x01, + 0x00, 0x00, 0xff, 0xff, 0x8f, 0x4f, 0x2f, 0x44, 0x44, 0x0a, 0x00, 0x00, +} diff --git a/vendor/google.golang.org/genproto/protobuf/field_mask/field_mask.pb.go b/vendor/google.golang.org/genproto/protobuf/field_mask/field_mask.pb.go index 485bf0066f3ae246aa0e7e3684343b7f1a156708..42693d6869ce90a061960d74371dcb6b83042cea 100644 --- a/vendor/google.golang.org/genproto/protobuf/field_mask/field_mask.pb.go +++ b/vendor/google.golang.org/genproto/protobuf/field_mask/field_mask.pb.go @@ -228,6 +228,12 @@ const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package // // Note that oneof type names ("test_oneof" in this case) cannot be used in // paths. +// +// ## Field Mask Verification +// +// The implementation of the all the API methods, which have any FieldMask type +// field in the request, should verify the included field paths, and return +// `INVALID_ARGUMENT` error if any path is duplicated or unmappable. type FieldMask struct { // The set of field mask paths. Paths []string `protobuf:"bytes,1,rep,name=paths" json:"paths,omitempty"`