go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers/os/connection/ssh/keypair/keygen.go (about) 1 // Copyright (c) Mondoo, Inc. 2 // SPDX-License-Identifier: BUSL-1.1 3 4 package keypair 5 6 import ( 7 "bytes" 8 "crypto/ed25519" 9 "crypto/rand" 10 "crypto/rsa" 11 "crypto/x509" 12 "encoding/pem" 13 14 "golang.org/x/crypto/ssh" 15 ) 16 17 const DefaultRsaBits = 4096 18 19 // SSH holds an SSH keys pair 20 type SSH struct { 21 // PrivateKey contains PEM encoded private key 22 PrivateKey []byte 23 24 // PublicKey serializes key for inclusion in an OpenSSH authorized_keys file 25 // https://datatracker.ietf.org/doc/html/rfc4253#section-6.6 26 PublicKey []byte 27 28 // Optional Passphrase 29 Passphrase []byte 30 } 31 32 // NewEd25519Keys creates EdD25519 key pair 33 func NewEd25519Keys() (*SSH, error) { 34 pubKey, privateKey, err := ed25519.GenerateKey(rand.Reader) 35 if err != nil { 36 return nil, err 37 } 38 39 publicKey, err := ssh.NewPublicKey(pubKey) 40 if err != nil { 41 return nil, err 42 } 43 44 return &SSH{ 45 PrivateKey: pem.EncodeToMemory(&pem.Block{ 46 Type: "OPENSSH PRIVATE KEY", 47 Bytes: MarshalED25519PrivateKey(privateKey), 48 }), 49 PublicKey: MarshalPublicKey(publicKey, ""), 50 }, nil 51 } 52 53 // NewRSAKeys creates RSA key pair 54 func NewRSAKeys(bits int, passphrase []byte) (*SSH, error) { 55 // generate rsa private key 56 privateKey, err := rsa.GenerateKey(rand.Reader, bits) 57 if err != nil { 58 return nil, err 59 } 60 61 err = privateKey.Validate() 62 if err != nil { 63 return nil, err 64 } 65 66 block := &pem.Block{ 67 Type: "RSA PRIVATE KEY", 68 Headers: nil, 69 Bytes: x509.MarshalPKCS1PrivateKey(privateKey), // ASN.1 DER format 70 } 71 72 // optional: encrypt private key with passphrase 73 if len(passphrase) > 0 { 74 block, err = x509.EncryptPEMBlock(rand.Reader, block.Type, block.Bytes, passphrase, x509.PEMCipherAES256) 75 if err != nil { 76 return nil, err 77 } 78 } 79 80 // generate rsa public key 81 publicRSAKey, err := ssh.NewPublicKey(privateKey.Public()) 82 if err != nil { 83 return nil, err 84 } 85 86 return &SSH{ 87 PrivateKey: pem.EncodeToMemory(block), // PEM encoded 88 PublicKey: MarshalPublicKey(publicRSAKey, ""), 89 Passphrase: passphrase, 90 }, nil 91 } 92 93 func MarshalPublicKey(pubKey ssh.PublicKey, note string) []byte { 94 return append(bytes.TrimRight(ssh.MarshalAuthorizedKey(pubKey), "\n"), []byte(note)...) 95 }