Last active
August 9, 2021 14:54
-
-
Save Mic92/24c40996cd97cb8edd53fd688c60ab6f to your computer and use it in GitHub Desktop.
Convert ssh private keys i.e. /etc/ssh/ssh_host_rsa_key to gpg
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"crypto" | |
"crypto/rsa" | |
"fmt" | |
"io/ioutil" | |
"os" | |
"reflect" | |
"time" | |
"golang.org/x/crypto/openpgp" | |
"golang.org/x/crypto/openpgp/packet" | |
"golang.org/x/crypto/ssh" | |
) | |
func loadSSHPrivateKey(path string) (*rsa.PrivateKey, error) { | |
content, err := ioutil.ReadFile(path) | |
if err != nil { | |
return nil, fmt.Errorf("Error reading %s: %s", path, err) | |
} | |
privateKey, err := ssh.ParseRawPrivateKey(content) | |
if err != nil { | |
panic(err) | |
} | |
rsaKey, ok := privateKey.(*rsa.PrivateKey) | |
if !ok { | |
return nil, fmt.Errorf("Only RSA keys are supported right now, got: %s", reflect.TypeOf(privateKey)) | |
} | |
return rsaKey, nil | |
} | |
func gpgFromPrivateKey(key *rsa.PrivateKey) (*openpgp.Entity, error) { | |
name, err := os.Hostname() | |
if err != nil { | |
return nil, fmt.Errorf("Failed to get hostname(): %s", err) | |
} | |
uid := packet.NewUserId("root", "Imported from ssh key", fmt.Sprintf("root@%s", name)) | |
// Let's make keys reproducible | |
timeNull := time.Unix(0, 0) | |
e := &openpgp.Entity{ | |
PrimaryKey: packet.NewRSAPublicKey(timeNull, &key.PublicKey), | |
PrivateKey: packet.NewRSAPrivateKey(timeNull, key), | |
Identities: make(map[string]*openpgp.Identity), | |
} | |
isPrimaryId := true | |
e.Identities[uid.Id] = &openpgp.Identity{ | |
Name: uid.Id, | |
UserId: uid, | |
SelfSignature: &packet.Signature{ | |
CreationTime: timeNull, | |
SigType: packet.SigTypePositiveCert, | |
PubKeyAlgo: packet.PubKeyAlgoRSA, | |
Hash: crypto.SHA256, | |
IsPrimaryId: &isPrimaryId, | |
FlagsValid: true, | |
// TODO what flags do we actually need here? | |
FlagSign: true, | |
FlagCertify: true, | |
FlagEncryptStorage: true, | |
FlagEncryptCommunications: true, | |
IssuerKeyId: &e.PrimaryKey.KeyId, | |
}, | |
} | |
return e, nil | |
} | |
func main() { | |
if len(os.Args) < 3 { | |
fmt.Printf("USAGE: %s /etc/ssh/ssh_host_rsa_key gpg-key\n", os.Args[0]) | |
os.Exit(1) | |
} | |
privateKeyPath := os.Args[1] | |
gpgKeyPath := os.Args[2] | |
key, err := loadSSHPrivateKey(privateKeyPath) | |
if err != nil { | |
panic(err) | |
} | |
gpgKey, err := gpgFromPrivateKey(key) | |
if err != nil { | |
panic(err) | |
} | |
f, err := os.Create(gpgKeyPath) | |
defer f.Close() | |
if err := gpgKey.SerializePrivate(f, nil); err != nil { | |
panic(err) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment