mirror of
https://github.com/paralus/paralus.git
synced 2026-05-09 18:06:38 +00:00
* restructure rcloud-base as a single base controller * updated master.rest * moved sentry from internal to pkg as it is used by relay * removing unused rpc and it's dependencies * Fix usermgmt tests * Don't redefine variables in rest file Co-authored-by: Abin Simon <abin.simon@rafay.co>
142 lines
3.0 KiB
Go
142 lines
3.0 KiB
Go
package cryptoutil
|
|
|
|
import (
|
|
"crypto"
|
|
"crypto/ecdsa"
|
|
"crypto/elliptic"
|
|
"crypto/rand"
|
|
"crypto/rsa"
|
|
"crypto/x509"
|
|
"encoding/pem"
|
|
"fmt"
|
|
)
|
|
|
|
const (
|
|
ecKeyType = "EC PRIVATE KEY"
|
|
rsaKeyType = "RSA PRIVATE KEY"
|
|
)
|
|
|
|
// PasswordFunc is the signature for passing password while
|
|
// PEM encoding/decoding private keys
|
|
type PasswordFunc func() ([]byte, error)
|
|
|
|
// NoPassword should be used when the private key need not be encrypted
|
|
var NoPassword = func() ([]byte, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
// EncodePrivateKey PEM encodes private key
|
|
// when password is not empty private key is encrypted with password
|
|
func EncodePrivateKey(privKey crypto.PrivateKey, f PasswordFunc) ([]byte, error) {
|
|
password, err := f()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("unable to get password %s", err.Error())
|
|
}
|
|
|
|
switch privKey.(type) {
|
|
case *ecdsa.PrivateKey:
|
|
ecPrivKey := privKey.(*ecdsa.PrivateKey)
|
|
b, err := x509.MarshalECPrivateKey(ecPrivKey)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var p *pem.Block
|
|
|
|
if len(password) == 0 {
|
|
p = &pem.Block{
|
|
Type: ecKeyType,
|
|
Bytes: b,
|
|
}
|
|
} else {
|
|
p, err = x509.EncryptPEMBlock(rand.Reader, ecKeyType, b, password, x509.PEMCipherAES256)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return pem.EncodeToMemory(p), nil
|
|
case *rsa.PrivateKey:
|
|
rsaPrivKey := privKey.(*rsa.PrivateKey)
|
|
b := x509.MarshalPKCS1PrivateKey(rsaPrivKey)
|
|
|
|
var p *pem.Block
|
|
|
|
if len(password) == 0 {
|
|
p = &pem.Block{
|
|
Type: rsaKeyType,
|
|
Bytes: b,
|
|
}
|
|
} else {
|
|
p, err = x509.EncryptPEMBlock(rand.Reader, rsaKeyType, b, password, x509.PEMCipherAES256)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return pem.EncodeToMemory(p), nil
|
|
default:
|
|
return nil, fmt.Errorf("unsupported private key %T", privKey)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// DecodePrivateKey decodes PEM encoded private key
|
|
// when PasswordFunc is provied private key is decrypted with password
|
|
func DecodePrivateKey(privKey []byte, f PasswordFunc) (crypto.PrivateKey, error) {
|
|
p, err := decodePEM(privKey)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
password, err := f()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var b []byte
|
|
|
|
switch {
|
|
case x509.IsEncryptedPEMBlock(p):
|
|
b, err = x509.DecryptPEMBlock(p, password)
|
|
if err != nil {
|
|
fmt.Print("DecryptPEMBlock here is the error", err.Error())
|
|
return nil, err
|
|
}
|
|
default:
|
|
b = p.Bytes
|
|
}
|
|
|
|
fmt.Print("p.Type", p.Type)
|
|
|
|
switch p.Type {
|
|
case ecKeyType:
|
|
return x509.ParseECPrivateKey(b)
|
|
case rsaKeyType:
|
|
return x509.ParsePKCS1PrivateKey(b)
|
|
default:
|
|
return nil, fmt.Errorf("type %s is not suported", p.Type)
|
|
}
|
|
|
|
}
|
|
|
|
// DecryptPrivateKeyAsPem returns a decrypted private key in PEM encoding
|
|
func DecryptPrivateKeyAsPem(privKey []byte, f PasswordFunc) ([]byte, error) {
|
|
pk, err := DecodePrivateKey(privKey, f)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return EncodePrivateKey(pk, NoPassword)
|
|
}
|
|
|
|
// GenerateECDSAPrivateKey generates new ECDSA private key
|
|
func GenerateECDSAPrivateKey() (*ecdsa.PrivateKey, error) {
|
|
ecKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return ecKey, err
|
|
|
|
}
|