From 031fe1ac5e24227daac611989614f63b460bacf8 Mon Sep 17 00:00:00 2001 From: Xuu Date: Sat, 17 Oct 2020 10:32:03 -0600 Subject: [PATCH] initial work on openpgp key --- Makefile | 2 +- debian/Makefile | 4 +- go.mod | 2 + go.sum | 5 ++ src/routes/shorturl.go | 107 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 117 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index b36584c..b4909ed 100644 --- a/Makefile +++ b/Makefile @@ -30,7 +30,7 @@ fmt: test: $(ROUTE_ASSET) $(DOCS_ASSET) go test ./... go vet ./... -run: $(BINARY) +run: go run \ -ldflags "-X main.AppVersion=$(VERSION_PAT) -X main.AppBuild=$(DATE)" \ $(PKG) -vv serve diff --git a/debian/Makefile b/debian/Makefile index 7525d5f..6e7b660 100644 --- a/debian/Makefile +++ b/debian/Makefile @@ -25,8 +25,8 @@ build: export BUILD="BUILD/$(NAME)_$(VERSION)"; \ env GOOS=linux GOARCH=amd64 go build -v -o $${BUILD}/opt/sour.is/bin/paste \ -ldflags "-X main.AppVersion=$(VERSION) -X main.AppBuild=$(DATE)"\ - sour.is/x/paste/cmd/paste; \ - dpkg -b $${BUILD}; + sour.is/x/paste/cmd/paste && \ + dpkg -b $${BUILD} copy: export BUILD="BUILD/$(NAME)_$(VERSION)"; \ diff --git a/go.mod b/go.mod index a2f9a94..eb25b76 100644 --- a/go.mod +++ b/go.mod @@ -13,8 +13,10 @@ require ( github.com/gorilla/mux v1.8.0 github.com/h2non/filetype v1.1.0 github.com/remyoudompheng/go-liblzma v0.0.0-20190506200333-81bf2d431b96 + github.com/sour-is/crypto v0.0.0-20201016232853-f42a24ba5a81 github.com/sour-is/go-assetfs v1.0.0 github.com/spf13/viper v1.7.1 + github.com/tv42/zbase32 v0.0.0-20190604154422-aacc64a8f915 github.com/vektah/dataloaden v0.3.0 go.etcd.io/bbolt v1.3.5 // indirect golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a diff --git a/go.sum b/go.sum index 2311a7b..cd7c026 100644 --- a/go.sum +++ b/go.sum @@ -435,6 +435,8 @@ github.com/smartystreets/goconvey v0.0.0-20170602164621-9e8dc3f972df/go.mod h1:X github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sour-is/crypto v0.0.0-20201016232853-f42a24ba5a81 h1:7LadZJfye3tq1Dr5c46uy1ign6mQr2bAOlCJeAXpB1A= +github.com/sour-is/crypto v0.0.0-20201016232853-f42a24ba5a81/go.mod h1:7/Of5cnNodFyJ6PH2C3STkdCRvqbhj9yA3BhQ/E62wA= github.com/sour-is/go-assetfs v1.0.0 h1:84Fd12qIAdZUOKjYIgsA1J27fcQF/JiSgiflz+2hqEA= github.com/sour-is/go-assetfs v1.0.0/go.mod h1:y4ShXMTRymi5OMvwbtfT3sxcRE72sx1ycYymT46JbRE= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= @@ -484,6 +486,8 @@ github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhV github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/toqueteos/webbrowser v1.2.0 h1:tVP/gpK69Fx+qMJKsLE7TD8LuGWPnEV71wBN9rrstGQ= github.com/toqueteos/webbrowser v1.2.0/go.mod h1:XWoZq4cyp9WeUeak7w7LXRUQf1F1ATJMir8RTqb4ayM= +github.com/tv42/zbase32 v0.0.0-20190604154422-aacc64a8f915 h1:vX9DBbEHmrebYnVthUTzMO6Zc1vvConJdD2s0uvXrfw= +github.com/tv42/zbase32 v0.0.0-20190604154422-aacc64a8f915/go.mod h1:Y5DJgF9Eou+hSWetC39Mns8E0PU7DykCLNWiYeOINrE= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= @@ -534,6 +538,7 @@ golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899 h1:DZhuSZLsGlFL4CmhA8BcRA0mnthyA/nZ00AqCUo7vHg= golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= diff --git a/src/routes/shorturl.go b/src/routes/shorturl.go index 756ea25..3877cd3 100644 --- a/src/routes/shorturl.go +++ b/src/routes/shorturl.go @@ -2,13 +2,21 @@ package routes import ( "bytes" + "crypto/sha1" "encoding/json" + "fmt" + "io" "net/http" + "net/mail" "net/url" "regexp" + "strings" "github.com/coreos/bbolt" "github.com/gorilla/mux" + "github.com/sour-is/crypto/openpgp" + "github.com/tv42/zbase32" + "sour.is/x/toolbox/httpsrv" "sour.is/x/toolbox/log" "sour.is/x/toolbox/uuid" @@ -21,6 +29,7 @@ func init() { httpsrv.HttpRegister("short", httpsrv.HttpRoutes{ {Name: "getShort", Method: "GET", Pattern: "/s/{id}", HandlerFunc: s.getShort}, {Name: "putShort", Method: "PUT", Pattern: "/s/{id}", HandlerFunc: s.putShort}, + {Name: "getIdentity", Method: "GET", Pattern: "/id/{id}", HandlerFunc: s.getIdentity}, }) } @@ -190,3 +199,101 @@ func (s *shortDB) PutURL(id string, url *shortURL) { log.Errorf("ShortURL: failed to write db at [%s]", s.path) } } + +func (s *shortDB) getIdentity(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + + id := vars["id"] + + useArmored := false + addr := "" + + if isFingerprint(id) { + addr = "https://keys.openpgp.org/vks/v1/by-fingerprint/" + strings.ToUpper(id) + useArmored = true + } else if email, err := mail.ParseAddress(id); err == nil { + addr = getWKDPubKeyAddr(email) + useArmored = false + } else { + httpsrv.WriteError(w, 400, err.Error()) + return + } + + resp, err := http.Get(addr) + if err != nil { + print(err) + } + + defer resp.Body.Close() + + if resp.Header.Get("Content-Type") == "application/pgp-keys" { + useArmored = true + } + log.Infos("getIdentity", "id", id, "useArmored", useArmored, "status", resp.Status, "addr", addr) + + var lis openpgp.EntityList + if useArmored { + lis, err = openpgp.ReadArmoredKeyRing(resp.Body) + } else { + lis, err = openpgp.ReadKeyRing(resp.Body) + } + if err != nil { + fmt.Println(err) + httpsrv.WriteError(w, 400, "bad decode") + return + } + + for _, entity := range lis { + entityString(w, entity) + } +} + +func isFingerprint(s string) bool { + for _, r := range s { + switch r { + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F': + default: + return false + } + } + + return true +} + +func entityString(out io.Writer, e *openpgp.Entity) { + if e == nil { + return + } + + if e.Identities != nil { + fmt.Fprintln(out, "Identities:") + for name, identity := range e.Identities { + fmt.Fprintf(out, " %s:\n", name) + identityString(out, identity) + fmt.Fprintln(out) + } + } +} + +func identityString(out io.Writer, i *openpgp.Identity) { + if i == nil || i.SelfSignature == nil { + return + } + + fmt.Fprintf(out, "name: %s\n", i.Name) + + for key, valueList := range i.SelfSignature.NotationData { + for _, value := range valueList { + fmt.Fprintln(out, " ", key, value) + } + } +} + +func getWKDPubKeyAddr(email *mail.Address) string { + parts := strings.SplitN(email.Address, "@", 2) + + hash := sha1.Sum([]byte(parts[0])) + lp := zbase32.EncodeToString(hash[:]) + + return fmt.Sprintf("https://%s/.well-known/openpgpkey/hu/%s", parts[1], lp) +}