From f9164f3f99edf4ae8343d6c67b915e788a5624f8 Mon Sep 17 00:00:00 2001 From: Gibheer Date: Sun, 15 Feb 2015 21:04:59 +0100 Subject: [PATCH] initial commit for pki pki is a small library to make building some of the crypto stuff easier in go. --- README.md | 7 +++++ ecdsa.go | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++ pem_marshal.go | 15 +++++++++++ rsa.go | 54 +++++++++++++++++++++++++++++++++++++++ types.go | 31 +++++++++++++++++++++++ 5 files changed, 176 insertions(+) create mode 100644 README.md create mode 100644 ecdsa.go create mode 100644 pem_marshal.go create mode 100644 rsa.go create mode 100644 types.go diff --git a/README.md b/README.md new file mode 100644 index 0000000..8c9a336 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +pki +=== + +This is a small library to make building private keys, public keys, signatures +and most of the certificate stuff a bit easier. + +For a cli you can take a look at [pkictl](https://git.zero-knowledge.org/gibheer/pkictl) diff --git a/ecdsa.go b/ecdsa.go new file mode 100644 index 0000000..170786b --- /dev/null +++ b/ecdsa.go @@ -0,0 +1,69 @@ +package pkilib + +import ( + "crypto" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/x509" + "encoding/pem" + "errors" +) + +const ( + PemLabelEcdsa = "EC PRIVATE KEY" +) + +type ( + // This type handles the function calls to the ecdsa private key by + // implementing the interface. + EcdsaPrivateKey struct { + private_key *ecdsa.PrivateKey + } + + EcdsaPublicKey struct { + public_key *ecdsa.PublicKey + } +) + +// generate a new ecdsa private key +func NewPrivateKeyEcdsa(curve elliptic.Curve) (*EcdsaPrivateKey, error) { + key, err := ecdsa.GenerateKey(curve, rand.Reader) + if err != nil { return nil, err } + return &EcdsaPrivateKey{key}, nil +} + +// load the private key from the raw data +func LoadPrivateKeyEcdsa(raw []byte) (*EcdsaPrivateKey, error) { + key, err := x509.ParseECPrivateKey(raw) + if err != nil { return nil, err } + return &EcdsaPrivateKey{key}, nil +} + +// derive a public key from the private key +func (pr EcdsaPrivateKey) Public() PublicKey { + return &EcdsaPublicKey{pr.private_key.Public().(*ecdsa.PublicKey)} +} + +// sign a message with the private key +func (pr EcdsaPrivateKey) Sign(message []byte) ([]byte, error) { + return make([]byte, 0), errors.New("not implemented yet!") +} + +// get the private key +func (pr EcdsaPrivateKey) privateKey() crypto.PrivateKey { + return pr.private_key +} + +// implement Pemmer interface +func (pr EcdsaPrivateKey) MarshalPem() (marshalledPemBlock, error) { + asn1, err := x509.MarshalECPrivateKey(pr.private_key) + if err != nil { return nil, err } + pem_block := pem.Block{Type: PemLabelEcdsa, Bytes: asn1} + return pem.EncodeToMemory(&pem_block), nil +} + +// verify a message using the ecdsa public key +func (pu *EcdsaPublicKey) Verify(message []byte, signature []byte) (bool, error) { + return false, errors.New("not implemented yet!") +} diff --git a/pem_marshal.go b/pem_marshal.go new file mode 100644 index 0000000..c9be63d --- /dev/null +++ b/pem_marshal.go @@ -0,0 +1,15 @@ +package pkilib + +import ( + "io" +) + +type ( + marshalledPemBlock []byte +) + +// This function writes the marshalled pem block to a writer and returns the +// number of written bytes and eventual errors. +func (b marshalledPemBlock) WriteTo(stream io.Writer) (int, error) { + return stream.Write(b) +} diff --git a/rsa.go b/rsa.go new file mode 100644 index 0000000..48135b2 --- /dev/null +++ b/rsa.go @@ -0,0 +1,54 @@ +package pkilib + +import ( + "crypto" + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "errors" +) + +type ( + RsaPrivateKey struct { + private_key *rsa.PrivateKey + } + + RsaPublicKey struct { + public_key rsa.PublicKey + } +) + +// generate a new rsa private key +func NewPrivateKeyRsa(size int) (*RsaPrivateKey, error) { + key, err := rsa.GenerateKey(rand.Reader, size) + if err != nil { return nil, err } + return &RsaPrivateKey{key}, nil +} + +// load a rsa private key its ASN.1 presentation +func LoadPrivateKeyRsa(raw []byte) (*RsaPrivateKey, error) { + key, err := x509.ParsePKCS1PrivateKey(raw) + if err != nil { return nil, err } + return &RsaPrivateKey{key}, nil +} + +func (pr *RsaPrivateKey) Public() PublicKey { + return &RsaPublicKey{pr.private_key.Public().(rsa.PublicKey)} +} + +func (pr RsaPrivateKey) Sign(message []byte) ([]byte, error) { + return make([]byte, 0), errors.New("not implemented yet!") +} + +// get the private key +func (pr RsaPrivateKey) privateKey() crypto.PrivateKey { + return pr.private_key +} + +func (pr RsaPrivateKey) MarshalPem() (marshalledPemBlock, error) { + return nil, errors.New("not implemented yet!") +} + +func (pu *RsaPublicKey) Verify(message []byte, signature []byte) (bool, error) { + return false, errors.New("not implemented yet!") +} diff --git a/types.go b/types.go new file mode 100644 index 0000000..e9326ee --- /dev/null +++ b/types.go @@ -0,0 +1,31 @@ +package pkilib + +import ( + "crypto" +) + +// this file holds all the interfaces used in the program until it can be split +// properly + +type ( + // interface for any private key + PrivateKey interface { + // derive a public key from the private key + Public() PublicKey + // sign a message with the private key + Sign(message []byte) ([]byte, error) + + // return the private key structure + privateKey() crypto.PrivateKey + } + + // interface for any public key + PublicKey interface { + // use the public key to verify a message against a signature + Verify(message []byte, signature []byte) (bool, error) + } + + Pemmer interface { + MarshalPem() (marshalledPemBlock, error) + } +)