diff options
-rw-r--r-- | certificate.go | 212 | ||||
-rw-r--r-- | certificate_test.go | 81 | ||||
-rw-r--r-- | ecdsa.go | 130 | ||||
-rw-r--r-- | pem_marshal.go | 8 | ||||
-rw-r--r-- | private_key_test.go | 141 | ||||
-rw-r--r-- | rsa.go | 70 | ||||
-rw-r--r-- | types.go | 56 |
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 } @@ -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) } @@ -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!") } @@ -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) + } ) |