summaryrefslogtreecommitdiff
path: root/vendor/github.com/SherClockHolmes/webpush-go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/SherClockHolmes/webpush-go')
-rw-r--r--vendor/github.com/SherClockHolmes/webpush-go/.gitignore4
-rw-r--r--vendor/github.com/SherClockHolmes/webpush-go/LICENSE21
-rw-r--r--vendor/github.com/SherClockHolmes/webpush-go/README.md63
-rw-r--r--vendor/github.com/SherClockHolmes/webpush-go/urgency.go26
-rw-r--r--vendor/github.com/SherClockHolmes/webpush-go/vapid.go118
-rw-r--r--vendor/github.com/SherClockHolmes/webpush-go/webpush.go286
6 files changed, 0 insertions, 518 deletions
diff --git a/vendor/github.com/SherClockHolmes/webpush-go/.gitignore b/vendor/github.com/SherClockHolmes/webpush-go/.gitignore
deleted file mode 100644
index 13b7c32ac..000000000
--- a/vendor/github.com/SherClockHolmes/webpush-go/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-vendor/**
-
-.DS_Store
-*.out
diff --git a/vendor/github.com/SherClockHolmes/webpush-go/LICENSE b/vendor/github.com/SherClockHolmes/webpush-go/LICENSE
deleted file mode 100644
index 161eac777..000000000
--- a/vendor/github.com/SherClockHolmes/webpush-go/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2016 Ethan Holmes
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/vendor/github.com/SherClockHolmes/webpush-go/README.md b/vendor/github.com/SherClockHolmes/webpush-go/README.md
deleted file mode 100644
index c313fc6b1..000000000
--- a/vendor/github.com/SherClockHolmes/webpush-go/README.md
+++ /dev/null
@@ -1,63 +0,0 @@
-# webpush-go
-
-[![Go Report Card](https://goreportcard.com/badge/github.com/SherClockHolmes/webpush-go)](https://goreportcard.com/report/github.com/SherClockHolmes/webpush-go)
-[![GoDoc](https://godoc.org/github.com/SherClockHolmes/webpush-go?status.svg)](https://godoc.org/github.com/SherClockHolmes/webpush-go)
-
-Web Push API Encryption with VAPID support.
-
-```bash
-go get -u github.com/SherClockHolmes/webpush-go
-```
-
-## Example
-
-For a full example, refer to the code in the [example](example/) directory.
-
-```go
-package main
-
-import (
- "encoding/json"
-
- webpush "github.com/SherClockHolmes/webpush-go"
-)
-
-func main() {
- // Decode subscription
- s := &webpush.Subscription{}
- json.Unmarshal([]byte("<YOUR_SUBSCRIPTION>"), s)
-
- // Send Notification
- resp, err := webpush.SendNotification([]byte("Test"), s, &webpush.Options{
- Subscriber: "example@example.com",
- VAPIDPublicKey: "<YOUR_VAPID_PUBLIC_KEY>",
- VAPIDPrivateKey: "<YOUR_VAPID_PRIVATE_KEY>",
- TTL: 30,
- })
- if err != nil {
- // TODO: Handle error
- }
- defer resp.Body.Close()
-}
-```
-
-### Generating VAPID Keys
-
-Use the helper method `GenerateVAPIDKeys` to generate the VAPID key pair.
-
-```golang
-privateKey, publicKey, err := webpush.GenerateVAPIDKeys()
-if err != nil {
- // TODO: Handle error
-}
-```
-
-## Development
-
-1. Install [Go 1.11+](https://golang.org/)
-2. `go mod vendor`
-3. `go test`
-
-#### For other language implementations visit:
-
-[WebPush Libs](https://github.com/web-push-libs)
diff --git a/vendor/github.com/SherClockHolmes/webpush-go/urgency.go b/vendor/github.com/SherClockHolmes/webpush-go/urgency.go
deleted file mode 100644
index 97c4a32b4..000000000
--- a/vendor/github.com/SherClockHolmes/webpush-go/urgency.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package webpush
-
-// Urgency indicates to the push service how important a message is to the user.
-// This can be used by the push service to help conserve the battery life of a user's device
-// by only waking up for important messages when battery is low.
-type Urgency string
-
-const (
- // UrgencyVeryLow requires device state: on power and Wi-Fi
- UrgencyVeryLow Urgency = "very-low"
- // UrgencyLow requires device state: on either power or Wi-Fi
- UrgencyLow Urgency = "low"
- // UrgencyNormal excludes device state: low battery
- UrgencyNormal Urgency = "normal"
- // UrgencyHigh admits device state: low battery
- UrgencyHigh Urgency = "high"
-)
-
-// Checking allowable values for the urgency header
-func isValidUrgency(urgency Urgency) bool {
- switch urgency {
- case UrgencyVeryLow, UrgencyLow, UrgencyNormal, UrgencyHigh:
- return true
- }
- return false
-}
diff --git a/vendor/github.com/SherClockHolmes/webpush-go/vapid.go b/vendor/github.com/SherClockHolmes/webpush-go/vapid.go
deleted file mode 100644
index d1c2a9154..000000000
--- a/vendor/github.com/SherClockHolmes/webpush-go/vapid.go
+++ /dev/null
@@ -1,118 +0,0 @@
-package webpush
-
-import (
- "crypto/ecdsa"
- "crypto/elliptic"
- "crypto/rand"
- "encoding/base64"
- "math/big"
- "net/url"
- "strings"
- "time"
-
- "github.com/golang-jwt/jwt/v5"
-)
-
-// GenerateVAPIDKeys will create a private and public VAPID key pair
-func GenerateVAPIDKeys() (privateKey, publicKey string, err error) {
- // Get the private key from the P256 curve
- curve := elliptic.P256()
-
- private, x, y, err := elliptic.GenerateKey(curve, rand.Reader)
- if err != nil {
- return
- }
-
- public := elliptic.Marshal(curve, x, y)
-
- // Convert to base64
- publicKey = base64.RawURLEncoding.EncodeToString(public)
- privateKey = base64.RawURLEncoding.EncodeToString(private)
-
- return
-}
-
-// Generates the ECDSA public and private keys for the JWT encryption
-func generateVAPIDHeaderKeys(privateKey []byte) *ecdsa.PrivateKey {
- // Public key
- curve := elliptic.P256()
- px, py := curve.ScalarMult(
- curve.Params().Gx,
- curve.Params().Gy,
- privateKey,
- )
-
- pubKey := ecdsa.PublicKey{
- Curve: curve,
- X: px,
- Y: py,
- }
-
- // Private key
- d := &big.Int{}
- d.SetBytes(privateKey)
-
- return &ecdsa.PrivateKey{
- PublicKey: pubKey,
- D: d,
- }
-}
-
-// getVAPIDAuthorizationHeader
-func getVAPIDAuthorizationHeader(
- endpoint,
- subscriber,
- vapidPublicKey,
- vapidPrivateKey string,
- expiration time.Time,
-) (string, error) {
- // Create the JWT token
- subURL, err := url.Parse(endpoint)
- if err != nil {
- return "", err
- }
-
- // Unless subscriber is an HTTPS URL, assume an e-mail address
- if !strings.HasPrefix(subscriber, "https:") {
- subscriber = "mailto:" + subscriber
- }
-
- token := jwt.NewWithClaims(jwt.SigningMethodES256, jwt.MapClaims{
- "aud": subURL.Scheme + "://" + subURL.Host,
- "exp": time.Now().Add(time.Hour * 12).Unix(),
- "sub": subscriber,
- })
-
- // Decode the VAPID private key
- decodedVapidPrivateKey, err := decodeVapidKey(vapidPrivateKey)
- if err != nil {
- return "", err
- }
-
- privKey := generateVAPIDHeaderKeys(decodedVapidPrivateKey)
-
- // Sign token with private key
- jwtString, err := token.SignedString(privKey)
- if err != nil {
- return "", err
- }
-
- // Decode the VAPID public key
- pubKey, err := decodeVapidKey(vapidPublicKey)
- if err != nil {
- return "", err
- }
-
- return "vapid t=" + jwtString + ", k=" + base64.RawURLEncoding.EncodeToString(pubKey), nil
-}
-
-// Need to decode the vapid private key in multiple base64 formats
-// Solution from: https://github.com/SherClockHolmes/webpush-go/issues/29
-func decodeVapidKey(key string) ([]byte, error) {
- bytes, err := base64.URLEncoding.DecodeString(key)
- if err == nil {
- return bytes, nil
- }
-
- return base64.RawURLEncoding.DecodeString(key)
-}
diff --git a/vendor/github.com/SherClockHolmes/webpush-go/webpush.go b/vendor/github.com/SherClockHolmes/webpush-go/webpush.go
deleted file mode 100644
index a6ee7cd0c..000000000
--- a/vendor/github.com/SherClockHolmes/webpush-go/webpush.go
+++ /dev/null
@@ -1,286 +0,0 @@
-package webpush
-
-import (
- "bytes"
- "context"
- "crypto/aes"
- "crypto/cipher"
- "crypto/elliptic"
- "crypto/rand"
- "crypto/sha256"
- "encoding/base64"
- "encoding/binary"
- "errors"
- "io"
- "net/http"
- "strconv"
- "strings"
- "time"
-
- "golang.org/x/crypto/hkdf"
-)
-
-const MaxRecordSize uint32 = 4096
-
-var ErrMaxPadExceeded = errors.New("payload has exceeded the maximum length")
-
-// saltFunc generates a salt of 16 bytes
-var saltFunc = func() ([]byte, error) {
- salt := make([]byte, 16)
- _, err := io.ReadFull(rand.Reader, salt)
- if err != nil {
- return salt, err
- }
-
- return salt, nil
-}
-
-// HTTPClient is an interface for sending the notification HTTP request / testing
-type HTTPClient interface {
- Do(*http.Request) (*http.Response, error)
-}
-
-// Options are config and extra params needed to send a notification
-type Options struct {
- HTTPClient HTTPClient // Will replace with *http.Client by default if not included
- RecordSize uint32 // Limit the record size
- Subscriber string // Sub in VAPID JWT token
- Topic string // Set the Topic header to collapse a pending messages (Optional)
- TTL int // Set the TTL on the endpoint POST request
- Urgency Urgency // Set the Urgency header to change a message priority (Optional)
- VAPIDPublicKey string // VAPID public key, passed in VAPID Authorization header
- VAPIDPrivateKey string // VAPID private key, used to sign VAPID JWT token
- VapidExpiration time.Time // optional expiration for VAPID JWT token (defaults to now + 12 hours)
-}
-
-// Keys are the base64 encoded values from PushSubscription.getKey()
-type Keys struct {
- Auth string `json:"auth"`
- P256dh string `json:"p256dh"`
-}
-
-// Subscription represents a PushSubscription object from the Push API
-type Subscription struct {
- Endpoint string `json:"endpoint"`
- Keys Keys `json:"keys"`
-}
-
-// SendNotification calls SendNotificationWithContext with default context for backwards-compatibility
-func SendNotification(message []byte, s *Subscription, options *Options) (*http.Response, error) {
- return SendNotificationWithContext(context.Background(), message, s, options)
-}
-
-// SendNotificationWithContext sends a push notification to a subscription's endpoint
-// Message Encryption for Web Push, and VAPID protocols.
-// FOR MORE INFORMATION SEE RFC8291: https://datatracker.ietf.org/doc/rfc8291
-func SendNotificationWithContext(ctx context.Context, message []byte, s *Subscription, options *Options) (*http.Response, error) {
- // Authentication secret (auth_secret)
- authSecret, err := decodeSubscriptionKey(s.Keys.Auth)
- if err != nil {
- return nil, err
- }
-
- // dh (Diffie Hellman)
- dh, err := decodeSubscriptionKey(s.Keys.P256dh)
- if err != nil {
- return nil, err
- }
-
- // Generate 16 byte salt
- salt, err := saltFunc()
- if err != nil {
- return nil, err
- }
-
- // Create the ecdh_secret shared key pair
- curve := elliptic.P256()
-
- // Application server key pairs (single use)
- localPrivateKey, x, y, err := elliptic.GenerateKey(curve, rand.Reader)
- if err != nil {
- return nil, err
- }
-
- localPublicKey := elliptic.Marshal(curve, x, y)
-
- // Combine application keys with receiver's EC public key
- sharedX, sharedY := elliptic.Unmarshal(curve, dh)
- if sharedX == nil {
- return nil, errors.New("Unmarshal Error: Public key is not a valid point on the curve")
- }
-
- // Derive ECDH shared secret
- sx, sy := curve.ScalarMult(sharedX, sharedY, localPrivateKey)
- if !curve.IsOnCurve(sx, sy) {
- return nil, errors.New("Encryption error: ECDH shared secret isn't on curve")
- }
- mlen := curve.Params().BitSize / 8
- sharedECDHSecret := make([]byte, mlen)
- sx.FillBytes(sharedECDHSecret)
-
- hash := sha256.New
-
- // ikm
- prkInfoBuf := bytes.NewBuffer([]byte("WebPush: info\x00"))
- prkInfoBuf.Write(dh)
- prkInfoBuf.Write(localPublicKey)
-
- prkHKDF := hkdf.New(hash, sharedECDHSecret, authSecret, prkInfoBuf.Bytes())
- ikm, err := getHKDFKey(prkHKDF, 32)
- if err != nil {
- return nil, err
- }
-
- // Derive Content Encryption Key
- contentEncryptionKeyInfo := []byte("Content-Encoding: aes128gcm\x00")
- contentHKDF := hkdf.New(hash, ikm, salt, contentEncryptionKeyInfo)
- contentEncryptionKey, err := getHKDFKey(contentHKDF, 16)
- if err != nil {
- return nil, err
- }
-
- // Derive the Nonce
- nonceInfo := []byte("Content-Encoding: nonce\x00")
- nonceHKDF := hkdf.New(hash, ikm, salt, nonceInfo)
- nonce, err := getHKDFKey(nonceHKDF, 12)
- if err != nil {
- return nil, err
- }
-
- // Cipher
- c, err := aes.NewCipher(contentEncryptionKey)
- if err != nil {
- return nil, err
- }
-
- gcm, err := cipher.NewGCM(c)
- if err != nil {
- return nil, err
- }
-
- // Get the record size
- recordSize := options.RecordSize
- if recordSize == 0 {
- recordSize = MaxRecordSize
- }
-
- recordLength := int(recordSize) - 16
-
- // Encryption Content-Coding Header
- recordBuf := bytes.NewBuffer(salt)
-
- rs := make([]byte, 4)
- binary.BigEndian.PutUint32(rs, recordSize)
-
- recordBuf.Write(rs)
- recordBuf.Write([]byte{byte(len(localPublicKey))})
- recordBuf.Write(localPublicKey)
-
- // Data
- dataBuf := bytes.NewBuffer(message)
-
- // Pad content to max record size - 16 - header
- // Padding ending delimeter
- dataBuf.Write([]byte("\x02"))
- if err := pad(dataBuf, recordLength-recordBuf.Len()); err != nil {
- return nil, err
- }
-
- // Compose the ciphertext
- ciphertext := gcm.Seal([]byte{}, nonce, dataBuf.Bytes(), nil)
- recordBuf.Write(ciphertext)
-
- // POST request
- req, err := http.NewRequest("POST", s.Endpoint, recordBuf)
- if err != nil {
- return nil, err
- }
-
- if ctx != nil {
- req = req.WithContext(ctx)
- }
-
- req.Header.Set("Content-Encoding", "aes128gcm")
- req.Header.Set("Content-Type", "application/octet-stream")
- req.Header.Set("TTL", strconv.Itoa(options.TTL))
-
- // Сheck the optional headers
- if len(options.Topic) > 0 {
- req.Header.Set("Topic", options.Topic)
- }
-
- if isValidUrgency(options.Urgency) {
- req.Header.Set("Urgency", string(options.Urgency))
- }
-
- expiration := options.VapidExpiration
- if expiration.IsZero() {
- expiration = time.Now().Add(time.Hour * 12)
- }
-
- // Get VAPID Authorization header
- vapidAuthHeader, err := getVAPIDAuthorizationHeader(
- s.Endpoint,
- options.Subscriber,
- options.VAPIDPublicKey,
- options.VAPIDPrivateKey,
- expiration,
- )
- if err != nil {
- return nil, err
- }
-
- req.Header.Set("Authorization", vapidAuthHeader)
-
- // Send the request
- var client HTTPClient
- if options.HTTPClient != nil {
- client = options.HTTPClient
- } else {
- client = &http.Client{}
- }
-
- return client.Do(req)
-}
-
-// decodeSubscriptionKey decodes a base64 subscription key.
-// if necessary, add "=" padding to the key for URL decode
-func decodeSubscriptionKey(key string) ([]byte, error) {
- // "=" padding
- buf := bytes.NewBufferString(key)
- if rem := len(key) % 4; rem != 0 {
- buf.WriteString(strings.Repeat("=", 4-rem))
- }
-
- bytes, err := base64.StdEncoding.DecodeString(buf.String())
- if err == nil {
- return bytes, nil
- }
-
- return base64.URLEncoding.DecodeString(buf.String())
-}
-
-// Returns a key of length "length" given an hkdf function
-func getHKDFKey(hkdf io.Reader, length int) ([]byte, error) {
- key := make([]byte, length)
- n, err := io.ReadFull(hkdf, key)
- if n != len(key) || err != nil {
- return key, err
- }
-
- return key, nil
-}
-
-func pad(payload *bytes.Buffer, maxPadLen int) error {
- payloadLen := payload.Len()
- if payloadLen > maxPadLen {
- return ErrMaxPadExceeded
- }
-
- padLen := maxPadLen - payloadLen
-
- padding := make([]byte, padLen)
- payload.Write(padding)
-
- return nil
-}