-
-
Save julie-is-late/259a87a7146393aab5819873a193b88c to your computer and use it in GitHub Desktop.
| package config | |
| import ( | |
| "crypto/rand" | |
| "crypto/rsa" | |
| "crypto/x509" | |
| "encoding/pem" | |
| "io/ioutil" | |
| "github.com/CodeCollaborate/Server/utils" | |
| ) | |
| func rsaConfigSetup(rsaPrivateKeyLocation, rsaPrivateKeyPassword string) (*rsa.PrivateKey, error) { | |
| if rsaPrivateKeyLocation == "" { | |
| utils.LogWarn("No RSA Key given, generating temp one", nil) | |
| return GenRSA(4096) | |
| } | |
| priv, err := ioutil.ReadFile(rsaPrivateKeyLocation) | |
| if err != nil { | |
| utils.LogWarn("No RSA private key found, generating temp one", nil) | |
| return GenRSA(4096) | |
| } | |
| privPem, _ := pem.Decode(priv) | |
| var privPemBytes []byte | |
| if privPem.Type != "RSA PRIVATE KEY" { | |
| utils.LogWarn("RSA private key is of the wrong type", utils.LogFields{ | |
| "Pem Type": privPem.Type, | |
| }) | |
| } | |
| if rsaPrivateKeyPassword != "" { | |
| privPemBytes, err = x509.DecryptPEMBlock(privPem, []byte(rsaPrivateKeyPassword)) | |
| } else { | |
| privPemBytes = privPem.Bytes | |
| } | |
| var parsedKey interface{} | |
| if parsedKey, err = x509.ParsePKCS1PrivateKey(privPemBytes); err != nil { | |
| if parsedKey, err = x509.ParsePKCS8PrivateKey(privPemBytes); err != nil { // note this returns type `interface{}` | |
| utils.LogError("Unable to parse RSA private key, generating a temp one", err, utils.LogFields{}) | |
| return GenRSA(4096) | |
| } | |
| } | |
| var privateKey *rsa.PrivateKey | |
| var ok bool | |
| privateKey, ok = parsedKey.(*rsa.PrivateKey) | |
| if !ok { | |
| utils.LogError("Unable to parse RSA private key, generating a temp one", err, utils.LogFields{}) | |
| return GenRSA(4096) | |
| } | |
| pub, err := ioutil.ReadFile(rsaPublicKeyLocation) | |
| if err != nil { | |
| utils.LogWarn("No RSA public key found, generating temp one", nil) | |
| return GenRSA(4096) | |
| } | |
| pubPem, _ := pem.Decode(pub) | |
| if pubPem == nil { | |
| utils.LogError("Use `ssh-keygen -f id_rsa.pub -e -m pem > id_rsa.pem` to generate the pem encoding of your RSA public key", | |
| errors.New("rsa public key not in pem format"), utils.LogFields{ | |
| "Public key location": rsaPublicKeyLocation, | |
| }) | |
| return GenRSA(4096) | |
| } | |
| if pubPem.Type != "RSA PUBLIC KEY" { | |
| utils.LogWarn("RSA public key is of the wrong type", utils.LogFields{ | |
| "Pem Type": pubPem.Type, | |
| }) | |
| return GenRSA(4096) | |
| } | |
| if parsedKey, err = x509.ParsePKIXPublicKey(pubPem.Bytes); err != nil { | |
| utils.LogError("Unable to parse RSA public key, generating a temp one", err, utils.LogFields{}) | |
| return GenRSA(4096) | |
| } | |
| var pubKey *rsa.PublicKey | |
| if pubKey, ok = parsedKey.(*rsa.PublicKey); !ok { | |
| utils.LogError("Unable to parse RSA public key, generating a temp one", err, utils.LogFields{}) | |
| return GenRSA(4096) | |
| } | |
| privateKey.PublicKey = pubKey | |
| return privateKey, nil | |
| } | |
| // GenRSA returns a new RSA key of bits length | |
| func GenRSA(bits int) (*rsa.PrivateKey, error) { | |
| key, err := rsa.GenerateKey(rand.Reader, bits) | |
| utils.LogFatal("Failed to generate signing key", err, nil) | |
| return key, err | |
| } |
If you want to generate a key pair for this with openssl, use the old genrsa subcommand, for example:
openssl genrsa -aes256 -out private.key 8192
openssl rsa -in private.key -pubout -out public.key
Do not use the new genpkey subcommand, for example:
openssl genpkey -algorithm RSA -aes256 -pkeyopt rsa_keygen_bits:8192 -out private.pem
openssl rsa -in private.pem -pubout -outform PEM -out public.pem
While both command generates RSA key pair, the key file format is different.
openssl genrsa generates private key as pkcs#1 block, which formats like this:
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC,1DA219DB746F88C6DDA0D852A0FD3232
AEf09rGkgGEJ79GgO4dEVsArwv4IbbODlxy95uHhfkdGYmuk6OlTpiCUE0GT68wn
KFJfBcHr8Z3VqiHGsXxM5QlKhgnfptxfbrdKErgBD5LQcrvnqmf43KeD4lGQcpiy
...
...
mAKMCwiU/GKZz8ZwQ4qGkBlVVCOFfgwmfbqguJF2l8yzM8lYI9MZ9NEwKkvEbc
-----END RSA PRIVATE KEY-----
openssl genpkey generates private key as pkcs#8 block, which formats like this:
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIISrTBXBgkqhkiG9w0BBQ0wSjKpBgkqhkiG9w0BBQwwHAQIKL+ordsVfqsCAggB
MAwGCCqGSIb3DQIJCQAwHQYJYIZIWAUDBAEqBBCipOAAxWkC0/zkNLNYTSMgBIIS
...
...
zfdxjZ0XmPiwED2azsLMnRrWnRj2UqMtnv9zO/ucik9za
-----END ENCRYPTED PRIVATE KEY-----
The function x509.DecryptPEMBlock only works with pkcs#1. If you provide it with a pkcs#8 block, it would give you an error: "x509: no DEK-Info header in block".
As specified in #8860, the core library has no real plan to support pkcs#8 in the near future. If you want to work with it, you'll have better luck with 3rd party library like github.com/youmark/pkcs8 (Documentation).
Nice work!
FYI L25 should be followed with a
if privPem == nilerror check. If bad key-bytes are passed toDecode, it returns nil, and will thus cause theprivPem.Typereference to panic.