├── .gitignore ├── LICENSE ├── README.md ├── main.go └── vendor ├── github.com ├── labstack │ ├── echo │ │ ├── LICENSE │ │ ├── README.md │ │ ├── binder.go │ │ ├── context.go │ │ ├── echo.go │ │ ├── glide.lock │ │ ├── glide.yaml │ │ ├── group.go │ │ ├── logger.go │ │ ├── response.go │ │ └── router.go │ └── gommon │ │ ├── LICENSE │ │ ├── color │ │ ├── README.md │ │ └── color.go │ │ └── log │ │ ├── README.md │ │ ├── color.go │ │ ├── log.go │ │ └── white.go ├── mattn │ ├── go-colorable │ │ ├── LICENSE │ │ ├── README.md │ │ ├── colorable_others.go │ │ ├── colorable_windows.go │ │ └── noncolorable.go │ └── go-isatty │ │ ├── LICENSE │ │ ├── README.md │ │ ├── doc.go │ │ ├── isatty_appengine.go │ │ ├── isatty_bsd.go │ │ ├── isatty_linux.go │ │ ├── isatty_solaris.go │ │ └── isatty_windows.go ├── rsc │ └── letsencrypt │ │ ├── LICENSE │ │ ├── README │ │ └── lets.go ├── tylerb │ └── graceful │ │ ├── LICENSE │ │ ├── README.md │ │ ├── graceful.go │ │ ├── keepalive_listener.go │ │ ├── limit_listen.go │ │ ├── signal.go │ │ └── signal_appengine.go ├── valyala │ └── fasttemplate │ │ ├── LICENSE │ │ ├── README.md │ │ └── template.go └── xenolf │ └── lego │ ├── LICENSE │ └── acme │ ├── challenges.go │ ├── client.go │ ├── crypto.go │ ├── error.go │ ├── http.go │ ├── http_challenge.go │ ├── http_challenge_server.go │ ├── jws.go │ ├── messages.go │ ├── provider.go │ ├── tls_sni_challenge.go │ ├── tls_sni_challenge_server.go │ └── utils.go ├── golang.org └── x │ ├── crypto │ ├── LICENSE │ ├── PATENTS │ └── ocsp │ │ └── ocsp.go │ ├── net │ ├── LICENSE │ ├── PATENTS │ └── context │ │ └── context.go │ └── time │ ├── LICENSE │ ├── PATENTS │ └── rate │ └── rate.go ├── gopkg.in └── square │ └── go-jose.v1 │ ├── BUG-BOUNTY.md │ ├── CONTRIBUTING.md │ ├── LICENSE │ ├── README.md │ ├── asymmetric.go │ ├── cipher │ ├── cbc_hmac.go │ ├── concat_kdf.go │ ├── ecdh_es.go │ └── key_wrap.go │ ├── crypter.go │ ├── doc.go │ ├── encoding.go │ ├── json │ ├── LICENSE │ ├── README.md │ ├── decode.go │ ├── encode.go │ ├── indent.go │ ├── scanner.go │ ├── stream.go │ └── tags.go │ ├── jwe.go │ ├── jwk.go │ ├── jws.go │ ├── shared.go │ ├── signing.go │ ├── symmetric.go │ └── utils.go └── vendor.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | *.prof 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Vinicius Souza 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # go-graphql-subscription 2 | Sample Golang implementation of Subscriptions in Graphql 3 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "log" 7 | "math/rand" 8 | "net/http" 9 | 10 | "github.com/graphql-go/graphql" 11 | ) 12 | 13 | var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") 14 | 15 | func randSeq(n int) string { 16 | b := make([]rune, n) 17 | for i := range b { 18 | b[i] = letters[rand.Intn(len(letters))] 19 | } 20 | return string(b) 21 | } 22 | 23 | var commentType = graphql.NewObject( 24 | graphql.ObjectConfig{ 25 | Name: "Comment", 26 | Fields: graphql.Fields{ 27 | "commentTitle": &graphql.Field{ 28 | Type: graphql.String, 29 | Resolve: func(p graphql.ResolveParams) (interface{}, error) { 30 | return randSeq(10), nil 31 | }, 32 | }, 33 | "commentDescription": &graphql.Field{ 34 | Type: graphql.String, 35 | Resolve: func(p graphql.ResolveParams) (interface{}, error) { 36 | return randSeq(10), nil 37 | }, 38 | }, 39 | }, 40 | }, 41 | ) 42 | 43 | var subscriptionType = graphql.NewObject( 44 | graphql.ObjectConfig{ 45 | Name: "Subscription", 46 | Fields: graphql.Fields{ 47 | "newComments": &graphql.Field{ 48 | Type: commentType, 49 | Args: graphql.FieldConfigArgument{ 50 | "postId": &graphql.ArgumentConfig{ 51 | Type: graphql.String, 52 | }, 53 | }, 54 | Resolve: func(p graphql.ResolveParams) (interface{}, error) { 55 | return randSeq(10), nil 56 | }, 57 | }, 58 | }, 59 | }) 60 | 61 | var schema, _ = graphql.NewSchema( 62 | graphql.SchemaConfig{ 63 | Subscription: subscriptionType, 64 | Query: commentType, 65 | }, 66 | ) 67 | 68 | func executeQuery(query string, schema graphql.Schema) *graphql.Result { 69 | result := graphql.Do(graphql.Params{ 70 | Schema: schema, 71 | RequestString: query, 72 | }) 73 | if len(result.Errors) > 0 { 74 | fmt.Printf("wrong result, unexpected errors: %v", result.Errors) 75 | } 76 | return result 77 | } 78 | 79 | func subscriptionHandler(w http.ResponseWriter, r *http.Request) { 80 | query := r.URL.Query()["query"] 81 | if len(query) > 0 { 82 | result := executeQuery(query[0], schema) 83 | json.NewEncoder(w).Encode(result) 84 | return 85 | } 86 | http.Error(w, "query cannot be empty", http.StatusBadRequest) 87 | } 88 | 89 | func main() { 90 | http.HandleFunc("/subscription", subscriptionHandler) 91 | log.Println("Listening...") 92 | http.ListenAndServe(":8000", nil) 93 | 94 | } 95 | -------------------------------------------------------------------------------- /vendor/github.com/labstack/echo/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 LabStack 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/labstack/echo/README.md: -------------------------------------------------------------------------------- 1 | # [Echo] (https://echo.labstack.com) [![GoDoc](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](http://godoc.org/github.com/labstack/echo) [![License](http://img.shields.io/badge/license-mit-blue.svg?style=flat-square)](https://raw.githubusercontent.com/labstack/echo/master/LICENSE) [![Build Status](http://img.shields.io/travis/labstack/echo.svg?style=flat-square)](https://travis-ci.org/labstack/echo) [![Coverage Status](http://img.shields.io/coveralls/labstack/echo.svg?style=flat-square)](https://coveralls.io/r/labstack/echo) [![Join the chat at https://gitter.im/labstack/echo](https://img.shields.io/badge/gitter-join%20chat-brightgreen.svg?style=flat-square)](https://gitter.im/labstack/echo) [![Twitter](https://img.shields.io/badge/twitter-@labstack-55acee.svg?style=flat-square)](https://twitter.com/labstack) 2 | 3 | ### Fast and unfancy HTTP server framework for Go (Golang). 4 | 5 | ## Feature Overview 6 | 7 | - Optimized HTTP router which smartly prioritize routes 8 | - Build robust and scalable RESTful APIs 9 | - Group APIs 10 | - Extensible middleware framework 11 | - Define middleware at root, group or route level 12 | - Data binding for JSON, XML and form payload 13 | - Handy functions to send variety of HTTP responses 14 | - Centralized HTTP error handling 15 | - Template rendering with any template engine 16 | - Define your format for the logger 17 | - Highly customizable 18 | - Automatic TLS via Let’s Encrypt 19 | - Built-in graceful shutdown 20 | 21 | ## Performance 22 | 23 | ![Performance](https://i.imgur.com/F2V7TfO.png) 24 | 25 | ## Quick Start 26 | 27 | ### Installation 28 | 29 | ```sh 30 | $ go get -u github.com/labstack/echo 31 | ``` 32 | 33 | ### Hello, World! 34 | 35 | Create `server.go` 36 | 37 | ```go 38 | package main 39 | 40 | import ( 41 | "net/http" 42 | 43 | "github.com/labstack/echo" 44 | ) 45 | 46 | func main() { 47 | e := echo.New() 48 | e.GET("/", func(c echo.Context) error { 49 | return c.String(http.StatusOK, "Hello, World!") 50 | }) 51 | e.Logger.Fatal(e.Start(":1323")) 52 | } 53 | ``` 54 | 55 | Start server 56 | 57 | ```sh 58 | $ go run server.go 59 | ``` 60 | 61 | Browse to [http://localhost:1323](http://localhost:1323) and you should see 62 | Hello, World! on the page. 63 | 64 | ### Routing 65 | 66 | ```go 67 | e.POST("/users", saveUser) 68 | e.GET("/users/:id", getUser) 69 | e.PUT("/users/:id", updateUser) 70 | e.DELETE("/users/:id", deleteUser) 71 | ``` 72 | 73 | ### Path Parameters 74 | 75 | ```go 76 | // e.GET("/users/:id", getUser) 77 | func getUser(c echo.Context) error { 78 | // User ID from path `users/:id` 79 | id := c.Param("id") 80 | return c.String(http.StatusOK, id) 81 | } 82 | ``` 83 | 84 | Browse to http://localhost:1323/users/Joe and you should see 'Joe' on the page. 85 | 86 | ### Query Parameters 87 | 88 | `/show?team=x-men&member=wolverine` 89 | 90 | ```go 91 | //e.GET("/show", show) 92 | func show(c echo.Context) error { 93 | // Get team and member from the query string 94 | team := c.QueryParam("team") 95 | member := c.QueryParam("member") 96 | return c.String(http.StatusOK, "team:" + team + ", member:" + member) 97 | } 98 | ``` 99 | 100 | Browse to http://localhost:1323/show?team=x-men&member=wolverine and you should see 'team:x-men, member:wolverine' on the page. 101 | 102 | ### Form `application/x-www-form-urlencoded` 103 | 104 | `POST` `/save` 105 | 106 | name | value 107 | :--- | :--- 108 | name | Joe Smith 109 | email | joe@labstack.com 110 | 111 | 112 | ```go 113 | // e.POST("/save", save) 114 | func save(c echo.Context) error { 115 | // Get name and email 116 | name := c.FormValue("name") 117 | email := c.FormValue("email") 118 | return c.String(http.StatusOK, "name:" + name + ", email:" + email) 119 | } 120 | ``` 121 | 122 | Run the following command: 123 | 124 | ```sh 125 | $ curl -F "name=Joe Smith" -F "email=joe@labstack.com" http://localhost:1323/save 126 | // => name:Joe Smith, email:joe@labstack.com 127 | ``` 128 | 129 | ### Form `multipart/form-data` 130 | 131 | `POST` `/save` 132 | 133 | name | value 134 | :--- | :--- 135 | name | Joe Smith 136 | avatar | avatar 137 | 138 | ```go 139 | func save(c echo.Context) error { 140 | // Get name 141 | name := c.FormValue("name") 142 | // Get avatar 143 | avatar, err := c.FormFile("avatar") 144 | if err != nil { 145 | return err 146 | } 147 | 148 | // Source 149 | src, err := avatar.Open() 150 | if err != nil { 151 | return err 152 | } 153 | defer src.Close() 154 | 155 | // Destination 156 | dst, err := os.Create(avatar.Filename) 157 | if err != nil { 158 | return err 159 | } 160 | defer dst.Close() 161 | 162 | // Copy 163 | if _, err = io.Copy(dst, src); err != nil { 164 | return err 165 | } 166 | 167 | return c.HTML(http.StatusOK, "Thank you! " + name + "") 168 | } 169 | ``` 170 | 171 | Run the following command. 172 | ```sh 173 | $ curl -F "name=Joe Smith" -F "avatar=@/path/to/your/avatar.png" http://localhost:1323/save 174 | // => Thank you! Joe Smith 175 | ``` 176 | 177 | For checking uploaded image, run the following command. 178 | 179 | ```sh 180 | cd 181 | ls avatar.png 182 | // => avatar.png 183 | ``` 184 | 185 | ### Handling Request 186 | 187 | - Bind `JSON` or `XML` or `form` payload into Go struct based on `Content-Type` request header. 188 | - Render response as `JSON` or `XML` with status code. 189 | 190 | ```go 191 | type User struct { 192 | Name string `json:"name" xml:"name" form:"name"` 193 | Email string `json:"email" xml:"email" form:"email"` 194 | } 195 | 196 | e.POST("/users", func(c echo.Context) error { 197 | u := new(User) 198 | if err := c.Bind(u); err != nil { 199 | return err 200 | } 201 | return c.JSON(http.StatusCreated, u) 202 | // or 203 | // return c.XML(http.StatusCreated, u) 204 | }) 205 | ``` 206 | 207 | ### Static Content 208 | 209 | Server any file from static directory for path `/static/*`. 210 | 211 | ```go 212 | e.Static("/static", "static") 213 | ``` 214 | 215 | ##### [Learn More](https://echo.labstack.com/guide/static-files) 216 | 217 | ### [Template Rendering](https://echo.labstack.com/guide/templates) 218 | 219 | ### Middleware 220 | 221 | ```go 222 | // Root level middleware 223 | e.Use(middleware.Logger()) 224 | e.Use(middleware.Recover()) 225 | 226 | // Group level middleware 227 | g := e.Group("/admin") 228 | g.Use(middleware.BasicAuth(func(username, password string) bool { 229 | if username == "joe" && password == "secret" { 230 | return true 231 | } 232 | return false 233 | })) 234 | 235 | // Route level middleware 236 | track := func(next echo.HandlerFunc) echo.HandlerFunc { 237 | return func(c echo.Context) error { 238 | println("request to /users") 239 | return next(c) 240 | } 241 | } 242 | e.GET("/users", func(c echo.Context) error { 243 | return c.String(http.StatusOK, "/users") 244 | }, track) 245 | ``` 246 | 247 | #### Built-in Middleware 248 | 249 | Middleware | Description 250 | :--- | :--- 251 | [BodyLimit](https://echo.labstack.com/middleware/body-limit) | Limit request body 252 | [Logger](https://echo.labstack.com/middleware/logger) | Log HTTP requests 253 | [Recover](https://echo.labstack.com/middleware/recover) | Recover from panics 254 | [Gzip](https://echo.labstack.com/middleware/gzip) | Send gzip HTTP response 255 | [BasicAuth](https://echo.labstack.com/middleware/basic-auth) | HTTP basic authentication 256 | [JWTAuth](https://echo.labstack.com/middleware/jwt) | JWT authentication 257 | [Secure](https://echo.labstack.com/middleware/secure) | Protection against attacks 258 | [CORS](https://echo.labstack.com/middleware/cors) | Cross-Origin Resource Sharing 259 | [CSRF](https://echo.labstack.com/middleware/csrf) | Cross-Site Request Forgery 260 | [HTTPSRedirect](https://echo.labstack.com/middleware/redirect#httpsredirect-middleware) | Redirect HTTP requests to HTTPS 261 | [HTTPSWWWRedirect](https://echo.labstack.com/middleware/redirect#httpswwwredirect-middleware) | Redirect HTTP requests to WWW HTTPS 262 | [WWWRedirect](https://echo.labstack.com/middleware/redirect#wwwredirect-middleware) | Redirect non WWW requests to WWW 263 | [NonWWWRedirect](https://echo.labstack.com/middleware/redirect#nonwwwredirect-middleware) | Redirect WWW requests to non WWW 264 | [AddTrailingSlash](https://echo.labstack.com/middleware/trailing-slash#addtrailingslash-middleware) | Add trailing slash to the request URI 265 | [RemoveTrailingSlash](https://echo.labstack.com/middleware/trailing-slash#removetrailingslash-middleware) | Remove trailing slash from the request URI 266 | [MethodOverride](https://echo.labstack.com/middleware/method-override) | Override request method 267 | 268 | ##### [Learn More](https://echo.labstack.com/middleware/overview) 269 | 270 | #### Third-party Middleware 271 | 272 | Middleware | Description 273 | :--- | :--- 274 | [echoperm](https://github.com/xyproto/echoperm) | Keeping track of users, login states and permissions. 275 | [echopprof](https://github.com/mtojek/echopprof) | Adapt net/http/pprof to labstack/echo. 276 | 277 | ### Next 278 | 279 | - Head over to [guide](https://echo.labstack.com/guide/installation) 280 | - Browse [recipes](https://echo.labstack.com/recipes/hello-world) 281 | 282 | ### Need help? 283 | 284 | - [Hop on to chat](https://gitter.im/labstack/echo) 285 | - [Open an issue](https://github.com/labstack/echo/issues/new) 286 | 287 | ## Support Us 288 | 289 | - :star: the project 290 | - [Donate](https://echo.labstack.com/support-echo) 291 | - :earth_americas: spread the word 292 | - [Contribute](#contribute) to the project 293 | 294 | ## Contribute 295 | 296 | **Use issues for everything** 297 | 298 | - Report issues 299 | - Discuss on chat before sending a pull request 300 | - Suggest new features or enhancements 301 | - Improve/fix documentation 302 | 303 | ## Credits 304 | - [Vishal Rana](https://github.com/vishr) - Author 305 | - [Nitin Rana](https://github.com/nr17) - Consultant 306 | - [Contributors](https://github.com/labstack/echo/graphs/contributors) 307 | 308 | ## License 309 | 310 | [MIT](https://github.com/labstack/echo/blob/master/LICENSE) 311 | -------------------------------------------------------------------------------- /vendor/github.com/labstack/echo/binder.go: -------------------------------------------------------------------------------- 1 | package echo 2 | 3 | import ( 4 | "encoding/json" 5 | "encoding/xml" 6 | "errors" 7 | "fmt" 8 | "net/http" 9 | "reflect" 10 | "strconv" 11 | "strings" 12 | ) 13 | 14 | type ( 15 | // Binder is the interface that wraps the Bind method. 16 | Binder interface { 17 | Bind(interface{}, Context) error 18 | } 19 | 20 | binder struct{} 21 | ) 22 | 23 | func (b *binder) Bind(i interface{}, c Context) (err error) { 24 | req := c.Request() 25 | if req.Method == GET { 26 | if err = b.bindData(i, c.QueryParams()); err != nil { 27 | return NewHTTPError(http.StatusBadRequest, err.Error()) 28 | } 29 | return 30 | } 31 | ctype := req.Header.Get(HeaderContentType) 32 | if req.ContentLength == 0 { 33 | return NewHTTPError(http.StatusBadRequest, "request body can't be empty") 34 | } 35 | switch { 36 | case strings.HasPrefix(ctype, MIMEApplicationJSON): 37 | if err = json.NewDecoder(req.Body).Decode(i); err != nil { 38 | if ute, ok := err.(*json.UnmarshalTypeError); ok { 39 | return NewHTTPError(http.StatusBadRequest, fmt.Sprintf("unmarshal type error: expected=%v, got=%v, offset=%v", ute.Type, ute.Value, ute.Offset)) 40 | } else if se, ok := err.(*json.SyntaxError); ok { 41 | return NewHTTPError(http.StatusBadRequest, fmt.Sprintf("syntax error: offset=%v, error=%v", se.Offset, se.Error())) 42 | } else { 43 | return NewHTTPError(http.StatusBadRequest, err.Error()) 44 | } 45 | } 46 | case strings.HasPrefix(ctype, MIMEApplicationXML): 47 | if err = xml.NewDecoder(req.Body).Decode(i); err != nil { 48 | if ute, ok := err.(*xml.UnsupportedTypeError); ok { 49 | return NewHTTPError(http.StatusBadRequest, fmt.Sprintf("unsupported type error: type=%v, error=%v", ute.Type, ute.Error())) 50 | } else if se, ok := err.(*xml.SyntaxError); ok { 51 | return NewHTTPError(http.StatusBadRequest, fmt.Sprintf("syntax error: line=%v, error=%v", se.Line, se.Error())) 52 | } else { 53 | return NewHTTPError(http.StatusBadRequest, err.Error()) 54 | } 55 | } 56 | case strings.HasPrefix(ctype, MIMEApplicationForm), strings.HasPrefix(ctype, MIMEMultipartForm): 57 | params, err := c.FormParams() 58 | if err != nil { 59 | return NewHTTPError(http.StatusBadRequest, err.Error()) 60 | } 61 | if err = b.bindData(i, params); err != nil { 62 | return NewHTTPError(http.StatusBadRequest, err.Error()) 63 | } 64 | default: 65 | return ErrUnsupportedMediaType 66 | } 67 | return 68 | } 69 | 70 | func (b *binder) bindData(ptr interface{}, data map[string][]string) error { 71 | typ := reflect.TypeOf(ptr).Elem() 72 | val := reflect.ValueOf(ptr).Elem() 73 | 74 | if typ.Kind() != reflect.Struct { 75 | return errors.New("binding element must be a struct") 76 | } 77 | 78 | for i := 0; i < typ.NumField(); i++ { 79 | typeField := typ.Field(i) 80 | structField := val.Field(i) 81 | if !structField.CanSet() { 82 | continue 83 | } 84 | structFieldKind := structField.Kind() 85 | inputFieldName := typeField.Tag.Get("form") 86 | 87 | if inputFieldName == "" { 88 | inputFieldName = typeField.Name 89 | // If "form" tag is nil, we inspect if the field is a struct. 90 | if structFieldKind == reflect.Struct { 91 | err := b.bindData(structField.Addr().Interface(), data) 92 | if err != nil { 93 | return err 94 | } 95 | continue 96 | } 97 | } 98 | inputValue, exists := data[inputFieldName] 99 | if !exists { 100 | continue 101 | } 102 | 103 | numElems := len(inputValue) 104 | if structFieldKind == reflect.Slice && numElems > 0 { 105 | sliceOf := structField.Type().Elem().Kind() 106 | slice := reflect.MakeSlice(structField.Type(), numElems, numElems) 107 | for j := 0; j < numElems; j++ { 108 | if err := setWithProperType(sliceOf, inputValue[j], slice.Index(j)); err != nil { 109 | return err 110 | } 111 | } 112 | val.Field(i).Set(slice) 113 | } else { 114 | if err := setWithProperType(typeField.Type.Kind(), inputValue[0], structField); err != nil { 115 | return err 116 | } 117 | } 118 | } 119 | return nil 120 | } 121 | 122 | func setWithProperType(valueKind reflect.Kind, val string, structField reflect.Value) error { 123 | switch valueKind { 124 | case reflect.Int: 125 | return setIntField(val, 0, structField) 126 | case reflect.Int8: 127 | return setIntField(val, 8, structField) 128 | case reflect.Int16: 129 | return setIntField(val, 16, structField) 130 | case reflect.Int32: 131 | return setIntField(val, 32, structField) 132 | case reflect.Int64: 133 | return setIntField(val, 64, structField) 134 | case reflect.Uint: 135 | return setUintField(val, 0, structField) 136 | case reflect.Uint8: 137 | return setUintField(val, 8, structField) 138 | case reflect.Uint16: 139 | return setUintField(val, 16, structField) 140 | case reflect.Uint32: 141 | return setUintField(val, 32, structField) 142 | case reflect.Uint64: 143 | return setUintField(val, 64, structField) 144 | case reflect.Bool: 145 | return setBoolField(val, structField) 146 | case reflect.Float32: 147 | return setFloatField(val, 32, structField) 148 | case reflect.Float64: 149 | return setFloatField(val, 64, structField) 150 | case reflect.String: 151 | structField.SetString(val) 152 | default: 153 | return errors.New("unknown type") 154 | } 155 | return nil 156 | } 157 | 158 | func setIntField(value string, bitSize int, field reflect.Value) error { 159 | if value == "" { 160 | value = "0" 161 | } 162 | intVal, err := strconv.ParseInt(value, 10, bitSize) 163 | if err == nil { 164 | field.SetInt(intVal) 165 | } 166 | return err 167 | } 168 | 169 | func setUintField(value string, bitSize int, field reflect.Value) error { 170 | if value == "" { 171 | value = "0" 172 | } 173 | uintVal, err := strconv.ParseUint(value, 10, bitSize) 174 | if err == nil { 175 | field.SetUint(uintVal) 176 | } 177 | return err 178 | } 179 | 180 | func setBoolField(value string, field reflect.Value) error { 181 | if value == "" { 182 | value = "false" 183 | } 184 | boolVal, err := strconv.ParseBool(value) 185 | if err == nil { 186 | field.SetBool(boolVal) 187 | } 188 | return err 189 | } 190 | 191 | func setFloatField(value string, bitSize int, field reflect.Value) error { 192 | if value == "" { 193 | value = "0.0" 194 | } 195 | floatVal, err := strconv.ParseFloat(value, bitSize) 196 | if err == nil { 197 | field.SetFloat(floatVal) 198 | } 199 | return err 200 | } 201 | -------------------------------------------------------------------------------- /vendor/github.com/labstack/echo/glide.lock: -------------------------------------------------------------------------------- 1 | hash: d63c27ff06a540317f63f231ada71f3d03f1c09e79a2c47b29b43c654903fc8b 2 | updated: 2016-11-17T10:05:04.395879866-08:00 3 | imports: 4 | - name: github.com/daaku/go.zipexe 5 | version: a5fe2436ffcb3236e175e5149162b41cd28bd27d 6 | - name: github.com/dgrijalva/jwt-go 7 | version: 24c63f56522a87ec5339cc3567883f1039378fdb 8 | - name: github.com/GeertJohan/go.rice 9 | version: 9fdfd46f9806a9228aae341d65ab75c5235c383c 10 | subpackages: 11 | - embedded 12 | - name: github.com/golang/protobuf 13 | version: 98fa357170587e470c5f27d3c3ea0947b71eb455 14 | subpackages: 15 | - proto 16 | - name: github.com/gorilla/websocket 17 | version: 0b847f2facc24ec406130a05bb1bb72d41993b05 18 | - name: github.com/kardianos/osext 19 | version: c2c54e542fb797ad986b31721e1baedf214ca413 20 | - name: github.com/labstack/gommon 21 | version: 2d272df536d051e737aea353b86c979d6e88bce0 22 | subpackages: 23 | - bytes 24 | - color 25 | - log 26 | - random 27 | - name: github.com/mattn/go-colorable 28 | version: 6c903ff4aa50920ca86087a280590b36b3152b9c 29 | - name: github.com/mattn/go-isatty 30 | version: 66b8e73f3f5cda9f96b69efd03dd3d7fc4a5cdb8 31 | - name: github.com/miekg/dns 32 | version: 58f52c57ce9df13460ac68200cef30a008b9c468 33 | - name: github.com/rsc/letsencrypt 34 | version: 76104d26167d38b6a0010f42bfc8ec5487742e8b 35 | - name: github.com/tylerb/graceful 36 | version: 50a48b6e73fcc75b45e22c05b79629a67c79e938 37 | - name: github.com/valyala/fasttemplate 38 | version: 3b874956e03f1636d171bda64b130f9135f42cff 39 | - name: github.com/xenolf/lego 40 | version: 4bb8bea031eb805f361c04ca222f266b9e7feced 41 | subpackages: 42 | - acme 43 | - name: golang.org/x/crypto 44 | version: ca7e7f10cb9fd9c1a6ff7f60436c086d73714180 45 | subpackages: 46 | - ocsp 47 | - name: golang.org/x/net 48 | version: 65dfc08770ce66f74becfdff5f8ab01caef4e946 49 | subpackages: 50 | - context 51 | - publicsuffix 52 | - websocket 53 | - name: golang.org/x/sys 54 | version: c200b10b5d5e122be351b67af224adc6128af5bf 55 | subpackages: 56 | - unix 57 | - name: golang.org/x/time 58 | version: 711ca1cb87636abec28122ef3bc6a77269d433f3 59 | subpackages: 60 | - rate 61 | - name: google.golang.org/appengine 62 | version: 5b8c3b819891014a2d12354528f7d046dd53c89e 63 | subpackages: 64 | - internal 65 | - internal/app_identity 66 | - internal/base 67 | - internal/datastore 68 | - internal/log 69 | - internal/modules 70 | - internal/remote_api 71 | - name: gopkg.in/square/go-jose.v1 72 | version: aa2e30fdd1fe9dd3394119af66451ae790d50e0d 73 | subpackages: 74 | - cipher 75 | - json 76 | testImports: 77 | - name: github.com/davecgh/go-spew 78 | version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 79 | subpackages: 80 | - spew 81 | - name: github.com/pmezard/go-difflib 82 | version: d8ed2627bdf02c080bf22230dbb337003b7aba2d 83 | subpackages: 84 | - difflib 85 | - name: github.com/stretchr/testify 86 | version: 976c720a22c8eb4eb6a0b4348ad85ad12491a506 87 | subpackages: 88 | - assert 89 | -------------------------------------------------------------------------------- /vendor/github.com/labstack/echo/glide.yaml: -------------------------------------------------------------------------------- 1 | package: github.com/labstack/echo 2 | import: 3 | - package: github.com/GeertJohan/go.rice 4 | - package: github.com/dgrijalva/jwt-go 5 | - package: github.com/gorilla/websocket 6 | - package: github.com/labstack/gommon 7 | subpackages: 8 | - bytes 9 | - color 10 | - log 11 | - random 12 | - package: github.com/mattn/go-isatty 13 | - package: github.com/rsc/letsencrypt 14 | - package: github.com/tylerb/graceful 15 | - package: github.com/valyala/fasttemplate 16 | - package: golang.org/x/net 17 | subpackages: 18 | - websocket 19 | - package: google.golang.org/appengine 20 | testImport: 21 | - package: github.com/stretchr/testify 22 | subpackages: 23 | - assert 24 | -------------------------------------------------------------------------------- /vendor/github.com/labstack/echo/group.go: -------------------------------------------------------------------------------- 1 | package echo 2 | 3 | type ( 4 | // Group is a set of sub-routes for a specified route. It can be used for inner 5 | // routes that share a common middlware or functionality that should be separate 6 | // from the parent echo instance while still inheriting from it. 7 | Group struct { 8 | prefix string 9 | middleware []MiddlewareFunc 10 | echo *Echo 11 | } 12 | ) 13 | 14 | // Use implements `Echo#Use()` for sub-routes within the Group. 15 | func (g *Group) Use(middleware ...MiddlewareFunc) { 16 | g.middleware = append(g.middleware, middleware...) 17 | } 18 | 19 | // CONNECT implements `Echo#CONNECT()` for sub-routes within the Group. 20 | func (g *Group) CONNECT(path string, h HandlerFunc, m ...MiddlewareFunc) { 21 | g.add(CONNECT, path, h, m...) 22 | } 23 | 24 | // DELETE implements `Echo#DELETE()` for sub-routes within the Group. 25 | func (g *Group) DELETE(path string, h HandlerFunc, m ...MiddlewareFunc) { 26 | g.add(DELETE, path, h, m...) 27 | } 28 | 29 | // GET implements `Echo#GET()` for sub-routes within the Group. 30 | func (g *Group) GET(path string, h HandlerFunc, m ...MiddlewareFunc) { 31 | g.add(GET, path, h, m...) 32 | } 33 | 34 | // HEAD implements `Echo#HEAD()` for sub-routes within the Group. 35 | func (g *Group) HEAD(path string, h HandlerFunc, m ...MiddlewareFunc) { 36 | g.add(HEAD, path, h, m...) 37 | } 38 | 39 | // OPTIONS implements `Echo#OPTIONS()` for sub-routes within the Group. 40 | func (g *Group) OPTIONS(path string, h HandlerFunc, m ...MiddlewareFunc) { 41 | g.add(OPTIONS, path, h, m...) 42 | } 43 | 44 | // PATCH implements `Echo#PATCH()` for sub-routes within the Group. 45 | func (g *Group) PATCH(path string, h HandlerFunc, m ...MiddlewareFunc) { 46 | g.add(PATCH, path, h, m...) 47 | } 48 | 49 | // POST implements `Echo#POST()` for sub-routes within the Group. 50 | func (g *Group) POST(path string, h HandlerFunc, m ...MiddlewareFunc) { 51 | g.add(POST, path, h, m...) 52 | } 53 | 54 | // PUT implements `Echo#PUT()` for sub-routes within the Group. 55 | func (g *Group) PUT(path string, h HandlerFunc, m ...MiddlewareFunc) { 56 | g.add(PUT, path, h, m...) 57 | } 58 | 59 | // TRACE implements `Echo#TRACE()` for sub-routes within the Group. 60 | func (g *Group) TRACE(path string, h HandlerFunc, m ...MiddlewareFunc) { 61 | g.add(TRACE, path, h, m...) 62 | } 63 | 64 | // Any implements `Echo#Any()` for sub-routes within the Group. 65 | func (g *Group) Any(path string, handler HandlerFunc, middleware ...MiddlewareFunc) { 66 | for _, m := range methods { 67 | g.add(m, path, handler, middleware...) 68 | } 69 | } 70 | 71 | // Match implements `Echo#Match()` for sub-routes within the Group. 72 | func (g *Group) Match(methods []string, path string, handler HandlerFunc, middleware ...MiddlewareFunc) { 73 | for _, m := range methods { 74 | g.add(m, path, handler, middleware...) 75 | } 76 | } 77 | 78 | // Group creates a new sub-group with prefix and optional sub-group-level middleware. 79 | func (g *Group) Group(prefix string, middleware ...MiddlewareFunc) *Group { 80 | m := []MiddlewareFunc{} 81 | m = append(m, g.middleware...) 82 | m = append(m, middleware...) 83 | return g.echo.Group(g.prefix+prefix, m...) 84 | } 85 | 86 | // Static implements `Echo#Static()` for sub-routes within the Group. 87 | func (g *Group) Static(prefix, root string) { 88 | static(g, prefix, root) 89 | } 90 | 91 | // File implements `Echo#File()` for sub-routes within the Group. 92 | func (g *Group) File(path, file string) { 93 | g.echo.File(g.prefix+path, file) 94 | } 95 | 96 | func (g *Group) add(method, path string, handler HandlerFunc, middleware ...MiddlewareFunc) { 97 | // Combine into a new slice to avoid accidentally passing the same slice for 98 | // multiple routes, which would lead to later add() calls overwriting the 99 | // middleware from earlier calls. 100 | m := []MiddlewareFunc{} 101 | m = append(m, g.middleware...) 102 | m = append(m, middleware...) 103 | g.echo.add(method, g.prefix+path, handler, m...) 104 | } 105 | -------------------------------------------------------------------------------- /vendor/github.com/labstack/echo/logger.go: -------------------------------------------------------------------------------- 1 | package echo 2 | 3 | import ( 4 | "io" 5 | 6 | "github.com/labstack/gommon/log" 7 | ) 8 | 9 | type ( 10 | // Logger defines the logging interface. 11 | Logger interface { 12 | Output() io.Writer 13 | SetOutput(io.Writer) 14 | Level() log.Lvl 15 | SetLevel(log.Lvl) 16 | Prefix() string 17 | SetPrefix(string) 18 | Print(...interface{}) 19 | Printf(string, ...interface{}) 20 | Printj(log.JSON) 21 | Debug(...interface{}) 22 | Debugf(string, ...interface{}) 23 | Debugj(log.JSON) 24 | Info(...interface{}) 25 | Infof(string, ...interface{}) 26 | Infoj(log.JSON) 27 | Warn(...interface{}) 28 | Warnf(string, ...interface{}) 29 | Warnj(log.JSON) 30 | Error(...interface{}) 31 | Errorf(string, ...interface{}) 32 | Errorj(log.JSON) 33 | Fatal(...interface{}) 34 | Fatalj(log.JSON) 35 | Fatalf(string, ...interface{}) 36 | Panic(...interface{}) 37 | Panicj(log.JSON) 38 | Panicf(string, ...interface{}) 39 | } 40 | ) 41 | -------------------------------------------------------------------------------- /vendor/github.com/labstack/echo/response.go: -------------------------------------------------------------------------------- 1 | package echo 2 | 3 | import ( 4 | "bufio" 5 | "net" 6 | "net/http" 7 | ) 8 | 9 | type ( 10 | // Response wraps an http.ResponseWriter and implements its interface to be used 11 | // by an HTTP handler to construct an HTTP response. 12 | // See: https://golang.org/pkg/net/http/#ResponseWriter 13 | Response struct { 14 | writer http.ResponseWriter 15 | Status int 16 | Size int64 17 | Committed bool 18 | echo *Echo 19 | } 20 | ) 21 | 22 | // NewResponse creates a new instance of Response. 23 | func NewResponse(w http.ResponseWriter, e *Echo) (r *Response) { 24 | return &Response{writer: w, echo: e} 25 | } 26 | 27 | // SetWriter sets the http.ResponseWriter instance for this Response. 28 | func (r *Response) SetWriter(w http.ResponseWriter) { 29 | r.writer = w 30 | } 31 | 32 | // Writer returns the http.ResponseWriter instance for this Response. 33 | func (r *Response) Writer() http.ResponseWriter { 34 | return r.writer 35 | } 36 | 37 | // Header returns the header map for the writer that will be sent by 38 | // WriteHeader. Changing the header after a call to WriteHeader (or Write) has 39 | // no effect unless the modified headers were declared as trailers by setting 40 | // the "Trailer" header before the call to WriteHeader (see example) 41 | // To suppress implicit response headers, set their value to nil. 42 | // Example: https://golang.org/pkg/net/http/#example_ResponseWriter_trailers 43 | func (r *Response) Header() http.Header { 44 | return r.writer.Header() 45 | } 46 | 47 | // WriteHeader sends an HTTP response header with status code. If WriteHeader is 48 | // not called explicitly, the first call to Write will trigger an implicit 49 | // WriteHeader(http.StatusOK). Thus explicit calls to WriteHeader are mainly 50 | // used to send error codes. 51 | func (r *Response) WriteHeader(code int) { 52 | if r.Committed { 53 | r.echo.Logger.Warn("response already committed") 54 | return 55 | } 56 | r.Status = code 57 | r.writer.WriteHeader(code) 58 | r.Committed = true 59 | } 60 | 61 | // Write writes the data to the connection as part of an HTTP reply. 62 | func (r *Response) Write(b []byte) (n int, err error) { 63 | if !r.Committed { 64 | r.WriteHeader(http.StatusOK) 65 | } 66 | n, err = r.writer.Write(b) 67 | r.Size += int64(n) 68 | return 69 | } 70 | 71 | // Flush implements the http.Flusher interface to allow an HTTP handler to flush 72 | // buffered data to the client. 73 | // See [http.Flusher](https://golang.org/pkg/net/http/#Flusher) 74 | func (r *Response) Flush() { 75 | r.writer.(http.Flusher).Flush() 76 | } 77 | 78 | // Hijack implements the http.Hijacker interface to allow an HTTP handler to 79 | // take over the connection. 80 | // See [http.Hijacker](https://golang.org/pkg/net/http/#Hijacker) 81 | func (r *Response) Hijack() (net.Conn, *bufio.ReadWriter, error) { 82 | return r.writer.(http.Hijacker).Hijack() 83 | } 84 | 85 | // CloseNotify implements the http.CloseNotifier interface to allow detecting 86 | // when the underlying connection has gone away. 87 | // This mechanism can be used to cancel long operations on the server if the 88 | // client has disconnected before the response is ready. 89 | // See [http.CloseNotifier](https://golang.org/pkg/net/http/#CloseNotifier) 90 | func (r *Response) CloseNotify() <-chan bool { 91 | return r.writer.(http.CloseNotifier).CloseNotify() 92 | } 93 | 94 | func (r *Response) reset(w http.ResponseWriter) { 95 | r.writer = w 96 | r.Size = 0 97 | r.Status = http.StatusOK 98 | r.Committed = false 99 | } 100 | -------------------------------------------------------------------------------- /vendor/github.com/labstack/gommon/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 labstack 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /vendor/github.com/labstack/gommon/color/README.md: -------------------------------------------------------------------------------- 1 | # Color 2 | 3 | Style terminal text. 4 | 5 | ## Installation 6 | 7 | ```sh 8 | go get github.com/labstack/gommon/color 9 | ``` 10 | 11 | ## Windows? 12 | 13 | Try [cmder](http://bliker.github.io/cmder) or https://github.com/mattn/go-colorable 14 | 15 | ## [Usage](https://github.com/labstack/gommon/blob/master/color/color_test.go) 16 | 17 | ```sh 18 | import github.com/labstack/gommon/color 19 | ``` 20 | 21 | ### Colored text 22 | 23 | ```go 24 | color.Println(color.Black("black")) 25 | color.Println(color.Red("red")) 26 | color.Println(color.Green("green")) 27 | color.Println(color.Yellow("yellow")) 28 | color.Println(color.Blue("blue")) 29 | color.Println(color.Magenta("magenta")) 30 | color.Println(color.Cyan("cyan")) 31 | color.Println(color.White("white")) 32 | color.Println(color.Grey("grey")) 33 | ``` 34 | ![Colored Text](http://i.imgur.com/8RtY1QR.png) 35 | 36 | ### Colored background 37 | 38 | ```go 39 | color.Println(color.BlackBg("black background", color.Wht)) 40 | color.Println(color.RedBg("red background")) 41 | color.Println(color.GreenBg("green background")) 42 | color.Println(color.YellowBg("yellow background")) 43 | color.Println(color.BlueBg("blue background")) 44 | color.Println(color.MagentaBg("magenta background")) 45 | color.Println(color.CyanBg("cyan background")) 46 | color.Println(color.WhiteBg("white background")) 47 | ``` 48 | ![Colored Background](http://i.imgur.com/SrrS6lw.png) 49 | 50 | ### Emphasis 51 | 52 | ```go 53 | color.Println(color.Bold("bold")) 54 | color.Println(color.Dim("dim")) 55 | color.Println(color.Italic("italic")) 56 | color.Println(color.Underline("underline")) 57 | color.Println(color.Inverse("inverse")) 58 | color.Println(color.Hidden("hidden")) 59 | color.Println(color.Strikeout("strikeout")) 60 | ``` 61 | ![Emphasis](http://i.imgur.com/3RSJBbc.png) 62 | 63 | ### Mix and match 64 | 65 | ```go 66 | color.Println(color.Green("bold green with white background", color.B, color.WhtBg)) 67 | color.Println(color.Red("underline red", color.U)) 68 | color.Println(color.Yellow("dim yellow", color.D)) 69 | color.Println(color.Cyan("inverse cyan", color.In)) 70 | color.Println(color.Blue("bold underline dim blue", color.B, color.U, color.D)) 71 | ``` 72 | ![Mix and match](http://i.imgur.com/jWGq9Ca.png) 73 | 74 | ### Enable/Disable the package 75 | 76 | ```go 77 | color.Disable() 78 | color.Enable() 79 | ``` 80 | 81 | ### New instance 82 | 83 | ```go 84 | c := New() 85 | c.Green("green") 86 | ``` 87 | -------------------------------------------------------------------------------- /vendor/github.com/labstack/gommon/log/README.md: -------------------------------------------------------------------------------- 1 | ## WORK IN PROGRESS 2 | 3 | ### Usage 4 | 5 | [log_test.go](log_test.go) 6 | -------------------------------------------------------------------------------- /vendor/github.com/labstack/gommon/log/color.go: -------------------------------------------------------------------------------- 1 | // +build !appengine 2 | 3 | package log 4 | 5 | import ( 6 | "io" 7 | 8 | "github.com/mattn/go-colorable" 9 | ) 10 | 11 | func output() io.Writer { 12 | return colorable.NewColorableStdout() 13 | } 14 | -------------------------------------------------------------------------------- /vendor/github.com/labstack/gommon/log/log.go: -------------------------------------------------------------------------------- 1 | package log 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "fmt" 7 | "io" 8 | "os" 9 | "path" 10 | "runtime" 11 | "sync" 12 | "time" 13 | 14 | "strconv" 15 | 16 | "github.com/mattn/go-isatty" 17 | "github.com/valyala/fasttemplate" 18 | 19 | "github.com/labstack/gommon/color" 20 | ) 21 | 22 | type ( 23 | Logger struct { 24 | prefix string 25 | level Lvl 26 | output io.Writer 27 | template *fasttemplate.Template 28 | levels []string 29 | color *color.Color 30 | bufferPool sync.Pool 31 | mutex sync.Mutex 32 | } 33 | 34 | Lvl uint8 35 | 36 | JSON map[string]interface{} 37 | ) 38 | 39 | const ( 40 | DEBUG Lvl = iota + 1 41 | INFO 42 | WARN 43 | ERROR 44 | OFF 45 | ) 46 | 47 | var ( 48 | global = New("-") 49 | defaultHeader = `{"time":"${time_rfc3339}","level":"${level}","prefix":"${prefix}",` + 50 | `"file":"${short_file}","line":"${line}"}` 51 | ) 52 | 53 | func New(prefix string) (l *Logger) { 54 | l = &Logger{ 55 | level: INFO, 56 | prefix: prefix, 57 | template: l.newTemplate(defaultHeader), 58 | color: color.New(), 59 | bufferPool: sync.Pool{ 60 | New: func() interface{} { 61 | return bytes.NewBuffer(make([]byte, 256)) 62 | }, 63 | }, 64 | } 65 | l.initLevels() 66 | l.SetOutput(output()) 67 | return 68 | } 69 | 70 | func (l *Logger) initLevels() { 71 | l.levels = []string{ 72 | "-", 73 | l.color.Blue("DEBUG"), 74 | l.color.Green("INFO"), 75 | l.color.Yellow("WARN"), 76 | l.color.Red("ERROR"), 77 | } 78 | } 79 | 80 | func (l *Logger) newTemplate(format string) *fasttemplate.Template { 81 | return fasttemplate.New(format, "${", "}") 82 | } 83 | 84 | func (l *Logger) DisableColor() { 85 | l.color.Disable() 86 | l.initLevels() 87 | } 88 | 89 | func (l *Logger) EnableColor() { 90 | l.color.Enable() 91 | l.initLevels() 92 | } 93 | 94 | func (l *Logger) Prefix() string { 95 | return l.prefix 96 | } 97 | 98 | func (l *Logger) SetPrefix(p string) { 99 | l.prefix = p 100 | } 101 | 102 | func (l *Logger) Level() Lvl { 103 | return l.level 104 | } 105 | 106 | func (l *Logger) SetLevel(v Lvl) { 107 | l.level = v 108 | } 109 | 110 | func (l *Logger) Output() io.Writer { 111 | return l.output 112 | } 113 | 114 | func (l *Logger) SetOutput(w io.Writer) { 115 | l.output = w 116 | if w, ok := w.(*os.File); !ok || !isatty.IsTerminal(w.Fd()) { 117 | l.DisableColor() 118 | } 119 | } 120 | 121 | func (l *Logger) Color() *color.Color { 122 | return l.color 123 | } 124 | 125 | func (l *Logger) SetHeader(h string) { 126 | l.template = l.newTemplate(h) 127 | } 128 | 129 | func (l *Logger) Print(i ...interface{}) { 130 | l.log(0, "", i...) 131 | // fmt.Fprintln(l.output, i...) 132 | } 133 | 134 | func (l *Logger) Printf(format string, args ...interface{}) { 135 | l.log(0, format, args...) 136 | } 137 | 138 | func (l *Logger) Printj(j JSON) { 139 | l.log(0, "json", j) 140 | } 141 | 142 | func (l *Logger) Debug(i ...interface{}) { 143 | l.log(DEBUG, "", i...) 144 | } 145 | 146 | func (l *Logger) Debugf(format string, args ...interface{}) { 147 | l.log(DEBUG, format, args...) 148 | } 149 | 150 | func (l *Logger) Debugj(j JSON) { 151 | l.log(DEBUG, "json", j) 152 | } 153 | 154 | func (l *Logger) Info(i ...interface{}) { 155 | l.log(INFO, "", i...) 156 | } 157 | 158 | func (l *Logger) Infof(format string, args ...interface{}) { 159 | l.log(INFO, format, args...) 160 | } 161 | 162 | func (l *Logger) Infoj(j JSON) { 163 | l.log(INFO, "json", j) 164 | } 165 | 166 | func (l *Logger) Warn(i ...interface{}) { 167 | l.log(WARN, "", i...) 168 | } 169 | 170 | func (l *Logger) Warnf(format string, args ...interface{}) { 171 | l.log(WARN, format, args...) 172 | } 173 | 174 | func (l *Logger) Warnj(j JSON) { 175 | l.log(WARN, "json", j) 176 | } 177 | 178 | func (l *Logger) Error(i ...interface{}) { 179 | l.log(ERROR, "", i...) 180 | } 181 | 182 | func (l *Logger) Errorf(format string, args ...interface{}) { 183 | l.log(ERROR, format, args...) 184 | } 185 | 186 | func (l *Logger) Errorj(j JSON) { 187 | l.log(ERROR, "json", j) 188 | } 189 | 190 | func (l *Logger) Fatal(i ...interface{}) { 191 | l.Print(i...) 192 | os.Exit(1) 193 | } 194 | 195 | func (l *Logger) Fatalf(format string, args ...interface{}) { 196 | l.Printf(format, args...) 197 | os.Exit(1) 198 | } 199 | 200 | func (l *Logger) Fatalj(j JSON) { 201 | l.Printj(j) 202 | os.Exit(1) 203 | } 204 | 205 | func (l *Logger) Panic(i ...interface{}) { 206 | l.Print(i...) 207 | panic(fmt.Sprint(i...)) 208 | } 209 | 210 | func (l *Logger) Panicf(format string, args ...interface{}) { 211 | l.Printf(format, args...) 212 | panic(fmt.Sprintf(format, args)) 213 | } 214 | 215 | func (l *Logger) Panicj(j JSON) { 216 | l.Printj(j) 217 | panic(j) 218 | } 219 | 220 | func DisableColor() { 221 | global.DisableColor() 222 | } 223 | 224 | func EnableColor() { 225 | global.EnableColor() 226 | } 227 | 228 | func Prefix() string { 229 | return global.Prefix() 230 | } 231 | 232 | func SetPrefix(p string) { 233 | global.SetPrefix(p) 234 | } 235 | 236 | func Level() Lvl { 237 | return global.Level() 238 | } 239 | 240 | func SetLevel(v Lvl) { 241 | global.SetLevel(v) 242 | } 243 | 244 | func Output() io.Writer { 245 | return global.Output() 246 | } 247 | 248 | func SetOutput(w io.Writer) { 249 | global.SetOutput(w) 250 | } 251 | 252 | func SetHeader(h string) { 253 | global.SetHeader(h) 254 | } 255 | 256 | func Print(i ...interface{}) { 257 | global.Print(i...) 258 | } 259 | 260 | func Printf(format string, args ...interface{}) { 261 | global.Printf(format, args...) 262 | } 263 | 264 | func Printj(j JSON) { 265 | global.Printj(j) 266 | } 267 | 268 | func Debug(i ...interface{}) { 269 | global.Debug(i...) 270 | } 271 | 272 | func Debugf(format string, args ...interface{}) { 273 | global.Debugf(format, args...) 274 | } 275 | 276 | func Debugj(j JSON) { 277 | global.Debugj(j) 278 | } 279 | 280 | func Info(i ...interface{}) { 281 | global.Info(i...) 282 | } 283 | 284 | func Infof(format string, args ...interface{}) { 285 | global.Infof(format, args...) 286 | } 287 | 288 | func Infoj(j JSON) { 289 | global.Infoj(j) 290 | } 291 | 292 | func Warn(i ...interface{}) { 293 | global.Warn(i...) 294 | } 295 | 296 | func Warnf(format string, args ...interface{}) { 297 | global.Warnf(format, args...) 298 | } 299 | 300 | func Warnj(j JSON) { 301 | global.Warnj(j) 302 | } 303 | 304 | func Error(i ...interface{}) { 305 | global.Error(i...) 306 | } 307 | 308 | func Errorf(format string, args ...interface{}) { 309 | global.Errorf(format, args...) 310 | } 311 | 312 | func Errorj(j JSON) { 313 | global.Errorj(j) 314 | } 315 | 316 | func Fatal(i ...interface{}) { 317 | global.Fatal(i...) 318 | } 319 | 320 | func Fatalf(format string, args ...interface{}) { 321 | global.Fatalf(format, args...) 322 | } 323 | 324 | func Fatalj(j JSON) { 325 | global.Fatalj(j) 326 | } 327 | 328 | func Panic(i ...interface{}) { 329 | global.Panic(i...) 330 | } 331 | 332 | func Panicf(format string, args ...interface{}) { 333 | global.Panicf(format, args...) 334 | } 335 | 336 | func Panicj(j JSON) { 337 | global.Panicj(j) 338 | } 339 | 340 | func (l *Logger) log(v Lvl, format string, args ...interface{}) { 341 | l.mutex.Lock() 342 | defer l.mutex.Unlock() 343 | buf := l.bufferPool.Get().(*bytes.Buffer) 344 | buf.Reset() 345 | defer l.bufferPool.Put(buf) 346 | _, file, line, _ := runtime.Caller(3) 347 | 348 | if v >= l.level || v == 0 { 349 | message := "" 350 | if format == "" { 351 | message = fmt.Sprint(args...) 352 | } else if format == "json" { 353 | b, err := json.Marshal(args[0]) 354 | if err != nil { 355 | panic(err) 356 | } 357 | message = string(b) 358 | } else { 359 | message = fmt.Sprintf(format, args...) 360 | } 361 | 362 | _, err := l.template.ExecuteFunc(buf, func(w io.Writer, tag string) (int, error) { 363 | switch tag { 364 | case "time_rfc3339": 365 | return w.Write([]byte(time.Now().Format(time.RFC3339))) 366 | case "level": 367 | return w.Write([]byte(l.levels[v])) 368 | case "prefix": 369 | return w.Write([]byte(l.prefix)) 370 | case "long_file": 371 | return w.Write([]byte(file)) 372 | case "short_file": 373 | return w.Write([]byte(path.Base(file))) 374 | case "line": 375 | return w.Write([]byte(strconv.Itoa(line))) 376 | } 377 | return 0, nil 378 | }) 379 | 380 | if err == nil { 381 | s := buf.String() 382 | i := buf.Len() - 1 383 | if s[i] == '}' { 384 | // JSON header 385 | buf.Truncate(i) 386 | buf.WriteByte(',') 387 | if format == "json" { 388 | buf.WriteString(message[1:]) 389 | } else { 390 | buf.WriteString(`"message":"`) 391 | buf.WriteString(message) 392 | buf.WriteString(`"}`) 393 | } 394 | } else { 395 | // Text header 396 | buf.WriteByte(' ') 397 | buf.WriteString(message) 398 | } 399 | buf.WriteByte('\n') 400 | l.output.Write(buf.Bytes()) 401 | } 402 | } 403 | } 404 | -------------------------------------------------------------------------------- /vendor/github.com/labstack/gommon/log/white.go: -------------------------------------------------------------------------------- 1 | // +build appengine 2 | 3 | package log 4 | 5 | import ( 6 | "io" 7 | "os" 8 | ) 9 | 10 | func output() io.Writer { 11 | return os.Stdout 12 | } 13 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-colorable/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Yasuhiro Matsumoto 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-colorable/README.md: -------------------------------------------------------------------------------- 1 | # go-colorable 2 | 3 | Colorable writer for windows. 4 | 5 | For example, most of logger packages doesn't show colors on windows. (I know we can do it with ansicon. But I don't want.) 6 | This package is possible to handle escape sequence for ansi color on windows. 7 | 8 | ## Too Bad! 9 | 10 | ![](https://raw.githubusercontent.com/mattn/go-colorable/gh-pages/bad.png) 11 | 12 | 13 | ## So Good! 14 | 15 | ![](https://raw.githubusercontent.com/mattn/go-colorable/gh-pages/good.png) 16 | 17 | ## Usage 18 | 19 | ```go 20 | logrus.SetFormatter(&logrus.TextFormatter{ForceColors: true}) 21 | logrus.SetOutput(colorable.NewColorableStdout()) 22 | 23 | logrus.Info("succeeded") 24 | logrus.Warn("not correct") 25 | logrus.Error("something error") 26 | logrus.Fatal("panic") 27 | ``` 28 | 29 | You can compile above code on non-windows OSs. 30 | 31 | ## Installation 32 | 33 | ``` 34 | $ go get github.com/mattn/go-colorable 35 | ``` 36 | 37 | # License 38 | 39 | MIT 40 | 41 | # Author 42 | 43 | Yasuhiro Matsumoto (a.k.a mattn) 44 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-colorable/colorable_others.go: -------------------------------------------------------------------------------- 1 | // +build !windows 2 | 3 | package colorable 4 | 5 | import ( 6 | "io" 7 | "os" 8 | ) 9 | 10 | // NewColorable return new instance of Writer which handle escape sequence. 11 | func NewColorable(file *os.File) io.Writer { 12 | if file == nil { 13 | panic("nil passed instead of *os.File to NewColorable()") 14 | } 15 | 16 | return file 17 | } 18 | 19 | // NewColorableStdout return new instance of Writer which handle escape sequence for stdout. 20 | func NewColorableStdout() io.Writer { 21 | return os.Stdout 22 | } 23 | 24 | // NewColorableStderr return new instance of Writer which handle escape sequence for stderr. 25 | func NewColorableStderr() io.Writer { 26 | return os.Stderr 27 | } 28 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-colorable/noncolorable.go: -------------------------------------------------------------------------------- 1 | package colorable 2 | 3 | import ( 4 | "bytes" 5 | "io" 6 | ) 7 | 8 | // NonColorable hold writer but remove escape sequence. 9 | type NonColorable struct { 10 | out io.Writer 11 | lastbuf bytes.Buffer 12 | } 13 | 14 | // NewNonColorable return new instance of Writer which remove escape sequence from Writer. 15 | func NewNonColorable(w io.Writer) io.Writer { 16 | return &NonColorable{out: w} 17 | } 18 | 19 | // Write write data on console 20 | func (w *NonColorable) Write(data []byte) (n int, err error) { 21 | er := bytes.NewReader(data) 22 | var bw [1]byte 23 | loop: 24 | for { 25 | c1, err := er.ReadByte() 26 | if err != nil { 27 | break loop 28 | } 29 | if c1 != 0x1b { 30 | bw[0] = c1 31 | w.out.Write(bw[:]) 32 | continue 33 | } 34 | c2, err := er.ReadByte() 35 | if err != nil { 36 | w.lastbuf.WriteByte(c1) 37 | break loop 38 | } 39 | if c2 != 0x5b { 40 | w.lastbuf.WriteByte(c1) 41 | w.lastbuf.WriteByte(c2) 42 | continue 43 | } 44 | 45 | var buf bytes.Buffer 46 | for { 47 | c, err := er.ReadByte() 48 | if err != nil { 49 | w.lastbuf.WriteByte(c1) 50 | w.lastbuf.WriteByte(c2) 51 | w.lastbuf.Write(buf.Bytes()) 52 | break loop 53 | } 54 | if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' { 55 | break 56 | } 57 | buf.Write([]byte(string(c))) 58 | } 59 | } 60 | return len(data) - w.lastbuf.Len(), nil 61 | } 62 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-isatty/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) Yasuhiro MATSUMOTO 2 | 3 | MIT License (Expat) 4 | 5 | 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: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | 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. 10 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-isatty/README.md: -------------------------------------------------------------------------------- 1 | # go-isatty 2 | 3 | isatty for golang 4 | 5 | ## Usage 6 | 7 | ```go 8 | package main 9 | 10 | import ( 11 | "fmt" 12 | "github.com/mattn/go-isatty" 13 | "os" 14 | ) 15 | 16 | func main() { 17 | if isatty.IsTerminal(os.Stdout.Fd()) { 18 | fmt.Println("Is Terminal") 19 | } else { 20 | fmt.Println("Is Not Terminal") 21 | } 22 | } 23 | ``` 24 | 25 | ## Installation 26 | 27 | ``` 28 | $ go get github.com/mattn/go-isatty 29 | ``` 30 | 31 | # License 32 | 33 | MIT 34 | 35 | # Author 36 | 37 | Yasuhiro Matsumoto (a.k.a mattn) 38 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-isatty/doc.go: -------------------------------------------------------------------------------- 1 | // Package isatty implements interface to isatty 2 | package isatty 3 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-isatty/isatty_appengine.go: -------------------------------------------------------------------------------- 1 | // +build appengine 2 | 3 | package isatty 4 | 5 | // IsTerminal returns true if the file descriptor is terminal which 6 | // is always false on on appengine classic which is a sandboxed PaaS. 7 | func IsTerminal(fd uintptr) bool { 8 | return false 9 | } 10 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-isatty/isatty_bsd.go: -------------------------------------------------------------------------------- 1 | // +build darwin freebsd openbsd netbsd dragonfly 2 | // +build !appengine 3 | 4 | package isatty 5 | 6 | import ( 7 | "syscall" 8 | "unsafe" 9 | ) 10 | 11 | const ioctlReadTermios = syscall.TIOCGETA 12 | 13 | // IsTerminal return true if the file descriptor is terminal. 14 | func IsTerminal(fd uintptr) bool { 15 | var termios syscall.Termios 16 | _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0) 17 | return err == 0 18 | } 19 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-isatty/isatty_linux.go: -------------------------------------------------------------------------------- 1 | // +build linux 2 | // +build !appengine 3 | 4 | package isatty 5 | 6 | import ( 7 | "syscall" 8 | "unsafe" 9 | ) 10 | 11 | const ioctlReadTermios = syscall.TCGETS 12 | 13 | // IsTerminal return true if the file descriptor is terminal. 14 | func IsTerminal(fd uintptr) bool { 15 | var termios syscall.Termios 16 | _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0) 17 | return err == 0 18 | } 19 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-isatty/isatty_solaris.go: -------------------------------------------------------------------------------- 1 | // +build solaris 2 | // +build !appengine 3 | 4 | package isatty 5 | 6 | import ( 7 | "golang.org/x/sys/unix" 8 | ) 9 | 10 | // IsTerminal returns true if the given file descriptor is a terminal. 11 | // see: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libbc/libc/gen/common/isatty.c 12 | func IsTerminal(fd uintptr) bool { 13 | var termio unix.Termio 14 | err := unix.IoctlSetTermio(int(fd), unix.TCGETA, &termio) 15 | return err == nil 16 | } 17 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-isatty/isatty_windows.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | // +build !appengine 3 | 4 | package isatty 5 | 6 | import ( 7 | "syscall" 8 | "unsafe" 9 | ) 10 | 11 | var kernel32 = syscall.NewLazyDLL("kernel32.dll") 12 | var procGetConsoleMode = kernel32.NewProc("GetConsoleMode") 13 | 14 | // IsTerminal return true if the file descriptor is terminal. 15 | func IsTerminal(fd uintptr) bool { 16 | var st uint32 17 | r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, fd, uintptr(unsafe.Pointer(&st)), 0) 18 | return r != 0 && e == 0 19 | } 20 | -------------------------------------------------------------------------------- /vendor/github.com/rsc/letsencrypt/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/github.com/rsc/letsencrypt/README: -------------------------------------------------------------------------------- 1 | package letsencrypt // import "rsc.io/letsencrypt" 2 | 3 | Package letsencrypt obtains TLS certificates from LetsEncrypt.org. 4 | 5 | LetsEncrypt.org is a service that issues free SSL/TLS certificates to 6 | servers that can prove control over the given domain's DNS records or the 7 | servers pointed at by those records. 8 | 9 | 10 | Warning 11 | 12 | Like any other random code you find on the internet, this package should not 13 | be relied upon in important, production systems without thorough testing to 14 | ensure that it meets your needs. 15 | 16 | In the long term you should be using 17 | https://golang.org/x/crypto/acme/autocert instead of this package. Send 18 | improvements there, not here. 19 | 20 | This is a package that I wrote for my own personal web sites (swtch.com, 21 | rsc.io) in a hurry when my paid-for SSL certificate was expiring. It has no 22 | tests, has barely been used, and there is some anecdotal evidence that it 23 | does not properly renew certificates in a timely fashion, so servers that 24 | run for more than 3 months may run into trouble. I don't run this code 25 | anymore: to simplify maintenance, I moved the sites off of Ubuntu VMs and 26 | onto Google App Engine, configured with inexpensive long-term certificates 27 | purchased from cheapsslsecurity.com. 28 | 29 | This package was interesting primarily as an example of how simple the API 30 | for using LetsEncrypt.org could be made, in contrast to the low-level 31 | implementations that existed at the time. In that respect, it helped inform 32 | the design of the golang.org/x/crypto/acme/autocert package. 33 | 34 | 35 | Quick Start 36 | 37 | A complete HTTP/HTTPS web server using TLS certificates from 38 | LetsEncrypt.org, redirecting all HTTP access to HTTPS, and maintaining TLS 39 | certificates in a file letsencrypt.cache across server restarts. 40 | 41 | package main 42 | 43 | import ( 44 | "fmt" 45 | "log" 46 | "net/http" 47 | "rsc.io/letsencrypt" 48 | ) 49 | 50 | func main() { 51 | http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 52 | fmt.Fprintf(w, "Hello, TLS!\n") 53 | }) 54 | var m letsencrypt.Manager 55 | if err := m.CacheFile("letsencrypt.cache"); err != nil { 56 | log.Fatal(err) 57 | } 58 | log.Fatal(m.Serve()) 59 | } 60 | 61 | 62 | Overview 63 | 64 | The fundamental type in this package is the Manager, which manages obtaining 65 | and refreshing a collection of TLS certificates, typically for use by an 66 | HTTPS server. The example above shows the most basic use of a Manager. The 67 | use can be customized by calling additional methods of the Manager. 68 | 69 | 70 | Registration 71 | 72 | A Manager m registers anonymously with LetsEncrypt.org, including agreeing 73 | to the letsencrypt.org terms of service, the first time it needs to obtain a 74 | certificate. To register with a particular email address and with the option 75 | of a prompt for agreement with the terms of service, call m.Register. 76 | 77 | 78 | GetCertificate 79 | 80 | The Manager's GetCertificate method returns certificates from the Manager's 81 | cache, filling the cache by requesting certificates from LetsEncrypt.org. In 82 | this way, a server with a tls.Config.GetCertificate set to m.GetCertificate 83 | will demand load a certificate for any host name it serves. To force loading 84 | of certificates ahead of time, install m.GetCertificate as before but then 85 | call m.Cert for each host name. 86 | 87 | A Manager can only obtain a certificate for a given host name if it can 88 | prove control of that host name to LetsEncrypt.org. By default it proves 89 | control by answering an HTTPS-based challenge: when the LetsEncrypt.org 90 | servers connect to the named host on port 443 (HTTPS), the TLS SNI handshake 91 | must use m.GetCertificate to obtain a per-host certificate. The most common 92 | way to satisfy this requirement is for the host name to resolve to the IP 93 | address of a (single) computer running m.ServeHTTPS, or at least running a 94 | Go TLS server with tls.Config.GetCertificate set to m.GetCertificate. 95 | However, other configurations are possible. For example, a group of machines 96 | could use an implementation of tls.Config.GetCertificate that cached 97 | certificates but handled cache misses by making RPCs to a Manager m on an 98 | elected leader machine. 99 | 100 | In typical usage, then, the setting of tls.Config.GetCertificate to 101 | m.GetCertificate serves two purposes: it provides certificates to the TLS 102 | server for ordinary serving, and it also answers challenges to prove 103 | ownership of the domains in order to obtain those certificates. 104 | 105 | To force the loading of a certificate for a given host into the Manager's 106 | cache, use m.Cert. 107 | 108 | 109 | Persistent Storage 110 | 111 | If a server always starts with a zero Manager m, the server effectively 112 | fetches a new certificate for each of its host name from LetsEncrypt.org on 113 | each restart. This is unfortunate both because the server cannot start if 114 | LetsEncrypt.org is unavailable and because LetsEncrypt.org limits how often 115 | it will issue a certificate for a given host name (at time of writing, the 116 | limit is 5 per week for a given host name). To save server state proactively 117 | to a cache file and to reload the server state from that same file when 118 | creating a new manager, call m.CacheFile with the name of the file to use. 119 | 120 | For alternate storage uses, m.Marshal returns the current state of the 121 | Manager as an opaque string, m.Unmarshal sets the state of the Manager using 122 | a string previously returned by m.Marshal (usually a different m), and 123 | m.Watch returns a channel that receives notifications about state changes. 124 | 125 | 126 | Limits 127 | 128 | To avoid hitting basic rate limits on LetsEncrypt.org, a given Manager 129 | limits all its interactions to at most one request every minute, with an 130 | initial allowed burst of 20 requests. 131 | 132 | By default, if GetCertificate is asked for a certificate it does not have, 133 | it will in turn ask LetsEncrypt.org for that certificate. This opens a 134 | potential attack where attackers connect to a server by IP address and 135 | pretend to be asking for an incorrect host name. Then GetCertificate will 136 | attempt to obtain a certificate for that host, incorrectly, eventually 137 | hitting LetsEncrypt.org's rate limit for certificate requests and making it 138 | impossible to obtain actual certificates. Because servers hold certificates 139 | for months at a time, however, an attack would need to be sustained over a 140 | time period of at least a month in order to cause real problems. 141 | 142 | To mitigate this kind of attack, a given Manager limits itself to an average 143 | of one certificate request for a new host every three hours, with an initial 144 | allowed burst of up to 20 requests. Long-running servers will therefore stay 145 | within the LetsEncrypt.org limit of 300 failed requests per month. 146 | Certificate refreshes are not subject to this limit. 147 | 148 | To eliminate the attack entirely, call m.SetHosts to enumerate the exact set 149 | of hosts that are allowed in certificate requests. 150 | 151 | 152 | Web Servers 153 | 154 | The basic requirement for use of a Manager is that there be an HTTPS server 155 | running on port 443 and calling m.GetCertificate to obtain TLS certificates. 156 | Using standard primitives, the way to do this is: 157 | 158 | srv := &http.Server{ 159 | Addr: ":https", 160 | TLSConfig: &tls.Config{ 161 | GetCertificate: m.GetCertificate, 162 | }, 163 | } 164 | srv.ListenAndServeTLS("", "") 165 | 166 | However, this pattern of serving HTTPS with demand-loaded TLS certificates 167 | comes up enough to wrap into a single method m.ServeHTTPS. 168 | 169 | Similarly, many HTTPS servers prefer to redirect HTTP clients to the HTTPS 170 | URLs. That functionality is provided by RedirectHTTP. 171 | 172 | The combination of serving HTTPS with demand-loaded TLS certificates and 173 | serving HTTPS redirects to HTTP clients is provided by m.Serve, as used in 174 | the original example above. 175 | 176 | func RedirectHTTP(w http.ResponseWriter, r *http.Request) 177 | type Manager struct { ... } 178 | -------------------------------------------------------------------------------- /vendor/github.com/tylerb/graceful/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Tyler Bunnell 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/tylerb/graceful/README.md: -------------------------------------------------------------------------------- 1 | graceful [![GoDoc](https://godoc.org/github.com/tylerb/graceful?status.png)](http://godoc.org/github.com/tylerb/graceful) [![Build Status](https://travis-ci.org/tylerb/graceful.svg?branch=master)](https://travis-ci.org/tylerb/graceful) [![Coverage Status](https://coveralls.io/repos/tylerb/graceful/badge.svg)](https://coveralls.io/r/tylerb/graceful) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/tylerb/graceful?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) 2 | ======== 3 | 4 | Graceful is a Go 1.3+ package enabling graceful shutdown of http.Handler servers. 5 | 6 | ## Installation 7 | 8 | To install, simply execute: 9 | 10 | ``` 11 | go get gopkg.in/tylerb/graceful.v1 12 | ``` 13 | 14 | I am using [gopkg.in](http://labix.org/gopkg.in) to control releases. 15 | 16 | ## Usage 17 | 18 | Using Graceful is easy. Simply create your http.Handler and pass it to the `Run` function: 19 | 20 | ```go 21 | package main 22 | 23 | import ( 24 | "gopkg.in/tylerb/graceful.v1" 25 | "net/http" 26 | "fmt" 27 | "time" 28 | ) 29 | 30 | func main() { 31 | mux := http.NewServeMux() 32 | mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { 33 | fmt.Fprintf(w, "Welcome to the home page!") 34 | }) 35 | 36 | graceful.Run(":3001",10*time.Second,mux) 37 | } 38 | ``` 39 | 40 | Another example, using [Negroni](https://github.com/codegangsta/negroni), functions in much the same manner: 41 | 42 | ```go 43 | package main 44 | 45 | import ( 46 | "github.com/codegangsta/negroni" 47 | "gopkg.in/tylerb/graceful.v1" 48 | "net/http" 49 | "fmt" 50 | "time" 51 | ) 52 | 53 | func main() { 54 | mux := http.NewServeMux() 55 | mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { 56 | fmt.Fprintf(w, "Welcome to the home page!") 57 | }) 58 | 59 | n := negroni.Classic() 60 | n.UseHandler(mux) 61 | //n.Run(":3000") 62 | graceful.Run(":3001",10*time.Second,n) 63 | } 64 | ``` 65 | 66 | In addition to Run there are the http.Server counterparts ListenAndServe, ListenAndServeTLS and Serve, which allow you to configure HTTPS, custom timeouts and error handling. 67 | Graceful may also be used by instantiating its Server type directly, which embeds an http.Server: 68 | 69 | ```go 70 | mux := // ... 71 | 72 | srv := &graceful.Server{ 73 | Timeout: 10 * time.Second, 74 | 75 | Server: &http.Server{ 76 | Addr: ":1234", 77 | Handler: mux, 78 | }, 79 | } 80 | 81 | srv.ListenAndServe() 82 | ``` 83 | 84 | This form allows you to set the ConnState callback, which works in the same way as in http.Server: 85 | 86 | ```go 87 | mux := // ... 88 | 89 | srv := &graceful.Server{ 90 | Timeout: 10 * time.Second, 91 | 92 | ConnState: func(conn net.Conn, state http.ConnState) { 93 | // conn has a new state 94 | }, 95 | 96 | Server: &http.Server{ 97 | Addr: ":1234", 98 | Handler: mux, 99 | }, 100 | } 101 | 102 | srv.ListenAndServe() 103 | ``` 104 | 105 | ## Behaviour 106 | 107 | When Graceful is sent a SIGINT or SIGTERM (possibly from ^C or a kill command), it: 108 | 109 | 1. Disables keepalive connections. 110 | 2. Closes the listening socket, allowing another process to listen on that port immediately. 111 | 3. Starts a timer of `timeout` duration to give active requests a chance to finish. 112 | 4. When timeout expires, closes all active connections. 113 | 5. Closes the `stopChan`, waking up any blocking goroutines. 114 | 6. Returns from the function, allowing the server to terminate. 115 | 116 | ## Notes 117 | 118 | If the `timeout` argument to `Run` is 0, the server never times out, allowing all active requests to complete. 119 | 120 | If you wish to stop the server in some way other than an OS signal, you may call the `Stop()` function. 121 | This function stops the server, gracefully, using the new timeout value you provide. The `StopChan()` function 122 | returns a channel on which you can block while waiting for the server to stop. This channel will be closed when 123 | the server is stopped, allowing your execution to proceed. Multiple goroutines can block on this channel at the 124 | same time and all will be signalled when stopping is complete. 125 | 126 | ### Important things to note when setting `timeout` to 0: 127 | 128 | If you set the `timeout` to `0`, it waits for all connections to the server to disconnect before shutting down. 129 | This means that even though requests over a connection have finished, it is possible for the client to hold the 130 | connection open and block the server from shutting down indefinitely. 131 | 132 | This is especially evident when graceful is used to run HTTP/2 servers. Clients like Chrome and Firefox have been 133 | observed to hold onto the open connection indefinitely over HTTP/2, preventing the server from shutting down. In 134 | addition, there is also the risk of malicious clients holding and keeping the connection alive. 135 | 136 | It is understandable that sometimes, you might want to wait for the client indefinitely because they might be 137 | uploading large files. In these type of cases, it is recommended that you set a reasonable timeout to kill the 138 | connection, and have the client perform resumable uploads. For example, the client can divide the file into chunks 139 | and reupload chunks that were in transit when the connection was terminated. 140 | 141 | ## Contributing 142 | 143 | If you would like to contribute, please: 144 | 145 | 1. Create a GitHub issue regarding the contribution. Features and bugs should be discussed beforehand. 146 | 2. Fork the repository. 147 | 3. Create a pull request with your solution. This pull request should reference and close the issues (Fix #2). 148 | 149 | All pull requests should: 150 | 151 | 1. Pass [gometalinter -t .](https://github.com/alecthomas/gometalinter) with no warnings. 152 | 2. Be `go fmt` formatted. 153 | -------------------------------------------------------------------------------- /vendor/github.com/tylerb/graceful/keepalive_listener.go: -------------------------------------------------------------------------------- 1 | package graceful 2 | 3 | import ( 4 | "net" 5 | "time" 6 | ) 7 | 8 | type keepAliveConn interface { 9 | SetKeepAlive(bool) error 10 | SetKeepAlivePeriod(d time.Duration) error 11 | } 12 | 13 | // keepAliveListener sets TCP keep-alive timeouts on accepted 14 | // connections. It's used by ListenAndServe and ListenAndServeTLS so 15 | // dead TCP connections (e.g. closing laptop mid-download) eventually 16 | // go away. 17 | type keepAliveListener struct { 18 | net.Listener 19 | keepAlivePeriod time.Duration 20 | } 21 | 22 | func (ln keepAliveListener) Accept() (net.Conn, error) { 23 | c, err := ln.Listener.Accept() 24 | if err != nil { 25 | return nil, err 26 | } 27 | 28 | kac := c.(keepAliveConn) 29 | kac.SetKeepAlive(true) 30 | kac.SetKeepAlivePeriod(ln.keepAlivePeriod) 31 | return c, nil 32 | } 33 | -------------------------------------------------------------------------------- /vendor/github.com/tylerb/graceful/limit_listen.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The etcd Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package graceful 16 | 17 | import ( 18 | "errors" 19 | "net" 20 | "sync" 21 | "time" 22 | ) 23 | 24 | // ErrNotTCP indicates that network connection is not a TCP connection. 25 | var ErrNotTCP = errors.New("only tcp connections have keepalive") 26 | 27 | // LimitListener returns a Listener that accepts at most n simultaneous 28 | // connections from the provided Listener. 29 | func LimitListener(l net.Listener, n int) net.Listener { 30 | return &limitListener{l, make(chan struct{}, n)} 31 | } 32 | 33 | type limitListener struct { 34 | net.Listener 35 | sem chan struct{} 36 | } 37 | 38 | func (l *limitListener) acquire() { l.sem <- struct{}{} } 39 | func (l *limitListener) release() { <-l.sem } 40 | 41 | func (l *limitListener) Accept() (net.Conn, error) { 42 | l.acquire() 43 | c, err := l.Listener.Accept() 44 | if err != nil { 45 | l.release() 46 | return nil, err 47 | } 48 | return &limitListenerConn{Conn: c, release: l.release}, nil 49 | } 50 | 51 | type limitListenerConn struct { 52 | net.Conn 53 | releaseOnce sync.Once 54 | release func() 55 | } 56 | 57 | func (l *limitListenerConn) Close() error { 58 | err := l.Conn.Close() 59 | l.releaseOnce.Do(l.release) 60 | return err 61 | } 62 | 63 | func (l *limitListenerConn) SetKeepAlive(doKeepAlive bool) error { 64 | tcpc, ok := l.Conn.(*net.TCPConn) 65 | if !ok { 66 | return ErrNotTCP 67 | } 68 | return tcpc.SetKeepAlive(doKeepAlive) 69 | } 70 | 71 | func (l *limitListenerConn) SetKeepAlivePeriod(d time.Duration) error { 72 | tcpc, ok := l.Conn.(*net.TCPConn) 73 | if !ok { 74 | return ErrNotTCP 75 | } 76 | return tcpc.SetKeepAlivePeriod(d) 77 | } 78 | -------------------------------------------------------------------------------- /vendor/github.com/tylerb/graceful/signal.go: -------------------------------------------------------------------------------- 1 | //+build !appengine 2 | 3 | package graceful 4 | 5 | import ( 6 | "os" 7 | "os/signal" 8 | "syscall" 9 | ) 10 | 11 | func signalNotify(interrupt chan<- os.Signal) { 12 | signal.Notify(interrupt, syscall.SIGINT, syscall.SIGTERM) 13 | } 14 | 15 | func sendSignalInt(interrupt chan<- os.Signal) { 16 | interrupt <- syscall.SIGINT 17 | } 18 | -------------------------------------------------------------------------------- /vendor/github.com/tylerb/graceful/signal_appengine.go: -------------------------------------------------------------------------------- 1 | //+build appengine 2 | 3 | package graceful 4 | 5 | import "os" 6 | 7 | func signalNotify(interrupt chan<- os.Signal) { 8 | // Does not notify in the case of AppEngine. 9 | } 10 | 11 | func sendSignalInt(interrupt chan<- os.Signal) { 12 | // Does not send in the case of AppEngine. 13 | } 14 | -------------------------------------------------------------------------------- /vendor/github.com/valyala/fasttemplate/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Aliaksandr Valialkin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /vendor/github.com/valyala/fasttemplate/README.md: -------------------------------------------------------------------------------- 1 | fasttemplate 2 | ============ 3 | 4 | Simple and fast template engine for Go. 5 | 6 | Fasttemplate peforms only a single task - it substitutes template placeholders 7 | with user-defined values. At high speed :) 8 | 9 | Take a look at [quicktemplate](https://github.com/valyala/quicktemplate) if you need fast yet powerful html template engine. 10 | 11 | *Please note that fasttemplate doesn't do any escaping on template values 12 | unlike [html/template](http://golang.org/pkg/html/template/) do. So values 13 | must be properly escaped before passing them to fasttemplate.* 14 | 15 | Fasttemplate is faster than [text/template](http://golang.org/pkg/text/template/), 16 | [strings.Replace](http://golang.org/pkg/strings/#Replace), 17 | [strings.Replacer](http://golang.org/pkg/strings/#Replacer) 18 | and [fmt.Fprintf](https://golang.org/pkg/fmt/#Fprintf) on placeholders' substitution. 19 | 20 | Below are benchmark results comparing fasttemplate performance to text/template, 21 | strings.Replace, strings.Replacer and fmt.Fprintf: 22 | 23 | ``` 24 | $ go test -bench=. -benchmem 25 | PASS 26 | BenchmarkFmtFprintf-4 2000000 790 ns/op 0 B/op 0 allocs/op 27 | BenchmarkStringsReplace-4 500000 3474 ns/op 2112 B/op 14 allocs/op 28 | BenchmarkStringsReplacer-4 500000 2657 ns/op 2256 B/op 23 allocs/op 29 | BenchmarkTextTemplate-4 500000 3333 ns/op 336 B/op 19 allocs/op 30 | BenchmarkFastTemplateExecuteFunc-4 5000000 349 ns/op 0 B/op 0 allocs/op 31 | BenchmarkFastTemplateExecute-4 3000000 383 ns/op 0 B/op 0 allocs/op 32 | BenchmarkFastTemplateExecuteFuncString-4 3000000 549 ns/op 144 B/op 1 allocs/op 33 | BenchmarkFastTemplateExecuteString-4 3000000 572 ns/op 144 B/op 1 allocs/op 34 | BenchmarkFastTemplateExecuteTagFunc-4 2000000 743 ns/op 144 B/op 3 allocs/op 35 | ``` 36 | 37 | 38 | Docs 39 | ==== 40 | 41 | See http://godoc.org/github.com/valyala/fasttemplate . 42 | 43 | 44 | Usage 45 | ===== 46 | 47 | ```go 48 | template := "http://{{host}}/?q={{query}}&foo={{bar}}{{bar}}" 49 | t := fasttemplate.New(template, "{{", "}}") 50 | s := t.ExecuteString(map[string]interface{}{ 51 | "host": "google.com", 52 | "query": url.QueryEscape("hello=world"), 53 | "bar": "foobar", 54 | }) 55 | fmt.Printf("%s", s) 56 | 57 | // Output: 58 | // http://google.com/?q=hello%3Dworld&foo=foobarfoobar 59 | ``` 60 | 61 | 62 | Advanced usage 63 | ============== 64 | 65 | ```go 66 | template := "Hello, [user]! You won [prize]!!! [foobar]" 67 | t, err := fasttemplate.NewTemplate(template, "[", "]") 68 | if err != nil { 69 | log.Fatalf("unexpected error when parsing template: %s", err) 70 | } 71 | s := t.ExecuteFuncString(func(w io.Writer, tag string) (int, error) { 72 | switch tag { 73 | case "user": 74 | return w.Write([]byte("John")) 75 | case "prize": 76 | return w.Write([]byte("$100500")) 77 | default: 78 | return w.Write([]byte(fmt.Sprintf("[unknown tag %q]", tag))) 79 | } 80 | }) 81 | fmt.Printf("%s", s) 82 | 83 | // Output: 84 | // Hello, John! You won $100500!!! [unknown tag "foobar"] 85 | ``` 86 | -------------------------------------------------------------------------------- /vendor/github.com/valyala/fasttemplate/template.go: -------------------------------------------------------------------------------- 1 | // Package fasttemplate implements simple and fast template library. 2 | // 3 | // Fasttemplate is faster than text/template, strings.Replace 4 | // and strings.Replacer. 5 | // 6 | // Fasttemplate ideally fits for fast and simple placeholders' substitutions. 7 | package fasttemplate 8 | 9 | import ( 10 | "bytes" 11 | "fmt" 12 | "io" 13 | "sync" 14 | ) 15 | 16 | // Template implements simple template engine, which can be used for fast 17 | // tags' (aka placeholders) substitution. 18 | type Template struct { 19 | texts [][]byte 20 | tags []string 21 | bytesBufferPool sync.Pool 22 | } 23 | 24 | // New parses the given template using the given startTag and endTag 25 | // as tag start and tag end. 26 | // 27 | // The returned template can be executed by concurrently running goroutines 28 | // using Execute* methods. 29 | // 30 | // New panics if the given template cannot be parsed. Use NewTemplate instead 31 | // if template may contain errors. 32 | func New(template, startTag, endTag string) *Template { 33 | t, err := NewTemplate(template, startTag, endTag) 34 | if err != nil { 35 | panic(err) 36 | } 37 | return t 38 | } 39 | 40 | // NewTemplate parses the given template using the given startTag and endTag 41 | // as tag start and tag end. 42 | // 43 | // The returned template can be executed by concurrently running goroutines 44 | // using Execute* methods. 45 | func NewTemplate(template, startTag, endTag string) (*Template, error) { 46 | var t Template 47 | 48 | if len(startTag) == 0 { 49 | panic("startTag cannot be empty") 50 | } 51 | if len(endTag) == 0 { 52 | panic("endTag cannot be empty") 53 | } 54 | 55 | s := []byte(template) 56 | a := []byte(startTag) 57 | b := []byte(endTag) 58 | 59 | for { 60 | n := bytes.Index(s, a) 61 | if n < 0 { 62 | t.texts = append(t.texts, s) 63 | break 64 | } 65 | t.texts = append(t.texts, s[:n]) 66 | 67 | s = s[n+len(a):] 68 | n = bytes.Index(s, b) 69 | if n < 0 { 70 | return nil, fmt.Errorf("Cannot find end tag=%q in the template=%q starting from %q", endTag, template, s) 71 | } 72 | 73 | t.tags = append(t.tags, string(s[:n])) 74 | s = s[n+len(b):] 75 | } 76 | 77 | t.bytesBufferPool.New = newBytesBuffer 78 | return &t, nil 79 | } 80 | 81 | func newBytesBuffer() interface{} { 82 | return &bytes.Buffer{} 83 | } 84 | 85 | // TagFunc can be used as a substitution value in the map passed to Execute*. 86 | // Execute* functions pass tag (placeholder) name in 'tag' argument. 87 | // 88 | // TagFunc must be safe to call from concurrently running goroutines. 89 | // 90 | // TagFunc must write contents to w and return the number of bytes written. 91 | type TagFunc func(w io.Writer, tag string) (int, error) 92 | 93 | // ExecuteFunc calls f on each template tag (placeholder) occurrence. 94 | // 95 | // Returns the number of bytes written to w. 96 | func (t *Template) ExecuteFunc(w io.Writer, f TagFunc) (int64, error) { 97 | var nn int64 98 | 99 | n := len(t.texts) - 1 100 | for i := 0; i < n; i++ { 101 | ni, err := w.Write(t.texts[i]) 102 | if err != nil { 103 | return nn, err 104 | } 105 | nn += int64(ni) 106 | 107 | if ni, err = f(w, t.tags[i]); err != nil { 108 | return nn, err 109 | } 110 | nn += int64(ni) 111 | } 112 | ni, err := w.Write(t.texts[n]) 113 | if err != nil { 114 | return nn, err 115 | } 116 | nn += int64(ni) 117 | return nn, nil 118 | } 119 | 120 | // Execute substitutes template tags (placeholders) with the corresponding 121 | // values from the map m and writes the result to the given writer w. 122 | // 123 | // Substitution map m may contain values with the following types: 124 | // * []byte - the fastest value type 125 | // * string - convenient value type 126 | // * TagFunc - flexible value type 127 | // 128 | // Returns the number of bytes written to w. 129 | func (t *Template) Execute(w io.Writer, m map[string]interface{}) (int64, error) { 130 | return t.ExecuteFunc(w, func(w io.Writer, tag string) (int, error) { return stdTagFunc(w, tag, m) }) 131 | } 132 | 133 | // ExecuteFuncString call f on each template tag (placeholder) occurrence 134 | // and substitutes it with the data written to TagFunc's w. 135 | // 136 | // Returns the resulting string. 137 | func (t *Template) ExecuteFuncString(f TagFunc) string { 138 | w := t.bytesBufferPool.Get().(*bytes.Buffer) 139 | if _, err := t.ExecuteFunc(w, f); err != nil { 140 | panic(fmt.Sprintf("unexpected error: %s", err)) 141 | } 142 | s := string(w.Bytes()) 143 | w.Reset() 144 | t.bytesBufferPool.Put(w) 145 | return s 146 | } 147 | 148 | // ExecuteString substitutes template tags (placeholders) with the corresponding 149 | // values from the map m and returns the result. 150 | // 151 | // Substitution map m may contain values with the following types: 152 | // * []byte - the fastest value type 153 | // * string - convenient value type 154 | // * TagFunc - flexible value type 155 | // 156 | func (t *Template) ExecuteString(m map[string]interface{}) string { 157 | return t.ExecuteFuncString(func(w io.Writer, tag string) (int, error) { return stdTagFunc(w, tag, m) }) 158 | } 159 | 160 | func stdTagFunc(w io.Writer, tag string, m map[string]interface{}) (int, error) { 161 | v := m[tag] 162 | if v == nil { 163 | return 0, nil 164 | } 165 | switch value := v.(type) { 166 | case []byte: 167 | return w.Write(value) 168 | case string: 169 | return w.Write([]byte(value)) 170 | case TagFunc: 171 | return value(w, tag) 172 | default: 173 | panic(fmt.Sprintf("tag=%q contains unexpected value type=%#v. Expected []byte, string or TagFunc", tag, v)) 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /vendor/github.com/xenolf/lego/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Sebastian Erhart 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/xenolf/lego/acme/challenges.go: -------------------------------------------------------------------------------- 1 | package acme 2 | 3 | // Challenge is a string that identifies a particular type and version of ACME challenge. 4 | type Challenge string 5 | 6 | const ( 7 | // HTTP01 is the "http-01" ACME challenge https://github.com/ietf-wg-acme/acme/blob/master/draft-ietf-acme-acme.md#http 8 | // Note: HTTP01ChallengePath returns the URL path to fulfill this challenge 9 | HTTP01 = Challenge("http-01") 10 | // TLSSNI01 is the "tls-sni-01" ACME challenge https://github.com/ietf-wg-acme/acme/blob/master/draft-ietf-acme-acme.md#tls-with-server-name-indication-tls-sni 11 | // Note: TLSSNI01ChallengeCert returns a certificate to fulfill this challenge 12 | TLSSNI01 = Challenge("tls-sni-01") 13 | // DNS01 is the "dns-01" ACME challenge https://github.com/ietf-wg-acme/acme/blob/master/draft-ietf-acme-acme.md#dns 14 | // Note: DNS01Record returns a DNS record which will fulfill this challenge 15 | DNS01 = Challenge("dns-01") 16 | ) 17 | -------------------------------------------------------------------------------- /vendor/github.com/xenolf/lego/acme/crypto.go: -------------------------------------------------------------------------------- 1 | package acme 2 | 3 | import ( 4 | "bytes" 5 | "crypto" 6 | "crypto/ecdsa" 7 | "crypto/elliptic" 8 | "crypto/rand" 9 | "crypto/rsa" 10 | "crypto/x509" 11 | "crypto/x509/pkix" 12 | "encoding/base64" 13 | "encoding/pem" 14 | "errors" 15 | "fmt" 16 | "io" 17 | "io/ioutil" 18 | "math/big" 19 | "net/http" 20 | "strings" 21 | "time" 22 | 23 | "golang.org/x/crypto/ocsp" 24 | ) 25 | 26 | // KeyType represents the key algo as well as the key size or curve to use. 27 | type KeyType string 28 | type derCertificateBytes []byte 29 | 30 | // Constants for all key types we support. 31 | const ( 32 | EC256 = KeyType("P256") 33 | EC384 = KeyType("P384") 34 | RSA2048 = KeyType("2048") 35 | RSA4096 = KeyType("4096") 36 | RSA8192 = KeyType("8192") 37 | ) 38 | 39 | const ( 40 | // OCSPGood means that the certificate is valid. 41 | OCSPGood = ocsp.Good 42 | // OCSPRevoked means that the certificate has been deliberately revoked. 43 | OCSPRevoked = ocsp.Revoked 44 | // OCSPUnknown means that the OCSP responder doesn't know about the certificate. 45 | OCSPUnknown = ocsp.Unknown 46 | // OCSPServerFailed means that the OCSP responder failed to process the request. 47 | OCSPServerFailed = ocsp.ServerFailed 48 | ) 49 | 50 | // GetOCSPForCert takes a PEM encoded cert or cert bundle returning the raw OCSP response, 51 | // the parsed response, and an error, if any. The returned []byte can be passed directly 52 | // into the OCSPStaple property of a tls.Certificate. If the bundle only contains the 53 | // issued certificate, this function will try to get the issuer certificate from the 54 | // IssuingCertificateURL in the certificate. If the []byte and/or ocsp.Response return 55 | // values are nil, the OCSP status may be assumed OCSPUnknown. 56 | func GetOCSPForCert(bundle []byte) ([]byte, *ocsp.Response, error) { 57 | certificates, err := parsePEMBundle(bundle) 58 | if err != nil { 59 | return nil, nil, err 60 | } 61 | 62 | // We expect the certificate slice to be ordered downwards the chain. 63 | // SRV CRT -> CA. We need to pull the leaf and issuer certs out of it, 64 | // which should always be the first two certificates. If there's no 65 | // OCSP server listed in the leaf cert, there's nothing to do. And if 66 | // we have only one certificate so far, we need to get the issuer cert. 67 | issuedCert := certificates[0] 68 | if len(issuedCert.OCSPServer) == 0 { 69 | return nil, nil, errors.New("no OCSP server specified in cert") 70 | } 71 | if len(certificates) == 1 { 72 | // TODO: build fallback. If this fails, check the remaining array entries. 73 | if len(issuedCert.IssuingCertificateURL) == 0 { 74 | return nil, nil, errors.New("no issuing certificate URL") 75 | } 76 | 77 | resp, err := httpGet(issuedCert.IssuingCertificateURL[0]) 78 | if err != nil { 79 | return nil, nil, err 80 | } 81 | defer resp.Body.Close() 82 | 83 | issuerBytes, err := ioutil.ReadAll(limitReader(resp.Body, 1024*1024)) 84 | if err != nil { 85 | return nil, nil, err 86 | } 87 | 88 | issuerCert, err := x509.ParseCertificate(issuerBytes) 89 | if err != nil { 90 | return nil, nil, err 91 | } 92 | 93 | // Insert it into the slice on position 0 94 | // We want it ordered right SRV CRT -> CA 95 | certificates = append(certificates, issuerCert) 96 | } 97 | issuerCert := certificates[1] 98 | 99 | // Finally kick off the OCSP request. 100 | ocspReq, err := ocsp.CreateRequest(issuedCert, issuerCert, nil) 101 | if err != nil { 102 | return nil, nil, err 103 | } 104 | 105 | reader := bytes.NewReader(ocspReq) 106 | req, err := httpPost(issuedCert.OCSPServer[0], "application/ocsp-request", reader) 107 | if err != nil { 108 | return nil, nil, err 109 | } 110 | defer req.Body.Close() 111 | 112 | ocspResBytes, err := ioutil.ReadAll(limitReader(req.Body, 1024*1024)) 113 | ocspRes, err := ocsp.ParseResponse(ocspResBytes, issuerCert) 114 | if err != nil { 115 | return nil, nil, err 116 | } 117 | 118 | if ocspRes.Certificate == nil { 119 | err = ocspRes.CheckSignatureFrom(issuerCert) 120 | if err != nil { 121 | return nil, nil, err 122 | } 123 | } 124 | 125 | return ocspResBytes, ocspRes, nil 126 | } 127 | 128 | func getKeyAuthorization(token string, key interface{}) (string, error) { 129 | var publicKey crypto.PublicKey 130 | switch k := key.(type) { 131 | case *ecdsa.PrivateKey: 132 | publicKey = k.Public() 133 | case *rsa.PrivateKey: 134 | publicKey = k.Public() 135 | } 136 | 137 | // Generate the Key Authorization for the challenge 138 | jwk := keyAsJWK(publicKey) 139 | if jwk == nil { 140 | return "", errors.New("Could not generate JWK from key.") 141 | } 142 | thumbBytes, err := jwk.Thumbprint(crypto.SHA256) 143 | if err != nil { 144 | return "", err 145 | } 146 | 147 | // unpad the base64URL 148 | keyThumb := base64.URLEncoding.EncodeToString(thumbBytes) 149 | index := strings.Index(keyThumb, "=") 150 | if index != -1 { 151 | keyThumb = keyThumb[:index] 152 | } 153 | 154 | return token + "." + keyThumb, nil 155 | } 156 | 157 | // parsePEMBundle parses a certificate bundle from top to bottom and returns 158 | // a slice of x509 certificates. This function will error if no certificates are found. 159 | func parsePEMBundle(bundle []byte) ([]*x509.Certificate, error) { 160 | var certificates []*x509.Certificate 161 | var certDERBlock *pem.Block 162 | 163 | for { 164 | certDERBlock, bundle = pem.Decode(bundle) 165 | if certDERBlock == nil { 166 | break 167 | } 168 | 169 | if certDERBlock.Type == "CERTIFICATE" { 170 | cert, err := x509.ParseCertificate(certDERBlock.Bytes) 171 | if err != nil { 172 | return nil, err 173 | } 174 | certificates = append(certificates, cert) 175 | } 176 | } 177 | 178 | if len(certificates) == 0 { 179 | return nil, errors.New("No certificates were found while parsing the bundle.") 180 | } 181 | 182 | return certificates, nil 183 | } 184 | 185 | func parsePEMPrivateKey(key []byte) (crypto.PrivateKey, error) { 186 | keyBlock, _ := pem.Decode(key) 187 | 188 | switch keyBlock.Type { 189 | case "RSA PRIVATE KEY": 190 | return x509.ParsePKCS1PrivateKey(keyBlock.Bytes) 191 | case "EC PRIVATE KEY": 192 | return x509.ParseECPrivateKey(keyBlock.Bytes) 193 | default: 194 | return nil, errors.New("Unknown PEM header value") 195 | } 196 | } 197 | 198 | func generatePrivateKey(keyType KeyType) (crypto.PrivateKey, error) { 199 | 200 | switch keyType { 201 | case EC256: 202 | return ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 203 | case EC384: 204 | return ecdsa.GenerateKey(elliptic.P384(), rand.Reader) 205 | case RSA2048: 206 | return rsa.GenerateKey(rand.Reader, 2048) 207 | case RSA4096: 208 | return rsa.GenerateKey(rand.Reader, 4096) 209 | case RSA8192: 210 | return rsa.GenerateKey(rand.Reader, 8192) 211 | } 212 | 213 | return nil, fmt.Errorf("Invalid KeyType: %s", keyType) 214 | } 215 | 216 | func generateCsr(privateKey crypto.PrivateKey, domain string, san []string) ([]byte, error) { 217 | template := x509.CertificateRequest{ 218 | Subject: pkix.Name{ 219 | CommonName: domain, 220 | }, 221 | } 222 | 223 | if len(san) > 0 { 224 | template.DNSNames = san 225 | } 226 | 227 | return x509.CreateCertificateRequest(rand.Reader, &template, privateKey) 228 | } 229 | 230 | func pemEncode(data interface{}) []byte { 231 | var pemBlock *pem.Block 232 | switch key := data.(type) { 233 | case *ecdsa.PrivateKey: 234 | keyBytes, _ := x509.MarshalECPrivateKey(key) 235 | pemBlock = &pem.Block{Type: "EC PRIVATE KEY", Bytes: keyBytes} 236 | case *rsa.PrivateKey: 237 | pemBlock = &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)} 238 | break 239 | case derCertificateBytes: 240 | pemBlock = &pem.Block{Type: "CERTIFICATE", Bytes: []byte(data.(derCertificateBytes))} 241 | } 242 | 243 | return pem.EncodeToMemory(pemBlock) 244 | } 245 | 246 | func pemDecode(data []byte) (*pem.Block, error) { 247 | pemBlock, _ := pem.Decode(data) 248 | if pemBlock == nil { 249 | return nil, fmt.Errorf("Pem decode did not yield a valid block. Is the certificate in the right format?") 250 | } 251 | 252 | return pemBlock, nil 253 | } 254 | 255 | func pemDecodeTox509(pem []byte) (*x509.Certificate, error) { 256 | pemBlock, err := pemDecode(pem) 257 | if pemBlock == nil { 258 | return nil, err 259 | } 260 | 261 | return x509.ParseCertificate(pemBlock.Bytes) 262 | } 263 | 264 | // GetPEMCertExpiration returns the "NotAfter" date of a PEM encoded certificate. 265 | // The certificate has to be PEM encoded. Any other encodings like DER will fail. 266 | func GetPEMCertExpiration(cert []byte) (time.Time, error) { 267 | pemBlock, err := pemDecode(cert) 268 | if pemBlock == nil { 269 | return time.Time{}, err 270 | } 271 | 272 | return getCertExpiration(pemBlock.Bytes) 273 | } 274 | 275 | // getCertExpiration returns the "NotAfter" date of a DER encoded certificate. 276 | func getCertExpiration(cert []byte) (time.Time, error) { 277 | pCert, err := x509.ParseCertificate(cert) 278 | if err != nil { 279 | return time.Time{}, err 280 | } 281 | 282 | return pCert.NotAfter, nil 283 | } 284 | 285 | func generatePemCert(privKey *rsa.PrivateKey, domain string) ([]byte, error) { 286 | derBytes, err := generateDerCert(privKey, time.Time{}, domain) 287 | if err != nil { 288 | return nil, err 289 | } 290 | 291 | return pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes}), nil 292 | } 293 | 294 | func generateDerCert(privKey *rsa.PrivateKey, expiration time.Time, domain string) ([]byte, error) { 295 | serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) 296 | serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) 297 | if err != nil { 298 | return nil, err 299 | } 300 | 301 | if expiration.IsZero() { 302 | expiration = time.Now().Add(365) 303 | } 304 | 305 | template := x509.Certificate{ 306 | SerialNumber: serialNumber, 307 | Subject: pkix.Name{ 308 | CommonName: "ACME Challenge TEMP", 309 | }, 310 | NotBefore: time.Now(), 311 | NotAfter: expiration, 312 | 313 | KeyUsage: x509.KeyUsageKeyEncipherment, 314 | BasicConstraintsValid: true, 315 | DNSNames: []string{domain}, 316 | } 317 | 318 | return x509.CreateCertificate(rand.Reader, &template, &template, &privKey.PublicKey, privKey) 319 | } 320 | 321 | func limitReader(rd io.ReadCloser, numBytes int64) io.ReadCloser { 322 | return http.MaxBytesReader(nil, rd, numBytes) 323 | } 324 | -------------------------------------------------------------------------------- /vendor/github.com/xenolf/lego/acme/error.go: -------------------------------------------------------------------------------- 1 | package acme 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "net/http" 7 | "strings" 8 | ) 9 | 10 | const ( 11 | tosAgreementError = "Must agree to subscriber agreement before any further actions" 12 | ) 13 | 14 | // RemoteError is the base type for all errors specific to the ACME protocol. 15 | type RemoteError struct { 16 | StatusCode int `json:"status,omitempty"` 17 | Type string `json:"type"` 18 | Detail string `json:"detail"` 19 | } 20 | 21 | func (e RemoteError) Error() string { 22 | return fmt.Sprintf("acme: Error %d - %s - %s", e.StatusCode, e.Type, e.Detail) 23 | } 24 | 25 | // TOSError represents the error which is returned if the user needs to 26 | // accept the TOS. 27 | // TODO: include the new TOS url if we can somehow obtain it. 28 | type TOSError struct { 29 | RemoteError 30 | } 31 | 32 | type domainError struct { 33 | Domain string 34 | Error error 35 | } 36 | 37 | type challengeError struct { 38 | RemoteError 39 | records []validationRecord 40 | } 41 | 42 | func (c challengeError) Error() string { 43 | 44 | var errStr string 45 | for _, validation := range c.records { 46 | errStr = errStr + fmt.Sprintf("\tValidation for %s:%s\n\tResolved to:\n\t\t%s\n\tUsed: %s\n\n", 47 | validation.Hostname, validation.Port, strings.Join(validation.ResolvedAddresses, "\n\t\t"), validation.UsedAddress) 48 | } 49 | 50 | return fmt.Sprintf("%s\nError Detail:\n%s", c.RemoteError.Error(), errStr) 51 | } 52 | 53 | func handleHTTPError(resp *http.Response) error { 54 | var errorDetail RemoteError 55 | decoder := json.NewDecoder(resp.Body) 56 | err := decoder.Decode(&errorDetail) 57 | if err != nil { 58 | return err 59 | } 60 | 61 | errorDetail.StatusCode = resp.StatusCode 62 | 63 | // Check for errors we handle specifically 64 | if errorDetail.StatusCode == http.StatusForbidden && errorDetail.Detail == tosAgreementError { 65 | return TOSError{errorDetail} 66 | } 67 | 68 | return errorDetail 69 | } 70 | 71 | func handleChallengeError(chlng challenge) error { 72 | return challengeError{chlng.Error, chlng.ValidationRecords} 73 | } 74 | -------------------------------------------------------------------------------- /vendor/github.com/xenolf/lego/acme/http.go: -------------------------------------------------------------------------------- 1 | package acme 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | "fmt" 7 | "io" 8 | "net/http" 9 | "runtime" 10 | "strings" 11 | "time" 12 | ) 13 | 14 | // UserAgent (if non-empty) will be tacked onto the User-Agent string in requests. 15 | var UserAgent string 16 | 17 | // defaultClient is an HTTP client with a reasonable timeout value. 18 | var defaultClient = http.Client{Timeout: 10 * time.Second} 19 | 20 | const ( 21 | // defaultGoUserAgent is the Go HTTP package user agent string. Too 22 | // bad it isn't exported. If it changes, we should update it here, too. 23 | defaultGoUserAgent = "Go-http-client/1.1" 24 | 25 | // ourUserAgent is the User-Agent of this underlying library package. 26 | ourUserAgent = "xenolf-acme" 27 | ) 28 | 29 | // httpHead performs a HEAD request with a proper User-Agent string. 30 | // The response body (resp.Body) is already closed when this function returns. 31 | func httpHead(url string) (resp *http.Response, err error) { 32 | req, err := http.NewRequest("HEAD", url, nil) 33 | if err != nil { 34 | return nil, err 35 | } 36 | 37 | req.Header.Set("User-Agent", userAgent()) 38 | 39 | resp, err = defaultClient.Do(req) 40 | if err != nil { 41 | return resp, err 42 | } 43 | resp.Body.Close() 44 | return resp, err 45 | } 46 | 47 | // httpPost performs a POST request with a proper User-Agent string. 48 | // Callers should close resp.Body when done reading from it. 49 | func httpPost(url string, bodyType string, body io.Reader) (resp *http.Response, err error) { 50 | req, err := http.NewRequest("POST", url, body) 51 | if err != nil { 52 | return nil, err 53 | } 54 | req.Header.Set("Content-Type", bodyType) 55 | req.Header.Set("User-Agent", userAgent()) 56 | 57 | return defaultClient.Do(req) 58 | } 59 | 60 | // httpGet performs a GET request with a proper User-Agent string. 61 | // Callers should close resp.Body when done reading from it. 62 | func httpGet(url string) (resp *http.Response, err error) { 63 | req, err := http.NewRequest("GET", url, nil) 64 | if err != nil { 65 | return nil, err 66 | } 67 | req.Header.Set("User-Agent", userAgent()) 68 | 69 | return defaultClient.Do(req) 70 | } 71 | 72 | // getJSON performs an HTTP GET request and parses the response body 73 | // as JSON, into the provided respBody object. 74 | func getJSON(uri string, respBody interface{}) (http.Header, error) { 75 | resp, err := httpGet(uri) 76 | if err != nil { 77 | return nil, fmt.Errorf("failed to get %q: %v", uri, err) 78 | } 79 | defer resp.Body.Close() 80 | 81 | if resp.StatusCode >= http.StatusBadRequest { 82 | return resp.Header, handleHTTPError(resp) 83 | } 84 | 85 | return resp.Header, json.NewDecoder(resp.Body).Decode(respBody) 86 | } 87 | 88 | // postJSON performs an HTTP POST request and parses the response body 89 | // as JSON, into the provided respBody object. 90 | func postJSON(j *jws, uri string, reqBody, respBody interface{}) (http.Header, error) { 91 | jsonBytes, err := json.Marshal(reqBody) 92 | if err != nil { 93 | return nil, errors.New("Failed to marshal network message...") 94 | } 95 | 96 | resp, err := j.post(uri, jsonBytes) 97 | if err != nil { 98 | return nil, fmt.Errorf("Failed to post JWS message. -> %v", err) 99 | } 100 | defer resp.Body.Close() 101 | 102 | if resp.StatusCode >= http.StatusBadRequest { 103 | return resp.Header, handleHTTPError(resp) 104 | } 105 | 106 | if respBody == nil { 107 | return resp.Header, nil 108 | } 109 | 110 | return resp.Header, json.NewDecoder(resp.Body).Decode(respBody) 111 | } 112 | 113 | // userAgent builds and returns the User-Agent string to use in requests. 114 | func userAgent() string { 115 | ua := fmt.Sprintf("%s (%s; %s) %s %s", defaultGoUserAgent, runtime.GOOS, runtime.GOARCH, ourUserAgent, UserAgent) 116 | return strings.TrimSpace(ua) 117 | } 118 | -------------------------------------------------------------------------------- /vendor/github.com/xenolf/lego/acme/http_challenge.go: -------------------------------------------------------------------------------- 1 | package acme 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | ) 7 | 8 | type httpChallenge struct { 9 | jws *jws 10 | validate validateFunc 11 | provider ChallengeProvider 12 | } 13 | 14 | // HTTP01ChallengePath returns the URL path for the `http-01` challenge 15 | func HTTP01ChallengePath(token string) string { 16 | return "/.well-known/acme-challenge/" + token 17 | } 18 | 19 | func (s *httpChallenge) Solve(chlng challenge, domain string) error { 20 | 21 | logf("[INFO][%s] acme: Trying to solve HTTP-01", domain) 22 | 23 | // Generate the Key Authorization for the challenge 24 | keyAuth, err := getKeyAuthorization(chlng.Token, s.jws.privKey) 25 | if err != nil { 26 | return err 27 | } 28 | 29 | err = s.provider.Present(domain, chlng.Token, keyAuth) 30 | if err != nil { 31 | return fmt.Errorf("[%s] error presenting token: %v", domain, err) 32 | } 33 | defer func() { 34 | err := s.provider.CleanUp(domain, chlng.Token, keyAuth) 35 | if err != nil { 36 | log.Printf("[%s] error cleaning up: %v", domain, err) 37 | } 38 | }() 39 | 40 | return s.validate(s.jws, domain, chlng.URI, challenge{Resource: "challenge", Type: chlng.Type, Token: chlng.Token, KeyAuthorization: keyAuth}) 41 | } 42 | -------------------------------------------------------------------------------- /vendor/github.com/xenolf/lego/acme/http_challenge_server.go: -------------------------------------------------------------------------------- 1 | package acme 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | "net/http" 7 | "strings" 8 | ) 9 | 10 | // HTTPProviderServer implements ChallengeProvider for `http-01` challenge 11 | // It may be instantiated without using the NewHTTPProviderServer function if 12 | // you want only to use the default values. 13 | type HTTPProviderServer struct { 14 | iface string 15 | port string 16 | done chan bool 17 | listener net.Listener 18 | } 19 | 20 | // NewHTTPProviderServer creates a new HTTPProviderServer on the selected interface and port. 21 | // Setting iface and / or port to an empty string will make the server fall back to 22 | // the "any" interface and port 80 respectively. 23 | func NewHTTPProviderServer(iface, port string) *HTTPProviderServer { 24 | return &HTTPProviderServer{iface: iface, port: port} 25 | } 26 | 27 | // Present starts a web server and makes the token available at `HTTP01ChallengePath(token)` for web requests. 28 | func (s *HTTPProviderServer) Present(domain, token, keyAuth string) error { 29 | if s.port == "" { 30 | s.port = "80" 31 | } 32 | 33 | var err error 34 | s.listener, err = net.Listen("tcp", net.JoinHostPort(s.iface, s.port)) 35 | if err != nil { 36 | return fmt.Errorf("Could not start HTTP server for challenge -> %v", err) 37 | } 38 | 39 | s.done = make(chan bool) 40 | go s.serve(domain, token, keyAuth) 41 | return nil 42 | } 43 | 44 | // CleanUp closes the HTTP server and removes the token from `HTTP01ChallengePath(token)` 45 | func (s *HTTPProviderServer) CleanUp(domain, token, keyAuth string) error { 46 | if s.listener == nil { 47 | return nil 48 | } 49 | s.listener.Close() 50 | <-s.done 51 | return nil 52 | } 53 | 54 | func (s *HTTPProviderServer) serve(domain, token, keyAuth string) { 55 | path := HTTP01ChallengePath(token) 56 | 57 | // The handler validates the HOST header and request type. 58 | // For validation it then writes the token the server returned with the challenge 59 | mux := http.NewServeMux() 60 | mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) { 61 | if strings.HasPrefix(r.Host, domain) && r.Method == "GET" { 62 | w.Header().Add("Content-Type", "text/plain") 63 | w.Write([]byte(keyAuth)) 64 | logf("[INFO][%s] Served key authentication", domain) 65 | } else { 66 | logf("[INFO] Received request for domain %s with method %s", r.Host, r.Method) 67 | w.Write([]byte("TEST")) 68 | } 69 | }) 70 | 71 | httpServer := &http.Server{ 72 | Handler: mux, 73 | } 74 | // Once httpServer is shut down we don't want any lingering 75 | // connections, so disable KeepAlives. 76 | httpServer.SetKeepAlivesEnabled(false) 77 | httpServer.Serve(s.listener) 78 | s.done <- true 79 | } 80 | -------------------------------------------------------------------------------- /vendor/github.com/xenolf/lego/acme/jws.go: -------------------------------------------------------------------------------- 1 | package acme 2 | 3 | import ( 4 | "bytes" 5 | "crypto" 6 | "crypto/ecdsa" 7 | "crypto/elliptic" 8 | "crypto/rsa" 9 | "fmt" 10 | "net/http" 11 | 12 | "gopkg.in/square/go-jose.v1" 13 | ) 14 | 15 | type jws struct { 16 | directoryURL string 17 | privKey crypto.PrivateKey 18 | nonces []string 19 | } 20 | 21 | func keyAsJWK(key interface{}) *jose.JsonWebKey { 22 | switch k := key.(type) { 23 | case *ecdsa.PublicKey: 24 | return &jose.JsonWebKey{Key: k, Algorithm: "EC"} 25 | case *rsa.PublicKey: 26 | return &jose.JsonWebKey{Key: k, Algorithm: "RSA"} 27 | 28 | default: 29 | return nil 30 | } 31 | } 32 | 33 | // Posts a JWS signed message to the specified URL 34 | func (j *jws) post(url string, content []byte) (*http.Response, error) { 35 | signedContent, err := j.signContent(content) 36 | if err != nil { 37 | return nil, err 38 | } 39 | 40 | resp, err := httpPost(url, "application/jose+json", bytes.NewBuffer([]byte(signedContent.FullSerialize()))) 41 | if err != nil { 42 | return nil, err 43 | } 44 | 45 | j.getNonceFromResponse(resp) 46 | 47 | return resp, err 48 | } 49 | 50 | func (j *jws) signContent(content []byte) (*jose.JsonWebSignature, error) { 51 | 52 | var alg jose.SignatureAlgorithm 53 | switch k := j.privKey.(type) { 54 | case *rsa.PrivateKey: 55 | alg = jose.RS256 56 | case *ecdsa.PrivateKey: 57 | if k.Curve == elliptic.P256() { 58 | alg = jose.ES256 59 | } else if k.Curve == elliptic.P384() { 60 | alg = jose.ES384 61 | } 62 | } 63 | 64 | signer, err := jose.NewSigner(alg, j.privKey) 65 | if err != nil { 66 | return nil, err 67 | } 68 | signer.SetNonceSource(j) 69 | 70 | signed, err := signer.Sign(content) 71 | if err != nil { 72 | return nil, err 73 | } 74 | return signed, nil 75 | } 76 | 77 | func (j *jws) getNonceFromResponse(resp *http.Response) error { 78 | nonce := resp.Header.Get("Replay-Nonce") 79 | if nonce == "" { 80 | return fmt.Errorf("Server did not respond with a proper nonce header.") 81 | } 82 | 83 | j.nonces = append(j.nonces, nonce) 84 | return nil 85 | } 86 | 87 | func (j *jws) getNonce() error { 88 | resp, err := httpHead(j.directoryURL) 89 | if err != nil { 90 | return err 91 | } 92 | 93 | return j.getNonceFromResponse(resp) 94 | } 95 | 96 | func (j *jws) Nonce() (string, error) { 97 | nonce := "" 98 | if len(j.nonces) == 0 { 99 | err := j.getNonce() 100 | if err != nil { 101 | return nonce, err 102 | } 103 | } 104 | 105 | nonce, j.nonces = j.nonces[len(j.nonces)-1], j.nonces[:len(j.nonces)-1] 106 | return nonce, nil 107 | } 108 | -------------------------------------------------------------------------------- /vendor/github.com/xenolf/lego/acme/messages.go: -------------------------------------------------------------------------------- 1 | package acme 2 | 3 | import ( 4 | "time" 5 | 6 | "gopkg.in/square/go-jose.v1" 7 | ) 8 | 9 | type directory struct { 10 | NewAuthzURL string `json:"new-authz"` 11 | NewCertURL string `json:"new-cert"` 12 | NewRegURL string `json:"new-reg"` 13 | RevokeCertURL string `json:"revoke-cert"` 14 | } 15 | 16 | type recoveryKeyMessage struct { 17 | Length int `json:"length,omitempty"` 18 | Client jose.JsonWebKey `json:"client,omitempty"` 19 | Server jose.JsonWebKey `json:"client,omitempty"` 20 | } 21 | 22 | type registrationMessage struct { 23 | Resource string `json:"resource"` 24 | Contact []string `json:"contact"` 25 | // RecoveryKey recoveryKeyMessage `json:"recoveryKey,omitempty"` 26 | } 27 | 28 | // Registration is returned by the ACME server after the registration 29 | // The client implementation should save this registration somewhere. 30 | type Registration struct { 31 | Resource string `json:"resource,omitempty"` 32 | ID int `json:"id"` 33 | Key jose.JsonWebKey `json:"key"` 34 | Contact []string `json:"contact"` 35 | Agreement string `json:"agreement,omitempty"` 36 | Authorizations string `json:"authorizations,omitempty"` 37 | Certificates string `json:"certificates,omitempty"` 38 | // RecoveryKey recoveryKeyMessage `json:"recoveryKey,omitempty"` 39 | } 40 | 41 | // RegistrationResource represents all important informations about a registration 42 | // of which the client needs to keep track itself. 43 | type RegistrationResource struct { 44 | Body Registration `json:"body,omitempty"` 45 | URI string `json:"uri,omitempty"` 46 | NewAuthzURL string `json:"new_authzr_uri,omitempty"` 47 | TosURL string `json:"terms_of_service,omitempty"` 48 | } 49 | 50 | type authorizationResource struct { 51 | Body authorization 52 | Domain string 53 | NewCertURL string 54 | AuthURL string 55 | } 56 | 57 | type authorization struct { 58 | Resource string `json:"resource,omitempty"` 59 | Identifier identifier `json:"identifier"` 60 | Status string `json:"status,omitempty"` 61 | Expires time.Time `json:"expires,omitempty"` 62 | Challenges []challenge `json:"challenges,omitempty"` 63 | Combinations [][]int `json:"combinations,omitempty"` 64 | } 65 | 66 | type identifier struct { 67 | Type string `json:"type"` 68 | Value string `json:"value"` 69 | } 70 | 71 | type validationRecord struct { 72 | URI string `json:"url,omitempty"` 73 | Hostname string `json:"hostname,omitempty"` 74 | Port string `json:"port,omitempty"` 75 | ResolvedAddresses []string `json:"addressesResolved,omitempty"` 76 | UsedAddress string `json:"addressUsed,omitempty"` 77 | } 78 | 79 | type challenge struct { 80 | Resource string `json:"resource,omitempty"` 81 | Type Challenge `json:"type,omitempty"` 82 | Status string `json:"status,omitempty"` 83 | URI string `json:"uri,omitempty"` 84 | Token string `json:"token,omitempty"` 85 | KeyAuthorization string `json:"keyAuthorization,omitempty"` 86 | TLS bool `json:"tls,omitempty"` 87 | Iterations int `json:"n,omitempty"` 88 | Error RemoteError `json:"error,omitempty"` 89 | ValidationRecords []validationRecord `json:"validationRecord,omitempty"` 90 | } 91 | 92 | type csrMessage struct { 93 | Resource string `json:"resource,omitempty"` 94 | Csr string `json:"csr"` 95 | Authorizations []string `json:"authorizations"` 96 | } 97 | 98 | type revokeCertMessage struct { 99 | Resource string `json:"resource"` 100 | Certificate string `json:"certificate"` 101 | } 102 | 103 | // CertificateResource represents a CA issued certificate. 104 | // PrivateKey and Certificate are both already PEM encoded 105 | // and can be directly written to disk. Certificate may 106 | // be a certificate bundle, depending on the options supplied 107 | // to create it. 108 | type CertificateResource struct { 109 | Domain string `json:"domain"` 110 | CertURL string `json:"certUrl"` 111 | CertStableURL string `json:"certStableUrl"` 112 | AccountRef string `json:"accountRef,omitempty"` 113 | PrivateKey []byte `json:"-"` 114 | Certificate []byte `json:"-"` 115 | } 116 | -------------------------------------------------------------------------------- /vendor/github.com/xenolf/lego/acme/provider.go: -------------------------------------------------------------------------------- 1 | package acme 2 | 3 | import "time" 4 | 5 | // ChallengeProvider enables implementing a custom challenge 6 | // provider. Present presents the solution to a challenge available to 7 | // be solved. CleanUp will be called by the challenge if Present ends 8 | // in a non-error state. 9 | type ChallengeProvider interface { 10 | Present(domain, token, keyAuth string) error 11 | CleanUp(domain, token, keyAuth string) error 12 | } 13 | 14 | // ChallengeProviderTimeout allows for implementing a 15 | // ChallengeProvider where an unusually long timeout is required when 16 | // waiting for an ACME challenge to be satisfied, such as when 17 | // checking for DNS record progagation. If an implementor of a 18 | // ChallengeProvider provides a Timeout method, then the return values 19 | // of the Timeout method will be used when appropriate by the acme 20 | // package. The interval value is the time between checks. 21 | // 22 | // The default values used for timeout and interval are 60 seconds and 23 | // 2 seconds respectively. These are used when no Timeout method is 24 | // defined for the ChallengeProvider. 25 | type ChallengeProviderTimeout interface { 26 | ChallengeProvider 27 | Timeout() (timeout, interval time.Duration) 28 | } 29 | -------------------------------------------------------------------------------- /vendor/github.com/xenolf/lego/acme/tls_sni_challenge.go: -------------------------------------------------------------------------------- 1 | package acme 2 | 3 | import ( 4 | "crypto/rsa" 5 | "crypto/sha256" 6 | "crypto/tls" 7 | "encoding/hex" 8 | "fmt" 9 | "log" 10 | ) 11 | 12 | type tlsSNIChallenge struct { 13 | jws *jws 14 | validate validateFunc 15 | provider ChallengeProvider 16 | } 17 | 18 | func (t *tlsSNIChallenge) Solve(chlng challenge, domain string) error { 19 | // FIXME: https://github.com/ietf-wg-acme/acme/pull/22 20 | // Currently we implement this challenge to track boulder, not the current spec! 21 | 22 | logf("[INFO][%s] acme: Trying to solve TLS-SNI-01", domain) 23 | 24 | // Generate the Key Authorization for the challenge 25 | keyAuth, err := getKeyAuthorization(chlng.Token, t.jws.privKey) 26 | if err != nil { 27 | return err 28 | } 29 | 30 | err = t.provider.Present(domain, chlng.Token, keyAuth) 31 | if err != nil { 32 | return fmt.Errorf("[%s] error presenting token: %v", domain, err) 33 | } 34 | defer func() { 35 | err := t.provider.CleanUp(domain, chlng.Token, keyAuth) 36 | if err != nil { 37 | log.Printf("[%s] error cleaning up: %v", domain, err) 38 | } 39 | }() 40 | return t.validate(t.jws, domain, chlng.URI, challenge{Resource: "challenge", Type: chlng.Type, Token: chlng.Token, KeyAuthorization: keyAuth}) 41 | } 42 | 43 | // TLSSNI01ChallengeCert returns a certificate and target domain for the `tls-sni-01` challenge 44 | func TLSSNI01ChallengeCertDomain(keyAuth string) (tls.Certificate, string, error) { 45 | // generate a new RSA key for the certificates 46 | tempPrivKey, err := generatePrivateKey(RSA2048) 47 | if err != nil { 48 | return tls.Certificate{}, "", err 49 | } 50 | rsaPrivKey := tempPrivKey.(*rsa.PrivateKey) 51 | rsaPrivPEM := pemEncode(rsaPrivKey) 52 | 53 | zBytes := sha256.Sum256([]byte(keyAuth)) 54 | z := hex.EncodeToString(zBytes[:sha256.Size]) 55 | domain := fmt.Sprintf("%s.%s.acme.invalid", z[:32], z[32:]) 56 | tempCertPEM, err := generatePemCert(rsaPrivKey, domain) 57 | if err != nil { 58 | return tls.Certificate{}, "", err 59 | } 60 | 61 | certificate, err := tls.X509KeyPair(tempCertPEM, rsaPrivPEM) 62 | if err != nil { 63 | return tls.Certificate{}, "", err 64 | } 65 | 66 | return certificate, domain, nil 67 | } 68 | 69 | // TLSSNI01ChallengeCert returns a certificate for the `tls-sni-01` challenge 70 | func TLSSNI01ChallengeCert(keyAuth string) (tls.Certificate, error) { 71 | cert, _, err := TLSSNI01ChallengeCertDomain(keyAuth) 72 | return cert, err 73 | } 74 | -------------------------------------------------------------------------------- /vendor/github.com/xenolf/lego/acme/tls_sni_challenge_server.go: -------------------------------------------------------------------------------- 1 | package acme 2 | 3 | import ( 4 | "crypto/tls" 5 | "fmt" 6 | "net" 7 | "net/http" 8 | ) 9 | 10 | // TLSProviderServer implements ChallengeProvider for `TLS-SNI-01` challenge 11 | // It may be instantiated without using the NewTLSProviderServer function if 12 | // you want only to use the default values. 13 | type TLSProviderServer struct { 14 | iface string 15 | port string 16 | done chan bool 17 | listener net.Listener 18 | } 19 | 20 | // NewTLSProviderServer creates a new TLSProviderServer on the selected interface and port. 21 | // Setting iface and / or port to an empty string will make the server fall back to 22 | // the "any" interface and port 443 respectively. 23 | func NewTLSProviderServer(iface, port string) *TLSProviderServer { 24 | return &TLSProviderServer{iface: iface, port: port} 25 | } 26 | 27 | // Present makes the keyAuth available as a cert 28 | func (s *TLSProviderServer) Present(domain, token, keyAuth string) error { 29 | if s.port == "" { 30 | s.port = "443" 31 | } 32 | 33 | cert, err := TLSSNI01ChallengeCert(keyAuth) 34 | if err != nil { 35 | return err 36 | } 37 | 38 | tlsConf := new(tls.Config) 39 | tlsConf.Certificates = []tls.Certificate{cert} 40 | 41 | s.listener, err = tls.Listen("tcp", net.JoinHostPort(s.iface, s.port), tlsConf) 42 | if err != nil { 43 | return fmt.Errorf("Could not start HTTPS server for challenge -> %v", err) 44 | } 45 | 46 | s.done = make(chan bool) 47 | go func() { 48 | http.Serve(s.listener, nil) 49 | s.done <- true 50 | }() 51 | return nil 52 | } 53 | 54 | // CleanUp closes the HTTP server. 55 | func (s *TLSProviderServer) CleanUp(domain, token, keyAuth string) error { 56 | if s.listener == nil { 57 | return nil 58 | } 59 | s.listener.Close() 60 | <-s.done 61 | return nil 62 | } 63 | -------------------------------------------------------------------------------- /vendor/github.com/xenolf/lego/acme/utils.go: -------------------------------------------------------------------------------- 1 | package acme 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | // WaitFor polls the given function 'f', once every 'interval', up to 'timeout'. 9 | func WaitFor(timeout, interval time.Duration, f func() (bool, error)) error { 10 | var lastErr string 11 | timeup := time.After(timeout) 12 | for { 13 | select { 14 | case <-timeup: 15 | return fmt.Errorf("Time limit exceeded. Last error: %s", lastErr) 16 | default: 17 | } 18 | 19 | stop, err := f() 20 | if stop { 21 | return nil 22 | } 23 | if err != nil { 24 | lastErr = err.Error() 25 | } 26 | 27 | time.Sleep(interval) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/PATENTS: -------------------------------------------------------------------------------- 1 | Additional IP Rights Grant (Patents) 2 | 3 | "This implementation" means the copyrightable works distributed by 4 | Google as part of the Go project. 5 | 6 | Google hereby grants to You a perpetual, worldwide, non-exclusive, 7 | no-charge, royalty-free, irrevocable (except as stated in this section) 8 | patent license to make, have made, use, offer to sell, sell, import, 9 | transfer and otherwise run, modify and propagate the contents of this 10 | implementation of Go, where such license applies only to those patent 11 | claims, both currently owned or controlled by Google and acquired in 12 | the future, licensable by Google that are necessarily infringed by this 13 | implementation of Go. This grant does not include claims that would be 14 | infringed only as a consequence of further modification of this 15 | implementation. If you or your agent or exclusive licensee institute or 16 | order or agree to the institution of patent litigation against any 17 | entity (including a cross-claim or counterclaim in a lawsuit) alleging 18 | that this implementation of Go or any code incorporated within this 19 | implementation of Go constitutes direct or contributory patent 20 | infringement, or inducement of patent infringement, then any patent 21 | rights granted to you under this License for this implementation of Go 22 | shall terminate as of the date such litigation is filed. 23 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/PATENTS: -------------------------------------------------------------------------------- 1 | Additional IP Rights Grant (Patents) 2 | 3 | "This implementation" means the copyrightable works distributed by 4 | Google as part of the Go project. 5 | 6 | Google hereby grants to You a perpetual, worldwide, non-exclusive, 7 | no-charge, royalty-free, irrevocable (except as stated in this section) 8 | patent license to make, have made, use, offer to sell, sell, import, 9 | transfer and otherwise run, modify and propagate the contents of this 10 | implementation of Go, where such license applies only to those patent 11 | claims, both currently owned or controlled by Google and acquired in 12 | the future, licensable by Google that are necessarily infringed by this 13 | implementation of Go. This grant does not include claims that would be 14 | infringed only as a consequence of further modification of this 15 | implementation. If you or your agent or exclusive licensee institute or 16 | order or agree to the institution of patent litigation against any 17 | entity (including a cross-claim or counterclaim in a lawsuit) alleging 18 | that this implementation of Go or any code incorporated within this 19 | implementation of Go constitutes direct or contributory patent 20 | infringement, or inducement of patent infringement, then any patent 21 | rights granted to you under this License for this implementation of Go 22 | shall terminate as of the date such litigation is filed. 23 | -------------------------------------------------------------------------------- /vendor/golang.org/x/time/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/golang.org/x/time/PATENTS: -------------------------------------------------------------------------------- 1 | Additional IP Rights Grant (Patents) 2 | 3 | "This implementation" means the copyrightable works distributed by 4 | Google as part of the Go project. 5 | 6 | Google hereby grants to You a perpetual, worldwide, non-exclusive, 7 | no-charge, royalty-free, irrevocable (except as stated in this section) 8 | patent license to make, have made, use, offer to sell, sell, import, 9 | transfer and otherwise run, modify and propagate the contents of this 10 | implementation of Go, where such license applies only to those patent 11 | claims, both currently owned or controlled by Google and acquired in 12 | the future, licensable by Google that are necessarily infringed by this 13 | implementation of Go. This grant does not include claims that would be 14 | infringed only as a consequence of further modification of this 15 | implementation. If you or your agent or exclusive licensee institute or 16 | order or agree to the institution of patent litigation against any 17 | entity (including a cross-claim or counterclaim in a lawsuit) alleging 18 | that this implementation of Go or any code incorporated within this 19 | implementation of Go constitutes direct or contributory patent 20 | infringement, or inducement of patent infringement, then any patent 21 | rights granted to you under this License for this implementation of Go 22 | shall terminate as of the date such litigation is filed. 23 | -------------------------------------------------------------------------------- /vendor/gopkg.in/square/go-jose.v1/BUG-BOUNTY.md: -------------------------------------------------------------------------------- 1 | Serious about security 2 | ====================== 3 | 4 | Square recognizes the important contributions the security research community 5 | can make. We therefore encourage reporting security issues with the code 6 | contained in this repository. 7 | 8 | If you believe you have discovered a security vulnerability, please follow the 9 | guidelines at . 10 | 11 | -------------------------------------------------------------------------------- /vendor/gopkg.in/square/go-jose.v1/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | If you would like to contribute code to go-jose you can do so through GitHub by 4 | forking the repository and sending a pull request. 5 | 6 | When submitting code, please make every effort to follow existing conventions 7 | and style in order to keep the code as readable as possible. Please also make 8 | sure all tests pass by running `go test`, and format your code with `go fmt`. 9 | We also recommend using `golint` and `errcheck`. 10 | 11 | Before your code can be accepted into the project you must also sign the 12 | [Individual Contributor License Agreement][1]. 13 | 14 | [1]: https://spreadsheets.google.com/spreadsheet/viewform?formkey=dDViT2xzUHAwRkI3X3k5Z0lQM091OGc6MQ&ndplr=1 15 | -------------------------------------------------------------------------------- /vendor/gopkg.in/square/go-jose.v1/README.md: -------------------------------------------------------------------------------- 1 | # Go JOSE 2 | 3 | [![godoc](http://img.shields.io/badge/godoc-reference-blue.svg?style=flat)](https://godoc.org/gopkg.in/square/go-jose.v1) [![license](http://img.shields.io/badge/license-apache_2.0-blue.svg?style=flat)](https://raw.githubusercontent.com/square/go-jose/master/LICENSE) 4 | [![release](https://img.shields.io/github/release/square/go-jose.svg?style=flat)](https://github.com/square/go-jose/releases) 5 | [![build](https://travis-ci.org/square/go-jose.svg?branch=master)](https://travis-ci.org/square/go-jose) 6 | [![coverage](https://coveralls.io/repos/github/square/go-jose/badge.svg?branch=master)](https://coveralls.io/r/square/go-jose) 7 | 8 | Package jose aims to provide an implementation of the Javascript Object Signing 9 | and Encryption set of standards. For the moment, it mainly focuses on encryption 10 | and signing based on the JSON Web Encryption and JSON Web Signature standards. 11 | 12 | **Disclaimer**: This library contains encryption software that is subject to 13 | the U.S. Export Administration Regulations. You may not export, re-export, 14 | transfer or download this code or any part of it in violation of any United 15 | States law, directive or regulation. In particular this software may not be 16 | exported or re-exported in any form or on any media to Iran, North Sudan, 17 | Syria, Cuba, or North Korea, or to denied persons or entities mentioned on any 18 | US maintained blocked list. 19 | 20 | ## Overview 21 | 22 | The implementation follows the 23 | [JSON Web Encryption](http://dx.doi.org/10.17487/RFC7516) 24 | standard (RFC 7516) and 25 | [JSON Web Signature](http://dx.doi.org/10.17487/RFC7515) 26 | standard (RFC 7515). Tables of supported algorithms are shown below. 27 | The library supports both the compact and full serialization formats, and has 28 | optional support for multiple recipients. It also comes with a small 29 | command-line utility 30 | ([`jose-util`](https://github.com/square/go-jose/tree/master/jose-util)) 31 | for dealing with JOSE messages in a shell. 32 | 33 | **Note**: We use a forked version of the `encoding/json` package from the Go 34 | standard library which uses case-sensitive matching for member names (instead 35 | of [case-insensitive matching](https://www.ietf.org/mail-archive/web/json/current/msg03763.html)). 36 | This is to avoid differences in interpretation of messages between go-jose and 37 | libraries in other languages. If you do not like this behavior, you can use the 38 | `std_json` build tag to disable it (though we do not recommend doing so). 39 | 40 | ### Versions 41 | 42 | We use [gopkg.in](https://gopkg.in) for versioning. 43 | 44 | [Version 1](https://gopkg.in/square/go-jose.v1) is the current stable version: 45 | 46 | import "gopkg.in/square/go-jose.v1" 47 | 48 | The interface for [go-jose.v1](https://gopkg.in/square/go-jose.v1) will remain 49 | backwards compatible. We're currently sketching out ideas for a new version, to 50 | clean up the interface a bit. If you have ideas or feature requests [please let 51 | us know](https://github.com/square/go-jose/issues/64)! 52 | 53 | ### Supported algorithms 54 | 55 | See below for a table of supported algorithms. Algorithm identifiers match 56 | the names in the 57 | [JSON Web Algorithms](http://dx.doi.org/10.17487/RFC7518) 58 | standard where possible. The 59 | [Godoc reference](https://godoc.org/github.com/square/go-jose#pkg-constants) 60 | has a list of constants. 61 | 62 | Key encryption | Algorithm identifier(s) 63 | :------------------------- | :------------------------------ 64 | RSA-PKCS#1v1.5 | RSA1_5 65 | RSA-OAEP | RSA-OAEP, RSA-OAEP-256 66 | AES key wrap | A128KW, A192KW, A256KW 67 | AES-GCM key wrap | A128GCMKW, A192GCMKW, A256GCMKW 68 | ECDH-ES + AES key wrap | ECDH-ES+A128KW, ECDH-ES+A192KW, ECDH-ES+A256KW 69 | ECDH-ES (direct) | ECDH-ES1 70 | Direct encryption | dir1 71 | 72 | 1. Not supported in multi-recipient mode 73 | 74 | Signing / MAC | Algorithm identifier(s) 75 | :------------------------- | :------------------------------ 76 | RSASSA-PKCS#1v1.5 | RS256, RS384, RS512 77 | RSASSA-PSS | PS256, PS384, PS512 78 | HMAC | HS256, HS384, HS512 79 | ECDSA | ES256, ES384, ES512 80 | 81 | Content encryption | Algorithm identifier(s) 82 | :------------------------- | :------------------------------ 83 | AES-CBC+HMAC | A128CBC-HS256, A192CBC-HS384, A256CBC-HS512 84 | AES-GCM | A128GCM, A192GCM, A256GCM 85 | 86 | Compression | Algorithm identifiers(s) 87 | :------------------------- | ------------------------------- 88 | DEFLATE (RFC 1951) | DEF 89 | 90 | ### Supported key types 91 | 92 | See below for a table of supported key types. These are understood by the 93 | library, and can be passed to corresponding functions such as `NewEncrypter` or 94 | `NewSigner`. Note that if you are creating a new encrypter or signer with a 95 | JsonWebKey, the key id of the JsonWebKey (if present) will be added to any 96 | resulting messages. 97 | 98 | Algorithm(s) | Corresponding types 99 | :------------------------- | ------------------------------- 100 | RSA | *[rsa.PublicKey](http://golang.org/pkg/crypto/rsa/#PublicKey), *[rsa.PrivateKey](http://golang.org/pkg/crypto/rsa/#PrivateKey), *[jose.JsonWebKey](https://godoc.org/github.com/square/go-jose#JsonWebKey) 101 | ECDH, ECDSA | *[ecdsa.PublicKey](http://golang.org/pkg/crypto/ecdsa/#PublicKey), *[ecdsa.PrivateKey](http://golang.org/pkg/crypto/ecdsa/#PrivateKey), *[jose.JsonWebKey](https://godoc.org/github.com/square/go-jose#JsonWebKey) 102 | AES, HMAC | []byte, *[jose.JsonWebKey](https://godoc.org/github.com/square/go-jose#JsonWebKey) 103 | 104 | ## Examples 105 | 106 | Encryption/decryption example using RSA: 107 | 108 | ```Go 109 | // Generate a public/private key pair to use for this example. The library 110 | // also provides two utility functions (LoadPublicKey and LoadPrivateKey) 111 | // that can be used to load keys from PEM/DER-encoded data. 112 | privateKey, err := rsa.GenerateKey(rand.Reader, 2048) 113 | if err != nil { 114 | panic(err) 115 | } 116 | 117 | // Instantiate an encrypter using RSA-OAEP with AES128-GCM. An error would 118 | // indicate that the selected algorithm(s) are not currently supported. 119 | publicKey := &privateKey.PublicKey 120 | encrypter, err := NewEncrypter(RSA_OAEP, A128GCM, publicKey) 121 | if err != nil { 122 | panic(err) 123 | } 124 | 125 | // Encrypt a sample plaintext. Calling the encrypter returns an encrypted 126 | // JWE object, which can then be serialized for output afterwards. An error 127 | // would indicate a problem in an underlying cryptographic primitive. 128 | var plaintext = []byte("Lorem ipsum dolor sit amet") 129 | object, err := encrypter.Encrypt(plaintext) 130 | if err != nil { 131 | panic(err) 132 | } 133 | 134 | // Serialize the encrypted object using the full serialization format. 135 | // Alternatively you can also use the compact format here by calling 136 | // object.CompactSerialize() instead. 137 | serialized := object.FullSerialize() 138 | 139 | // Parse the serialized, encrypted JWE object. An error would indicate that 140 | // the given input did not represent a valid message. 141 | object, err = ParseEncrypted(serialized) 142 | if err != nil { 143 | panic(err) 144 | } 145 | 146 | // Now we can decrypt and get back our original plaintext. An error here 147 | // would indicate the the message failed to decrypt, e.g. because the auth 148 | // tag was broken or the message was tampered with. 149 | decrypted, err := object.Decrypt(privateKey) 150 | if err != nil { 151 | panic(err) 152 | } 153 | 154 | fmt.Printf(string(decrypted)) 155 | // output: Lorem ipsum dolor sit amet 156 | ``` 157 | 158 | Signing/verification example using RSA: 159 | 160 | ```Go 161 | // Generate a public/private key pair to use for this example. The library 162 | // also provides two utility functions (LoadPublicKey and LoadPrivateKey) 163 | // that can be used to load keys from PEM/DER-encoded data. 164 | privateKey, err := rsa.GenerateKey(rand.Reader, 2048) 165 | if err != nil { 166 | panic(err) 167 | } 168 | 169 | // Instantiate a signer using RSASSA-PSS (SHA512) with the given private key. 170 | signer, err := NewSigner(PS512, privateKey) 171 | if err != nil { 172 | panic(err) 173 | } 174 | 175 | // Sign a sample payload. Calling the signer returns a protected JWS object, 176 | // which can then be serialized for output afterwards. An error would 177 | // indicate a problem in an underlying cryptographic primitive. 178 | var payload = []byte("Lorem ipsum dolor sit amet") 179 | object, err := signer.Sign(payload) 180 | if err != nil { 181 | panic(err) 182 | } 183 | 184 | // Serialize the encrypted object using the full serialization format. 185 | // Alternatively you can also use the compact format here by calling 186 | // object.CompactSerialize() instead. 187 | serialized := object.FullSerialize() 188 | 189 | // Parse the serialized, protected JWS object. An error would indicate that 190 | // the given input did not represent a valid message. 191 | object, err = ParseSigned(serialized) 192 | if err != nil { 193 | panic(err) 194 | } 195 | 196 | // Now we can verify the signature on the payload. An error here would 197 | // indicate the the message failed to verify, e.g. because the signature was 198 | // broken or the message was tampered with. 199 | output, err := object.Verify(&privateKey.PublicKey) 200 | if err != nil { 201 | panic(err) 202 | } 203 | 204 | fmt.Printf(string(output)) 205 | // output: Lorem ipsum dolor sit amet 206 | ``` 207 | 208 | More examples can be found in the [Godoc 209 | reference](https://godoc.org/github.com/square/go-jose) for this package. The 210 | [`jose-util`](https://github.com/square/go-jose/tree/master/jose-util) 211 | subdirectory also contains a small command-line utility which might 212 | be useful as an example. 213 | -------------------------------------------------------------------------------- /vendor/gopkg.in/square/go-jose.v1/cipher/cbc_hmac.go: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2014 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package josecipher 18 | 19 | import ( 20 | "bytes" 21 | "crypto/cipher" 22 | "crypto/hmac" 23 | "crypto/sha256" 24 | "crypto/sha512" 25 | "crypto/subtle" 26 | "encoding/binary" 27 | "errors" 28 | "hash" 29 | ) 30 | 31 | const ( 32 | nonceBytes = 16 33 | ) 34 | 35 | // NewCBCHMAC instantiates a new AEAD based on CBC+HMAC. 36 | func NewCBCHMAC(key []byte, newBlockCipher func([]byte) (cipher.Block, error)) (cipher.AEAD, error) { 37 | keySize := len(key) / 2 38 | integrityKey := key[:keySize] 39 | encryptionKey := key[keySize:] 40 | 41 | blockCipher, err := newBlockCipher(encryptionKey) 42 | if err != nil { 43 | return nil, err 44 | } 45 | 46 | var hash func() hash.Hash 47 | switch keySize { 48 | case 16: 49 | hash = sha256.New 50 | case 24: 51 | hash = sha512.New384 52 | case 32: 53 | hash = sha512.New 54 | } 55 | 56 | return &cbcAEAD{ 57 | hash: hash, 58 | blockCipher: blockCipher, 59 | authtagBytes: keySize, 60 | integrityKey: integrityKey, 61 | }, nil 62 | } 63 | 64 | // An AEAD based on CBC+HMAC 65 | type cbcAEAD struct { 66 | hash func() hash.Hash 67 | authtagBytes int 68 | integrityKey []byte 69 | blockCipher cipher.Block 70 | } 71 | 72 | func (ctx *cbcAEAD) NonceSize() int { 73 | return nonceBytes 74 | } 75 | 76 | func (ctx *cbcAEAD) Overhead() int { 77 | // Maximum overhead is block size (for padding) plus auth tag length, where 78 | // the length of the auth tag is equivalent to the key size. 79 | return ctx.blockCipher.BlockSize() + ctx.authtagBytes 80 | } 81 | 82 | // Seal encrypts and authenticates the plaintext. 83 | func (ctx *cbcAEAD) Seal(dst, nonce, plaintext, data []byte) []byte { 84 | // Output buffer -- must take care not to mangle plaintext input. 85 | ciphertext := make([]byte, uint64(len(plaintext))+uint64(ctx.Overhead()))[:len(plaintext)] 86 | copy(ciphertext, plaintext) 87 | ciphertext = padBuffer(ciphertext, ctx.blockCipher.BlockSize()) 88 | 89 | cbc := cipher.NewCBCEncrypter(ctx.blockCipher, nonce) 90 | 91 | cbc.CryptBlocks(ciphertext, ciphertext) 92 | authtag := ctx.computeAuthTag(data, nonce, ciphertext) 93 | 94 | ret, out := resize(dst, uint64(len(dst))+uint64(len(ciphertext))+uint64(len(authtag))) 95 | copy(out, ciphertext) 96 | copy(out[len(ciphertext):], authtag) 97 | 98 | return ret 99 | } 100 | 101 | // Open decrypts and authenticates the ciphertext. 102 | func (ctx *cbcAEAD) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { 103 | if len(ciphertext) < ctx.authtagBytes { 104 | return nil, errors.New("square/go-jose: invalid ciphertext (too short)") 105 | } 106 | 107 | offset := len(ciphertext) - ctx.authtagBytes 108 | expectedTag := ctx.computeAuthTag(data, nonce, ciphertext[:offset]) 109 | match := subtle.ConstantTimeCompare(expectedTag, ciphertext[offset:]) 110 | if match != 1 { 111 | return nil, errors.New("square/go-jose: invalid ciphertext (auth tag mismatch)") 112 | } 113 | 114 | cbc := cipher.NewCBCDecrypter(ctx.blockCipher, nonce) 115 | 116 | // Make copy of ciphertext buffer, don't want to modify in place 117 | buffer := append([]byte{}, []byte(ciphertext[:offset])...) 118 | 119 | if len(buffer)%ctx.blockCipher.BlockSize() > 0 { 120 | return nil, errors.New("square/go-jose: invalid ciphertext (invalid length)") 121 | } 122 | 123 | cbc.CryptBlocks(buffer, buffer) 124 | 125 | // Remove padding 126 | plaintext, err := unpadBuffer(buffer, ctx.blockCipher.BlockSize()) 127 | if err != nil { 128 | return nil, err 129 | } 130 | 131 | ret, out := resize(dst, uint64(len(dst))+uint64(len(plaintext))) 132 | copy(out, plaintext) 133 | 134 | return ret, nil 135 | } 136 | 137 | // Compute an authentication tag 138 | func (ctx *cbcAEAD) computeAuthTag(aad, nonce, ciphertext []byte) []byte { 139 | buffer := make([]byte, uint64(len(aad))+uint64(len(nonce))+uint64(len(ciphertext))+8) 140 | n := 0 141 | n += copy(buffer, aad) 142 | n += copy(buffer[n:], nonce) 143 | n += copy(buffer[n:], ciphertext) 144 | binary.BigEndian.PutUint64(buffer[n:], uint64(len(aad))*8) 145 | 146 | // According to documentation, Write() on hash.Hash never fails. 147 | hmac := hmac.New(ctx.hash, ctx.integrityKey) 148 | _, _ = hmac.Write(buffer) 149 | 150 | return hmac.Sum(nil)[:ctx.authtagBytes] 151 | } 152 | 153 | // resize ensures the the given slice has a capacity of at least n bytes. 154 | // If the capacity of the slice is less than n, a new slice is allocated 155 | // and the existing data will be copied. 156 | func resize(in []byte, n uint64) (head, tail []byte) { 157 | if uint64(cap(in)) >= n { 158 | head = in[:n] 159 | } else { 160 | head = make([]byte, n) 161 | copy(head, in) 162 | } 163 | 164 | tail = head[len(in):] 165 | return 166 | } 167 | 168 | // Apply padding 169 | func padBuffer(buffer []byte, blockSize int) []byte { 170 | missing := blockSize - (len(buffer) % blockSize) 171 | ret, out := resize(buffer, uint64(len(buffer))+uint64(missing)) 172 | padding := bytes.Repeat([]byte{byte(missing)}, missing) 173 | copy(out, padding) 174 | return ret 175 | } 176 | 177 | // Remove padding 178 | func unpadBuffer(buffer []byte, blockSize int) ([]byte, error) { 179 | if len(buffer)%blockSize != 0 { 180 | return nil, errors.New("square/go-jose: invalid padding") 181 | } 182 | 183 | last := buffer[len(buffer)-1] 184 | count := int(last) 185 | 186 | if count == 0 || count > blockSize || count > len(buffer) { 187 | return nil, errors.New("square/go-jose: invalid padding") 188 | } 189 | 190 | padding := bytes.Repeat([]byte{last}, count) 191 | if !bytes.HasSuffix(buffer, padding) { 192 | return nil, errors.New("square/go-jose: invalid padding") 193 | } 194 | 195 | return buffer[:len(buffer)-count], nil 196 | } 197 | -------------------------------------------------------------------------------- /vendor/gopkg.in/square/go-jose.v1/cipher/concat_kdf.go: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2014 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package josecipher 18 | 19 | import ( 20 | "crypto" 21 | "encoding/binary" 22 | "hash" 23 | "io" 24 | ) 25 | 26 | type concatKDF struct { 27 | z, info []byte 28 | i uint32 29 | cache []byte 30 | hasher hash.Hash 31 | } 32 | 33 | // NewConcatKDF builds a KDF reader based on the given inputs. 34 | func NewConcatKDF(hash crypto.Hash, z, algID, ptyUInfo, ptyVInfo, supPubInfo, supPrivInfo []byte) io.Reader { 35 | buffer := make([]byte, uint64(len(algID))+uint64(len(ptyUInfo))+uint64(len(ptyVInfo))+uint64(len(supPubInfo))+uint64(len(supPrivInfo))) 36 | n := 0 37 | n += copy(buffer, algID) 38 | n += copy(buffer[n:], ptyUInfo) 39 | n += copy(buffer[n:], ptyVInfo) 40 | n += copy(buffer[n:], supPubInfo) 41 | copy(buffer[n:], supPrivInfo) 42 | 43 | hasher := hash.New() 44 | 45 | return &concatKDF{ 46 | z: z, 47 | info: buffer, 48 | hasher: hasher, 49 | cache: []byte{}, 50 | i: 1, 51 | } 52 | } 53 | 54 | func (ctx *concatKDF) Read(out []byte) (int, error) { 55 | copied := copy(out, ctx.cache) 56 | ctx.cache = ctx.cache[copied:] 57 | 58 | for copied < len(out) { 59 | ctx.hasher.Reset() 60 | 61 | // Write on a hash.Hash never fails 62 | _ = binary.Write(ctx.hasher, binary.BigEndian, ctx.i) 63 | _, _ = ctx.hasher.Write(ctx.z) 64 | _, _ = ctx.hasher.Write(ctx.info) 65 | 66 | hash := ctx.hasher.Sum(nil) 67 | chunkCopied := copy(out[copied:], hash) 68 | copied += chunkCopied 69 | ctx.cache = hash[chunkCopied:] 70 | 71 | ctx.i++ 72 | } 73 | 74 | return copied, nil 75 | } 76 | -------------------------------------------------------------------------------- /vendor/gopkg.in/square/go-jose.v1/cipher/ecdh_es.go: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2014 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package josecipher 18 | 19 | import ( 20 | "crypto" 21 | "crypto/ecdsa" 22 | "encoding/binary" 23 | ) 24 | 25 | // DeriveECDHES derives a shared encryption key using ECDH/ConcatKDF as described in JWE/JWA. 26 | // It is an error to call this function with a private/public key that are not on the same 27 | // curve. Callers must ensure that the keys are valid before calling this function. Output 28 | // size may be at most 1<<16 bytes (64 KiB). 29 | func DeriveECDHES(alg string, apuData, apvData []byte, priv *ecdsa.PrivateKey, pub *ecdsa.PublicKey, size int) []byte { 30 | if size > 1<<16 { 31 | panic("ECDH-ES output size too large, must be less than 1<<16") 32 | } 33 | 34 | // algId, partyUInfo, partyVInfo inputs must be prefixed with the length 35 | algID := lengthPrefixed([]byte(alg)) 36 | ptyUInfo := lengthPrefixed(apuData) 37 | ptyVInfo := lengthPrefixed(apvData) 38 | 39 | // suppPubInfo is the encoded length of the output size in bits 40 | supPubInfo := make([]byte, 4) 41 | binary.BigEndian.PutUint32(supPubInfo, uint32(size)*8) 42 | 43 | if !priv.PublicKey.Curve.IsOnCurve(pub.X, pub.Y) { 44 | panic("public key not on same curve as private key") 45 | } 46 | 47 | z, _ := priv.PublicKey.Curve.ScalarMult(pub.X, pub.Y, priv.D.Bytes()) 48 | reader := NewConcatKDF(crypto.SHA256, z.Bytes(), algID, ptyUInfo, ptyVInfo, supPubInfo, []byte{}) 49 | 50 | key := make([]byte, size) 51 | 52 | // Read on the KDF will never fail 53 | _, _ = reader.Read(key) 54 | return key 55 | } 56 | 57 | func lengthPrefixed(data []byte) []byte { 58 | out := make([]byte, len(data)+4) 59 | binary.BigEndian.PutUint32(out, uint32(len(data))) 60 | copy(out[4:], data) 61 | return out 62 | } 63 | -------------------------------------------------------------------------------- /vendor/gopkg.in/square/go-jose.v1/cipher/key_wrap.go: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2014 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package josecipher 18 | 19 | import ( 20 | "crypto/cipher" 21 | "crypto/subtle" 22 | "encoding/binary" 23 | "errors" 24 | ) 25 | 26 | var defaultIV = []byte{0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6} 27 | 28 | // KeyWrap implements NIST key wrapping; it wraps a content encryption key (cek) with the given block cipher. 29 | func KeyWrap(block cipher.Block, cek []byte) ([]byte, error) { 30 | if len(cek)%8 != 0 { 31 | return nil, errors.New("square/go-jose: key wrap input must be 8 byte blocks") 32 | } 33 | 34 | n := len(cek) / 8 35 | r := make([][]byte, n) 36 | 37 | for i := range r { 38 | r[i] = make([]byte, 8) 39 | copy(r[i], cek[i*8:]) 40 | } 41 | 42 | buffer := make([]byte, 16) 43 | tBytes := make([]byte, 8) 44 | copy(buffer, defaultIV) 45 | 46 | for t := 0; t < 6*n; t++ { 47 | copy(buffer[8:], r[t%n]) 48 | 49 | block.Encrypt(buffer, buffer) 50 | 51 | binary.BigEndian.PutUint64(tBytes, uint64(t+1)) 52 | 53 | for i := 0; i < 8; i++ { 54 | buffer[i] = buffer[i] ^ tBytes[i] 55 | } 56 | copy(r[t%n], buffer[8:]) 57 | } 58 | 59 | out := make([]byte, (n+1)*8) 60 | copy(out, buffer[:8]) 61 | for i := range r { 62 | copy(out[(i+1)*8:], r[i]) 63 | } 64 | 65 | return out, nil 66 | } 67 | 68 | // KeyUnwrap implements NIST key unwrapping; it unwraps a content encryption key (cek) with the given block cipher. 69 | func KeyUnwrap(block cipher.Block, ciphertext []byte) ([]byte, error) { 70 | if len(ciphertext)%8 != 0 { 71 | return nil, errors.New("square/go-jose: key wrap input must be 8 byte blocks") 72 | } 73 | 74 | n := (len(ciphertext) / 8) - 1 75 | r := make([][]byte, n) 76 | 77 | for i := range r { 78 | r[i] = make([]byte, 8) 79 | copy(r[i], ciphertext[(i+1)*8:]) 80 | } 81 | 82 | buffer := make([]byte, 16) 83 | tBytes := make([]byte, 8) 84 | copy(buffer[:8], ciphertext[:8]) 85 | 86 | for t := 6*n - 1; t >= 0; t-- { 87 | binary.BigEndian.PutUint64(tBytes, uint64(t+1)) 88 | 89 | for i := 0; i < 8; i++ { 90 | buffer[i] = buffer[i] ^ tBytes[i] 91 | } 92 | copy(buffer[8:], r[t%n]) 93 | 94 | block.Decrypt(buffer, buffer) 95 | 96 | copy(r[t%n], buffer[8:]) 97 | } 98 | 99 | if subtle.ConstantTimeCompare(buffer[:8], defaultIV) == 0 { 100 | return nil, errors.New("square/go-jose: failed to unwrap key") 101 | } 102 | 103 | out := make([]byte, n*8) 104 | for i := range r { 105 | copy(out[i*8:], r[i]) 106 | } 107 | 108 | return out, nil 109 | } 110 | -------------------------------------------------------------------------------- /vendor/gopkg.in/square/go-jose.v1/doc.go: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2014 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | 19 | Package jose aims to provide an implementation of the Javascript Object Signing 20 | and Encryption set of standards. For the moment, it mainly focuses on 21 | encryption and signing based on the JSON Web Encryption and JSON Web Signature 22 | standards. The library supports both the compact and full serialization 23 | formats, and has optional support for multiple recipients. 24 | 25 | */ 26 | package jose // import "gopkg.in/square/go-jose.v1" 27 | -------------------------------------------------------------------------------- /vendor/gopkg.in/square/go-jose.v1/encoding.go: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2014 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package jose 18 | 19 | import ( 20 | "bytes" 21 | "compress/flate" 22 | "encoding/base64" 23 | "encoding/binary" 24 | "io" 25 | "math/big" 26 | "regexp" 27 | "strings" 28 | 29 | "gopkg.in/square/go-jose.v1/json" 30 | ) 31 | 32 | var stripWhitespaceRegex = regexp.MustCompile("\\s") 33 | 34 | // Url-safe base64 encode that strips padding 35 | func base64URLEncode(data []byte) string { 36 | var result = base64.URLEncoding.EncodeToString(data) 37 | return strings.TrimRight(result, "=") 38 | } 39 | 40 | // Url-safe base64 decoder that adds padding 41 | func base64URLDecode(data string) ([]byte, error) { 42 | var missing = (4 - len(data)%4) % 4 43 | data += strings.Repeat("=", missing) 44 | return base64.URLEncoding.DecodeString(data) 45 | } 46 | 47 | // Helper function to serialize known-good objects. 48 | // Precondition: value is not a nil pointer. 49 | func mustSerializeJSON(value interface{}) []byte { 50 | out, err := json.Marshal(value) 51 | if err != nil { 52 | panic(err) 53 | } 54 | // We never want to serialize the top-level value "null," since it's not a 55 | // valid JOSE message. But if a caller passes in a nil pointer to this method, 56 | // MarshalJSON will happily serialize it as the top-level value "null". If 57 | // that value is then embedded in another operation, for instance by being 58 | // base64-encoded and fed as input to a signing algorithm 59 | // (https://github.com/square/go-jose/issues/22), the result will be 60 | // incorrect. Because this method is intended for known-good objects, and a nil 61 | // pointer is not a known-good object, we are free to panic in this case. 62 | // Note: It's not possible to directly check whether the data pointed at by an 63 | // interface is a nil pointer, so we do this hacky workaround. 64 | // https://groups.google.com/forum/#!topic/golang-nuts/wnH302gBa4I 65 | if string(out) == "null" { 66 | panic("Tried to serialize a nil pointer.") 67 | } 68 | return out 69 | } 70 | 71 | // Strip all newlines and whitespace 72 | func stripWhitespace(data string) string { 73 | return stripWhitespaceRegex.ReplaceAllString(data, "") 74 | } 75 | 76 | // Perform compression based on algorithm 77 | func compress(algorithm CompressionAlgorithm, input []byte) ([]byte, error) { 78 | switch algorithm { 79 | case DEFLATE: 80 | return deflate(input) 81 | default: 82 | return nil, ErrUnsupportedAlgorithm 83 | } 84 | } 85 | 86 | // Perform decompression based on algorithm 87 | func decompress(algorithm CompressionAlgorithm, input []byte) ([]byte, error) { 88 | switch algorithm { 89 | case DEFLATE: 90 | return inflate(input) 91 | default: 92 | return nil, ErrUnsupportedAlgorithm 93 | } 94 | } 95 | 96 | // Compress with DEFLATE 97 | func deflate(input []byte) ([]byte, error) { 98 | output := new(bytes.Buffer) 99 | 100 | // Writing to byte buffer, err is always nil 101 | writer, _ := flate.NewWriter(output, 1) 102 | _, _ = io.Copy(writer, bytes.NewBuffer(input)) 103 | 104 | err := writer.Close() 105 | return output.Bytes(), err 106 | } 107 | 108 | // Decompress with DEFLATE 109 | func inflate(input []byte) ([]byte, error) { 110 | output := new(bytes.Buffer) 111 | reader := flate.NewReader(bytes.NewBuffer(input)) 112 | 113 | _, err := io.Copy(output, reader) 114 | if err != nil { 115 | return nil, err 116 | } 117 | 118 | err = reader.Close() 119 | return output.Bytes(), err 120 | } 121 | 122 | // byteBuffer represents a slice of bytes that can be serialized to url-safe base64. 123 | type byteBuffer struct { 124 | data []byte 125 | } 126 | 127 | func newBuffer(data []byte) *byteBuffer { 128 | if data == nil { 129 | return nil 130 | } 131 | return &byteBuffer{ 132 | data: data, 133 | } 134 | } 135 | 136 | func newFixedSizeBuffer(data []byte, length int) *byteBuffer { 137 | if len(data) > length { 138 | panic("square/go-jose: invalid call to newFixedSizeBuffer (len(data) > length)") 139 | } 140 | pad := make([]byte, length-len(data)) 141 | return newBuffer(append(pad, data...)) 142 | } 143 | 144 | func newBufferFromInt(num uint64) *byteBuffer { 145 | data := make([]byte, 8) 146 | binary.BigEndian.PutUint64(data, num) 147 | return newBuffer(bytes.TrimLeft(data, "\x00")) 148 | } 149 | 150 | func (b *byteBuffer) MarshalJSON() ([]byte, error) { 151 | return json.Marshal(b.base64()) 152 | } 153 | 154 | func (b *byteBuffer) UnmarshalJSON(data []byte) error { 155 | var encoded string 156 | err := json.Unmarshal(data, &encoded) 157 | if err != nil { 158 | return err 159 | } 160 | 161 | if encoded == "" { 162 | return nil 163 | } 164 | 165 | decoded, err := base64URLDecode(encoded) 166 | if err != nil { 167 | return err 168 | } 169 | 170 | *b = *newBuffer(decoded) 171 | 172 | return nil 173 | } 174 | 175 | func (b *byteBuffer) base64() string { 176 | return base64URLEncode(b.data) 177 | } 178 | 179 | func (b *byteBuffer) bytes() []byte { 180 | // Handling nil here allows us to transparently handle nil slices when serializing. 181 | if b == nil { 182 | return nil 183 | } 184 | return b.data 185 | } 186 | 187 | func (b byteBuffer) bigInt() *big.Int { 188 | return new(big.Int).SetBytes(b.data) 189 | } 190 | 191 | func (b byteBuffer) toInt() int { 192 | return int(b.bigInt().Int64()) 193 | } 194 | -------------------------------------------------------------------------------- /vendor/gopkg.in/square/go-jose.v1/json/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/gopkg.in/square/go-jose.v1/json/README.md: -------------------------------------------------------------------------------- 1 | # Safe JSON 2 | 3 | This repository contains a fork of the `encoding/json` package from Go 1.6. 4 | 5 | The following changes were made: 6 | 7 | * Object deserialization uses case-sensitive member name matching instead of 8 | [case-insensitive matching](https://www.ietf.org/mail-archive/web/json/current/msg03763.html). 9 | This is to avoid differences in the interpretation of JOSE messages between 10 | go-jose and libraries written in other languages. 11 | * When deserializing a JSON object, we check for duplicate keys and reject the 12 | input whenever we detect a duplicate. Rather than trying to work with malformed 13 | data, we prefer to reject it right away. 14 | -------------------------------------------------------------------------------- /vendor/gopkg.in/square/go-jose.v1/json/indent.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package json 6 | 7 | import "bytes" 8 | 9 | // Compact appends to dst the JSON-encoded src with 10 | // insignificant space characters elided. 11 | func Compact(dst *bytes.Buffer, src []byte) error { 12 | return compact(dst, src, false) 13 | } 14 | 15 | func compact(dst *bytes.Buffer, src []byte, escape bool) error { 16 | origLen := dst.Len() 17 | var scan scanner 18 | scan.reset() 19 | start := 0 20 | for i, c := range src { 21 | if escape && (c == '<' || c == '>' || c == '&') { 22 | if start < i { 23 | dst.Write(src[start:i]) 24 | } 25 | dst.WriteString(`\u00`) 26 | dst.WriteByte(hex[c>>4]) 27 | dst.WriteByte(hex[c&0xF]) 28 | start = i + 1 29 | } 30 | // Convert U+2028 and U+2029 (E2 80 A8 and E2 80 A9). 31 | if c == 0xE2 && i+2 < len(src) && src[i+1] == 0x80 && src[i+2]&^1 == 0xA8 { 32 | if start < i { 33 | dst.Write(src[start:i]) 34 | } 35 | dst.WriteString(`\u202`) 36 | dst.WriteByte(hex[src[i+2]&0xF]) 37 | start = i + 3 38 | } 39 | v := scan.step(&scan, c) 40 | if v >= scanSkipSpace { 41 | if v == scanError { 42 | break 43 | } 44 | if start < i { 45 | dst.Write(src[start:i]) 46 | } 47 | start = i + 1 48 | } 49 | } 50 | if scan.eof() == scanError { 51 | dst.Truncate(origLen) 52 | return scan.err 53 | } 54 | if start < len(src) { 55 | dst.Write(src[start:]) 56 | } 57 | return nil 58 | } 59 | 60 | func newline(dst *bytes.Buffer, prefix, indent string, depth int) { 61 | dst.WriteByte('\n') 62 | dst.WriteString(prefix) 63 | for i := 0; i < depth; i++ { 64 | dst.WriteString(indent) 65 | } 66 | } 67 | 68 | // Indent appends to dst an indented form of the JSON-encoded src. 69 | // Each element in a JSON object or array begins on a new, 70 | // indented line beginning with prefix followed by one or more 71 | // copies of indent according to the indentation nesting. 72 | // The data appended to dst does not begin with the prefix nor 73 | // any indentation, to make it easier to embed inside other formatted JSON data. 74 | // Although leading space characters (space, tab, carriage return, newline) 75 | // at the beginning of src are dropped, trailing space characters 76 | // at the end of src are preserved and copied to dst. 77 | // For example, if src has no trailing spaces, neither will dst; 78 | // if src ends in a trailing newline, so will dst. 79 | func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error { 80 | origLen := dst.Len() 81 | var scan scanner 82 | scan.reset() 83 | needIndent := false 84 | depth := 0 85 | for _, c := range src { 86 | scan.bytes++ 87 | v := scan.step(&scan, c) 88 | if v == scanSkipSpace { 89 | continue 90 | } 91 | if v == scanError { 92 | break 93 | } 94 | if needIndent && v != scanEndObject && v != scanEndArray { 95 | needIndent = false 96 | depth++ 97 | newline(dst, prefix, indent, depth) 98 | } 99 | 100 | // Emit semantically uninteresting bytes 101 | // (in particular, punctuation in strings) unmodified. 102 | if v == scanContinue { 103 | dst.WriteByte(c) 104 | continue 105 | } 106 | 107 | // Add spacing around real punctuation. 108 | switch c { 109 | case '{', '[': 110 | // delay indent so that empty object and array are formatted as {} and []. 111 | needIndent = true 112 | dst.WriteByte(c) 113 | 114 | case ',': 115 | dst.WriteByte(c) 116 | newline(dst, prefix, indent, depth) 117 | 118 | case ':': 119 | dst.WriteByte(c) 120 | dst.WriteByte(' ') 121 | 122 | case '}', ']': 123 | if needIndent { 124 | // suppress indent in empty object/array 125 | needIndent = false 126 | } else { 127 | depth-- 128 | newline(dst, prefix, indent, depth) 129 | } 130 | dst.WriteByte(c) 131 | 132 | default: 133 | dst.WriteByte(c) 134 | } 135 | } 136 | if scan.eof() == scanError { 137 | dst.Truncate(origLen) 138 | return scan.err 139 | } 140 | return nil 141 | } 142 | -------------------------------------------------------------------------------- /vendor/gopkg.in/square/go-jose.v1/json/tags.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package json 6 | 7 | import ( 8 | "strings" 9 | ) 10 | 11 | // tagOptions is the string following a comma in a struct field's "json" 12 | // tag, or the empty string. It does not include the leading comma. 13 | type tagOptions string 14 | 15 | // parseTag splits a struct field's json tag into its name and 16 | // comma-separated options. 17 | func parseTag(tag string) (string, tagOptions) { 18 | if idx := strings.Index(tag, ","); idx != -1 { 19 | return tag[:idx], tagOptions(tag[idx+1:]) 20 | } 21 | return tag, tagOptions("") 22 | } 23 | 24 | // Contains reports whether a comma-separated list of options 25 | // contains a particular substr flag. substr must be surrounded by a 26 | // string boundary or commas. 27 | func (o tagOptions) Contains(optionName string) bool { 28 | if len(o) == 0 { 29 | return false 30 | } 31 | s := string(o) 32 | for s != "" { 33 | var next string 34 | i := strings.Index(s, ",") 35 | if i >= 0 { 36 | s, next = s[:i], s[i+1:] 37 | } 38 | if s == optionName { 39 | return true 40 | } 41 | s = next 42 | } 43 | return false 44 | } 45 | -------------------------------------------------------------------------------- /vendor/gopkg.in/square/go-jose.v1/jwe.go: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2014 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package jose 18 | 19 | import ( 20 | "fmt" 21 | "strings" 22 | 23 | "gopkg.in/square/go-jose.v1/json" 24 | ) 25 | 26 | // rawJsonWebEncryption represents a raw JWE JSON object. Used for parsing/serializing. 27 | type rawJsonWebEncryption struct { 28 | Protected *byteBuffer `json:"protected,omitempty"` 29 | Unprotected *rawHeader `json:"unprotected,omitempty"` 30 | Header *rawHeader `json:"header,omitempty"` 31 | Recipients []rawRecipientInfo `json:"recipients,omitempty"` 32 | Aad *byteBuffer `json:"aad,omitempty"` 33 | EncryptedKey *byteBuffer `json:"encrypted_key,omitempty"` 34 | Iv *byteBuffer `json:"iv,omitempty"` 35 | Ciphertext *byteBuffer `json:"ciphertext,omitempty"` 36 | Tag *byteBuffer `json:"tag,omitempty"` 37 | } 38 | 39 | // rawRecipientInfo represents a raw JWE Per-Recipient header JSON object. Used for parsing/serializing. 40 | type rawRecipientInfo struct { 41 | Header *rawHeader `json:"header,omitempty"` 42 | EncryptedKey string `json:"encrypted_key,omitempty"` 43 | } 44 | 45 | // JsonWebEncryption represents an encrypted JWE object after parsing. 46 | type JsonWebEncryption struct { 47 | Header JoseHeader 48 | protected, unprotected *rawHeader 49 | recipients []recipientInfo 50 | aad, iv, ciphertext, tag []byte 51 | original *rawJsonWebEncryption 52 | } 53 | 54 | // recipientInfo represents a raw JWE Per-Recipient header JSON object after parsing. 55 | type recipientInfo struct { 56 | header *rawHeader 57 | encryptedKey []byte 58 | } 59 | 60 | // GetAuthData retrieves the (optional) authenticated data attached to the object. 61 | func (obj JsonWebEncryption) GetAuthData() []byte { 62 | if obj.aad != nil { 63 | out := make([]byte, len(obj.aad)) 64 | copy(out, obj.aad) 65 | return out 66 | } 67 | 68 | return nil 69 | } 70 | 71 | // Get the merged header values 72 | func (obj JsonWebEncryption) mergedHeaders(recipient *recipientInfo) rawHeader { 73 | out := rawHeader{} 74 | out.merge(obj.protected) 75 | out.merge(obj.unprotected) 76 | 77 | if recipient != nil { 78 | out.merge(recipient.header) 79 | } 80 | 81 | return out 82 | } 83 | 84 | // Get the additional authenticated data from a JWE object. 85 | func (obj JsonWebEncryption) computeAuthData() []byte { 86 | var protected string 87 | 88 | if obj.original != nil { 89 | protected = obj.original.Protected.base64() 90 | } else { 91 | protected = base64URLEncode(mustSerializeJSON((obj.protected))) 92 | } 93 | 94 | output := []byte(protected) 95 | if obj.aad != nil { 96 | output = append(output, '.') 97 | output = append(output, []byte(base64URLEncode(obj.aad))...) 98 | } 99 | 100 | return output 101 | } 102 | 103 | // ParseEncrypted parses an encrypted message in compact or full serialization format. 104 | func ParseEncrypted(input string) (*JsonWebEncryption, error) { 105 | input = stripWhitespace(input) 106 | if strings.HasPrefix(input, "{") { 107 | return parseEncryptedFull(input) 108 | } 109 | 110 | return parseEncryptedCompact(input) 111 | } 112 | 113 | // parseEncryptedFull parses a message in compact format. 114 | func parseEncryptedFull(input string) (*JsonWebEncryption, error) { 115 | var parsed rawJsonWebEncryption 116 | err := json.Unmarshal([]byte(input), &parsed) 117 | if err != nil { 118 | return nil, err 119 | } 120 | 121 | return parsed.sanitized() 122 | } 123 | 124 | // sanitized produces a cleaned-up JWE object from the raw JSON. 125 | func (parsed *rawJsonWebEncryption) sanitized() (*JsonWebEncryption, error) { 126 | obj := &JsonWebEncryption{ 127 | original: parsed, 128 | unprotected: parsed.Unprotected, 129 | } 130 | 131 | // Check that there is not a nonce in the unprotected headers 132 | if (parsed.Unprotected != nil && parsed.Unprotected.Nonce != "") || 133 | (parsed.Header != nil && parsed.Header.Nonce != "") { 134 | return nil, ErrUnprotectedNonce 135 | } 136 | 137 | if parsed.Protected != nil && len(parsed.Protected.bytes()) > 0 { 138 | err := json.Unmarshal(parsed.Protected.bytes(), &obj.protected) 139 | if err != nil { 140 | return nil, fmt.Errorf("square/go-jose: invalid protected header: %s, %s", err, parsed.Protected.base64()) 141 | } 142 | } 143 | 144 | // Note: this must be called _after_ we parse the protected header, 145 | // otherwise fields from the protected header will not get picked up. 146 | obj.Header = obj.mergedHeaders(nil).sanitized() 147 | 148 | if len(parsed.Recipients) == 0 { 149 | obj.recipients = []recipientInfo{ 150 | recipientInfo{ 151 | header: parsed.Header, 152 | encryptedKey: parsed.EncryptedKey.bytes(), 153 | }, 154 | } 155 | } else { 156 | obj.recipients = make([]recipientInfo, len(parsed.Recipients)) 157 | for r := range parsed.Recipients { 158 | encryptedKey, err := base64URLDecode(parsed.Recipients[r].EncryptedKey) 159 | if err != nil { 160 | return nil, err 161 | } 162 | 163 | // Check that there is not a nonce in the unprotected header 164 | if parsed.Recipients[r].Header != nil && parsed.Recipients[r].Header.Nonce != "" { 165 | return nil, ErrUnprotectedNonce 166 | } 167 | 168 | obj.recipients[r].header = parsed.Recipients[r].Header 169 | obj.recipients[r].encryptedKey = encryptedKey 170 | } 171 | } 172 | 173 | for _, recipient := range obj.recipients { 174 | headers := obj.mergedHeaders(&recipient) 175 | if headers.Alg == "" || headers.Enc == "" { 176 | return nil, fmt.Errorf("square/go-jose: message is missing alg/enc headers") 177 | } 178 | } 179 | 180 | obj.iv = parsed.Iv.bytes() 181 | obj.ciphertext = parsed.Ciphertext.bytes() 182 | obj.tag = parsed.Tag.bytes() 183 | obj.aad = parsed.Aad.bytes() 184 | 185 | return obj, nil 186 | } 187 | 188 | // parseEncryptedCompact parses a message in compact format. 189 | func parseEncryptedCompact(input string) (*JsonWebEncryption, error) { 190 | parts := strings.Split(input, ".") 191 | if len(parts) != 5 { 192 | return nil, fmt.Errorf("square/go-jose: compact JWE format must have five parts") 193 | } 194 | 195 | rawProtected, err := base64URLDecode(parts[0]) 196 | if err != nil { 197 | return nil, err 198 | } 199 | 200 | encryptedKey, err := base64URLDecode(parts[1]) 201 | if err != nil { 202 | return nil, err 203 | } 204 | 205 | iv, err := base64URLDecode(parts[2]) 206 | if err != nil { 207 | return nil, err 208 | } 209 | 210 | ciphertext, err := base64URLDecode(parts[3]) 211 | if err != nil { 212 | return nil, err 213 | } 214 | 215 | tag, err := base64URLDecode(parts[4]) 216 | if err != nil { 217 | return nil, err 218 | } 219 | 220 | raw := &rawJsonWebEncryption{ 221 | Protected: newBuffer(rawProtected), 222 | EncryptedKey: newBuffer(encryptedKey), 223 | Iv: newBuffer(iv), 224 | Ciphertext: newBuffer(ciphertext), 225 | Tag: newBuffer(tag), 226 | } 227 | 228 | return raw.sanitized() 229 | } 230 | 231 | // CompactSerialize serializes an object using the compact serialization format. 232 | func (obj JsonWebEncryption) CompactSerialize() (string, error) { 233 | if len(obj.recipients) != 1 || obj.unprotected != nil || 234 | obj.protected == nil || obj.recipients[0].header != nil { 235 | return "", ErrNotSupported 236 | } 237 | 238 | serializedProtected := mustSerializeJSON(obj.protected) 239 | 240 | return fmt.Sprintf( 241 | "%s.%s.%s.%s.%s", 242 | base64URLEncode(serializedProtected), 243 | base64URLEncode(obj.recipients[0].encryptedKey), 244 | base64URLEncode(obj.iv), 245 | base64URLEncode(obj.ciphertext), 246 | base64URLEncode(obj.tag)), nil 247 | } 248 | 249 | // FullSerialize serializes an object using the full JSON serialization format. 250 | func (obj JsonWebEncryption) FullSerialize() string { 251 | raw := rawJsonWebEncryption{ 252 | Unprotected: obj.unprotected, 253 | Iv: newBuffer(obj.iv), 254 | Ciphertext: newBuffer(obj.ciphertext), 255 | EncryptedKey: newBuffer(obj.recipients[0].encryptedKey), 256 | Tag: newBuffer(obj.tag), 257 | Aad: newBuffer(obj.aad), 258 | Recipients: []rawRecipientInfo{}, 259 | } 260 | 261 | if len(obj.recipients) > 1 { 262 | for _, recipient := range obj.recipients { 263 | info := rawRecipientInfo{ 264 | Header: recipient.header, 265 | EncryptedKey: base64URLEncode(recipient.encryptedKey), 266 | } 267 | raw.Recipients = append(raw.Recipients, info) 268 | } 269 | } else { 270 | // Use flattened serialization 271 | raw.Header = obj.recipients[0].header 272 | raw.EncryptedKey = newBuffer(obj.recipients[0].encryptedKey) 273 | } 274 | 275 | if obj.protected != nil { 276 | raw.Protected = newBuffer(mustSerializeJSON(obj.protected)) 277 | } 278 | 279 | return string(mustSerializeJSON(raw)) 280 | } 281 | -------------------------------------------------------------------------------- /vendor/gopkg.in/square/go-jose.v1/jws.go: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2014 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package jose 18 | 19 | import ( 20 | "errors" 21 | "fmt" 22 | "strings" 23 | 24 | "gopkg.in/square/go-jose.v1/json" 25 | ) 26 | 27 | // rawJsonWebSignature represents a raw JWS JSON object. Used for parsing/serializing. 28 | type rawJsonWebSignature struct { 29 | Payload *byteBuffer `json:"payload,omitempty"` 30 | Signatures []rawSignatureInfo `json:"signatures,omitempty"` 31 | Protected *byteBuffer `json:"protected,omitempty"` 32 | Header *rawHeader `json:"header,omitempty"` 33 | Signature *byteBuffer `json:"signature,omitempty"` 34 | } 35 | 36 | // rawSignatureInfo represents a single JWS signature over the JWS payload and protected header. 37 | type rawSignatureInfo struct { 38 | Protected *byteBuffer `json:"protected,omitempty"` 39 | Header *rawHeader `json:"header,omitempty"` 40 | Signature *byteBuffer `json:"signature,omitempty"` 41 | } 42 | 43 | // JsonWebSignature represents a signed JWS object after parsing. 44 | type JsonWebSignature struct { 45 | payload []byte 46 | // Signatures attached to this object (may be more than one for multi-sig). 47 | // Be careful about accessing these directly, prefer to use Verify() or 48 | // VerifyMulti() to ensure that the data you're getting is verified. 49 | Signatures []Signature 50 | } 51 | 52 | // Signature represents a single signature over the JWS payload and protected header. 53 | type Signature struct { 54 | // Header fields, such as the signature algorithm 55 | Header JoseHeader 56 | 57 | // The actual signature value 58 | Signature []byte 59 | 60 | protected *rawHeader 61 | header *rawHeader 62 | original *rawSignatureInfo 63 | } 64 | 65 | // ParseSigned parses a signed message in compact or full serialization format. 66 | func ParseSigned(input string) (*JsonWebSignature, error) { 67 | input = stripWhitespace(input) 68 | if strings.HasPrefix(input, "{") { 69 | return parseSignedFull(input) 70 | } 71 | 72 | return parseSignedCompact(input) 73 | } 74 | 75 | // Get a header value 76 | func (sig Signature) mergedHeaders() rawHeader { 77 | out := rawHeader{} 78 | out.merge(sig.protected) 79 | out.merge(sig.header) 80 | return out 81 | } 82 | 83 | // Compute data to be signed 84 | func (obj JsonWebSignature) computeAuthData(signature *Signature) []byte { 85 | var serializedProtected string 86 | 87 | if signature.original != nil && signature.original.Protected != nil { 88 | serializedProtected = signature.original.Protected.base64() 89 | } else if signature.protected != nil { 90 | serializedProtected = base64URLEncode(mustSerializeJSON(signature.protected)) 91 | } else { 92 | serializedProtected = "" 93 | } 94 | 95 | return []byte(fmt.Sprintf("%s.%s", 96 | serializedProtected, 97 | base64URLEncode(obj.payload))) 98 | } 99 | 100 | // parseSignedFull parses a message in full format. 101 | func parseSignedFull(input string) (*JsonWebSignature, error) { 102 | var parsed rawJsonWebSignature 103 | err := json.Unmarshal([]byte(input), &parsed) 104 | if err != nil { 105 | return nil, err 106 | } 107 | 108 | return parsed.sanitized() 109 | } 110 | 111 | // sanitized produces a cleaned-up JWS object from the raw JSON. 112 | func (parsed *rawJsonWebSignature) sanitized() (*JsonWebSignature, error) { 113 | if parsed.Payload == nil { 114 | return nil, fmt.Errorf("square/go-jose: missing payload in JWS message") 115 | } 116 | 117 | obj := &JsonWebSignature{ 118 | payload: parsed.Payload.bytes(), 119 | Signatures: make([]Signature, len(parsed.Signatures)), 120 | } 121 | 122 | if len(parsed.Signatures) == 0 { 123 | // No signatures array, must be flattened serialization 124 | signature := Signature{} 125 | if parsed.Protected != nil && len(parsed.Protected.bytes()) > 0 { 126 | signature.protected = &rawHeader{} 127 | err := json.Unmarshal(parsed.Protected.bytes(), signature.protected) 128 | if err != nil { 129 | return nil, err 130 | } 131 | } 132 | 133 | // Check that there is not a nonce in the unprotected header 134 | if parsed.Header != nil && parsed.Header.Nonce != "" { 135 | return nil, ErrUnprotectedNonce 136 | } 137 | 138 | signature.header = parsed.Header 139 | signature.Signature = parsed.Signature.bytes() 140 | // Make a fake "original" rawSignatureInfo to store the unprocessed 141 | // Protected header. This is necessary because the Protected header can 142 | // contain arbitrary fields not registered as part of the spec. See 143 | // https://tools.ietf.org/html/draft-ietf-jose-json-web-signature-41#section-4 144 | // If we unmarshal Protected into a rawHeader with its explicit list of fields, 145 | // we cannot marshal losslessly. So we have to keep around the original bytes. 146 | // This is used in computeAuthData, which will first attempt to use 147 | // the original bytes of a protected header, and fall back on marshaling the 148 | // header struct only if those bytes are not available. 149 | signature.original = &rawSignatureInfo{ 150 | Protected: parsed.Protected, 151 | Header: parsed.Header, 152 | Signature: parsed.Signature, 153 | } 154 | 155 | signature.Header = signature.mergedHeaders().sanitized() 156 | 157 | // As per RFC 7515 Section 4.1.3, only public keys are allowed to be embedded. 158 | jwk := signature.Header.JsonWebKey 159 | if jwk != nil && (!jwk.Valid() || !jwk.IsPublic()) { 160 | return nil, errors.New("square/go-jose: invalid embedded jwk, must be public key") 161 | } 162 | 163 | obj.Signatures = append(obj.Signatures, signature) 164 | } 165 | 166 | for i, sig := range parsed.Signatures { 167 | if sig.Protected != nil && len(sig.Protected.bytes()) > 0 { 168 | obj.Signatures[i].protected = &rawHeader{} 169 | err := json.Unmarshal(sig.Protected.bytes(), obj.Signatures[i].protected) 170 | if err != nil { 171 | return nil, err 172 | } 173 | } 174 | 175 | // Check that there is not a nonce in the unprotected header 176 | if sig.Header != nil && sig.Header.Nonce != "" { 177 | return nil, ErrUnprotectedNonce 178 | } 179 | 180 | obj.Signatures[i].Header = obj.Signatures[i].mergedHeaders().sanitized() 181 | obj.Signatures[i].Signature = sig.Signature.bytes() 182 | 183 | // As per RFC 7515 Section 4.1.3, only public keys are allowed to be embedded. 184 | jwk := obj.Signatures[i].Header.JsonWebKey 185 | if jwk != nil && (!jwk.Valid() || !jwk.IsPublic()) { 186 | return nil, errors.New("square/go-jose: invalid embedded jwk, must be public key") 187 | } 188 | 189 | // Copy value of sig 190 | original := sig 191 | 192 | obj.Signatures[i].header = sig.Header 193 | obj.Signatures[i].original = &original 194 | } 195 | 196 | return obj, nil 197 | } 198 | 199 | // parseSignedCompact parses a message in compact format. 200 | func parseSignedCompact(input string) (*JsonWebSignature, error) { 201 | parts := strings.Split(input, ".") 202 | if len(parts) != 3 { 203 | return nil, fmt.Errorf("square/go-jose: compact JWS format must have three parts") 204 | } 205 | 206 | rawProtected, err := base64URLDecode(parts[0]) 207 | if err != nil { 208 | return nil, err 209 | } 210 | 211 | payload, err := base64URLDecode(parts[1]) 212 | if err != nil { 213 | return nil, err 214 | } 215 | 216 | signature, err := base64URLDecode(parts[2]) 217 | if err != nil { 218 | return nil, err 219 | } 220 | 221 | raw := &rawJsonWebSignature{ 222 | Payload: newBuffer(payload), 223 | Protected: newBuffer(rawProtected), 224 | Signature: newBuffer(signature), 225 | } 226 | return raw.sanitized() 227 | } 228 | 229 | // CompactSerialize serializes an object using the compact serialization format. 230 | func (obj JsonWebSignature) CompactSerialize() (string, error) { 231 | if len(obj.Signatures) != 1 || obj.Signatures[0].header != nil || obj.Signatures[0].protected == nil { 232 | return "", ErrNotSupported 233 | } 234 | 235 | serializedProtected := mustSerializeJSON(obj.Signatures[0].protected) 236 | 237 | return fmt.Sprintf( 238 | "%s.%s.%s", 239 | base64URLEncode(serializedProtected), 240 | base64URLEncode(obj.payload), 241 | base64URLEncode(obj.Signatures[0].Signature)), nil 242 | } 243 | 244 | // FullSerialize serializes an object using the full JSON serialization format. 245 | func (obj JsonWebSignature) FullSerialize() string { 246 | raw := rawJsonWebSignature{ 247 | Payload: newBuffer(obj.payload), 248 | } 249 | 250 | if len(obj.Signatures) == 1 { 251 | if obj.Signatures[0].protected != nil { 252 | serializedProtected := mustSerializeJSON(obj.Signatures[0].protected) 253 | raw.Protected = newBuffer(serializedProtected) 254 | } 255 | raw.Header = obj.Signatures[0].header 256 | raw.Signature = newBuffer(obj.Signatures[0].Signature) 257 | } else { 258 | raw.Signatures = make([]rawSignatureInfo, len(obj.Signatures)) 259 | for i, signature := range obj.Signatures { 260 | raw.Signatures[i] = rawSignatureInfo{ 261 | Header: signature.header, 262 | Signature: newBuffer(signature.Signature), 263 | } 264 | 265 | if signature.protected != nil { 266 | raw.Signatures[i].Protected = newBuffer(mustSerializeJSON(signature.protected)) 267 | } 268 | } 269 | } 270 | 271 | return string(mustSerializeJSON(raw)) 272 | } 273 | -------------------------------------------------------------------------------- /vendor/gopkg.in/square/go-jose.v1/shared.go: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2014 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package jose 18 | 19 | import ( 20 | "crypto/elliptic" 21 | "errors" 22 | "fmt" 23 | ) 24 | 25 | // KeyAlgorithm represents a key management algorithm. 26 | type KeyAlgorithm string 27 | 28 | // SignatureAlgorithm represents a signature (or MAC) algorithm. 29 | type SignatureAlgorithm string 30 | 31 | // ContentEncryption represents a content encryption algorithm. 32 | type ContentEncryption string 33 | 34 | // CompressionAlgorithm represents an algorithm used for plaintext compression. 35 | type CompressionAlgorithm string 36 | 37 | var ( 38 | // ErrCryptoFailure represents an error in cryptographic primitive. This 39 | // occurs when, for example, a message had an invalid authentication tag or 40 | // could not be decrypted. 41 | ErrCryptoFailure = errors.New("square/go-jose: error in cryptographic primitive") 42 | 43 | // ErrUnsupportedAlgorithm indicates that a selected algorithm is not 44 | // supported. This occurs when trying to instantiate an encrypter for an 45 | // algorithm that is not yet implemented. 46 | ErrUnsupportedAlgorithm = errors.New("square/go-jose: unknown/unsupported algorithm") 47 | 48 | // ErrUnsupportedKeyType indicates that the given key type/format is not 49 | // supported. This occurs when trying to instantiate an encrypter and passing 50 | // it a key of an unrecognized type or with unsupported parameters, such as 51 | // an RSA private key with more than two primes. 52 | ErrUnsupportedKeyType = errors.New("square/go-jose: unsupported key type/format") 53 | 54 | // ErrNotSupported serialization of object is not supported. This occurs when 55 | // trying to compact-serialize an object which can't be represented in 56 | // compact form. 57 | ErrNotSupported = errors.New("square/go-jose: compact serialization not supported for object") 58 | 59 | // ErrUnprotectedNonce indicates that while parsing a JWS or JWE object, a 60 | // nonce header parameter was included in an unprotected header object. 61 | ErrUnprotectedNonce = errors.New("square/go-jose: Nonce parameter included in unprotected header") 62 | ) 63 | 64 | // Key management algorithms 65 | const ( 66 | RSA1_5 = KeyAlgorithm("RSA1_5") // RSA-PKCS1v1.5 67 | RSA_OAEP = KeyAlgorithm("RSA-OAEP") // RSA-OAEP-SHA1 68 | RSA_OAEP_256 = KeyAlgorithm("RSA-OAEP-256") // RSA-OAEP-SHA256 69 | A128KW = KeyAlgorithm("A128KW") // AES key wrap (128) 70 | A192KW = KeyAlgorithm("A192KW") // AES key wrap (192) 71 | A256KW = KeyAlgorithm("A256KW") // AES key wrap (256) 72 | DIRECT = KeyAlgorithm("dir") // Direct encryption 73 | ECDH_ES = KeyAlgorithm("ECDH-ES") // ECDH-ES 74 | ECDH_ES_A128KW = KeyAlgorithm("ECDH-ES+A128KW") // ECDH-ES + AES key wrap (128) 75 | ECDH_ES_A192KW = KeyAlgorithm("ECDH-ES+A192KW") // ECDH-ES + AES key wrap (192) 76 | ECDH_ES_A256KW = KeyAlgorithm("ECDH-ES+A256KW") // ECDH-ES + AES key wrap (256) 77 | A128GCMKW = KeyAlgorithm("A128GCMKW") // AES-GCM key wrap (128) 78 | A192GCMKW = KeyAlgorithm("A192GCMKW") // AES-GCM key wrap (192) 79 | A256GCMKW = KeyAlgorithm("A256GCMKW") // AES-GCM key wrap (256) 80 | PBES2_HS256_A128KW = KeyAlgorithm("PBES2-HS256+A128KW") // PBES2 + HMAC-SHA256 + AES key wrap (128) 81 | PBES2_HS384_A192KW = KeyAlgorithm("PBES2-HS384+A192KW") // PBES2 + HMAC-SHA384 + AES key wrap (192) 82 | PBES2_HS512_A256KW = KeyAlgorithm("PBES2-HS512+A256KW") // PBES2 + HMAC-SHA512 + AES key wrap (256) 83 | ) 84 | 85 | // Signature algorithms 86 | const ( 87 | HS256 = SignatureAlgorithm("HS256") // HMAC using SHA-256 88 | HS384 = SignatureAlgorithm("HS384") // HMAC using SHA-384 89 | HS512 = SignatureAlgorithm("HS512") // HMAC using SHA-512 90 | RS256 = SignatureAlgorithm("RS256") // RSASSA-PKCS-v1.5 using SHA-256 91 | RS384 = SignatureAlgorithm("RS384") // RSASSA-PKCS-v1.5 using SHA-384 92 | RS512 = SignatureAlgorithm("RS512") // RSASSA-PKCS-v1.5 using SHA-512 93 | ES256 = SignatureAlgorithm("ES256") // ECDSA using P-256 and SHA-256 94 | ES384 = SignatureAlgorithm("ES384") // ECDSA using P-384 and SHA-384 95 | ES512 = SignatureAlgorithm("ES512") // ECDSA using P-521 and SHA-512 96 | PS256 = SignatureAlgorithm("PS256") // RSASSA-PSS using SHA256 and MGF1-SHA256 97 | PS384 = SignatureAlgorithm("PS384") // RSASSA-PSS using SHA384 and MGF1-SHA384 98 | PS512 = SignatureAlgorithm("PS512") // RSASSA-PSS using SHA512 and MGF1-SHA512 99 | ) 100 | 101 | // Content encryption algorithms 102 | const ( 103 | A128CBC_HS256 = ContentEncryption("A128CBC-HS256") // AES-CBC + HMAC-SHA256 (128) 104 | A192CBC_HS384 = ContentEncryption("A192CBC-HS384") // AES-CBC + HMAC-SHA384 (192) 105 | A256CBC_HS512 = ContentEncryption("A256CBC-HS512") // AES-CBC + HMAC-SHA512 (256) 106 | A128GCM = ContentEncryption("A128GCM") // AES-GCM (128) 107 | A192GCM = ContentEncryption("A192GCM") // AES-GCM (192) 108 | A256GCM = ContentEncryption("A256GCM") // AES-GCM (256) 109 | ) 110 | 111 | // Compression algorithms 112 | const ( 113 | NONE = CompressionAlgorithm("") // No compression 114 | DEFLATE = CompressionAlgorithm("DEF") // DEFLATE (RFC 1951) 115 | ) 116 | 117 | // rawHeader represents the JOSE header for JWE/JWS objects (used for parsing). 118 | type rawHeader struct { 119 | Alg string `json:"alg,omitempty"` 120 | Enc ContentEncryption `json:"enc,omitempty"` 121 | Zip CompressionAlgorithm `json:"zip,omitempty"` 122 | Crit []string `json:"crit,omitempty"` 123 | Apu *byteBuffer `json:"apu,omitempty"` 124 | Apv *byteBuffer `json:"apv,omitempty"` 125 | Epk *JsonWebKey `json:"epk,omitempty"` 126 | Iv *byteBuffer `json:"iv,omitempty"` 127 | Tag *byteBuffer `json:"tag,omitempty"` 128 | Jwk *JsonWebKey `json:"jwk,omitempty"` 129 | Kid string `json:"kid,omitempty"` 130 | Nonce string `json:"nonce,omitempty"` 131 | } 132 | 133 | // JoseHeader represents the read-only JOSE header for JWE/JWS objects. 134 | type JoseHeader struct { 135 | KeyID string 136 | JsonWebKey *JsonWebKey 137 | Algorithm string 138 | Nonce string 139 | } 140 | 141 | // sanitized produces a cleaned-up header object from the raw JSON. 142 | func (parsed rawHeader) sanitized() JoseHeader { 143 | return JoseHeader{ 144 | KeyID: parsed.Kid, 145 | JsonWebKey: parsed.Jwk, 146 | Algorithm: parsed.Alg, 147 | Nonce: parsed.Nonce, 148 | } 149 | } 150 | 151 | // Merge headers from src into dst, giving precedence to headers from l. 152 | func (dst *rawHeader) merge(src *rawHeader) { 153 | if src == nil { 154 | return 155 | } 156 | 157 | if dst.Alg == "" { 158 | dst.Alg = src.Alg 159 | } 160 | if dst.Enc == "" { 161 | dst.Enc = src.Enc 162 | } 163 | if dst.Zip == "" { 164 | dst.Zip = src.Zip 165 | } 166 | if dst.Crit == nil { 167 | dst.Crit = src.Crit 168 | } 169 | if dst.Crit == nil { 170 | dst.Crit = src.Crit 171 | } 172 | if dst.Apu == nil { 173 | dst.Apu = src.Apu 174 | } 175 | if dst.Apv == nil { 176 | dst.Apv = src.Apv 177 | } 178 | if dst.Epk == nil { 179 | dst.Epk = src.Epk 180 | } 181 | if dst.Iv == nil { 182 | dst.Iv = src.Iv 183 | } 184 | if dst.Tag == nil { 185 | dst.Tag = src.Tag 186 | } 187 | if dst.Kid == "" { 188 | dst.Kid = src.Kid 189 | } 190 | if dst.Jwk == nil { 191 | dst.Jwk = src.Jwk 192 | } 193 | if dst.Nonce == "" { 194 | dst.Nonce = src.Nonce 195 | } 196 | } 197 | 198 | // Get JOSE name of curve 199 | func curveName(crv elliptic.Curve) (string, error) { 200 | switch crv { 201 | case elliptic.P256(): 202 | return "P-256", nil 203 | case elliptic.P384(): 204 | return "P-384", nil 205 | case elliptic.P521(): 206 | return "P-521", nil 207 | default: 208 | return "", fmt.Errorf("square/go-jose: unsupported/unknown elliptic curve") 209 | } 210 | } 211 | 212 | // Get size of curve in bytes 213 | func curveSize(crv elliptic.Curve) int { 214 | bits := crv.Params().BitSize 215 | 216 | div := bits / 8 217 | mod := bits % 8 218 | 219 | if mod == 0 { 220 | return div 221 | } 222 | 223 | return div + 1 224 | } 225 | -------------------------------------------------------------------------------- /vendor/gopkg.in/square/go-jose.v1/signing.go: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2014 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package jose 18 | 19 | import ( 20 | "crypto/ecdsa" 21 | "crypto/rsa" 22 | "errors" 23 | "fmt" 24 | ) 25 | 26 | // NonceSource represents a source of random nonces to go into JWS objects 27 | type NonceSource interface { 28 | Nonce() (string, error) 29 | } 30 | 31 | // Signer represents a signer which takes a payload and produces a signed JWS object. 32 | type Signer interface { 33 | Sign(payload []byte) (*JsonWebSignature, error) 34 | SetNonceSource(source NonceSource) 35 | SetEmbedJwk(embed bool) 36 | } 37 | 38 | // MultiSigner represents a signer which supports multiple recipients. 39 | type MultiSigner interface { 40 | Sign(payload []byte) (*JsonWebSignature, error) 41 | SetNonceSource(source NonceSource) 42 | SetEmbedJwk(embed bool) 43 | AddRecipient(alg SignatureAlgorithm, signingKey interface{}) error 44 | } 45 | 46 | type payloadSigner interface { 47 | signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) 48 | } 49 | 50 | type payloadVerifier interface { 51 | verifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error 52 | } 53 | 54 | type genericSigner struct { 55 | recipients []recipientSigInfo 56 | nonceSource NonceSource 57 | embedJwk bool 58 | } 59 | 60 | type recipientSigInfo struct { 61 | sigAlg SignatureAlgorithm 62 | keyID string 63 | publicKey *JsonWebKey 64 | signer payloadSigner 65 | } 66 | 67 | // NewSigner creates an appropriate signer based on the key type 68 | func NewSigner(alg SignatureAlgorithm, signingKey interface{}) (Signer, error) { 69 | // NewMultiSigner never fails (currently) 70 | signer := NewMultiSigner() 71 | 72 | err := signer.AddRecipient(alg, signingKey) 73 | if err != nil { 74 | return nil, err 75 | } 76 | 77 | return signer, nil 78 | } 79 | 80 | // NewMultiSigner creates a signer for multiple recipients 81 | func NewMultiSigner() MultiSigner { 82 | return &genericSigner{ 83 | recipients: []recipientSigInfo{}, 84 | embedJwk: true, 85 | } 86 | } 87 | 88 | // newVerifier creates a verifier based on the key type 89 | func newVerifier(verificationKey interface{}) (payloadVerifier, error) { 90 | switch verificationKey := verificationKey.(type) { 91 | case *rsa.PublicKey: 92 | return &rsaEncrypterVerifier{ 93 | publicKey: verificationKey, 94 | }, nil 95 | case *ecdsa.PublicKey: 96 | return &ecEncrypterVerifier{ 97 | publicKey: verificationKey, 98 | }, nil 99 | case []byte: 100 | return &symmetricMac{ 101 | key: verificationKey, 102 | }, nil 103 | case *JsonWebKey: 104 | return newVerifier(verificationKey.Key) 105 | default: 106 | return nil, ErrUnsupportedKeyType 107 | } 108 | } 109 | 110 | func (ctx *genericSigner) AddRecipient(alg SignatureAlgorithm, signingKey interface{}) error { 111 | recipient, err := makeJWSRecipient(alg, signingKey) 112 | if err != nil { 113 | return err 114 | } 115 | 116 | ctx.recipients = append(ctx.recipients, recipient) 117 | return nil 118 | } 119 | 120 | func makeJWSRecipient(alg SignatureAlgorithm, signingKey interface{}) (recipientSigInfo, error) { 121 | switch signingKey := signingKey.(type) { 122 | case *rsa.PrivateKey: 123 | return newRSASigner(alg, signingKey) 124 | case *ecdsa.PrivateKey: 125 | return newECDSASigner(alg, signingKey) 126 | case []byte: 127 | return newSymmetricSigner(alg, signingKey) 128 | case *JsonWebKey: 129 | recipient, err := makeJWSRecipient(alg, signingKey.Key) 130 | if err != nil { 131 | return recipientSigInfo{}, err 132 | } 133 | recipient.keyID = signingKey.KeyID 134 | return recipient, nil 135 | default: 136 | return recipientSigInfo{}, ErrUnsupportedKeyType 137 | } 138 | } 139 | 140 | func (ctx *genericSigner) Sign(payload []byte) (*JsonWebSignature, error) { 141 | obj := &JsonWebSignature{} 142 | obj.payload = payload 143 | obj.Signatures = make([]Signature, len(ctx.recipients)) 144 | 145 | for i, recipient := range ctx.recipients { 146 | protected := &rawHeader{ 147 | Alg: string(recipient.sigAlg), 148 | } 149 | 150 | if recipient.publicKey != nil && ctx.embedJwk { 151 | protected.Jwk = recipient.publicKey 152 | } 153 | if recipient.keyID != "" { 154 | protected.Kid = recipient.keyID 155 | } 156 | 157 | if ctx.nonceSource != nil { 158 | nonce, err := ctx.nonceSource.Nonce() 159 | if err != nil { 160 | return nil, fmt.Errorf("square/go-jose: Error generating nonce: %v", err) 161 | } 162 | protected.Nonce = nonce 163 | } 164 | 165 | serializedProtected := mustSerializeJSON(protected) 166 | 167 | input := []byte(fmt.Sprintf("%s.%s", 168 | base64URLEncode(serializedProtected), 169 | base64URLEncode(payload))) 170 | 171 | signatureInfo, err := recipient.signer.signPayload(input, recipient.sigAlg) 172 | if err != nil { 173 | return nil, err 174 | } 175 | 176 | signatureInfo.protected = protected 177 | obj.Signatures[i] = signatureInfo 178 | } 179 | 180 | return obj, nil 181 | } 182 | 183 | // SetNonceSource provides or updates a nonce pool to the first recipients. 184 | // After this method is called, the signer will consume one nonce per 185 | // signature, returning an error it is unable to get a nonce. 186 | func (ctx *genericSigner) SetNonceSource(source NonceSource) { 187 | ctx.nonceSource = source 188 | } 189 | 190 | // SetEmbedJwk specifies if the signing key should be embedded in the protected 191 | // header, if any. It defaults to 'true', though that may change in the future. 192 | // Note that the use of embedded JWKs in the signature header can be dangerous, 193 | // as you cannot assume that the key received in a payload is trusted. 194 | func (ctx *genericSigner) SetEmbedJwk(embed bool) { 195 | ctx.embedJwk = embed 196 | } 197 | 198 | // Verify validates the signature on the object and returns the payload. 199 | // This function does not support multi-signature, if you desire multi-sig 200 | // verification use VerifyMulti instead. 201 | // 202 | // Be careful when verifying signatures based on embedded JWKs inside the 203 | // payload header. You cannot assume that the key received in a payload is 204 | // trusted. 205 | func (obj JsonWebSignature) Verify(verificationKey interface{}) ([]byte, error) { 206 | verifier, err := newVerifier(verificationKey) 207 | if err != nil { 208 | return nil, err 209 | } 210 | 211 | if len(obj.Signatures) > 1 { 212 | return nil, errors.New("square/go-jose: too many signatures in payload; expecting only one") 213 | } 214 | 215 | signature := obj.Signatures[0] 216 | headers := signature.mergedHeaders() 217 | if len(headers.Crit) > 0 { 218 | // Unsupported crit header 219 | return nil, ErrCryptoFailure 220 | } 221 | 222 | input := obj.computeAuthData(&signature) 223 | alg := SignatureAlgorithm(headers.Alg) 224 | err = verifier.verifyPayload(input, signature.Signature, alg) 225 | if err == nil { 226 | return obj.payload, nil 227 | } 228 | 229 | return nil, ErrCryptoFailure 230 | } 231 | 232 | // VerifyMulti validates (one of the multiple) signatures on the object and 233 | // returns the index of the signature that was verified, along with the signature 234 | // object and the payload. We return the signature and index to guarantee that 235 | // callers are getting the verified value. 236 | func (obj JsonWebSignature) VerifyMulti(verificationKey interface{}) (int, Signature, []byte, error) { 237 | verifier, err := newVerifier(verificationKey) 238 | if err != nil { 239 | return -1, Signature{}, nil, err 240 | } 241 | 242 | for i, signature := range obj.Signatures { 243 | headers := signature.mergedHeaders() 244 | if len(headers.Crit) > 0 { 245 | // Unsupported crit header 246 | continue 247 | } 248 | 249 | input := obj.computeAuthData(&signature) 250 | alg := SignatureAlgorithm(headers.Alg) 251 | err := verifier.verifyPayload(input, signature.Signature, alg) 252 | if err == nil { 253 | return i, signature, obj.payload, nil 254 | } 255 | } 256 | 257 | return -1, Signature{}, nil, ErrCryptoFailure 258 | } 259 | -------------------------------------------------------------------------------- /vendor/gopkg.in/square/go-jose.v1/symmetric.go: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2014 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package jose 18 | 19 | import ( 20 | "crypto/aes" 21 | "crypto/cipher" 22 | "crypto/hmac" 23 | "crypto/rand" 24 | "crypto/sha256" 25 | "crypto/sha512" 26 | "crypto/subtle" 27 | "errors" 28 | "hash" 29 | "io" 30 | 31 | "gopkg.in/square/go-jose.v1/cipher" 32 | ) 33 | 34 | // Random reader (stubbed out in tests) 35 | var randReader = rand.Reader 36 | 37 | // Dummy key cipher for shared symmetric key mode 38 | type symmetricKeyCipher struct { 39 | key []byte // Pre-shared content-encryption key 40 | } 41 | 42 | // Signer/verifier for MAC modes 43 | type symmetricMac struct { 44 | key []byte 45 | } 46 | 47 | // Input/output from an AEAD operation 48 | type aeadParts struct { 49 | iv, ciphertext, tag []byte 50 | } 51 | 52 | // A content cipher based on an AEAD construction 53 | type aeadContentCipher struct { 54 | keyBytes int 55 | authtagBytes int 56 | getAead func(key []byte) (cipher.AEAD, error) 57 | } 58 | 59 | // Random key generator 60 | type randomKeyGenerator struct { 61 | size int 62 | } 63 | 64 | // Static key generator 65 | type staticKeyGenerator struct { 66 | key []byte 67 | } 68 | 69 | // Create a new content cipher based on AES-GCM 70 | func newAESGCM(keySize int) contentCipher { 71 | return &aeadContentCipher{ 72 | keyBytes: keySize, 73 | authtagBytes: 16, 74 | getAead: func(key []byte) (cipher.AEAD, error) { 75 | aes, err := aes.NewCipher(key) 76 | if err != nil { 77 | return nil, err 78 | } 79 | 80 | return cipher.NewGCM(aes) 81 | }, 82 | } 83 | } 84 | 85 | // Create a new content cipher based on AES-CBC+HMAC 86 | func newAESCBC(keySize int) contentCipher { 87 | return &aeadContentCipher{ 88 | keyBytes: keySize * 2, 89 | authtagBytes: 16, 90 | getAead: func(key []byte) (cipher.AEAD, error) { 91 | return josecipher.NewCBCHMAC(key, aes.NewCipher) 92 | }, 93 | } 94 | } 95 | 96 | // Get an AEAD cipher object for the given content encryption algorithm 97 | func getContentCipher(alg ContentEncryption) contentCipher { 98 | switch alg { 99 | case A128GCM: 100 | return newAESGCM(16) 101 | case A192GCM: 102 | return newAESGCM(24) 103 | case A256GCM: 104 | return newAESGCM(32) 105 | case A128CBC_HS256: 106 | return newAESCBC(16) 107 | case A192CBC_HS384: 108 | return newAESCBC(24) 109 | case A256CBC_HS512: 110 | return newAESCBC(32) 111 | default: 112 | return nil 113 | } 114 | } 115 | 116 | // newSymmetricRecipient creates a JWE encrypter based on AES-GCM key wrap. 117 | func newSymmetricRecipient(keyAlg KeyAlgorithm, key []byte) (recipientKeyInfo, error) { 118 | switch keyAlg { 119 | case DIRECT, A128GCMKW, A192GCMKW, A256GCMKW, A128KW, A192KW, A256KW: 120 | default: 121 | return recipientKeyInfo{}, ErrUnsupportedAlgorithm 122 | } 123 | 124 | return recipientKeyInfo{ 125 | keyAlg: keyAlg, 126 | keyEncrypter: &symmetricKeyCipher{ 127 | key: key, 128 | }, 129 | }, nil 130 | } 131 | 132 | // newSymmetricSigner creates a recipientSigInfo based on the given key. 133 | func newSymmetricSigner(sigAlg SignatureAlgorithm, key []byte) (recipientSigInfo, error) { 134 | // Verify that key management algorithm is supported by this encrypter 135 | switch sigAlg { 136 | case HS256, HS384, HS512: 137 | default: 138 | return recipientSigInfo{}, ErrUnsupportedAlgorithm 139 | } 140 | 141 | return recipientSigInfo{ 142 | sigAlg: sigAlg, 143 | signer: &symmetricMac{ 144 | key: key, 145 | }, 146 | }, nil 147 | } 148 | 149 | // Generate a random key for the given content cipher 150 | func (ctx randomKeyGenerator) genKey() ([]byte, rawHeader, error) { 151 | key := make([]byte, ctx.size) 152 | _, err := io.ReadFull(randReader, key) 153 | if err != nil { 154 | return nil, rawHeader{}, err 155 | } 156 | 157 | return key, rawHeader{}, nil 158 | } 159 | 160 | // Key size for random generator 161 | func (ctx randomKeyGenerator) keySize() int { 162 | return ctx.size 163 | } 164 | 165 | // Generate a static key (for direct mode) 166 | func (ctx staticKeyGenerator) genKey() ([]byte, rawHeader, error) { 167 | cek := make([]byte, len(ctx.key)) 168 | copy(cek, ctx.key) 169 | return cek, rawHeader{}, nil 170 | } 171 | 172 | // Key size for static generator 173 | func (ctx staticKeyGenerator) keySize() int { 174 | return len(ctx.key) 175 | } 176 | 177 | // Get key size for this cipher 178 | func (ctx aeadContentCipher) keySize() int { 179 | return ctx.keyBytes 180 | } 181 | 182 | // Encrypt some data 183 | func (ctx aeadContentCipher) encrypt(key, aad, pt []byte) (*aeadParts, error) { 184 | // Get a new AEAD instance 185 | aead, err := ctx.getAead(key) 186 | if err != nil { 187 | return nil, err 188 | } 189 | 190 | // Initialize a new nonce 191 | iv := make([]byte, aead.NonceSize()) 192 | _, err = io.ReadFull(randReader, iv) 193 | if err != nil { 194 | return nil, err 195 | } 196 | 197 | ciphertextAndTag := aead.Seal(nil, iv, pt, aad) 198 | offset := len(ciphertextAndTag) - ctx.authtagBytes 199 | 200 | return &aeadParts{ 201 | iv: iv, 202 | ciphertext: ciphertextAndTag[:offset], 203 | tag: ciphertextAndTag[offset:], 204 | }, nil 205 | } 206 | 207 | // Decrypt some data 208 | func (ctx aeadContentCipher) decrypt(key, aad []byte, parts *aeadParts) ([]byte, error) { 209 | aead, err := ctx.getAead(key) 210 | if err != nil { 211 | return nil, err 212 | } 213 | 214 | return aead.Open(nil, parts.iv, append(parts.ciphertext, parts.tag...), aad) 215 | } 216 | 217 | // Encrypt the content encryption key. 218 | func (ctx *symmetricKeyCipher) encryptKey(cek []byte, alg KeyAlgorithm) (recipientInfo, error) { 219 | switch alg { 220 | case DIRECT: 221 | return recipientInfo{ 222 | header: &rawHeader{}, 223 | }, nil 224 | case A128GCMKW, A192GCMKW, A256GCMKW: 225 | aead := newAESGCM(len(ctx.key)) 226 | 227 | parts, err := aead.encrypt(ctx.key, []byte{}, cek) 228 | if err != nil { 229 | return recipientInfo{}, err 230 | } 231 | 232 | return recipientInfo{ 233 | header: &rawHeader{ 234 | Iv: newBuffer(parts.iv), 235 | Tag: newBuffer(parts.tag), 236 | }, 237 | encryptedKey: parts.ciphertext, 238 | }, nil 239 | case A128KW, A192KW, A256KW: 240 | block, err := aes.NewCipher(ctx.key) 241 | if err != nil { 242 | return recipientInfo{}, err 243 | } 244 | 245 | jek, err := josecipher.KeyWrap(block, cek) 246 | if err != nil { 247 | return recipientInfo{}, err 248 | } 249 | 250 | return recipientInfo{ 251 | encryptedKey: jek, 252 | header: &rawHeader{}, 253 | }, nil 254 | } 255 | 256 | return recipientInfo{}, ErrUnsupportedAlgorithm 257 | } 258 | 259 | // Decrypt the content encryption key. 260 | func (ctx *symmetricKeyCipher) decryptKey(headers rawHeader, recipient *recipientInfo, generator keyGenerator) ([]byte, error) { 261 | switch KeyAlgorithm(headers.Alg) { 262 | case DIRECT: 263 | cek := make([]byte, len(ctx.key)) 264 | copy(cek, ctx.key) 265 | return cek, nil 266 | case A128GCMKW, A192GCMKW, A256GCMKW: 267 | aead := newAESGCM(len(ctx.key)) 268 | 269 | parts := &aeadParts{ 270 | iv: headers.Iv.bytes(), 271 | ciphertext: recipient.encryptedKey, 272 | tag: headers.Tag.bytes(), 273 | } 274 | 275 | cek, err := aead.decrypt(ctx.key, []byte{}, parts) 276 | if err != nil { 277 | return nil, err 278 | } 279 | 280 | return cek, nil 281 | case A128KW, A192KW, A256KW: 282 | block, err := aes.NewCipher(ctx.key) 283 | if err != nil { 284 | return nil, err 285 | } 286 | 287 | cek, err := josecipher.KeyUnwrap(block, recipient.encryptedKey) 288 | if err != nil { 289 | return nil, err 290 | } 291 | return cek, nil 292 | } 293 | 294 | return nil, ErrUnsupportedAlgorithm 295 | } 296 | 297 | // Sign the given payload 298 | func (ctx symmetricMac) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) { 299 | mac, err := ctx.hmac(payload, alg) 300 | if err != nil { 301 | return Signature{}, errors.New("square/go-jose: failed to compute hmac") 302 | } 303 | 304 | return Signature{ 305 | Signature: mac, 306 | protected: &rawHeader{}, 307 | }, nil 308 | } 309 | 310 | // Verify the given payload 311 | func (ctx symmetricMac) verifyPayload(payload []byte, mac []byte, alg SignatureAlgorithm) error { 312 | expected, err := ctx.hmac(payload, alg) 313 | if err != nil { 314 | return errors.New("square/go-jose: failed to compute hmac") 315 | } 316 | 317 | if len(mac) != len(expected) { 318 | return errors.New("square/go-jose: invalid hmac") 319 | } 320 | 321 | match := subtle.ConstantTimeCompare(mac, expected) 322 | if match != 1 { 323 | return errors.New("square/go-jose: invalid hmac") 324 | } 325 | 326 | return nil 327 | } 328 | 329 | // Compute the HMAC based on the given alg value 330 | func (ctx symmetricMac) hmac(payload []byte, alg SignatureAlgorithm) ([]byte, error) { 331 | var hash func() hash.Hash 332 | 333 | switch alg { 334 | case HS256: 335 | hash = sha256.New 336 | case HS384: 337 | hash = sha512.New384 338 | case HS512: 339 | hash = sha512.New 340 | default: 341 | return nil, ErrUnsupportedAlgorithm 342 | } 343 | 344 | hmac := hmac.New(hash, ctx.key) 345 | 346 | // According to documentation, Write() on hash never fails 347 | _, _ = hmac.Write(payload) 348 | return hmac.Sum(nil), nil 349 | } 350 | -------------------------------------------------------------------------------- /vendor/gopkg.in/square/go-jose.v1/utils.go: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2014 Square Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package jose 18 | 19 | import ( 20 | "crypto/x509" 21 | "encoding/pem" 22 | "fmt" 23 | ) 24 | 25 | // LoadPublicKey loads a public key from PEM/DER-encoded data. 26 | func LoadPublicKey(data []byte) (interface{}, error) { 27 | input := data 28 | 29 | block, _ := pem.Decode(data) 30 | if block != nil { 31 | input = block.Bytes 32 | } 33 | 34 | // Try to load SubjectPublicKeyInfo 35 | pub, err0 := x509.ParsePKIXPublicKey(input) 36 | if err0 == nil { 37 | return pub, nil 38 | } 39 | 40 | cert, err1 := x509.ParseCertificate(input) 41 | if err1 == nil { 42 | return cert.PublicKey, nil 43 | } 44 | 45 | return nil, fmt.Errorf("square/go-jose: parse error, got '%s' and '%s'", err0, err1) 46 | } 47 | 48 | // LoadPrivateKey loads a private key from PEM/DER-encoded data. 49 | func LoadPrivateKey(data []byte) (interface{}, error) { 50 | input := data 51 | 52 | block, _ := pem.Decode(data) 53 | if block != nil { 54 | input = block.Bytes 55 | } 56 | 57 | var priv interface{} 58 | priv, err0 := x509.ParsePKCS1PrivateKey(input) 59 | if err0 == nil { 60 | return priv, nil 61 | } 62 | 63 | priv, err1 := x509.ParsePKCS8PrivateKey(input) 64 | if err1 == nil { 65 | return priv, nil 66 | } 67 | 68 | priv, err2 := x509.ParseECPrivateKey(input) 69 | if err2 == nil { 70 | return priv, nil 71 | } 72 | 73 | return nil, fmt.Errorf("square/go-jose: parse error, got '%s', '%s' and '%s'", err0, err1, err2) 74 | } 75 | -------------------------------------------------------------------------------- /vendor/vendor.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment": "", 3 | "ignore": "test", 4 | "package": [ 5 | { 6 | "checksumSHA1": "6HayARU0sIG8zlPalvsxwztc9ag=", 7 | "path": "github.com/labstack/echo", 8 | "revision": "069cddf05ab9a854fe601966de46762ff5efd569", 9 | "revisionTime": "2016-11-18T07:25:52Z" 10 | }, 11 | { 12 | "checksumSHA1": "R6DzcBLEP0BONPpsyr+11N7xh5w=", 13 | "path": "github.com/labstack/gommon/color", 14 | "revision": "9a43ff0d261e0e65594422e9eee08cf301aabbe7", 15 | "revisionTime": "2016-11-17T19:57:36Z" 16 | }, 17 | { 18 | "checksumSHA1": "E/VxZG1doV3Nf5jUygXtru2vP6g=", 19 | "path": "github.com/labstack/gommon/log", 20 | "revision": "9a43ff0d261e0e65594422e9eee08cf301aabbe7", 21 | "revisionTime": "2016-11-17T19:57:36Z" 22 | }, 23 | { 24 | "checksumSHA1": "I4njd26dG5hxFT2nawuByM4pxzY=", 25 | "path": "github.com/mattn/go-colorable", 26 | "revision": "d228849504861217f796da67fae4f6e347643f15", 27 | "revisionTime": "2016-11-03T16:00:40Z" 28 | }, 29 | { 30 | "checksumSHA1": "xZuhljnmBysJPta/lMyYmJdujCg=", 31 | "path": "github.com/mattn/go-isatty", 32 | "revision": "66b8e73f3f5cda9f96b69efd03dd3d7fc4a5cdb8", 33 | "revisionTime": "2016-08-06T12:27:52Z" 34 | }, 35 | { 36 | "checksumSHA1": "Ox0Iqm2T0qlNFleYiDYHMXDbkqg=", 37 | "path": "github.com/rsc/letsencrypt", 38 | "revision": "76104d26167d38b6a0010f42bfc8ec5487742e8b", 39 | "revisionTime": "2016-09-29T13:28:05Z" 40 | }, 41 | { 42 | "checksumSHA1": "9MBZGLtzg4VbsvcYLwm/6g9bB2M=", 43 | "path": "github.com/tylerb/graceful", 44 | "revision": "4df1190835320af7076dfcf27b3d071fd3612caf", 45 | "revisionTime": "2016-11-17T16:53:25Z" 46 | }, 47 | { 48 | "checksumSHA1": "PQy6kV2rK5B3qtCRpANzgRQPnFs=", 49 | "path": "github.com/valyala/fasttemplate", 50 | "revision": "3b874956e03f1636d171bda64b130f9135f42cff", 51 | "revisionTime": "2016-03-15T19:31:34Z" 52 | }, 53 | { 54 | "checksumSHA1": "dVgJf/okSqM79Y79+RH0fglgerA=", 55 | "origin": "github.com/rsc/letsencrypt/vendor/github.com/xenolf/lego/acme", 56 | "path": "github.com/xenolf/lego/acme", 57 | "revision": "76104d26167d38b6a0010f42bfc8ec5487742e8b", 58 | "revisionTime": "2016-09-29T13:28:05Z" 59 | }, 60 | { 61 | "checksumSHA1": "TJmmMKEHkGrmn+/39c9HiPpSQ3Q=", 62 | "path": "golang.org/x/crypto/ocsp", 63 | "revision": "9477e0b78b9ac3d0b03822fd95422e2fe07627cd", 64 | "revisionTime": "2016-10-31T15:37:30Z" 65 | }, 66 | { 67 | "checksumSHA1": "hKZGpbFuCrkE4s1vxubKK1aFlfI=", 68 | "path": "golang.org/x/net/context", 69 | "revision": "42ad50856d0131521b13983610e75c16da945ae3", 70 | "revisionTime": "2015-10-15T01:02:25Z" 71 | }, 72 | { 73 | "checksumSHA1": "eFQDEix/mGnhwnFu/Hq63zMfrX8=", 74 | "path": "golang.org/x/time/rate", 75 | "revision": "f51c12702a4d776e4c1fa9b0fabab841babae631", 76 | "revisionTime": "2016-10-28T04:02:39Z" 77 | }, 78 | { 79 | "checksumSHA1": "4FonadPMjBW33hDoyy+ZtBmU/bc=", 80 | "path": "gopkg.in/square/go-jose.v1", 81 | "revision": "aa2e30fdd1fe9dd3394119af66451ae790d50e0d", 82 | "revisionTime": "2016-09-23T00:08:11Z" 83 | }, 84 | { 85 | "checksumSHA1": "vSlztt3rfYwwDDKEiqUDWXl2LGw=", 86 | "path": "gopkg.in/square/go-jose.v1/cipher", 87 | "revision": "aa2e30fdd1fe9dd3394119af66451ae790d50e0d", 88 | "revisionTime": "2016-09-23T00:08:11Z" 89 | }, 90 | { 91 | "checksumSHA1": "UYvcpB3og7YJHbRu4feZFxXAU/A=", 92 | "path": "gopkg.in/square/go-jose.v1/json", 93 | "revision": "aa2e30fdd1fe9dd3394119af66451ae790d50e0d", 94 | "revisionTime": "2016-09-23T00:08:11Z" 95 | } 96 | ], 97 | "rootPath": "github.com/vsouza/go-graphql-subscription" 98 | } 99 | --------------------------------------------------------------------------------