aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--certificate.go212
-rw-r--r--certificate_test.go81
-rw-r--r--ecdsa.go130
-rw-r--r--pem_marshal.go8
-rw-r--r--private_key_test.go141
-rw-r--r--rsa.go70
-rw-r--r--types.go56
7 files changed, 385 insertions, 313 deletions
diff --git a/certificate.go b/certificate.go
index d065ab2..ac66fbc 100644
--- a/certificate.go
+++ b/certificate.go
@@ -1,83 +1,87 @@
package pki
import (
- "crypto/rand"
- "crypto/x509"
- "crypto/x509/pkix"
- "encoding/pem"
- "fmt"
- "math/big"
- "net"
- "time"
+ "crypto/rand"
+ "crypto/x509"
+ "crypto/x509/pkix"
+ "encoding/pem"
+ "fmt"
+ "math/big"
+ "net"
+ "time"
)
// labels used in the pem file format to mark certificate sign requests and certificates
const (
- PemLabelCertificateRequest = "CERTIFICATE REQUEST"
- PemLabelCertificate = "CERTIFICATE"
+ PemLabelCertificateRequest = "CERTIFICATE REQUEST"
+ PemLabelCertificate = "CERTIFICATE"
)
type (
- // Use CertificateData to fill in the minimum data you need to create a certificate
- // sign request.
- CertificateData struct {
- Subject pkix.Name
-
- DNSNames []string
- EmailAddresses []string
- IPAddresses []net.IP
- }
-
- // Certificate is an alias on the x509.Certificate to add some methods.
- Certificate x509.Certificate
- // CertificateRequest is an alias on the x509.CertificateRequest to add some methods.
- CertificateRequest x509.CertificateRequest
-
- // CertificateOptions is used to provide the necessary information to create
- // a certificate from a certificate sign request.
- CertificateOptions struct {
- SerialNumber *big.Int
- NotBefore time.Time
- NotAfter time.Time // Validity bounds.
- IsCA bool
- // how many sub ca are allowed between this ca and the end/final certificate
- // if it is -1, then no limit will be set
- CALength int
- KeyUsage x509.KeyUsage
- }
+ // Use CertificateData to fill in the minimum data you need to create a certificate
+ // sign request.
+ CertificateData struct {
+ Subject pkix.Name
+
+ DNSNames []string
+ EmailAddresses []string
+ IPAddresses []net.IP
+ }
+
+ // Certificate is an alias on the x509.Certificate to add some methods.
+ Certificate x509.Certificate
+ // CertificateRequest is an alias on the x509.CertificateRequest to add some methods.
+ CertificateRequest x509.CertificateRequest
+
+ // CertificateOptions is used to provide the necessary information to create
+ // a certificate from a certificate sign request.
+ CertificateOptions struct {
+ SerialNumber *big.Int
+ NotBefore time.Time
+ NotAfter time.Time // Validity bounds.
+ IsCA bool
+ // how many sub ca are allowed between this ca and the end/final certificate
+ // if it is -1, then no limit will be set
+ CALength int
+ KeyUsage x509.KeyUsage
+ }
)
// Create a new set of certificate data.
func NewCertificateData() *CertificateData {
- return &CertificateData{Subject: pkix.Name{}}
+ return &CertificateData{Subject: pkix.Name{}}
}
// Create a certificate sign request from the input data and the private key of
// the request creator.
func (c *CertificateData) ToCertificateRequest(private_key PrivateKey) (*CertificateRequest, error) {
- csr := &x509.CertificateRequest{}
-
- csr.Subject = c.Subject
- csr.DNSNames = c.DNSNames
- csr.IPAddresses = c.IPAddresses
- csr.EmailAddresses = c.EmailAddresses
-
- csr_asn1, err := x509.CreateCertificateRequest(rand.Reader, csr, private_key.PrivateKey())
- if err != nil { return nil, err }
- return LoadCertificateSignRequest(csr_asn1)
+ csr := &x509.CertificateRequest{}
+
+ csr.Subject = c.Subject
+ csr.DNSNames = c.DNSNames
+ csr.IPAddresses = c.IPAddresses
+ csr.EmailAddresses = c.EmailAddresses
+
+ csr_asn1, err := x509.CreateCertificateRequest(rand.Reader, csr, private_key.PrivateKey())
+ if err != nil {
+ return nil, err
+ }
+ return LoadCertificateSignRequest(csr_asn1)
}
// Load a certificate sign request from its asn1 representation.
func LoadCertificateSignRequest(raw []byte) (*CertificateRequest, error) {
- csr, err := x509.ParseCertificateRequest(raw)
- if err != nil { return nil, err }
- return (*CertificateRequest)(csr), nil
+ csr, err := x509.ParseCertificateRequest(raw)
+ if err != nil {
+ return nil, err
+ }
+ return (*CertificateRequest)(csr), nil
}
// Return the certificate sign request as a pem block.
func (c *CertificateRequest) MarshalPem() (marshalledPemBlock, error) {
- block := &pem.Block{Type: PemLabelCertificateRequest, Bytes: c.Raw}
- return pem.EncodeToMemory(block), nil
+ block := &pem.Block{Type: PemLabelCertificateRequest, Bytes: c.Raw}
+ return pem.EncodeToMemory(block), nil
}
// Convert the certificate sign request to a certificate using the private key
@@ -86,63 +90,71 @@ func (c *CertificateRequest) MarshalPem() (marshalledPemBlock, error) {
// Please also see the certificate options struct for information on mandatory fields.
// For more information, please read http://golang.org/pkg/crypto/x509/#CreateCertificate
func (c *CertificateRequest) ToCertificate(private_key PrivateKey,
- cert_opts CertificateOptions, ca *Certificate) (*Certificate, error) {
-
- if err := cert_opts.Valid(); err != nil { return nil, err }
-
- template := &x509.Certificate{}
- template.Subject = c.Subject
- template.DNSNames = c.DNSNames
- template.IPAddresses = c.IPAddresses
- template.EmailAddresses = c.EmailAddresses
-
- // if no ca is given, we have to set IsCA to self sign
- if ca == nil {
- template.IsCA = true
- }
-
- template.NotBefore = cert_opts.NotBefore
- template.NotAfter = cert_opts.NotAfter
- template.KeyUsage = cert_opts.KeyUsage
- template.IsCA = cert_opts.IsCA
- if cert_opts.IsCA {
- template.BasicConstraintsValid = true
- }
- if cert_opts.CALength >= 0 {
- template.MaxPathLen = cert_opts.CALength
- template.MaxPathLenZero = true
- template.BasicConstraintsValid = true
- }
- template.SerialNumber = cert_opts.SerialNumber
-
- var cert_asn1 []byte
- var err error
- // if we have no ca which can sign the cert, a self signed cert is wanted
- // (or isn't it? Maybe we should split creation of the template? But that would be ugly)
- if ca == nil {
- cert_asn1, err = x509.CreateCertificate(rand.Reader, template, template, c.PublicKey, private_key.PrivateKey())
- } else {
- cert_asn1, err = x509.CreateCertificate(rand.Reader, template, (*x509.Certificate)(ca), c.PublicKey, private_key.PrivateKey())
- }
- if err != nil { return nil, err }
- return LoadCertificate(cert_asn1)
+ cert_opts CertificateOptions, ca *Certificate) (*Certificate, error) {
+
+ if err := cert_opts.Valid(); err != nil {
+ return nil, err
+ }
+
+ template := &x509.Certificate{}
+ template.Subject = c.Subject
+ template.DNSNames = c.DNSNames
+ template.IPAddresses = c.IPAddresses
+ template.EmailAddresses = c.EmailAddresses
+
+ // if no ca is given, we have to set IsCA to self sign
+ if ca == nil {
+ template.IsCA = true
+ }
+
+ template.NotBefore = cert_opts.NotBefore
+ template.NotAfter = cert_opts.NotAfter
+ template.KeyUsage = cert_opts.KeyUsage
+ template.IsCA = cert_opts.IsCA
+ if cert_opts.IsCA {
+ template.BasicConstraintsValid = true
+ }
+ if cert_opts.CALength >= 0 {
+ template.MaxPathLen = cert_opts.CALength
+ template.MaxPathLenZero = true
+ template.BasicConstraintsValid = true
+ }
+ template.SerialNumber = cert_opts.SerialNumber
+
+ var cert_asn1 []byte
+ var err error
+ // if we have no ca which can sign the cert, a self signed cert is wanted
+ // (or isn't it? Maybe we should split creation of the template? But that would be ugly)
+ if ca == nil {
+ cert_asn1, err = x509.CreateCertificate(rand.Reader, template, template, c.PublicKey, private_key.PrivateKey())
+ } else {
+ cert_asn1, err = x509.CreateCertificate(rand.Reader, template, (*x509.Certificate)(ca), c.PublicKey, private_key.PrivateKey())
+ }
+ if err != nil {
+ return nil, err
+ }
+ return LoadCertificate(cert_asn1)
}
// Load a certificate from its asn1 representation.
func LoadCertificate(raw []byte) (*Certificate, error) {
- cert, err := x509.ParseCertificate(raw)
- if err != nil { return nil, err }
- return (*Certificate)(cert), nil
+ cert, err := x509.ParseCertificate(raw)
+ if err != nil {
+ return nil, err
+ }
+ return (*Certificate)(cert), nil
}
// marshal the certificate to a pem block
func (c *Certificate) MarshalPem() (marshalledPemBlock, error) {
- block := &pem.Block{Type: PemLabelCertificate, Bytes: c.Raw}
- return pem.EncodeToMemory(block), nil
+ block := &pem.Block{Type: PemLabelCertificate, Bytes: c.Raw}
+ return pem.EncodeToMemory(block), nil
}
// Check if the certificate options have the required fields set.
func (co *CertificateOptions) Valid() error {
- if co.SerialNumber == nil { return fmt.Errorf("No serial number set!") }
- return nil
+ if co.SerialNumber == nil {
+ return fmt.Errorf("No serial number set!")
+ }
+ return nil
}
diff --git a/certificate_test.go b/certificate_test.go
index 3cb4a64..8616641 100644
--- a/certificate_test.go
+++ b/certificate_test.go
@@ -1,46 +1,61 @@
package pki
import (
- "crypto/elliptic"
-// "crypto/x509"
- "crypto/x509/pkix"
- "math/big"
- "reflect"
- "testing"
+ "crypto/elliptic"
+ "crypto/x509/pkix"
+ "math/big"
+ "reflect"
+ "testing"
)
var (
- TestCertificateData = CertificateData{
- Subject: pkix.Name{CommonName: "foobar"},
- DNSNames: []string{"foo.bar", "example.com"},
- }
+ TestCertificateData = CertificateData{
+ Subject: pkix.Name{CommonName: "foobar"},
+ DNSNames: []string{"foo.bar", "example.com"},
+ }
)
func TestCertificateCreation(t *testing.T) {
- pk, err := NewPrivateKeyEcdsa(elliptic.P224())
- if err != nil { t.Errorf("cert: creating private key failed: %s", err) }
-
- csr, err := TestCertificateData.ToCertificateRequest(pk)
- if err != nil { t.Errorf("cert: creating csr failed: %s", err) }
-
- cert_opts := CertificateOptions{
- // KeyUsage: x509.KeyUsageEncipherOnly | x509.KeyUsageKeyEncipherment | x509.KeyUsageCertSign,
- SerialNumber: big.NewInt(1),
- }
-
- cert, err := csr.ToCertificate(pk, cert_opts, nil)
- if err != nil { t.Errorf("cert: creating cert failed: %s", err) }
-
- if !fieldsAreSame(TestCertificateData, cert) {
- t.Errorf("cert: Fields are not the same")
- }
+ pk, err := NewPrivateKeyEcdsa(elliptic.P224())
+ if err != nil {
+ t.Errorf("cert: creating private key failed: %s", err)
+ }
+
+ csr, err := TestCertificateData.ToCertificateRequest(pk)
+ if err != nil {
+ t.Errorf("cert: creating csr failed: %s", err)
+ }
+
+ cert_opts := CertificateOptions{
+ // KeyUsage: x509.KeyUsageEncipherOnly | x509.KeyUsageKeyEncipherment | x509.KeyUsageCertSign,
+ SerialNumber: big.NewInt(1),
+ }
+
+ cert, err := csr.ToCertificate(pk, cert_opts, nil)
+ if err != nil {
+ t.Errorf("cert: creating cert failed: %s", err)
+ }
+
+ if !fieldsAreSame(TestCertificateData, cert) {
+ t.Errorf("cert: Fields are not the same")
+ }
}
func fieldsAreSame(data CertificateData, cert *Certificate) bool {
- if data.Subject.CommonName != cert.Subject.CommonName { return false }
- if !reflect.DeepEqual(data.Subject.Country, cert.Subject.Country) { return false }
- if !reflect.DeepEqual(data.DNSNames, cert.DNSNames) { return false }
- if !reflect.DeepEqual(data.IPAddresses, cert.IPAddresses) { return false }
- if !reflect.DeepEqual(data.EmailAddresses, cert.EmailAddresses) { return false }
- return true
+ if data.Subject.CommonName != cert.Subject.CommonName {
+ return false
+ }
+ if !reflect.DeepEqual(data.Subject.Country, cert.Subject.Country) {
+ return false
+ }
+ if !reflect.DeepEqual(data.DNSNames, cert.DNSNames) {
+ return false
+ }
+ if !reflect.DeepEqual(data.IPAddresses, cert.IPAddresses) {
+ return false
+ }
+ if !reflect.DeepEqual(data.EmailAddresses, cert.EmailAddresses) {
+ return false
+ }
+ return true
}
diff --git a/ecdsa.go b/ecdsa.go
index 96c317f..66b73f5 100644
--- a/ecdsa.go
+++ b/ecdsa.go
@@ -1,112 +1,126 @@
package pki
import (
- "crypto"
- "crypto/ecdsa"
- "crypto/elliptic"
- "crypto/rand"
- "crypto/x509"
- "encoding/asn1"
- "encoding/pem"
- "errors"
- "io"
- "math/big"
+ "crypto"
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "crypto/rand"
+ "crypto/x509"
+ "encoding/asn1"
+ "encoding/pem"
+ "errors"
+ "io"
+ "math/big"
)
// This label is used as the type in the pem encoding of ECDSA private keys.
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
- }
+ // This type handles the function calls to the ecdsa private key by
+ // implementing the interface.
+ EcdsaPrivateKey struct {
+ private_key *ecdsa.PrivateKey
+ }
- // EcdsaPublicKey is the specific public key type for ecdsa. It implements the
- // the PublicKey interface.
- EcdsaPublicKey struct {
- public_key *ecdsa.PublicKey
- }
+ // EcdsaPublicKey is the specific public key type for ecdsa. It implements the
+ // the PublicKey interface.
+ EcdsaPublicKey struct {
+ public_key *ecdsa.PublicKey
+ }
- // This struct is used to marshal and parse the ecdsa signature.
- signatureEcdsa struct {
- R, S *big.Int
- }
+ // This struct is used to marshal and parse the ecdsa signature.
+ signatureEcdsa struct {
+ R, S *big.Int
+ }
)
// Create a new ECDSA private key using the specified curve.
// For available curves, please take a look at the crypto/elliptic package.
func NewPrivateKeyEcdsa(curve elliptic.Curve) (*EcdsaPrivateKey, error) {
- key, err := ecdsa.GenerateKey(curve, rand.Reader)
- if err != nil { return nil, err }
- return &EcdsaPrivateKey{key}, nil
+ key, err := ecdsa.GenerateKey(curve, rand.Reader)
+ if err != nil {
+ return nil, err
+ }
+ return &EcdsaPrivateKey{key}, nil
}
// Load the private key from the asn1 representation.
func LoadPrivateKeyEcdsa(raw []byte) (*EcdsaPrivateKey, error) {
- key, err := x509.ParseECPrivateKey(raw)
- if err != nil { return nil, err }
- return &EcdsaPrivateKey{key}, nil
+ key, err := x509.ParseECPrivateKey(raw)
+ if err != nil {
+ return nil, err
+ }
+ return &EcdsaPrivateKey{key}, nil
}
// Create a new public key from the private key.
func (pr EcdsaPrivateKey) Public() PublicKey {
- return &EcdsaPublicKey{pr.private_key.Public().(*ecdsa.PublicKey)}
+ return &EcdsaPublicKey{pr.private_key.Public().(*ecdsa.PublicKey)}
}
// Sign a message using the private key and the provided hash function.
func (pr EcdsaPrivateKey) Sign(message []byte, hash crypto.Hash) ([]byte, error) {
- empty := make([]byte, 0)
- if !hash.Available() {
- return empty, errors.New("Hash method is not available!")
- }
- hashed_message := hash.New()
- hashed_message.Write(message)
- return pr.private_key.Sign(rand.Reader, hashed_message.Sum(nil), hash)
+ empty := make([]byte, 0)
+ if !hash.Available() {
+ return empty, errors.New("Hash method is not available!")
+ }
+ hashed_message := hash.New()
+ hashed_message.Write(message)
+ return pr.private_key.Sign(rand.Reader, hashed_message.Sum(nil), hash)
}
// This function returns the crypto.PrivateKey structure of the ECDSA key.
func (pr EcdsaPrivateKey) PrivateKey() crypto.PrivateKey {
- return pr.private_key
+ return pr.private_key
}
// This function implements the Pemmer interface to marshal the private key
// into a pem block.
func (pr EcdsaPrivateKey) MarshalPem() (io.WriterTo, error) {
- asn1, err := x509.MarshalECPrivateKey(pr.private_key)
- if err != nil { return nil, err }
- pem_block := pem.Block{Type: PemLabelEcdsa, Bytes: asn1}
- return marshalledPemBlock(pem.EncodeToMemory(&pem_block)), nil
+ asn1, err := x509.MarshalECPrivateKey(pr.private_key)
+ if err != nil {
+ return nil, err
+ }
+ pem_block := pem.Block{Type: PemLabelEcdsa, Bytes: asn1}
+ return marshalledPemBlock(pem.EncodeToMemory(&pem_block)), nil
}
// This functoin loads an ecdsa public key from the asn.1 representation.
func LoadPublicKeyEcdsa(raw []byte) (*EcdsaPublicKey, error) {
- raw_pub, err := x509.ParsePKIXPublicKey(raw)
- if err != nil { return nil, err }
+ raw_pub, err := x509.ParsePKIXPublicKey(raw)
+ if err != nil {
+ return nil, err
+ }
- pub, ok := raw_pub.(*ecdsa.PublicKey)
- if !ok { return nil, errors.New("Not an ecdsa key!") }
- return &EcdsaPublicKey{pub}, nil
+ pub, ok := raw_pub.(*ecdsa.PublicKey)
+ if !ok {
+ return nil, errors.New("Not an ecdsa key!")
+ }
+ return &EcdsaPublicKey{pub}, nil
}
// This function implements the Pemmer interface to marshal the public key into
// a pem block.
func (pu *EcdsaPublicKey) MarshalPem() (io.WriterTo, error) {
- asn1, err := x509.MarshalPKIXPublicKey(pu.public_key)
- if err != nil { return nil, err }
- pem_block := pem.Block{Type: PemLabelPublic, Bytes: asn1}
- return marshalledPemBlock(pem.EncodeToMemory(&pem_block)), nil
+ asn1, err := x509.MarshalPKIXPublicKey(pu.public_key)
+ if err != nil {
+ return nil, err
+ }
+ pem_block := pem.Block{Type: PemLabelPublic, Bytes: asn1}
+ return marshalledPemBlock(pem.EncodeToMemory(&pem_block)), nil
}
// This function verifies a message using the public key, signature and hash
// function.
// The hash function must be the same as was used to create the signature.
func (pu *EcdsaPublicKey) Verify(message []byte, signature_raw []byte, hash crypto.Hash) (bool, error) {
- var sig signatureEcdsa
- _, err := asn1.Unmarshal(signature_raw, &sig)
- if err != nil { return false, err }
- hashed_message := hash.New()
- hashed_message.Write(message)
- return ecdsa.Verify(pu.public_key, hashed_message.Sum(nil), sig.R, sig.S), nil
+ var sig signatureEcdsa
+ _, err := asn1.Unmarshal(signature_raw, &sig)
+ if err != nil {
+ return false, err
+ }
+ hashed_message := hash.New()
+ hashed_message.Write(message)
+ return ecdsa.Verify(pu.public_key, hashed_message.Sum(nil), sig.R, sig.S), nil
}
diff --git a/pem_marshal.go b/pem_marshal.go
index 54ce1e0..89bd477 100644
--- a/pem_marshal.go
+++ b/pem_marshal.go
@@ -1,16 +1,16 @@
package pki
import (
- "io"
+ "io"
)
type (
- marshalledPemBlock []byte
+ 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) (int64, error) {
- numBytes, err := stream.Write(b)
- return int64(numBytes), err
+ numBytes, err := stream.Write(b)
+ return int64(numBytes), err
}
diff --git a/private_key_test.go b/private_key_test.go
index a22d2ed..7479f11 100644
--- a/private_key_test.go
+++ b/private_key_test.go
@@ -1,84 +1,109 @@
package pki
import (
- "crypto"
- "crypto/elliptic"
- "encoding/pem"
- "testing"
+ "crypto"
+ "crypto/elliptic"
+ "encoding/pem"
+ "testing"
)
var (
- SignatureMessage = []byte("foobar")
- SignatureHash = crypto.SHA512
+ SignatureMessage = []byte("foobar")
+ SignatureHash = crypto.SHA512
)
type (
- Loader func(raw []byte) (PublicKey, error)
+ Loader func(raw []byte) (PublicKey, error)
)
// run the marshal test
func RunMarshalTest(pkType string, pe Pemmer, label string, t *testing.T) ([]byte, error) {
- marshPem, err := pe.MarshalPem()
- if err != nil {
- t.Errorf("%s: marshal pem not working: %s", pkType, err)
- return nil, err
- }
-
- block, _ := pem.Decode(marshPem)
- if block.Type != label {
- t.Errorf("%s: marshalled pem wrong: %s", pkType, err)
- return nil, err
- }
- return block.Bytes, nil
+ marshPem, err := pe.MarshalPem()
+ if err != nil {
+ t.Errorf("%s: marshal pem not working: %s", pkType, err)
+ return nil, err
+ }
+
+ block, _ := pem.Decode(marshPem)
+ if block.Type != label {
+ t.Errorf("%s: marshalled pem wrong: %s", pkType, err)
+ return nil, err
+ }
+ return block.Bytes, nil
}
// test other private key functions
func RunPrivateKeyTests(pkType string, pk PrivateKey, pu PublicKey, t *testing.T) {
- signature, err := pk.Sign(SignatureMessage, SignatureHash)
- if err != nil { t.Errorf("%s: error creating a signature: %s", pkType, err) }
-
- valid, err := pu.Verify(SignatureMessage, signature, SignatureHash)
- if err != nil { t.Errorf("%s: could not verify message: %s", pkType, err) }
- if !valid { t.Errorf("%s: signature invalid, but should be valid!", pkType) }
+ signature, err := pk.Sign(SignatureMessage, SignatureHash)
+ if err != nil {
+ t.Errorf("%s: error creating a signature: %s", pkType, err)
+ }
+
+ valid, err := pu.Verify(SignatureMessage, signature, SignatureHash)
+ if err != nil {
+ t.Errorf("%s: could not verify message: %s", pkType, err)
+ }
+ if !valid {
+ t.Errorf("%s: signature invalid, but should be valid!", pkType)
+ }
}
// test ecdsa private key functions
func TestEcdsaFunctions(t *testing.T) {
- pk, err := NewPrivateKeyEcdsa(elliptic.P521())
- if err != nil { t.Errorf("ecdsa: creating private key failed: %s", err) }
-
- blockBytes, err := RunMarshalTest("ecdsa", pk, PemLabelEcdsa, t)
- if err != nil { return }
-
- pk, err = LoadPrivateKeyEcdsa(blockBytes)
- if err != nil { t.Errorf("ecdsa: pem content wrong: %s", err) }
-
- blockBytes, err = RunMarshalTest("ecdsa-public", pk.Public(), PemLabelPublic, t)
- if err != nil { return }
-
- pu, err := LoadPublicKeyEcdsa(blockBytes)
- if err != nil { t.Errorf("ecdsa-public: pem content wrong: %s", err) }
-
- RunPrivateKeyTests("ecdsa", pk, pu, t)
+ pk, err := NewPrivateKeyEcdsa(elliptic.P521())
+ if err != nil {
+ t.Errorf("ecdsa: creating private key failed: %s", err)
+ }
+
+ blockBytes, err := RunMarshalTest("ecdsa", pk, PemLabelEcdsa, t)
+ if err != nil {
+ return
+ }
+
+ pk, err = LoadPrivateKeyEcdsa(blockBytes)
+ if err != nil {
+ t.Errorf("ecdsa: pem content wrong: %s", err)
+ }
+
+ blockBytes, err = RunMarshalTest("ecdsa-public", pk.Public(), PemLabelPublic, t)
+ if err != nil {
+ return
+ }
+
+ pu, err := LoadPublicKeyEcdsa(blockBytes)
+ if err != nil {
+ t.Errorf("ecdsa-public: pem content wrong: %s", err)
+ }
+
+ RunPrivateKeyTests("ecdsa", pk, pu, t)
}
// test rsa private key functions
func TestRsaFunctions(t *testing.T) {
- pk, err := NewPrivateKeyRsa(2048)
- if err != nil { t.Errorf("rsa: creating private key failed: %s", err) }
-
- blockBytes, err := RunMarshalTest("rsa", pk, PemLabelRsa, t)
- if err != nil { return }
-
- pk, err = LoadPrivateKeyRsa(blockBytes)
- if err != nil { t.Errorf("rsa: pem content wrong: %s", err) }
-
-
- blockBytes, err = RunMarshalTest("rsa-public", pk.Public(), PemLabelPublic, t)
- if err != nil { return }
-
- pu, err := LoadPublicKeyRsa(blockBytes)
- if err != nil { t.Errorf("rsa-public: pem content wrong: %s", err) }
-
- RunPrivateKeyTests("rsa", pk, pu, t)
+ pk, err := NewPrivateKeyRsa(2048)
+ if err != nil {
+ t.Errorf("rsa: creating private key failed: %s", err)
+ }
+
+ blockBytes, err := RunMarshalTest("rsa", pk, PemLabelRsa, t)
+ if err != nil {
+ return
+ }
+
+ pk, err = LoadPrivateKeyRsa(blockBytes)
+ if err != nil {
+ t.Errorf("rsa: pem content wrong: %s", err)
+ }
+
+ blockBytes, err = RunMarshalTest("rsa-public", pk.Public(), PemLabelPublic, t)
+ if err != nil {
+ return
+ }
+
+ pu, err := LoadPublicKeyRsa(blockBytes)
+ if err != nil {
+ t.Errorf("rsa-public: pem content wrong: %s", err)
+ }
+
+ RunPrivateKeyTests("rsa", pk, pu, t)
}
diff --git a/rsa.go b/rsa.go
index bcdfe6e..11a770b 100644
--- a/rsa.go
+++ b/rsa.go
@@ -1,76 +1,82 @@
package pki
import (
- "crypto"
- "crypto/rand"
- "crypto/rsa"
- "crypto/x509"
- "encoding/pem"
- "errors"
- "io"
+ "crypto"
+ "crypto/rand"
+ "crypto/rsa"
+ "crypto/x509"
+ "encoding/pem"
+ "errors"
+ "io"
)
const (
- PemLabelRsa = "RSA PRIVATE KEY"
+ PemLabelRsa = "RSA PRIVATE KEY"
)
type (
- RsaPrivateKey struct {
- private_key *rsa.PrivateKey
- }
+ RsaPrivateKey struct {
+ private_key *rsa.PrivateKey
+ }
- RsaPublicKey struct {
- public_key *rsa.PublicKey
- }
+ 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
+ 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
+ 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)}
+ return &RsaPublicKey{pr.private_key.Public().(*rsa.PublicKey)}
}
func (pr RsaPrivateKey) Sign(message []byte, hash crypto.Hash) ([]byte, error) {
- return make([]byte, 0), errors.New("not implemented yet!")
+ return make([]byte, 0), errors.New("not implemented yet!")
}
// get the private key
func (pr RsaPrivateKey) PrivateKey() crypto.PrivateKey {
- return pr.private_key
+ return pr.private_key
}
func (pr RsaPrivateKey) MarshalPem() (io.WriterTo, error) {
- asn1 := x509.MarshalPKCS1PrivateKey(pr.private_key)
- pem_block := pem.Block{Type: PemLabelRsa, Bytes: asn1}
- return marshalledPemBlock(pem.EncodeToMemory(&pem_block)), nil
+ asn1 := x509.MarshalPKCS1PrivateKey(pr.private_key)
+ pem_block := pem.Block{Type: PemLabelRsa, Bytes: asn1}
+ return marshalledPemBlock(pem.EncodeToMemory(&pem_block)), nil
}
// restore a rsa public key
func LoadPublicKeyRsa(raw []byte) (*RsaPublicKey, error) {
- return nil, errors.New("not implemented yet!")
+ return nil, errors.New("not implemented yet!")
}
// marshal a rsa public key into pem format
func (pu *RsaPublicKey) MarshalPem() (io.WriterTo, error) {
- asn1, err := x509.MarshalPKIXPublicKey(pu.public_key)
- if err != nil { return nil, err }
- pem_block := pem.Block{Type: PemLabelPublic, Bytes: asn1}
- return marshalledPemBlock(pem.EncodeToMemory(&pem_block)), nil
+ asn1, err := x509.MarshalPKIXPublicKey(pu.public_key)
+ if err != nil {
+ return nil, err
+ }
+ pem_block := pem.Block{Type: PemLabelPublic, Bytes: asn1}
+ return marshalledPemBlock(pem.EncodeToMemory(&pem_block)), nil
}
// verify a message with a signature using the public key
func (pu *RsaPublicKey) Verify(message []byte, signature []byte, hash crypto.Hash) (bool, error) {
- return false, errors.New("not implemented yet!")
+ return false, errors.New("not implemented yet!")
}
diff --git a/types.go b/types.go
index 5feb2b1..47fe31a 100644
--- a/types.go
+++ b/types.go
@@ -15,41 +15,41 @@
package pki
import (
- "crypto"
- "io"
+ "crypto"
+ "io"
)
// This label is used as the type in the pem encoding of public keys.
const PemLabelPublic = "PUBLIC KEY"
type (
- // PrivateKey is a common interface for all crypto implementations to provide
- // the same functions, like deriving a public key or signing a message.
- PrivateKey interface {
- // Derive a new public key from the private key.
- Public() PublicKey
- // Sign a message using the public key and the given hash method.
- // To use a hash method, include the package
- // import _ "crypto/sha512"
- Sign(message []byte, hash crypto.Hash) ([]byte, error)
+ // PrivateKey is a common interface for all crypto implementations to provide
+ // the same functions, like deriving a public key or signing a message.
+ PrivateKey interface {
+ // Derive a new public key from the private key.
+ Public() PublicKey
+ // Sign a message using the public key and the given hash method.
+ // To use a hash method, include the package
+ // import _ "crypto/sha512"
+ Sign(message []byte, hash crypto.Hash) ([]byte, error)
- // Return the original go structure of the private key.
- PrivateKey() crypto.PrivateKey
- }
+ // Return the original go structure of the private key.
+ PrivateKey() crypto.PrivateKey
+ }
- // PublicKey is used by the different crypto implementations to provide the
- // same functionality like verifying a message against a signature.
- PublicKey interface {
- Pemmer
- // This function can be used to verify a message against a provided signature
- // using the given hash function.
- Verify(message []byte, signature []byte, hash crypto.Hash) (bool, error)
- }
+ // PublicKey is used by the different crypto implementations to provide the
+ // same functionality like verifying a message against a signature.
+ PublicKey interface {
+ Pemmer
+ // This function can be used to verify a message against a provided signature
+ // using the given hash function.
+ Verify(message []byte, signature []byte, hash crypto.Hash) (bool, error)
+ }
- // Pemmer is used by all crypto structures which need to be available
- // in the pem format. The result can then be written to any structure
- // implementing the io.Writer interface.
- Pemmer interface {
- MarshalPem() (io.WriterTo, error)
- }
+ // Pemmer is used by all crypto structures which need to be available
+ // in the pem format. The result can then be written to any structure
+ // implementing the io.Writer interface.
+ Pemmer interface {
+ MarshalPem() (io.WriterTo, error)
+ }
)