sig-auth.git

git clone https://git.crispbyte.dev/sig-auth.git

commit
61aa1be
parent
30cdf2c
author
cheddar
date
2025-02-21 02:45:49 +0100 CET
Reog and implement sqlite
9 files changed,  +223, -76
M go.mod
M go.sum
M go.mod
+1, -0
1@@ -5,6 +5,7 @@ go 1.23.4
2 require (
3 	github.com/common-fate/httpsig v0.2.1
4 	github.com/google/uuid v1.6.0
5+	github.com/mattn/go-sqlite3 v1.14.24
6 	github.com/opencontainers/go-digest v1.0.0
7 	golang.org/x/crypto v0.33.0
8 )
M go.sum
+2, -0
1@@ -6,6 +6,8 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
2 github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
3 github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
4 github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
5+github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM=
6+github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
7 github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
9 golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
A keydirectory/in_memory_directory.go
+45, -0
 1@@ -0,0 +1,45 @@
 2+package keydirectory
 3+
 4+import (
 5+	"context"
 6+	"crypto"
 7+	"errors"
 8+
 9+	"github.com/common-fate/httpsig/verifier"
10+)
11+
12+type inMemoryDirectory struct {
13+	records map[string]keyEntry
14+}
15+
16+func CreateMemoryDirectory() inMemoryDirectory {
17+	return inMemoryDirectory{
18+		records: map[string]keyEntry{},
19+	}
20+}
21+
22+func (dir inMemoryDirectory) GetKey(ctx context.Context, keyId string, _ string) (verifier.Algorithm, error) {
23+	entry, ok := dir.records[keyId]
24+
25+	if !ok {
26+		return nil, errors.New("key not found in directory")
27+	}
28+
29+	return entry.toAlg()
30+}
31+
32+func (dir inMemoryDirectory) RegisterKey(key crypto.PublicKey, alg string, userId string) (string, error) {
33+	keyId, err := generateKeyId()
34+
35+	if err != nil {
36+		return "", err
37+	}
38+
39+	dir.records[keyId] = keyEntry{
40+		Alg:       alg,
41+		PublicKey: key,
42+		UserId:    userId,
43+	}
44+
45+	return keyId, nil
46+}
A keydirectory/key_ids.go
+15, -0
 1@@ -0,0 +1,15 @@
 2+package keydirectory
 3+
 4+import "github.com/google/uuid"
 5+
 6+func generateKeyId() (string, error) {
 7+	uuid, err := uuid.NewRandom()
 8+
 9+	if err != nil {
10+		return "", err
11+	}
12+
13+	keyId := uuid.String()
14+
15+	return keyId, nil
16+}
M keydirectory/keyentry.go
+26, -2
 1@@ -1,9 +1,33 @@
 2 package keydirectory
 3 
 4-import "crypto"
 5+import (
 6+	"crypto"
 7+	"crypto/ed25519"
 8+	"fmt"
 9 
10-type KeyEntry struct {
11+	"github.com/common-fate/httpsig/alg_ed25519"
12+	"github.com/common-fate/httpsig/verifier"
13+)
14+
15+type keyEntry struct {
16 	Alg       string
17 	PublicKey crypto.PublicKey
18 	UserId    string
19 }
20+
21+func (k keyEntry) toAlg() (verifier.Algorithm, error) {
22+	var alg verifier.Algorithm
23+	var err error
24+
25+	switch k.Alg {
26+	case "ed25519":
27+		alg = alg_ed25519.Ed25519{
28+			PublicKey: k.PublicKey.(ed25519.PublicKey),
29+			Attrs:     k.UserId,
30+		}
31+	default:
32+		err = fmt.Errorf("unknown algoritm: %s", k.Alg)
33+	}
34+
35+	return alg, err
36+}
A keydirectory/sqlite.go
+110, -0
  1@@ -0,0 +1,110 @@
  2+package keydirectory
  3+
  4+import (
  5+	"context"
  6+	"crypto"
  7+	"crypto/ed25519"
  8+	"database/sql"
  9+	"fmt"
 10+
 11+	"github.com/common-fate/httpsig/verifier"
 12+	_ "github.com/mattn/go-sqlite3"
 13+)
 14+
 15+type dbWrapper struct {
 16+	db *sql.DB
 17+}
 18+
 19+func InitSqlite(dbPath string) (*dbWrapper, error) {
 20+	db, err := sql.Open("sqlite3", dbPath)
 21+
 22+	if err != nil {
 23+		return &dbWrapper{}, err
 24+	}
 25+
 26+	createStmt := `
 27+	create table
 28+	if not exists
 29+	keys(keyId text not null primary key, userId text, alg text, publicKey blob)
 30+	`
 31+
 32+	_, err = db.Exec(createStmt)
 33+
 34+	if err != nil {
 35+		return &dbWrapper{}, err
 36+	}
 37+
 38+	return &dbWrapper{db}, nil
 39+}
 40+
 41+func (dir *dbWrapper) GetKey(ctx context.Context, keyId string, _ string) (verifier.Algorithm, error) {
 42+	db := dir.db
 43+
 44+	query := "select userId, alg, publicKey from keys where keyId = ?"
 45+
 46+	stmt, err := db.Prepare(query)
 47+
 48+	if err != nil {
 49+		return nil, err
 50+	}
 51+
 52+	defer stmt.Close()
 53+
 54+	var userId string
 55+	var alg string
 56+	var keyBytes []byte
 57+
 58+	row := stmt.QueryRow(keyId)
 59+
 60+	err = row.Scan(&userId, &alg, &keyBytes)
 61+
 62+	if err != nil {
 63+		return nil, err
 64+	}
 65+
 66+	var publicKey crypto.PublicKey
 67+
 68+	switch alg {
 69+	case "ed25519":
 70+		publicKey = ed25519.PublicKey(keyBytes)
 71+	default:
 72+		return nil, fmt.Errorf("unknown algorithm: %s", alg)
 73+	}
 74+
 75+	keyEntry := keyEntry{
 76+		Alg:       alg,
 77+		UserId:    userId,
 78+		PublicKey: publicKey,
 79+	}
 80+
 81+	return keyEntry.toAlg()
 82+}
 83+
 84+func (dir *dbWrapper) RegisterKey(key crypto.PublicKey, alg string, userId string) (string, error) {
 85+	db := dir.db
 86+
 87+	keyId, err := generateKeyId()
 88+
 89+	if err != nil {
 90+		return "", err
 91+	}
 92+
 93+	stmt := "insert into keys(keyId, userId, alg, publicKey) values (?, ?, ?, ?)"
 94+
 95+	var keyBytes []byte
 96+
 97+	switch alg {
 98+	case "ed25519":
 99+		keyBytes = []byte(key.(ed25519.PublicKey))
100+	default:
101+		return "", fmt.Errorf("unknown algorithm: %s", alg)
102+	}
103+
104+	_, err = db.Exec(stmt, keyId, userId, alg, keyBytes)
105+
106+	if err != nil {
107+		return "", err
108+	}
109+
110+	return keyId, nil
111+}
M main.go
+24, -4
 1@@ -12,8 +12,8 @@ import (
 2 	"os"
 3 
 4 	"crispbyte.dev/sig-auth/client"
 5+	"crispbyte.dev/sig-auth/keydirectory"
 6 	"crispbyte.dev/sig-auth/server"
 7-	"crispbyte.dev/sig-auth/sqlite_directory"
 8 	"github.com/opencontainers/go-digest"
 9 	"golang.org/x/crypto/ssh"
10 )
11@@ -31,6 +31,10 @@ func main() {
12 
13 	simulateCaddy := flag.Bool("caddy", false, "Simulate caddy reverse proxy")
14 
15+	useTempDb := flag.Bool("temp-db", false, "Use a temporary in-memory database")
16+
17+	dbPath := flag.String("db", "", "Path to the sqlite database file")
18+
19 	flag.Parse()
20 
21 	if *useClient {
22@@ -48,7 +52,12 @@ func main() {
23 
24 		registerKey(*keyPath, *user)
25 	} else {
26-		runServer(*simulateCaddy)
27+		if !*useTempDb && *dbPath == "" {
28+			flag.PrintDefaults()
29+			return
30+		}
31+
32+		runServer(*simulateCaddy, *useTempDb, *dbPath)
33 	}
34 }
35 
36@@ -105,8 +114,19 @@ func runClient(keyFile string, keyId string, simulateCaddy bool) {
37 	fmt.Println(string(out[:]))
38 }
39 
40-func runServer(simulateCaddy bool) {
41-	keyDir := sqlite_directory.CreateDirectory()
42+func runServer(simulateCaddy bool, useTempDb bool, dbPath string) {
43+	var keyDir keydirectory.RegistrationDirectory
44+
45+	if useTempDb {
46+		keyDir = keydirectory.CreateMemoryDirectory()
47+	} else {
48+		var err error
49+		keyDir, err = keydirectory.InitSqlite(dbPath)
50+
51+		if err != nil {
52+			log.Fatal(err)
53+		}
54+	}
55 
56 	server.Start(simulateCaddy, keyDir)
57 }
D sqlite_directory/create_directory.go
+0, -11
 1@@ -1,11 +0,0 @@
 2-package sqlite_directory
 3-
 4-import (
 5-	"crispbyte.dev/sig-auth/keydirectory"
 6-)
 7-
 8-func CreateDirectory() InMemoryDirectory {
 9-	return InMemoryDirectory{
10-		records: map[string]keydirectory.KeyEntry{},
11-	}
12-}
D sqlite_directory/in_memory_directory.go
+0, -59
 1@@ -1,59 +0,0 @@
 2-package sqlite_directory
 3-
 4-import (
 5-	"context"
 6-	"crypto"
 7-	"crypto/ed25519"
 8-	"errors"
 9-	"fmt"
10-
11-	"github.com/common-fate/httpsig/alg_ed25519"
12-	"github.com/common-fate/httpsig/verifier"
13-	"github.com/google/uuid"
14-
15-	"crispbyte.dev/sig-auth/keydirectory"
16-)
17-
18-type InMemoryDirectory struct {
19-	records map[string]keydirectory.KeyEntry
20-}
21-
22-func (dir InMemoryDirectory) GetKey(ctx context.Context, keyId string, _ string) (verifier.Algorithm, error) {
23-	entry, ok := dir.records[keyId]
24-
25-	if !ok {
26-		return nil, errors.New("key not found in directory")
27-	}
28-
29-	var alg verifier.Algorithm
30-	var err error
31-
32-	switch entry.Alg {
33-	case "ed25519":
34-		alg = alg_ed25519.Ed25519{
35-			PublicKey: entry.PublicKey.(ed25519.PublicKey),
36-			Attrs:     entry.UserId,
37-		}
38-	default:
39-		err = fmt.Errorf("unknown algoritm: %s", entry.Alg)
40-	}
41-
42-	return alg, err
43-}
44-
45-func (dir InMemoryDirectory) RegisterKey(key crypto.PublicKey, alg string, userId string) (string, error) {
46-	uuid, err := uuid.NewRandom()
47-	keyId := uuid.String()
48-
49-	if err != nil {
50-		return "", err
51-	}
52-
53-	dir.records[keyId] = keydirectory.KeyEntry{
54-		Alg:       alg,
55-		PublicKey: key,
56-		UserId:    userId,
57-	}
58-
59-	return keyId, nil
60-}