package keydirectory import ( "context" "crypto" "crypto/ed25519" "database/sql" "fmt" "github.com/common-fate/httpsig/verifier" _ "github.com/mattn/go-sqlite3" ) type dbWrapper struct { db *sql.DB } func InitSqlite(dbPath string) (*dbWrapper, error) { db, err := sql.Open("sqlite3", dbPath) if err != nil { return &dbWrapper{}, err } createStmt := ` create table if not exists keys(keyId text not null primary key, userId text, alg text, publicKey blob) ` _, err = db.Exec(createStmt) if err != nil { return &dbWrapper{}, err } return &dbWrapper{db}, nil } func (dir *dbWrapper) GetKey(ctx context.Context, keyId string, _ string) (verifier.Algorithm, error) { db := dir.db query := "select userId, alg, publicKey from keys where keyId = ?" stmt, err := db.Prepare(query) if err != nil { return nil, err } defer stmt.Close() var userId string var alg string var keyBytes []byte row := stmt.QueryRow(keyId) err = row.Scan(&userId, &alg, &keyBytes) if err != nil { return nil, err } var publicKey crypto.PublicKey switch alg { case "ed25519": publicKey = ed25519.PublicKey(keyBytes) default: return nil, fmt.Errorf("unknown algorithm: %s", alg) } keyEntry := keyEntry{ Alg: alg, UserId: userId, PublicKey: publicKey, } return keyEntry.toAlg() } func (dir *dbWrapper) RegisterKey(key crypto.PublicKey, alg string, userId string) (string, error) { db := dir.db keyId, err := generateKeyId() if err != nil { return "", err } stmt := "insert into keys(keyId, userId, alg, publicKey) values (?, ?, ?, ?)" var keyBytes []byte switch alg { case "ed25519": keyBytes = []byte(key.(ed25519.PublicKey)) default: return "", fmt.Errorf("unknown algorithm: %s", alg) } _, err = db.Exec(stmt, keyId, userId, alg, keyBytes) if err != nil { return "", err } return keyId, nil }