aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFChannel0 <77419041+FChannel0@users.noreply.github.com>2021-07-03 16:17:46 -0700
committerGitHub <noreply@github.com>2021-07-03 16:17:46 -0700
commitab6edbbe8044d5a3c7d9456bd15e3a74af35111a (patch)
treeb45a5860c9a8e89071324ab980316054e1030695
parenta3f45e6a5cb85a43364756bd28a14936d1d95ae7 (diff)
parentd9cce000fdc8d804e73ff2fa4bfd2f1a151d90d9 (diff)
Merge pull request #35 from the-sageman/pem-failsafe
In case the PEM key is missing, do not fail too hard.
-rw-r--r--database.go46
-rw-r--r--main.go6
-rw-r--r--verification.go103
3 files changed, 122 insertions, 33 deletions
diff --git a/database.go b/database.go
index 6a871ba..baae16a 100644
--- a/database.go
+++ b/database.go
@@ -1,12 +1,15 @@
package main
-import "fmt"
-import "database/sql"
-import _ "github.com/lib/pq"
-import "time"
-import "os"
-import "strings"
-import "sort"
+import (
+ "database/sql"
+ "fmt"
+ "os"
+ "sort"
+ "strings"
+ "time"
+
+ _ "github.com/lib/pq"
+)
func GetActorFromDB(db *sql.DB, id string) Actor {
var nActor Actor
@@ -27,6 +30,10 @@ func GetActorFromDB(db *sql.DB, id string) Actor {
}
nActor.PublicKey = GetActorPemFromDB(db, publicKeyPem)
+ if nActor.PublicKey.PublicKeyPem == ""{
+ err = CreatePublicKeyFromPrivate(db, &nActor, publicKeyPem)
+ CheckError(err, "error creating public key from private")
+ }
return nActor
}
@@ -50,6 +57,10 @@ func GetActorByNameFromDB(db *sql.DB, name string) Actor {
}
nActor.PublicKey = GetActorPemFromDB(db, publicKeyPem)
+ if nActor.PublicKey.PublicKeyPem == ""{
+ err = CreatePublicKeyFromPrivate(db, &nActor, publicKeyPem)
+ CheckError(err, "error creating public key from private")
+ }
return nActor
}
@@ -1470,13 +1481,32 @@ func GetActorPemFromDB(db *sql.DB, pemID string) PublicKeyPem {
defer rows.Close()
rows.Next()
rows.Scan(&pem.Id, &pem.Owner, &pem.PublicKeyPem)
- f, _ := os.ReadFile(pem.PublicKeyPem)
+ f, err := os.ReadFile(pem.PublicKeyPem)
+ if err != nil{
+ pem.PublicKeyPem = ""
+ return pem
+ }
pem.PublicKeyPem = strings.ReplaceAll(string(f), "\r\n", `\n`)
return pem
}
+func GetActorPemFileFromDB(db *sql.DB, pemID string) string{
+ query := `select file from publickeypem where id=$1`
+ rows, err := db.Query(query, pemID)
+
+ CheckError(err, "could not get public key filename from database")
+
+ var file string
+
+ defer rows.Close()
+ rows.Next()
+ rows.Scan(&file)
+
+ return file
+}
+
func MarkObjectSensitive(db *sql.DB, id string, sensitive bool) {
var query = `update activitystream set sensitive=$1 where id=$2`
_, err := db.Exec(query, sensitive, id)
diff --git a/main.go b/main.go
index f98add9..7a30721 100644
--- a/main.go
+++ b/main.go
@@ -1899,7 +1899,8 @@ func MakeActivityRequestOutbox(db *sql.DB, activity Activity) {
path = re.ReplaceAllString(path, "")
sig := fmt.Sprintf("(request-target): %s %s\nhost: %s\ndate: %s", "post", path, instance, date)
- encSig := ActivitySign(db, *activity.Actor, sig)
+ encSig, err := ActivitySign(db, *activity.Actor, sig)
+ CheckError(err, "unable to sign activity response")
signature := fmt.Sprintf("keyId=\"%s\",headers=\"(request-target) host date\",signature=\"%s\"", activity.Actor.PublicKey.Id, encSig)
req.Header.Set("Content-Type", activitystreams)
@@ -1937,7 +1938,8 @@ func MakeActivityRequest(db *sql.DB, activity Activity) {
path = re.ReplaceAllString(path, "")
sig := fmt.Sprintf("(request-target): %s %s\nhost: %s\ndate: %s", "post", path, instance, date)
- encSig := ActivitySign(db, *activity.Actor, sig)
+ encSig, err := ActivitySign(db, *activity.Actor, sig)
+ CheckError(err, "unable to sign activity response")
signature := fmt.Sprintf("keyId=\"%s\",headers=\"(request-target) host date\",signature=\"%s\"", activity.Actor.PublicKey.Id, encSig)
req.Header.Set("Content-Type", activitystreams)
diff --git a/verification.go b/verification.go
index c649a4e..1e9c50e 100644
--- a/verification.go
+++ b/verification.go
@@ -1,24 +1,30 @@
package main
-import "fmt"
-import "database/sql"
-import _ "github.com/lib/pq"
-import "net/smtp"
-import "time"
-import "os/exec"
-import "os"
-import "math/rand"
-import "crypto"
-import "crypto/rsa"
-import "crypto/x509"
-import "crypto/sha256"
-import "encoding/pem"
-import "encoding/base64"
-import crand "crypto/rand"
-import "io/ioutil"
-import "strings"
-import "net/http"
-import "regexp"
+import (
+ "crypto"
+ "crypto/rsa"
+ "crypto/sha256"
+ "crypto/x509"
+ "database/sql"
+ "encoding/base64"
+ "encoding/pem"
+ "errors"
+ "fmt"
+ "math/rand"
+ "net/smtp"
+ "os"
+ "os/exec"
+ "time"
+
+ _ "github.com/lib/pq"
+
+ crand "crypto/rand"
+ "io/ioutil"
+ "net/http"
+ "regexp"
+ "strings"
+)
+
type Verify struct {
Type string
@@ -527,6 +533,50 @@ func CreatePem(db *sql.DB, actor Actor) {
} else {
StorePemToDB(db, actor)
}
+
+ fmt.Println(`Created PEM keypair for the "` + actor.Name +`" board. Please keep in mind that
+the PEM key is crucial in identifying yourself as the legitimate owner of the board,
+so DO NOT LOSE IT!!! If you lose it, YOU WILL LOSE ACCESS TO YOUR BOARD!`);
+}
+
+func CreatePublicKeyFromPrivate(db *sql.DB, actor *Actor, publicKeyPem string) error{
+ publicFilename := GetActorPemFileFromDB(db, publicKeyPem);
+ privateFilename := strings.ReplaceAll(publicFilename, "public.pem", "private.pem")
+ _, err := os.Stat(privateFilename)
+ if err == nil {
+ //Not a lost cause
+ priv, err := ioutil.ReadFile(privateFilename)
+
+ block, _ := pem.Decode([]byte(priv))
+ if block == nil || block.Type != "RSA PRIVATE KEY" {
+ return errors.New("failed to decode PEM block containing public key")
+ }
+ key, err := x509.ParsePKCS1PrivateKey(block.Bytes)
+ CheckError(err, "failed to parse private key")
+
+ publicKeyDer, err := x509.MarshalPKIXPublicKey(&key.PublicKey)
+ CheckError(err, "failed to marshal public key from private key")
+ pubKeyBlock := pem.Block{
+ Type: "PUBLIC KEY",
+ Headers: nil,
+ Bytes: publicKeyDer,
+ }
+ publicFileWriter, err := os.Create(publicFilename)
+ CheckError(err, "error creating public pem file for " + actor.Name)
+
+ err = pem.Encode(publicFileWriter, &pubKeyBlock)
+ CheckError(err, "error encoding public pem")
+ }else{
+ fmt.Println(`Unable to locate private key from public key generation. Now,
+this means that you are now missing the proof that you are the
+owner of the "` + actor.Name + `" board. If you are the developer,
+then your job is just as easy as generating a new keypair, but
+if this board is live, then you'll also have to convince the other
+owners to switch their public keys for you so that they will start
+accepting your posts from your board from this site. Good luck ;)`)
+ return errors.New("unable to locate private key")
+ }
+ return nil
}
func StorePemToDB(db *sql.DB, actor Actor) {
@@ -555,7 +605,7 @@ func StorePemToDB(db *sql.DB, actor Actor) {
CheckError(err, "error creating publicKeyPem for actor ")
}
-func ActivitySign(db *sql.DB, actor Actor, signature string) string {
+func ActivitySign(db *sql.DB, actor Actor, signature string) (string, error) {
query := `select file from publicKeyPem where id=$1 `
rows, err := db.Query(query, actor.PublicKey.Id)
@@ -581,10 +631,17 @@ func ActivitySign(db *sql.DB, actor Actor, signature string) string {
hashed.Write([]byte(signature))
cipher, _ := rsa.SignPKCS1v15(rng, pub, crypto.SHA256, hashed.Sum(nil))
- return base64.StdEncoding.EncodeToString(cipher)
+ return base64.StdEncoding.EncodeToString(cipher), nil
+ }else{
+ fmt.Println(`Unable to locate private key. Now,
+this means that you are now missing the proof that you are the
+owner of the "` + actor.Name + `" board. If you are the developer,
+then your job is just as easy as generating a new keypair, but
+if this board is live, then you'll also have to convince the other
+owners to switch their public keys for you so that they will start
+accepting your posts from your board from this site. Good luck ;)`)
+ return "", errors.New("unable to locate private key")
}
-
- return ""
}
func ActivityVerify(actor Actor, signature string, verify string) error {