Skip to content

Commit

Permalink
Merge pull request #96 from cviecco/add-library-support-for-ed25519-keys
Browse files Browse the repository at this point in the history
Add library support for ed25519 ssh certificates
  • Loading branch information
cviecco authored Mar 8, 2021
2 parents 8f7a3e3 + 7d2c0ae commit 492143b
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 3 deletions.
23 changes: 21 additions & 2 deletions lib/certgen/certgen.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ func GetUserPubKeyFromSSSD(username string) (string, error) {
func goCertToFileString(c ssh.Certificate, username string) (string, error) {
certBytes := c.Marshal()
encoded := base64.StdEncoding.EncodeToString(certBytes)
fileComment := "/tmp/" + username + "-cert.pub"
return "ssh-rsa-cert-v01@openssh.com " + encoded + " " + fileComment, nil
fileComment := "/tmp/" + username + "-" + c.SignatureKey.Type() + "-cert.pub"
return c.Type() + " " + encoded + " " + fileComment, nil
}

// gen_user_cert a username and key, returns a short lived cert for that user
Expand Down Expand Up @@ -133,6 +133,23 @@ func GetSignerFromPEMBytes(privateKey []byte) (crypto.Signer, error) {
return v, nil
case *ecdsa.PrivateKey:
return v, nil
case ed25519.PrivateKey:
return v, nil
default:
return nil, fmt.Errorf("Type not recognized %T!\n", v)
}
case "OPENSSH PRIVATE KEY":
parsedIface, err := ssh.ParseRawPrivateKey(privateKey)
if err != nil {
return nil, err
}
switch v := parsedIface.(type) {
case *rsa.PrivateKey:
return v, nil
case *ecdsa.PrivateKey:
return v, nil
case *ed25519.PrivateKey:
return v, nil
default:
return nil, fmt.Errorf("Type not recognized %T!\n", v)
}
Expand All @@ -150,6 +167,8 @@ func publicKey(priv interface{}) interface{} {
// TODO: eventaully we need to suport ecdsa for CA
// case *ecdsa.PrivateKey:
// return &k.PublicKey
case ed25519.PrivateKey:
return k.Public().(ed25519.PublicKey)
default:
return nil
}
Expand Down
45 changes: 44 additions & 1 deletion lib/certgen/certgen_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"encoding/pem"
"os"
"os/user"
"strings"
"testing"
"time"

Expand Down Expand Up @@ -199,6 +200,20 @@ RBm1g0vfLOjV1tPs5/0QMy7ANExMLGtzIJidWWWzIzw2rx4WC7xcIkJ+iWFIIFNy
S9RSPfwJS7+Zr8LP4H6APpstQWZEXOo=
-----END EC PRIVATE KEY-----`

//openssl genpkey -algorithm ED25519 -out key.pem
const pkcs8Ed25519PrivateKey = `-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VwBCIEIHoHbl2RwHwmyWtXVLroUZEI+d/SqL3RKmECM5P7o7D5
-----END PRIVATE KEY-----`

// ssh-keygen -t ed25519
const keygenEd25519PrivateKey = `-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACDICn5DsRIjR4GyKVUPucWJ7A3+7TKoNfK/ImglUc6shQAAAKDzYr6j82K+
owAAAAtzc2gtZWQyNTUxOQAAACDICn5DsRIjR4GyKVUPucWJ7A3+7TKoNfK/ImglUc6shQ
AAAECdSciYZnODYp2QC0s838bYh8d2XEOuvBOqcOEA6MUjL8gKfkOxEiNHgbIpVQ+5xYns
Df7tMqg18r8iaCVRzqyFAAAAHWN2aWVjY29AY3ZpZWNjby0tTWFjQm9va1BybzE1
-----END OPENSSH PRIVATE KEY-----`

const testDuration = time.Duration(120 * time.Second)

// SSSD tests do require some setup... in this case we do some checks to ensure
Expand Down Expand Up @@ -241,10 +256,28 @@ func TestGenSSHCertFileStringGenerateSuccess(t *testing.T) {
t.Fatal(err)
}
t.Logf("got '%s'", certString)
if !strings.HasPrefix(certString, "ssh-rsa-cert-v01@openssh.com ") {
t.Logf("wrong prefix on stringification rsa-cert")
}
if len(cert.ValidPrincipals) != 1 || cert.ValidPrincipals[0] != username {
t.Fatal("invalid cert content, bad username")
}
// now test with an Ed25519
goodEd25519Signer, err := ssh.ParsePrivateKey([]byte(pkcs8Ed25519PrivateKey))
if err != nil {
t.Fatal(err)
}
certString, cert, err = GenSSHCertFileString(username, ed25519PublicSSH, goodEd25519Signer, hostIdentity, testDuration)
if err != nil {
t.Fatal(err)
}
t.Logf("got '%s'", certString)
if !strings.HasPrefix(certString, "ssh-ed25519-cert-v01@openssh.com ") {
t.Logf("wrong prefix on stringification for ed25519")
}
if len(cert.ValidPrincipals) != 1 || cert.ValidPrincipals[0] != username {
t.Fatal("invalid cert content, bad username")
}

}

func TestGenSSHCertFileStringGenerateFailBadPublicKey(t *testing.T) {
Expand Down Expand Up @@ -531,6 +564,16 @@ func TestGetSignerFromPEMBytesSuccess(t *testing.T) {
if err != nil {
t.Fatal(err)
}
// Ed25519 from openssl
_, err = GetSignerFromPEMBytes([]byte(pkcs8Ed25519PrivateKey))
if err != nil {
t.Fatal(err)
}
// keygenEd25519PrivateKey
_, err = GetSignerFromPEMBytes([]byte(keygenEd25519PrivateKey))
if err != nil {
t.Fatal(err)
}
}

func TestGetPubKeyFromPem(t *testing.T) {
Expand Down

0 comments on commit 492143b

Please sign in to comment.