Skip to content

Instantly share code, notes, and snippets.

@fishnix
Last active April 20, 2022 01:35
Show Gist options
  • Save fishnix/f3551e101e703641cd85833bf57525df to your computer and use it in GitHub Desktop.
Save fishnix/f3551e101e703641cd85833bf57525df to your computer and use it in GitHub Desktop.
SSH certificate signing example in golang
package main
import (
"crypto/rand"
"encoding/base64"
"fmt"
"os"
"time"
"golang.org/x/crypto/ssh"
)
var (
// ca generated with `ssh-keygen -q -N '' -C ca -f ca`
ca string = "/Users/me/ssh-ca/ca"
// public ssh key to sign
pub string = "/Users/me/.ssh/id_ed25519.pub"
)
func main() {
keyF, err := os.ReadFile(pub)
if err != nil {
panic(err)
}
key, c, _, _, err := ssh.ParseAuthorizedKey(keyF)
if err != nil {
panic(err)
}
// k := base64.StdEncoding.EncodeToString(key.Marshal())
// fmt.Printf("%s %s %s\n", key.Type(), k, c)
caF, err := os.ReadFile(ca)
if err != nil {
panic(err)
}
signer, err := ssh.ParsePrivateKey(caF)
if err != nil {
panic(err)
}
nonce := make([]byte, 32)
if _, err = rand.Read(nonce); err != nil {
panic(err)
}
cert := &ssh.Certificate{
Nonce: nonce,
Key: key,
Serial: 1,
CertType: ssh.UserCert,
KeyId: "me@example.com",
ValidPrincipals: []string{"root-everywhere"},
ValidAfter: uint64(time.Now().Unix()),
ValidBefore: uint64(time.Now().Add(8 * time.Hour).Unix()),
Permissions: ssh.Permissions{
Extensions: map[string]string{
"permit-X11-forwarding": "",
"permit-agent-forwarding": "",
"permit-port-forwarding": "",
"permit-pty": "",
"permit-user-rc": "",
},
},
// Reserved []byte
// SignatureKey PublicKey
// Signature *Signature
}
if cert.SignCert(rand.Reader, signer); err != nil {
panic(err)
}
s := base64.StdEncoding.EncodeToString(cert.Marshal())
fmt.Printf("%s %s %s\n", cert.Type(), s, c)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment