added shamir keys

This commit is contained in:
ston1th 2023-03-20 21:18:44 +01:00
commit be0f532628
14 changed files with 238 additions and 43 deletions

View file

@ -53,8 +53,6 @@ func main() {
arg := os.Args[1] arg := os.Args[1]
switch arg { switch arg {
case "new", "get", "ls", "req", "approve", "reject", "del": case "new", "get", "ls", "req", "approve", "reject", "del":
//flag.StringVar(&config, "config", "/etc/keyctl/url.conf", "path to client config file")
//flag.Parse()
cli.Run(arg) // does not return cli.Run(arg) // does not return
case "server": case "server":
fs := flag.NewFlagSet("", flag.ExitOnError) fs := flag.NewFlagSet("", flag.ExitOnError)

3
go.mod
View file

@ -19,8 +19,9 @@ require (
github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/gogo/protobuf v1.3.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.2 // indirect github.com/golang/protobuf v1.5.2 // indirect
github.com/hashicorp/vault v1.13.0 // indirect
github.com/inconshreveable/mousetrap v1.0.1 // indirect github.com/inconshreveable/mousetrap v1.0.1 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.2 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/prometheus/client_golang v1.14.0 // indirect github.com/prometheus/client_golang v1.14.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.37.0 // indirect github.com/prometheus/common v0.37.0 // indirect

5
go.sum
View file

@ -61,6 +61,7 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
@ -141,6 +142,8 @@ github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/vault v1.13.0 h1:/J/ldGnqRHKDlaSznOQAXy4STah76tCYy2fsUSsvYwk=
github.com/hashicorp/vault v1.13.0/go.mod h1:W1VOUMJ1klrGAHFnTJYDw2N2RlBh+kdwmCyYZTSGap0=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
@ -164,6 +167,7 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/matttproud/golang_protobuf_extensions v1.0.2 h1:hAHbPm5IJGijwng3PWk09JkG9WeqChjprR5s9bBZ+OM= github.com/matttproud/golang_protobuf_extensions v1.0.2 h1:hAHbPm5IJGijwng3PWk09JkG9WeqChjprR5s9bBZ+OM=
github.com/matttproud/golang_protobuf_extensions v1.0.2/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/matttproud/golang_protobuf_extensions v1.0.2/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
@ -176,6 +180,7 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=

View file

@ -51,7 +51,6 @@ func NewServer(log logr.Logger, listen, socket string) (*Server, error) {
s.listen = l s.listen = l
sock, err := unixListener(socket) sock, err := unixListener(socket)
net.Listen("unix", socket)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -83,14 +83,14 @@ func (c *Client) GetKey(ctx context.Context, id string) (key schema.Key, err err
return return
} }
func (c *Client) CreateKey(ctx context.Context, key schema.NewKey) (err error) { func (c *Client) CreateKey(ctx context.Context, newKey schema.NewKey) (key schema.Key, err error) {
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
path := keyPath path := keyPath
err = key.Validate() err = newKey.Validate()
if err != nil { if err != nil {
return return
} }
err = json.NewEncoder(buf).Encode(key) err = json.NewEncoder(buf).Encode(newKey)
if err != nil { if err != nil {
return return
} }
@ -98,7 +98,7 @@ func (c *Client) CreateKey(ctx context.Context, key schema.NewKey) (err error) {
if err != nil { if err != nil {
return return
} }
_, err = c.c.Do(req, nil) _, err = c.c.Do(req, &key)
return return
} }

View file

@ -3,7 +3,10 @@
package schema package schema
import ( import (
"encoding/hex"
"errors" "errors"
"fmt"
"time"
"git.giftfish.de/ston1th/keyctl/pkg/api/types" "git.giftfish.de/ston1th/keyctl/pkg/api/types"
"git.giftfish.de/ston1th/keyctl/pkg/core" "git.giftfish.de/ston1th/keyctl/pkg/core"
@ -22,6 +25,7 @@ type NewKey struct {
Name string `json:"name"` Name string `json:"name"`
Size int `json:"size"` Size int `json:"size"`
Encoding core.Encoding `json:"encoding"` Encoding core.Encoding `json:"encoding"`
Type core.Type `json:"type"`
} }
var ( var (
@ -58,13 +62,52 @@ type Key struct {
Created int64 `json:"created"` Created int64 `json:"created"`
Size int `json:"size"` Size int `json:"size"`
Encoding core.Encoding `json:"encoding"` Encoding core.Encoding `json:"encoding"`
Type core.Type `json:"type"`
Key string `json:"key,omitempty"` Key string `json:"key,omitempty"`
} }
func (k Key) Print(share string) (string, error) {
switch k.Type {
case core.Shamir:
part1, err := k.Encoding.Decode(k.Key)
if err != nil {
return "", err
}
part2, err := hex.DecodeString(share)
if err != nil {
return "", err
}
dec, err := k.Type.Decode(append(part1, part2...))
if err != nil {
return "", err
}
return k.Encoding.EncodeToString(dec), nil
}
return k.Key, nil
}
type Keys []Key type Keys []Key
func (Keys) Less(a, b Key) bool { return a.Name < b.Name } func (Keys) Less(a, b Key) bool { return a.Name < b.Name }
func (k Keys) Sort() { slices.SortStableFunc(k, k.Less) } func (k Keys) Sort() { slices.SortStableFunc(k, k.Less) }
func (k Keys) Len() int { return len(k) }
func (k Keys) Fields() string {
return "ID\t Name\t Created\t Size\t Encoding\t Type"
}
func (k Keys) Values() []string {
vals := make([]string, len(k))
for i, v := range k {
vals[i] = fmt.Sprintf("%s\t %s\t %s\t %d\t %s\t %s",
v.ID,
v.Name,
timeFmt(v.Created),
v.Size,
v.Encoding,
v.Type,
)
}
return vals
}
func NewKeys(keys core.Keys) (k Keys) { func NewKeys(keys core.Keys) (k Keys) {
for _, key := range keys { for _, key := range keys {
@ -87,6 +130,24 @@ type Approvals []Approval
func (Approvals) Less(a, b Approval) bool { return a.Name < b.Name } func (Approvals) Less(a, b Approval) bool { return a.Name < b.Name }
func (a Approvals) Sort() { slices.SortStableFunc(a, a.Less) } func (a Approvals) Sort() { slices.SortStableFunc(a, a.Less) }
func (a Approvals) Len() int { return len(a) }
func (a Approvals) Fields() string {
return "ID\t Approval ID\t Name\t Status\t Created\t IP"
}
func (a Approvals) Values() []string {
vals := make([]string, len(a))
for i, v := range a {
vals[i] = fmt.Sprintf("%s\t %s\t %s\t %s\t %s\t %s",
v.ID,
v.AID,
v.Name,
v.Status,
timeFmt(v.Created),
v.IP,
)
}
return vals
}
func NewApprovals(m types.ApprovalMap) (a Approvals) { func NewApprovals(m types.ApprovalMap) (a Approvals) {
for k, v := range m { for k, v := range m {
@ -102,3 +163,7 @@ func NewApprovals(m types.ApprovalMap) (a Approvals) {
a.Sort() a.Sort()
return return
} }
func timeFmt(t int64) string {
return time.Unix(t, 0).Format(time.RFC3339)
}

View file

@ -56,7 +56,7 @@ func newHandler(ctx *types.Context) {
ctx.Err(types.ErrInvalid) ctx.Err(types.ErrInvalid)
return return
} }
key, err := ctx.Data.DB.CreateKey(newKey.Name, newKey.Size, newKey.Encoding) key, err := ctx.Data.DB.CreateKey(newKey.Name, newKey.Size, newKey.Encoding, newKey.Type)
if err != nil { if err != nil {
ctx.Log.Error(err, "error writing key", "name", newKey.Name) ctx.Log.Error(err, "error writing key", "name", newKey.Name)
ctx.Err(types.ErrISE) ctx.Err(types.ErrISE)

View file

@ -5,9 +5,11 @@ package cli
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"errors"
"flag" "flag"
"fmt" "fmt"
"os" "os"
"text/tabwriter"
apiclient "git.giftfish.de/ston1th/keyctl/pkg/api/client" apiclient "git.giftfish.de/ston1th/keyctl/pkg/api/client"
clientv1 "git.giftfish.de/ston1th/keyctl/pkg/api/v1/client" clientv1 "git.giftfish.de/ston1th/keyctl/pkg/api/v1/client"
@ -27,33 +29,64 @@ func Run(arg string) {
ctx := context.Background() ctx := context.Background()
switch arg { switch arg {
case "new": case "new":
name, encoding, size := newKeyFlags() name, encoding, t, size, err := newKeyFlags()
if err != nil {
exit(err)
}
newKey := schema.NewKey{ newKey := schema.NewKey{
Name: name, Name: name,
Size: size, Size: size,
Encoding: core.EncodingFromString(encoding), Encoding: core.EncodingFromString(encoding),
Type: core.TypeFromString(t),
} }
c := client() c := client()
err = c.CreateKey(ctx, newKey) k, err := c.CreateKey(ctx, newKey)
if err != nil {
exit(err)
}
switch k.Type {
case core.Plain:
fmt.Println("Key ID:", k.ID)
case core.Shamir:
fmt.Println("Key ID:", k.ID)
fmt.Println("Key Share:", k.Key)
}
case "del": case "del":
id := idFlags("key id") id, err := idFlags("key id")
if err != nil {
exit(err)
}
c := client() c := client()
err = c.DeleteKey(ctx, id) err = c.DeleteKey(ctx, id)
case "approve": case "approve":
id := idFlags("approval id") id, err := idFlags("approval id")
if err != nil {
exit(err)
}
c := client() c := client()
err = c.AcceptApproval(ctx, id) err = c.AcceptApproval(ctx, id)
case "reject": case "reject":
id := idFlags("approval id") id, err := idFlags("approval id")
if err != nil {
exit(err)
}
c := client() c := client()
err = c.RejectApproval(ctx, id) err = c.RejectApproval(ctx, id)
case "get": case "get":
id, json := getFlags() id, share, json, err := getFlags()
if err != nil {
exit(err)
}
c := client() c := client()
key, err := c.GetKey(ctx, id) key, err := c.GetKey(ctx, id)
if err != nil { if err != nil {
exit(err) exit(err)
} }
out, err := key.Print(share)
if err != nil {
exit(err)
}
key.Key = out
if json { if json {
jsonOutput(key) // does not return jsonOutput(key) // does not return
} }
@ -68,15 +101,7 @@ func Run(arg string) {
if json { if json {
jsonOutput(keys) // does not return jsonOutput(keys) // does not return
} }
for _, k := range keys { print(keys)
fmt.Printf("%s %s %d %s %d\n",
k.ID,
k.Name,
k.Size,
k.Encoding,
k.Created,
)
}
case "req": case "req":
json := outputFlags() json := outputFlags()
c := client() c := client()
@ -87,16 +112,7 @@ func Run(arg string) {
if json { if json {
jsonOutput(approvals) // does not return jsonOutput(approvals) // does not return
} }
for _, a := range approvals { print(approvals)
fmt.Printf("%s %s %s %s %d %s\n",
a.ID,
a.AID,
a.Name,
a.Status,
a.Created,
a.IP,
)
}
} }
if err != nil { if err != nil {
exit(err) exit(err)
@ -126,16 +142,23 @@ func jsonOutput(v any) {
os.Exit(0) os.Exit(0)
} }
func idFlags(desc string) (id string) { func idFlags(desc string) (id string, err error) {
fs.StringVar(&id, "id", "", desc) fs.StringVar(&id, "id", "", desc)
fs.Parse(os.Args[2:]) fs.Parse(os.Args[2:])
if id == "" {
err = errors.New("missing flag: id")
}
return return
} }
func getFlags() (id string, json bool) { func getFlags() (id, share string, json bool, err error) {
fs.StringVar(&id, "id", "", "key id") fs.StringVar(&id, "id", "", "key id")
fs.StringVar(&share, "share", "", "shamir key share")
fs.BoolVar(&json, "json", false, "json output") fs.BoolVar(&json, "json", false, "json output")
fs.Parse(os.Args[2:]) fs.Parse(os.Args[2:])
if id == "" {
err = errors.New("missing flag: id")
}
return return
} }
@ -145,10 +168,26 @@ func outputFlags() (json bool) {
return return
} }
func newKeyFlags() (name, encoding string, size int) { func newKeyFlags() (name, encoding, t string, size int, err error) {
fs.StringVar(&name, "name", "", "key name") fs.StringVar(&name, "name", "", "key name")
fs.StringVar(&encoding, "enc", "hex", "key encoding scheme [hex|base32|base64|base64url]") fs.StringVar(&encoding, "enc", "hex", "key encoding scheme [hex|base32|base64|base64url]")
fs.StringVar(&t, "type", "plain", "key type [plain|shamir]")
fs.IntVar(&size, "size", 16, "key size in bytes") fs.IntVar(&size, "size", 16, "key size in bytes")
fs.Parse(os.Args[2:]) fs.Parse(os.Args[2:])
if name == "" {
err = errors.New("missing flag: name")
}
return return
} }
func print(tw core.TableWriter) {
if tw.Len() == 0 {
return
}
w := tabwriter.NewWriter(os.Stdout, 1, 0, 1, ' ', tabwriter.Debug)
fmt.Fprintln(w, tw.Fields())
for _, v := range tw.Values() {
fmt.Fprintln(w, v)
}
w.Flush()
}

View file

@ -36,6 +36,18 @@ func (e Encoding) EncodeToString(src []byte) string {
return hex.EncodeToString(src) return hex.EncodeToString(src)
} }
func (e Encoding) Decode(src string) ([]byte, error) {
switch e {
case Base32:
return b32raw.DecodeString(src)
case Base64:
return base64.RawStdEncoding.DecodeString(src)
case Base64URL:
return base64.RawURLEncoding.DecodeString(src)
}
return hex.DecodeString(src)
}
func EncodingFromString(e string) Encoding { func EncodingFromString(e string) Encoding {
switch e { switch e {
case "base32": case "base32":

View file

@ -20,6 +20,7 @@ type Key struct {
Created int64 Created int64
Size int Size int
Encoding Encoding Encoding Encoding
Type Type
Key string Key string
} }

9
pkg/core/tablewriter.go Normal file
View file

@ -0,0 +1,9 @@
// Copyright (C) 2023 Marius Schellenberger
package core
type TableWriter interface {
Len() int
Fields() string
Values() []string
}

55
pkg/core/type.go Normal file
View file

@ -0,0 +1,55 @@
// Copyright (C) 2023 Marius Schellenberger
package core
import (
"bytes"
"github.com/hashicorp/vault/shamir"
)
type Type int
func (t Type) String() string {
switch t {
case Shamir:
return "shamir"
}
return "plain"
}
func (t Type) Decode(src []byte) ([]byte, error) {
switch t {
case Shamir:
plen := len(src) / 2
part1 := src[0:plen]
part2 := src[plen:]
return shamir.Combine([][]byte{part1, part2})
}
return src, nil
}
func (t Type) Encode(src []byte) ([]byte, error) {
switch t {
case Shamir:
parts, err := shamir.Split(src, 2, 2)
if err != nil {
return nil, err
}
return bytes.Join(parts, nil), nil
}
return src, nil
}
func TypeFromString(t string) Type {
switch t {
case "shamir":
return Shamir
}
return Plain
}
const (
Plain Type = iota
Shamir
)

View file

@ -31,12 +31,12 @@ func (db *DB) GetKeyWithSecret(id string) (k core.Key, err error) {
return return
} }
func (db *DB) CreateKey(name string, size int, enc core.Encoding) (k core.Key, err error) { func (db *DB) CreateKey(name string, size int, enc core.Encoding, t core.Type) (k core.Key, err error) {
k, err = key.Generate(name, size, enc) kstore, k, err := key.Generate(name, size, enc, t)
if err != nil { if err != nil {
return return
} }
err = db.store.Set(keyPrefix+k.ID, &k) err = db.store.Set(keyPrefix+k.ID, &kstore)
return return
} }

View file

@ -27,7 +27,7 @@ func GenerateID() (string, error) {
return hex.EncodeToString(id), nil return hex.EncodeToString(id), nil
} }
func Generate(name string, size int, enc core.Encoding) (k core.Key, err error) { func Generate(name string, size int, enc core.Encoding, t core.Type) (kstore, k core.Key, err error) {
id, err := GenerateID() id, err := GenerateID()
if err != nil { if err != nil {
return return
@ -36,13 +36,24 @@ func Generate(name string, size int, enc core.Encoding) (k core.Key, err error)
if err != nil { if err != nil {
return return
} }
k = core.Key{ key, err = t.Encode(key)
if err != nil {
return
}
kstore = core.Key{
Name: name, Name: name,
ID: id, ID: id,
Size: size, Size: size,
Encoding: enc, Encoding: enc,
Key: enc.EncodeToString(key), Type: t,
Created: time.Now().Unix(), Created: time.Now().Unix(),
} }
k = kstore
if t == core.Shamir {
klen := len(key) / 2
k.Key = core.Hex.EncodeToString(key[klen:])
key = key[0:klen]
}
kstore.Key = enc.EncodeToString(key)
return return
} }