Skip to content

Commit

Permalink
add rsa & ssh to config_server
Browse files Browse the repository at this point in the history
Signed-off-by: dmitriy kalinin <dkalinin@pivotal.io>
  • Loading branch information
DennisDenuto authored and cppforlife committed Nov 17, 2016
1 parent 1752cc9 commit 10de537
Show file tree
Hide file tree
Showing 6 changed files with 295 additions and 0 deletions.
76 changes: 76 additions & 0 deletions vendor/config_server/types/rsa_key_generator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package types

import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"fmt"
)

const (
rsaKeyGeneratorKeyBits = 2048
rsaKeyGeneratorHeaderPrivateKey = "RSA PRIVATE KEY"
rsaKeyGeneratorHeaderPublicKey = "PUBLIC KEY"
)

type RSAKeyGenerator struct{}

func NewRSAKeyGenerator() RSAKeyGenerator {
return RSAKeyGenerator{}
}

type RSAKey struct {
PrivateKey string `json:"private_key" yaml:"private_key"`
PublicKey string `json:"public_key" yaml:"public_key"`
}

func (g RSAKeyGenerator) Generate(parameters interface{}) (interface{}, error) {
priv, pub, err := g.generateRSAKeyPair()
if err != nil {
return nil, fmt.Errorf("Generating RSA key pair: %s", err)
}

pubKeyStr, err := g.publicKeyToPEM(pub)
if err != nil {
return nil, fmt.Errorf("Generating RSA public key pair: %s", err)
}

return RSAKey{
PrivateKey: g.privateKeyToPEM(priv),
PublicKey: pubKeyStr,
}, nil
}

func (g RSAKeyGenerator) encodePEM(keyBytes []byte, keyType string) string {
block := &pem.Block{
Type: keyType,
Bytes: keyBytes,
}

return string(pem.EncodeToMemory(block))
}

func (g RSAKeyGenerator) generateRSAKeyPair() (*rsa.PrivateKey, *rsa.PublicKey, error) {
private, err := rsa.GenerateKey(rand.Reader, rsaKeyGeneratorKeyBits)
if err != nil {
return nil, nil, err
}

public := private.Public().(*rsa.PublicKey)

return private, public, nil
}

func (g RSAKeyGenerator) privateKeyToPEM(privateKey *rsa.PrivateKey) string {
return g.encodePEM(x509.MarshalPKCS1PrivateKey(privateKey), rsaKeyGeneratorHeaderPrivateKey)
}

func (g RSAKeyGenerator) publicKeyToPEM(publicKey *rsa.PublicKey) (string, error) {
keyBytes, err := x509.MarshalPKIXPublicKey(publicKey)
if err != nil {
return "", err
}

return g.encodePEM(keyBytes, rsaKeyGeneratorHeaderPublicKey), nil
}
59 changes: 59 additions & 0 deletions vendor/config_server/types/rsa_key_generator_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package types_test

import (
"crypto/x509"
"encoding/json"
"encoding/pem"

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"gopkg.in/yaml.v2"

. "config_server/types"
)

var _ = FDescribe("RSAKeyGenerator", func() {
var generator ValueGenerator

BeforeEach(func() {
generator = NewRSAKeyGenerator()
})

Context("Generate", func() {
It("generates an rsa key with 2048 bits", func() {
rsaKey, err := generator.Generate(nil)
Expect(err).ToNot(HaveOccurred())

typedRSAKey := rsaKey.(RSAKey)
Expect(typedRSAKey.PrivateKey).To(ContainSubstring("PRIVATE KEY"))
Expect(typedRSAKey.PublicKey).To(ContainSubstring("PUBLIC KEY"))

privBlock, _ := pem.Decode([]byte(typedRSAKey.PrivateKey))

privKey, err := x509.ParsePKCS1PrivateKey(privBlock.Bytes)
Expect(err).ToNot(HaveOccurred())

pubBlock, _ := pem.Decode([]byte(typedRSAKey.PublicKey))

pubKey, err := x509.ParsePKIXPublicKey(pubBlock.Bytes)
Expect(err).ToNot(HaveOccurred())

Expect(privKey.Public()).To(Equal(pubKey))
})

It("serializes nicely in json/yaml", func() {
rsaKey, err := generator.Generate(nil)
Expect(err).ToNot(HaveOccurred())

bytes, err := yaml.Marshal(rsaKey)
Expect(err).ToNot(HaveOccurred())
Expect(string(bytes)).To(ContainSubstring("private_key"))
Expect(string(bytes)).To(ContainSubstring("public_key"))

bytes, err = json.Marshal(rsaKey)
Expect(err).ToNot(HaveOccurred())
Expect(string(bytes)).To(ContainSubstring("private_key"))
Expect(string(bytes)).To(ContainSubstring("public_key"))
})
})
})
82 changes: 82 additions & 0 deletions vendor/config_server/types/ssh_key_generator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package types

import (
"crypto/md5"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"fmt"

"golang.org/x/crypto/ssh"
)

const (
sshKeyGeneratorKeyBits = 2048
sshKeyGeneratorHeaderPrivateKey = "RSA PRIVATE KEY"
sshKeyGeneratorHeaderPublicKey = "PUBLIC KEY"
)

