add private key handling

This also contains a couple fixes to the subject part.
This commit is contained in:
Gibheer 2017-05-28 23:55:39 +02:00
parent b9c2539073
commit bc8e1353af
8 changed files with 331 additions and 55 deletions

View File

@ -40,28 +40,16 @@ func main() {
err = setSubject(args, client)
case `show-subj`:
err = showSubject(args, client)
// case `list`:
// err = listDescription(args, client)
// case `create-file`:
// err = createFile(args, client)
// case `list-files`:
// err = listFile(args, client)
// case `delete-file`:
// err = deleteFile(args, client)
// case `create-private-key`:
// err = createPrivateKey(args, client)
// case `get-private-key`:
// err = getPrivateKey(args, client)
// case `list-private-keys`:
// err = listPrivateKey(args, client)
// case `delete-private-key`:
// err = deletePrivateKey(args, client)
// case `create-public-key`:
// err = createPublicKey(args, client)
// case `list-public-keys`:
// err = listPublicKey(args, client)
// case `delete-public-key`:
// err = deletePublicKey(args, client)
case `create-private`:
err = createPrivateKey(args, client)
case `delete-private`:
err = deletePrivateKey(args, client)
case `list-private`:
err = listPrivateKey(args, client)
case `set-private`:
err = setPrivateKey(args, client)
case `show-private`:
err = showPrivateKey(args, client)
default:
fmt.Printf("unknown subcommand '%s'\n", cmd)
printCommands()

116
cmd/pkiadm/private_key.go Normal file
View File

@ -0,0 +1,116 @@
package main
import (
"encoding/base64"
"fmt"
"os"
"text/tabwriter"
"github.com/gibheer/pkiadm"
"github.com/pkg/errors"
flag "github.com/spf13/pflag"
)
func createPrivateKey(args []string, client *pkiadm.Client) error {
fs := flag.NewFlagSet("create-private", flag.ExitOnError)
fs.Usage = func() {
fmt.Printf("Usage of %s:\n", "pkiadm create-private")
fmt.Println(`
Create a new private key for different use cases. The supported types are rsa,
ecdsa and ed25519. Please keep in mind, that ed25519 is currently not supported
for certificate generation.
`)
fs.PrintDefaults()
}
pk := pkiadm.PrivateKey{}
fs.StringVar(&pk.ID, "id", "", "set the unique id for the new private key")
var pkType = fs.String("type", "rsa", "set the type of the private key (rsa, ecdsa, ed25519)")
fs.UintVar(&pk.Bits, "bits", 2048, "set the number of bits to use. For rsa it can be 1024 up to 32768, for ecdsa 224, 256, 384, 521. Ed25519 is set to 256 by default.")
fs.Parse(args)
pkT, err := pkiadm.StringToPrivateKeyType(*pkType)
if err != nil {
return err
}
pk.Type = pkT
if err := client.CreatePrivateKey(pk); err != nil {
return errors.Wrap(err, "could not create private key")
}
return nil
}
func setPrivateKey(args []string, client *pkiadm.Client) error {
fs := flag.NewFlagSet("set-private", flag.ExitOnError)
pk := pkiadm.PrivateKey{}
fs.StringVar(&pk.ID, "id", "", "set the id of the private key to change")
var pkType = fs.String("type", "rsa", "set the type of the private key (rsa, ecdsa, ed25519)")
fs.UintVar(&pk.Bits, "bits", 2048, "set the number of bits to use. For rsa it can be 1024 up to 32768, for ecdsa 224, 256, 384, 521. Ed25519 is set to 256 by default.")
fs.Parse(args)
pkT, err := pkiadm.StringToPrivateKeyType(*pkType)
if err != nil {
return err
}
pk.Type = pkT
fieldList := []string{}
for _, field := range []string{"type", "bits"} {
flag := fs.Lookup(field)
if flag.Changed {
fieldList = append(fieldList, field)
}
}
if err := client.SetPrivateKey(pk, fieldList); err != nil {
return err
}
return nil
}
func deletePrivateKey(args []string, client *pkiadm.Client) error {
fs := flag.NewFlagSet("delete-private", flag.ExitOnError)
var id = fs.String("id", "", "set the id of the private key to delete")
fs.Parse(args)
if err := client.DeletePrivateKey(*id); err != nil {
return err
}
return nil
}
func listPrivateKey(args []string, client *pkiadm.Client) error {
fs := flag.NewFlagSet("list-private", flag.ExitOnError)
fs.Parse(args)
pks, err := client.ListPrivateKey()
if err != nil {
return err
}
if len(pks) == 0 {
return nil
}
out := tabwriter.NewWriter(os.Stdout, 2, 2, 1, ' ', tabwriter.AlignRight)
fmt.Fprintf(out, "%s\t%s\t%s\t\n", "id", "type", "bits")
for _, pk := range pks {
fmt.Fprintf(out, "%s\t%s\t%d\t\n", pk.ID, pk.Type.String(), pk.Bits)
}
out.Flush()
return nil
}
func showPrivateKey(args []string, client *pkiadm.Client) error {
fs := flag.NewFlagSet("show-private", flag.ExitOnError)
var id = fs.String("id", "", "set the id of the private key to show")
fs.Parse(args)
pk, err := client.ShowPrivateKey(*id)
if err != nil {
return err
}
out := tabwriter.NewWriter(os.Stdout, 2, 2, 1, ' ', tabwriter.AlignRight)
fmt.Fprintf(out, "ID:\t%s\t\n", pk.ID)
fmt.Fprintf(out, "type:\t%s\t\n", pk.Type.String())
fmt.Fprintf(out, "bits:\t%d\t\n", pk.Bits)
fmt.Fprintf(out, "checksum:\t%s\t\n", base64.StdEncoding.EncodeToString(pk.Checksum))
out.Flush()
return nil
}

View File

@ -32,7 +32,6 @@ In most cases only the common name, organization name and the country is provide
}
if err := client.CreateSubject(subj); err != nil {
fmt.Println("got an error")
return errors.Wrap(err, "could not create new subject")
}
return nil

