├── .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) [](http://godoc.org/github.com/labstack/echo) [](https://raw.githubusercontent.com/labstack/echo/master/LICENSE) [](https://travis-ci.org/labstack/echo) [](https://coveralls.io/r/labstack/echo) [](https://gitter.im/labstack/echo) [](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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
11 |
12 |
13 | ## So Good!
14 |
15 | 
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 [](http://godoc.org/github.com/tylerb/graceful) [](https://travis-ci.org/tylerb/graceful) [](https://coveralls.io/r/tylerb/graceful) [](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 | [](https://godoc.org/gopkg.in/square/go-jose.v1) [](https://raw.githubusercontent.com/square/go-jose/master/LICENSE)
4 | [](https://github.com/square/go-jose/releases)
5 | [](https://travis-ci.org/square/go-jose)
6 | [](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 |
--------------------------------------------------------------------------------