type SSHKeyGenerator struct{}

func NewSSHKeyGenerator() SSHKeyGenerator {
return SSHKeyGenerator{}
}

type SSHKey struct {
PrivateKey string `json:"private_key" yaml:"private_key"`
PublicKey string `json:"public_key" yaml:"public_key"`
PublicKeyFingerprint string `json:"public_key_fingerprint" yaml:"public_key_fingerprint"`
}

func (g SSHKeyGenerator) Generate(parameters interface{}) (interface{}, error) {
priv, pub, err := g.generateRSAKeyPair()
if err != nil {
return nil, fmt.Errorf("Generating RSA key pair: %s", err)
}

sshPubKey, err := ssh.NewPublicKey(pub)
if err != nil {
return nil, err
}

return SSHKey{
PrivateKey: g.privateKeyToPEM(priv),
PublicKey: string(ssh.MarshalAuthorizedKey(sshPubKey)),
PublicKeyFingerprint: g.fingerprintMD5(sshPubKey),
}, nil
}

func (g SSHKeyGenerator) encodePEM(keyBytes []byte, keyType string) string {
block := &pem.Block{
Type: keyType,
Bytes: keyBytes,
}

return string(pem.EncodeToMemory(block))
}

func (g SSHKeyGenerator) generateRSAKeyPair() (*rsa.PrivateKey, *rsa.PublicKey, error) {
private, err := rsa.GenerateKey(rand.Reader, sshKeyGeneratorKeyBits)
if err != nil {
return nil, nil, err
}
public := private.Public().(*rsa.PublicKey)
return private, public, nil
}

func (g SSHKeyGenerator) privateKeyToPEM(privateKey *rsa.PrivateKey) string {
return g.encodePEM(x509.MarshalPKCS1PrivateKey(privateKey), sshKeyGeneratorHeaderPrivateKey)
}

func (g SSHKeyGenerator) fingerprintMD5(key ssh.PublicKey) string {
hash := md5.Sum(key.Marshal())
out := ""
for i := 0; i < len(hash); i++ {
if i > 0 {
out += ":"
}
out += fmt.Sprintf("%02x", hash[i]) // don't forget the leading zeroes
}
return out
}
62 changes: 62 additions & 0 deletions vendor/config_server/types/ssh_key_generator_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package types_test

import (
"crypto/x509"
"encoding/json"
"encoding/pem"

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"golang.org/x/crypto/ssh"
"gopkg.in/yaml.v2"

. "config_server/types"
)

var _ = FDescribe("SSHKeyGenerator", func() {
var generator ValueGenerator

BeforeEach(func() {
generator = NewSSHKeyGenerator()
})

Context("Generate", func() {
It("generates an ssh key with 2048 bits", func() {
sshKey, err := generator.Generate(nil)
Expect(err).ToNot(HaveOccurred())

typedSSHKey := sshKey.(SSHKey)
Expect(typedSSHKey.PrivateKey).To(ContainSubstring("PRIVATE KEY"))
Expect(len(typedSSHKey.PublicKeyFingerprint)).To(Equal(47))
Expect(typedSSHKey.PublicKey).To(ContainSubstring("ssh-rsa "))

privBlock, _ := pem.Decode([]byte(typedSSHKey.PrivateKey))

privKey, err := x509.ParsePKCS1PrivateKey(privBlock.Bytes)
Expect(err).ToNot(HaveOccurred())

pubKey, err := ssh.NewPublicKey(privKey.Public())
Expect(err).ToNot(HaveOccurred())

expectedPubKey := ssh.MarshalAuthorizedKey(pubKey)
Expect(expectedPubKey).To(Equal([]byte(typedSSHKey.PublicKey)))
})

It("serializes nicely in json/yaml", func() {
sshKey, err := generator.Generate(nil)
Expect(err).ToNot(HaveOccurred())

bytes, err := yaml.Marshal(sshKey)
Expect(err).ToNot(HaveOccurred())
Expect(string(bytes)).To(ContainSubstring("private_key"))
Expect(string(bytes)).To(ContainSubstring("public_key"))
Expect(string(bytes)).To(ContainSubstring("public_key_fingerprint"))

bytes, err = json.Marshal(sshKey)
Expect(err).ToNot(HaveOccurred())
Expect(string(bytes)).To(ContainSubstring("private_key"))
Expect(string(bytes)).To(ContainSubstring("public_key"))
Expect(string(bytes)).To(ContainSubstring("public_key_fingerprint"))
})
})
})
12 changes: 12 additions & 0 deletions vendor/config_server/types/suite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package types_test

import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"testing"
)

func TestReg(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "config_server/types")
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ func (vgc ValueGeneratorConcrete) GetGenerator(valueType string) (ValueGenerator
switch valueType {
case "password":
return NewPasswordGenerator(), nil
case "ssh":
return NewSSHKeyGenerator(), nil
case "rsa":
return NewRSAKeyGenerator(), nil
case "certificate":
return NewCertificateGenerator(vgc.loader), nil
default:
Expand Down

0 comments on commit 10de537

Please sign in to comment.