-
-
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 == nil
error check. If bad key-bytes are passed toDecode
, it returns nil, and will thus cause theprivPem.Type
reference to panic.