Forked from azakordonets/generate_rsa_ssh_keys.go
Last active
August 28, 2025 09:34
-
-
Save goliatone/e9c13e5f046e34cef6e150d06f20a34c to your computer and use it in GitHub Desktop.
Revisions
-
goliatone revised this gist
Aug 30, 2020 . 1 changed file with 35 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,35 @@ import ( "fmt" "crypto/rsa" "crypto/rand" "crypto/x509" "encoding/pem" ) // MakeSSHKeyPair make a pair of public and private keys for SSH access. // Public key is encoded in the format for inclusion in an OpenSSH authorized_keys file. // Private Key generated is PEM encoded func MakeSSHKeyPair(pubKeyPath, privateKeyPath string) error { privateKey, err := rsa.GenerateKey(rand.Reader, 1024) if err != nil { return err } // generate and write private key as PEM privateKeyFile, err := os.Create(privateKeyPath) defer privateKeyFile.Close() if err != nil { return err } privateKeyPEM := &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)} if err := pem.Encode(privateKeyFile, privateKeyPEM); err != nil { return err } // generate and write public key pub, err := ssh.NewPublicKey(&privateKey.PublicKey) if err != nil { return err } return ioutil.WriteFile(pubKeyPath, ssh.MarshalAuthorizedKey(pub), 0655) } -
goliatone revised this gist
Aug 26, 2020 . 1 changed file with 250 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,250 @@ // Released under CC0 1.0 https://creativecommons.org/publicdomain/zero/1.0/ // To the extent possible under law, the author have dedicated all copyright // and related and neighboring rights to this software to the public domain // worldwide. This software is distributed without any warranty. //https://play.golang.org/p/BK9rxDD87ur //PBES2 format decoder package main import ( "crypto/aes" "crypto/cipher" "crypto/des" "crypto/sha1" "crypto/sha256" "crypto/sha512" "crypto/x509" "encoding/asn1" "encoding/pem" "errors" "fmt" "hash" "os" "strconv" "golang.org/x/crypto/pbkdf2" ) func appendOID(b asn1.ObjectIdentifier, v ...int) asn1.ObjectIdentifier { n := make(asn1.ObjectIdentifier, len(b), len(b)+len(v)) copy(n, b) return append(n, v...) } var ( oidRSADSI = asn1.ObjectIdentifier{1, 2, 840, 113549} oidPKCS5 = appendOID(oidRSADSI, 1, 5) oidPBKDF2 = appendOID(oidPKCS5, 12) oidPBES2 = appendOID(oidPKCS5, 13) oidDigestAlgorithm = appendOID(oidRSADSI, 2) oidHMACWithSHA1 = appendOID(oidDigestAlgorithm, 7) oidHMACWithSHA224 = appendOID(oidDigestAlgorithm, 8) oidHMACWithSHA256 = appendOID(oidDigestAlgorithm, 9) oidHMACWithSHA384 = appendOID(oidDigestAlgorithm, 10) oidHMACWithSHA512 = appendOID(oidDigestAlgorithm, 11) oidHMACWithSHA512_224 = appendOID(oidDigestAlgorithm, 12) oidHMACWithSHA512_256 = appendOID(oidDigestAlgorithm, 13) oidEncryptionAlgorithm = appendOID(oidRSADSI, 3) oidDESCBC = asn1.ObjectIdentifier{1, 3, 14, 3, 2, 7} oidDESEDE3CBC = appendOID(oidEncryptionAlgorithm, 7) oidAES = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1} oidAES128CBCPAD = appendOID(oidAES, 2) oidAES192CBCPAD = appendOID(oidAES, 22) oidAES256CBCPAD = appendOID(oidAES, 42) ) var ( ErrIncorrectPassword = errors.New("possilbly incorrect encryption password") errInvalidDataLen = errors.New("data size is not a multiple of cipher block size") errInvalidIVLen = errors.New("invalid IV size") errInvalidIter = errors.New("invalid iteration count") errNoData = errors.New("no data to decrypt") errNotPBES2 = errors.New("not PBES2 data") errUnsupportedKDF = errors.New("unsupported KDF") errUnsupportedPRF = errors.New("unsupported PRF") errUnsupportedEncS = errors.New("unsupported encryption scheme") ) type ErrTooManyIterations int func (err ErrTooManyIterations) Error() string { return "too many PBKDF2 iterations: " + strconv.Itoa(int(err)) } func prfByOID(oid asn1.ObjectIdentifier) func() hash.Hash { if len(oid) == 0 { return sha1.New } if oid.Equal(oidHMACWithSHA1) { return sha1.New } if oid.Equal(oidHMACWithSHA224) { return sha256.New224 } if oid.Equal(oidHMACWithSHA256) { return sha256.New } if oid.Equal(oidHMACWithSHA384) { return sha512.New384 } if oid.Equal(oidHMACWithSHA512) { return sha512.New } if oid.Equal(oidHMACWithSHA512_224) { return sha512.New512_224 } if oid.Equal(oidHMACWithSHA512_256) { return sha512.New512_256 } return nil } func encsByOID(oid asn1.ObjectIdentifier) (func([]byte) (cipher.Block, error), func(cipher.Block, []byte) cipher.BlockMode, int) { if oid.Equal(oidDESCBC) { return des.NewCipher, cipher.NewCBCDecrypter, 8 } if oid.Equal(oidDESEDE3CBC) { return des.NewTripleDESCipher, cipher.NewCBCDecrypter, 24 } if oid.Equal(oidAES128CBCPAD) { return aes.NewCipher, cipher.NewCBCDecrypter, 16 } if oid.Equal(oidAES192CBCPAD) { return aes.NewCipher, cipher.NewCBCDecrypter, 24 } if oid.Equal(oidAES256CBCPAD) { return aes.NewCipher, cipher.NewCBCDecrypter, 32 } return nil, nil, 0 } func DecryptPBES2(b, password []byte, maxIter int) (data, rest []byte, err error) { var p struct { ES struct { ID asn1.ObjectIdentifier Params struct { KDF struct { ID asn1.ObjectIdentifier Params struct { Salt []byte Iter int KeyLength int `asn1:"optional"` PRF struct { ID asn1.ObjectIdentifier Params asn1.RawValue } `asn1:"optional"` } } EncS struct { ID asn1.ObjectIdentifier Params []byte } } } Data []byte } rest, err = asn1.Unmarshal(b, &p) if err != nil { return } if !p.ES.ID.Equal(oidPBES2) { err = errNotPBES2 return } if !p.ES.Params.KDF.ID.Equal(oidPBKDF2) { err = errUnsupportedKDF return } if p.ES.Params.KDF.Params.Iter < 1 { err = errInvalidIter return } prf := prfByOID(p.ES.Params.KDF.Params.PRF.ID) if prf == nil { err = errUnsupportedPRF return } bcf, bmf, kl := encsByOID(p.ES.Params.EncS.ID) if bcf == nil || bmf == nil { err = errUnsupportedEncS return } if len(p.Data) == 0 { err = errNoData return } if maxIter > 0 && p.ES.Params.KDF.Params.Iter > maxIter { err = ErrTooManyIterations(p.ES.Params.KDF.Params.Iter) return } key := pbkdf2.Key(password, p.ES.Params.KDF.Params.Salt, p.ES.Params.KDF.Params.Iter, kl, prf) var bc cipher.Block bc, err = bcf(key) if err != nil { return } if len(p.ES.Params.EncS.Params) != bc.BlockSize() { err = errInvalidIVLen return } bm := bmf(bc, p.ES.Params.EncS.Params) if len(p.Data)%bm.BlockSize() != 0 { err = errInvalidDataLen return } data = make([]byte, len(p.Data)) bm.CryptBlocks(data, p.Data) pl := data[len(data)-1] if pl == 0 || int(pl) > bm.BlockSize() { err = ErrIncorrectPassword return } dl := len(data) - int(pl) for _, b := range data[dl:] { if b != pl { err = ErrIncorrectPassword return } } data = data[:dl] return } var pemKey = ([]byte)(`-----BEGIN ENCRYPTED PRIVATE KEY----- MIIBSzBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQIQAY0IsXMhucCAggA MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECHi4EIJK+T6FBIH4Fatl16Lwznm/ jIhKygStjhIlpww0A0aZDp/D0eEJpXzvPgRZWf2xhlf5gzTMblQ2XkNrbu/OWOOS f+qx//lh30WTFYOwu0ZWBuxGnjDQav2nc+GKRfzCWbTvgdj8EOKi3vgt8PkuBZWp IwX0GRrLLd19EmC/VpZ6zAoJIxeE2Oc76tBREJCs5T8o+4Y28rgo/mXbMJmxpdAK ncWa4y0f1IEcjdw2u3I8csvtwUIj6WjVLkrS1R3I0DS9jEbs0rZ9uORk5aFatzre ccfQA0JI0n15QPX8dGh/RnWmpzpGXMxShiwn434KGD/Fa0mZeQex26chknoV3YE= -----END ENCRYPTED PRIVATE KEY-----`) var password = ([]byte)("1234") func main() { block, _ := pem.Decode(pemKey) if block == nil { fmt.Fprintln(os.Stderr, "failed to decode PEM block") os.Exit(1) } var derKey []byte var err error if block.Type == "ENCRYPTED PRIVATE KEY" { derKey, _, err = DecryptPBES2(block.Bytes, password, 1000000) } else if x509.IsEncryptedPEMBlock(block) { derKey, err = x509.DecryptPEMBlock(block, password) } else { derKey = block.Bytes } if err != nil { fmt.Fprintln(os.Stderr, "failed to decrypt private key:", err) os.Exit(1) } key, err := x509.ParsePKCS8PrivateKey(derKey) if err != nil { fmt.Fprintln(os.Stderr, "failed to parse PKCS #8 private key:", err) os.Exit(1) } fmt.Printf("key type: %T\n", key) } -
azakordonets renamed this gist
Jul 28, 2020 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes. -
devinodaniel created this gist
Nov 21, 2017 .There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,102 @@ // This shows an example of how to generate a SSH RSA Private/Public key pair and save it locally package main import ( "crypto/rand" "crypto/rsa" "crypto/x509" "encoding/pem" "golang.org/x/crypto/ssh" "io/ioutil" "log" ) func main() { savePrivateFileTo := "./id_rsa_test" savePublicFileTo := "./id_rsa_test.pub" bitSize := 4096 privateKey, err := generatePrivateKey(bitSize) if err != nil { log.Fatal(err.Error()) } publicKeyBytes, err := generatePublicKey(&privateKey.PublicKey) if err != nil { log.Fatal(err.Error()) } privateKeyBytes := encodePrivateKeyToPEM(privateKey) err = writeKeyToFile(privateKeyBytes, savePrivateFileTo) if err != nil { log.Fatal(err.Error()) } err = writeKeyToFile([]byte(publicKeyBytes), savePublicFileTo) if err != nil { log.Fatal(err.Error()) } } // generatePrivateKey creates a RSA Private Key of specified byte size func generatePrivateKey(bitSize int) (*rsa.PrivateKey, error) { // Private Key generation privateKey, err := rsa.GenerateKey(rand.Reader, bitSize) if err != nil { return nil, err } // Validate Private Key err = privateKey.Validate() if err != nil { return nil, err } log.Println("Private Key generated") return privateKey, nil } // encodePrivateKeyToPEM encodes Private Key from RSA to PEM format func encodePrivateKeyToPEM(privateKey *rsa.PrivateKey) []byte { // Get ASN.1 DER format privDER := x509.MarshalPKCS1PrivateKey(privateKey) // pem.Block privBlock := pem.Block{ Type: "RSA PRIVATE KEY", Headers: nil, Bytes: privDER, } // Private key in PEM format privatePEM := pem.EncodeToMemory(&privBlock) return privatePEM } // generatePublicKey take a rsa.PublicKey and return bytes suitable for writing to .pub file // returns in the format "ssh-rsa ..." func generatePublicKey(privatekey *rsa.PublicKey) ([]byte, error) { publicRsaKey, err := ssh.NewPublicKey(privatekey) if err != nil { return nil, err } pubKeyBytes := ssh.MarshalAuthorizedKey(publicRsaKey) log.Println("Public key generated") return pubKeyBytes, nil } // writePemToFile writes keys to a file func writeKeyToFile(keyBytes []byte, saveFileTo string) error { err := ioutil.WriteFile(saveFileTo, keyBytes, 0600) if err != nil { return err } log.Printf("Key saved to: %s", saveFileTo) return nil }