View File

@ -6,12 +6,7 @@ import (
"fmt"
"github.com/gibheer/pki"
)
const (
PKTRSA PrivateKeyType = iota
PKTECDSA
PKTED25519
"github.com/gibheer/pkiadm"
)
const (
@ -23,24 +18,23 @@ const (
type (
PrivateKey struct {
ID string
PKType PrivateKeyType
Length uint
PKType pkiadm.PrivateKeyType
Bits uint
Key []byte
}
PrivateKeyType uint
)
func NewPrivateKey(id string, pkType PrivateKeyType, length uint) (*PrivateKey, error) {
func NewPrivateKey(id string, pkType pkiadm.PrivateKeyType, bits uint) (*PrivateKey, error) {
if id == "" {
return nil, ENoIDGiven
}
if err := verifyPK(pkType, length); err != nil {
if err := verifyPK(pkType, bits); err != nil {
return nil, err
}
pk := PrivateKey{
ID: id,
PKType: pkType,
Length: length,
Bits: bits,
}
return &pk, nil
}
@ -67,13 +61,13 @@ func (p *PrivateKey) Refresh(_ *Storage) error {
err error
)
switch p.PKType {
case PKTRSA:
key, err = pki.NewPrivateKeyRsa(int(p.Length))
case PKTED25519:
case pkiadm.PKTRSA:
key, err = pki.NewPrivateKeyRsa(int(p.Bits))
case pkiadm.PKTED25519:
key, err = pki.NewPrivateKeyEd25519()
case PKTECDSA:
case pkiadm.PKTECDSA:
var curve elliptic.Curve
switch p.Length {
switch p.Bits {
case 224:
curve = elliptic.P224()
case 256:
@ -120,20 +114,20 @@ func (p *PrivateKey) GetKey() (pki.PrivateKey, error) {
return key, nil
}
func verifyPK(pkType PrivateKeyType, length uint) error {
func verifyPK(pkType pkiadm.PrivateKeyType, bits uint) error {
switch pkType {
case PKTRSA:
if length < 1024 || length > 32768 {
case pkiadm.PKTRSA:
if bits < 1024 || bits > 32768 {
return ELengthOutOfBounds
}
case PKTECDSA:
switch length {
case pkiadm.PKTECDSA:
switch bits {
case 224, 256, 384, 521:
default:
return EWrongKeyLength
}
case PKTED25519:
if length != 256 {
case pkiadm.PKTED25519:
if bits != 256 {
return EWrongKeyLengthED25519
}
default:
@ -142,9 +136,92 @@ func verifyPK(pkType PrivateKeyType, length uint) error {
return nil
}
//func (p *PrivateKey) MarshalJSON() ([]byte, error) {
// return json.Marshal(*p)
//}
//func (p *PrivateKey) UnmarshalJSON(raw []byte) error {
// return json.Unmarshal(raw, p)
//}
func (s *Server) CreatePrivateKey(inPk pkiadm.PrivateKey, res *pkiadm.Result) error {
s.lock()
defer s.unlock()
pk, err := NewPrivateKey(inPk.ID, inPk.Type, inPk.Bits)
if err != nil {
res.SetError(err, "Could not create new private key '%s'", inPk.ID)
return nil
}
if err := s.storage.AddPrivateKey(pk); err != nil {
res.SetError(err, "Could not add private key '%s'", inPk.ID)
return nil
}
return nil
}
func (s *Server) SetPrivateKey(changeset pkiadm.PrivateKeyChange, res *pkiadm.Result) error {
s.lock()
defer s.unlock()
pk, err := s.storage.GetPrivateKey(ResourceName{ID: changeset.PrivateKey.ID, Type: RTPrivateKey})
if err != nil {
res.SetError(err, "Could not find private key '%s'", changeset.PrivateKey.ID)
return nil
}
for _, field := range changeset.FieldList {
switch field {
case "type":
pk.PKType = changeset.PrivateKey.Type
case "bits":
pk.Bits = changeset.PrivateKey.Bits
default:
res.SetError(fmt.Errorf("unknown field"), "unknown field '%s'", field)
return nil
}
}
if err := s.storage.Update(ResourceName{ID: pk.ID, Type: RTPrivateKey}); err != nil {
res.SetError(err, "Could not update private key '%s'", changeset.PrivateKey.ID)
return nil
}
return s.store(res)
}
func (s *Server) DeletePrivateKey(inPk pkiadm.ResourceName, res *pkiadm.Result) error {
s.lock()
defer s.unlock()
pk, err := s.storage.GetPrivateKey(ResourceName{ID: inPk.ID, Type: RTPrivateKey})
if err != nil {
res.SetError(err, "Could not find private key '%s'", inPk.ID)
return nil
}
if err := s.storage.Remove(pk); err != nil {
res.SetError(err, "Could not remove private key '%s'", pk.ID)
return nil
}
return s.store(res)
}
func (s *Server) ShowPrivateKey(inPk pkiadm.ResourceName, res *pkiadm.ResultPrivateKey) error {
s.lock()
defer s.unlock()
pk, err := s.storage.GetPrivateKey(ResourceName{ID: inPk.ID, Type: RTPrivateKey})
if err != nil {
res.Result.SetError(err, "Could not find private key '%s'", inPk.ID)
return nil
}
res.PrivateKeys = []pkiadm.PrivateKey{pkiadm.PrivateKey{
ID: pk.ID,
Type: pk.PKType,
Bits: pk.Bits,
Checksum: pk.Checksum(),
}}
return nil
}
func (s *Server) ListPrivateKey(filter pkiadm.Filter, res *pkiadm.ResultPrivateKey) error {
s.lock()
defer s.unlock()
for _, pk := range s.storage.PrivateKeys {
res.PrivateKeys = append(res.PrivateKeys, pkiadm.PrivateKey{
ID: pk.ID,
Type: pk.PKType,
Bits: pk.Bits,
Checksum: pk.Checksum(),
})
}
return nil
}

View File

@ -2,6 +2,7 @@ package main
import (
"crypto/x509/pkix"
"fmt"
"github.com/gibheer/pkiadm"
)
@ -90,10 +91,13 @@ func (s *Server) SetSubject(changeset pkiadm.SubjectChange, res *pkiadm.Result)
subj.Data.StreetAddress = changes.StreetAddress
case "code":
subj.Data.PostalCode = changes.PostalCode
default:
res.SetError(fmt.Errorf("unknown field"), "unknown field '%s'", field)
return nil
}
}
if err := s.storage.Update(ResourceName{ID: subj.ID, Type: RTSubject}); err != nil {
res.SetError(err, "Could update resource '%s'", changeset.Subject.ID)
res.SetError(err, "Could not update subject '%s'", changeset.Subject.ID)
return nil
}
return s.store(res)

63
private_key.go Normal file
View File

@ -0,0 +1,63 @@
package pkiadm
const (
PKTRSA PrivateKeyType = iota
PKTECDSA
PKTED25519
PKTUnknown
)
type (
PrivateKey struct {
ID string
Type PrivateKeyType
Bits uint
Checksum []byte // This field is only set by the server
}
PrivateKeyChange struct {
PrivateKey PrivateKey
FieldList []string
}
ResultPrivateKey struct {
Result Result
PrivateKeys []PrivateKey
}
PrivateKeyType uint
)
// CreatePrivateKey sends a RPC request to create a new private key.
func (c *Client) CreatePrivateKey(pk PrivateKey) error {
return c.exec("CreatePrivateKey", pk)
}
func (c *Client) SetPrivateKey(pk PrivateKey, fieldList []string) error {
changeset := PrivateKeyChange{pk, fieldList}
return c.exec("SetPrivateKey", changeset)
}
func (c *Client) DeletePrivateKey(id string) error {
pk := ResourceName{ID: id, Type: RTPrivateKey}
return c.exec("DeletePrivateKey", pk)
}
func (c *Client) ListPrivateKey() ([]PrivateKey, error) {
result := &ResultPrivateKey{}
if err := c.query("ListPrivateKey", Filter{}, result); err != nil {
return []PrivateKey{}, err
}
if result.Result.HasError {
return []PrivateKey{}, result.Result.Error
}
return result.PrivateKeys, nil
}
func (c *Client) ShowPrivateKey(id string) (PrivateKey, error) {
pk := ResourceName{ID: id, Type: RTPrivateKey}
result := &ResultPrivateKey{}
if err := c.query("ShowPrivateKey", pk, result); err != nil {
return PrivateKey{}, err
}
if result.Result.HasError {
return PrivateKey{}, result.Result.Error
}
for _, privateKey := range result.PrivateKeys {
return privateKey, nil
}
return PrivateKey{}, nil
}

29
privatekeytype_string.go Normal file
View File

@ -0,0 +1,29 @@
// Code generated by "stringer -type PrivateKeyType"; DO NOT EDIT
package pkiadm
import "fmt"
const _PrivateKeyType_name = "rsaecdsaed25519"
var _PrivateKeyType_index = [...]uint8{0, 3, 8, 15}
func (i PrivateKeyType) String() string {
if i >= PrivateKeyType(len(_PrivateKeyType_index)-1) {
return fmt.Sprintf("PrivateKeyType(%d)", i)
}
return _PrivateKeyType_name[_PrivateKeyType_index[i]:_PrivateKeyType_index[i+1]]
}
func StringToPrivateKeyType(t string) (PrivateKeyType, error) {
switch t {
case "rsa":
return PKTRSA, nil
case "ecdsa":
return PKTECDSA, nil
case "ed25519":
return PKTED25519, nil
default:
return PKTUnknown, fmt.Errorf("unknown private key type")
}
}

View File

@ -39,7 +39,7 @@ func (c *Client) ShowSubject(id string) (Subject, error) {
subj := ResourceName{ID: id, Type: RTSubject}
result := &ResultSubjects{}
if err := c.query("ShowSubject", subj, result); err != nil {
return Subject{}, nil
return Subject{}, err
}
if result.Result.HasError {
return Subject{}, result.Result.Error