From 7e1bf702ccbd6282a781c4f5e16359a045c8125d Mon Sep 17 00:00:00 2001 From: Ted Unangst Date: Sun, 28 Jul 2019 19:44:27 -0400 Subject: [PATCH] switch to common version of httpsig code --- activity.go | 3 +- fun.go | 9 ++- go.mod | 2 +- go.sum | 2 + honk.go | 3 +- util.go | 5 +- zig.go | 207 ---------------------------------------------------- 7 files changed, 15 insertions(+), 216 deletions(-) delete mode 100644 zig.go diff --git a/activity.go b/activity.go index 1a75d82..9e46458 100644 --- a/activity.go +++ b/activity.go @@ -32,6 +32,7 @@ import ( "sync" "time" + "humungus.tedunangst.com/r/webs/httpsig" "humungus.tedunangst.com/r/webs/image" "humungus.tedunangst.com/r/webs/junk" ) @@ -69,7 +70,7 @@ func PostMsg(keyname string, key *rsa.PrivateKey, url string, msg []byte) error } req.Header.Set("User-Agent", "honksnonk/5.0; "+serverName) req.Header.Set("Content-Type", theonetruename) - zig(keyname, key, req, msg) + httpsig.SignRequest(keyname, key, req, msg) resp, err := client.Do(req) if err != nil { return err diff --git a/fun.go b/fun.go index 9a9a198..1c72b45 100644 --- a/fun.go +++ b/fun.go @@ -29,6 +29,7 @@ import ( "sync" "humungus.tedunangst.com/r/webs/htfilter" + "humungus.tedunangst.com/r/webs/httpsig" ) func reverbolate(userid int64, honks []*Honk) { @@ -429,7 +430,7 @@ func ziggy(username string) (keyname string, key *rsa.PrivateKey) { var data string row.Scan(&data) var err error - key, _, err = pez(data) + key, _, err = httpsig.DecodeKey(data) if err != nil { log.Printf("error decoding %s seckey: %s", username, err) return @@ -473,7 +474,7 @@ func zaggy(keyname string) (key *rsa.PublicKey) { log.Printf("error finding %s pubkey owner", keyname) return } - _, key, err = pez(data) + _, key, err = httpsig.DecodeKey(data) if err != nil { log.Printf("error decoding %s pubkey: %s", keyname, err) return @@ -483,7 +484,7 @@ func zaggy(keyname string) (key *rsa.PublicKey) { log.Printf("error saving key: %s", err) } } else { - _, key, err = pez(data) + _, key, err = httpsig.DecodeKey(data) if err != nil { log.Printf("error decoding %s pubkey: %s", keyname, err) return @@ -503,7 +504,7 @@ func makeitworksomehowwithoutregardforkeycontinuity(keyname string, r *http.Requ ziggylock.Lock() delete(zaggies, keyname) ziggylock.Unlock() - return zag(r, payload) + return httpsig.VerifyRequest(r, payload, zaggy) } var thumbbiters map[int64]map[string]bool diff --git a/go.mod b/go.mod index de6a9b8..540ba2c 100644 --- a/go.mod +++ b/go.mod @@ -7,5 +7,5 @@ require ( golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4 golang.org/x/net v0.0.0-20190620200207-3b0461eec859 humungus.tedunangst.com/r/go-sqlite3 v1.1.3 - humungus.tedunangst.com/r/webs v0.5.6 + humungus.tedunangst.com/r/webs v0.6.0 ) diff --git a/go.sum b/go.sum index 04cd712..8380248 100644 --- a/go.sum +++ b/go.sum @@ -23,3 +23,5 @@ humungus.tedunangst.com/r/go-sqlite3 v1.1.3 h1:G2N4wzDS0NbuvrZtQJhh4F+3X+s7BF8b9 humungus.tedunangst.com/r/go-sqlite3 v1.1.3/go.mod h1:FtEEmQM7U2Ey1TuEEOyY1BmphTZnmiEjPsNLEAkpf/M= humungus.tedunangst.com/r/webs v0.5.6 h1:QY6VpWP+5Urys3bM8thtDjieoprhSUfHIMhvhiljhvY= humungus.tedunangst.com/r/webs v0.5.6/go.mod h1:Ho+nmafD/aUWF7LnH+Yl2/b0ob7f2pCkXm4onteWvLE= +humungus.tedunangst.com/r/webs v0.6.0 h1:EAd08IqS8qwzPBqDUNRZbHPdbm0cs7FnXbCWeYHYFiY= +humungus.tedunangst.com/r/webs v0.6.0/go.mod h1:Ho+nmafD/aUWF7LnH+Yl2/b0ob7f2pCkXm4onteWvLE= diff --git a/honk.go b/honk.go index 94fe1f2..c2dddb9 100644 --- a/honk.go +++ b/honk.go @@ -34,6 +34,7 @@ import ( "github.com/gorilla/mux" "humungus.tedunangst.com/r/webs/htfilter" + "humungus.tedunangst.com/r/webs/httpsig" "humungus.tedunangst.com/r/webs/image" "humungus.tedunangst.com/r/webs/junk" "humungus.tedunangst.com/r/webs/login" @@ -339,7 +340,7 @@ func inbox(w http.ResponseWriter, r *http.Request) { if crappola(j) { return } - keyname, err := zag(r, payload) + keyname, err := httpsig.VerifyRequest(r, payload, zaggy) if err != nil { log.Printf("inbox message failed signature: %s", err) if keyname != "" { diff --git a/util.go b/util.go index 0700eac..2a509a3 100644 --- a/util.go +++ b/util.go @@ -48,6 +48,7 @@ import ( "golang.org/x/crypto/bcrypt" _ "humungus.tedunangst.com/r/go-sqlite3" + "humungus.tedunangst.com/r/webs/httpsig" ) var savedstyleparams = make(map[string]string) @@ -223,11 +224,11 @@ func createuser(db *sql.DB, r *bufio.Reader) error { if err != nil { return err } - pubkey, err := zem(&k.PublicKey) + pubkey, err := httpsig.EncodeKey(&k.PublicKey) if err != nil { return err } - seckey, err := zem(k) + seckey, err := httpsig.EncodeKey(k) if err != nil { return err } diff --git a/zig.go b/zig.go deleted file mode 100644 index 064c143..0000000 --- a/zig.go +++ /dev/null @@ -1,207 +0,0 @@ -// -// Copyright (c) 2019 Ted Unangst -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -package main - -import ( - "bytes" - "crypto" - "crypto/rand" - "crypto/rsa" - "crypto/sha256" - "crypto/x509" - "encoding/base64" - "encoding/pem" - "fmt" - "io" - "log" - "net/http" - "regexp" - "strings" - "time" -) - -func sb64(data []byte) string { - var sb strings.Builder - b64 := base64.NewEncoder(base64.StdEncoding, &sb) - b64.Write(data) - b64.Close() - return sb.String() - -} -func b64s(s string) []byte { - var buf bytes.Buffer - b64 := base64.NewDecoder(base64.StdEncoding, strings.NewReader(s)) - io.Copy(&buf, b64) - return buf.Bytes() -} -func sb64sha256(content []byte) string { - h := sha256.New() - h.Write(content) - return sb64(h.Sum(nil)) -} - -func zig(keyname string, key *rsa.PrivateKey, req *http.Request, content []byte) { - headers := []string{"(request-target)", "date", "host", "content-type", "digest"} - var stuff []string - for _, h := range headers { - var s string - switch h { - case "(request-target)": - s = strings.ToLower(req.Method) + " " + req.URL.RequestURI() - case "date": - s = req.Header.Get(h) - if s == "" { - s = time.Now().UTC().Format(http.TimeFormat) - req.Header.Set(h, s) - } - case "host": - s = req.Header.Get(h) - if s == "" { - s = req.URL.Hostname() - req.Header.Set(h, s) - } - case "content-type": - s = req.Header.Get(h) - case "digest": - s = req.Header.Get(h) - if s == "" { - s = "SHA-256=" + sb64sha256(content) - req.Header.Set(h, s) - } - } - stuff = append(stuff, h+": "+s) - } - - h := sha256.New() - h.Write([]byte(strings.Join(stuff, "\n"))) - sig, _ := rsa.SignPKCS1v15(rand.Reader, key, crypto.SHA256, h.Sum(nil)) - bsig := sb64(sig) - - sighdr := fmt.Sprintf(`keyId="%s",algorithm="%s",headers="%s",signature="%s"`, - keyname, "rsa-sha256", strings.Join(headers, " "), bsig) - req.Header.Set("Signature", sighdr) -} - -var re_sighdrval = regexp.MustCompile(`(.*)="(.*)"`) - -func zag(req *http.Request, content []byte) (string, error) { - sighdr := req.Header.Get("Signature") - - var keyname, algo, heads, bsig string - for _, v := range strings.Split(sighdr, ",") { - m := re_sighdrval.FindStringSubmatch(v) - if len(m) != 3 { - return "", fmt.Errorf("bad scan: %s from %s\n", v, sighdr) - } - switch m[1] { - case "keyId": - keyname = m[2] - case "algorithm": - algo = m[2] - case "headers": - heads = m[2] - case "signature": - bsig = m[2] - default: - return "", fmt.Errorf("bad sig val: %s", m[1]) - } - } - if keyname == "" || algo == "" || heads == "" || bsig == "" { - return "", fmt.Errorf("missing a sig value") - } - - key := zaggy(keyname) - if key == nil { - return keyname, fmt.Errorf("no key for %s", keyname) - } - headers := strings.Split(heads, " ") - var stuff []string - for _, h := range headers { - var s string - switch h { - case "(request-target)": - s = strings.ToLower(req.Method) + " " + req.URL.RequestURI() - case "host": - s = req.Host - if s != serverName { - log.Printf("caution: servername host header mismatch") - } - case "digest": - s = req.Header.Get(h) - expv := "SHA-256=" + sb64sha256(content) - if s != expv { - return "", fmt.Errorf("digest header '%s' did not match content", s) - } - default: - s = req.Header.Get(h) - } - stuff = append(stuff, h+": "+s) - } - - h := sha256.New() - h.Write([]byte(strings.Join(stuff, "\n"))) - sig := b64s(bsig) - err := rsa.VerifyPKCS1v15(key, crypto.SHA256, h.Sum(nil), sig) - if err != nil { - return keyname, err - } - return keyname, nil -} - -func pez(s string) (pri *rsa.PrivateKey, pub *rsa.PublicKey, err error) { - block, _ := pem.Decode([]byte(s)) - if block == nil { - err = fmt.Errorf("no pem data") - return - } - switch block.Type { - case "PUBLIC KEY": - var k interface{} - k, err = x509.ParsePKIXPublicKey(block.Bytes) - if k != nil { - pub, _ = k.(*rsa.PublicKey) - } - case "RSA PUBLIC KEY": - pub, err = x509.ParsePKCS1PublicKey(block.Bytes) - case "RSA PRIVATE KEY": - pri, err = x509.ParsePKCS1PrivateKey(block.Bytes) - if err == nil { - pub = &pri.PublicKey - } - default: - err = fmt.Errorf("unknown key type") - } - return -} - -func zem(i interface{}) (string, error) { - var b pem.Block - var err error - switch k := i.(type) { - case *rsa.PrivateKey: - b.Type = "RSA PRIVATE KEY" - b.Bytes = x509.MarshalPKCS1PrivateKey(k) - case *rsa.PublicKey: - b.Type = "PUBLIC KEY" - b.Bytes, err = x509.MarshalPKIXPublicKey(k) - default: - err = fmt.Errorf("unknown key type: %s", k) - } - if err != nil { - return "", err - } - return string(pem.EncodeToMemory(&b)), nil -}