Zippytal-Node/encryption_manager.go

151 lines
3.5 KiB
Go

package localserver
import (
"context"
"crypto"
"crypto/hmac"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"fmt"
"io"
"os"
"path/filepath"
)
const PEM_PRIVATE_KEY = "RSA PRIVATE KEY"
const PEM_PUBLIC_KEY = "RSA PUBLIC KEY"
const OPENSSH_PRIVATE_KEY = "OPENSSH PRIVATE KEY"
type EncryptionManager struct {
PrivKey *rsa.PrivateKey
PeerKeys map[string]*rsa.PublicKey
}
func NewEncryptionManager() (eManager *EncryptionManager) {
eManager = new(EncryptionManager)
return
}
func (em *EncryptionManager) GenerateKeyPair(ctx context.Context, name string, pwd string) (privKey *rsa.PrivateKey, err error) {
privKey, err = rsa.GenerateKey(rand.Reader, 1<<12)
if err != nil {
return
}
block := &pem.Block{
Type: PEM_PRIVATE_KEY,
Bytes: x509.MarshalPKCS1PrivateKey(privKey),
}
if pwd != "" {
block, err = x509.EncryptPEMBlock(rand.Reader, block.Type, block.Bytes, []byte(pwd), x509.PEMCipherAES256)
if err != nil {
return
}
}
f, err := os.Create(filepath.Join(configPath, "config", name))
if err != nil {
return
}
_, err = f.Write(pem.EncodeToMemory(block))
if err != nil {
return
}
pubBlock := &pem.Block{
Type: PEM_PUBLIC_KEY,
Bytes: x509.MarshalPKCS1PublicKey(&privKey.PublicKey),
}
if pwd != "" {
pubBlock, err = x509.EncryptPEMBlock(rand.Reader, pubBlock.Type, pubBlock.Bytes, []byte(pwd), x509.PEMCipherAES256)
if err != nil {
return
}
}
pubf, err := os.Create(filepath.Join(configPath, "config", fmt.Sprintf("%s.pub", name)))
if err != nil {
return
}
_, err = pubf.Write(pem.EncodeToMemory(pubBlock))
return
}
func (em *EncryptionManager) LoadPrivKey(privKeyPath string, password string) (err error) {
f, err := os.Open(privKeyPath)
if err != nil {
return
}
var buff []byte
buff, err = io.ReadAll(f)
if err != nil {
return
}
privPem, _ := pem.Decode(buff)
var privePemBytes []byte
if privPem.Type != PEM_PRIVATE_KEY && privPem.Type != OPENSSH_PRIVATE_KEY {
logger.Println(privPem.Type)
err = fmt.Errorf("RSA Private key is of wrong type")
return
}
if password != "" {
privePemBytes, err = x509.DecryptPEMBlock(privPem, []byte(password))
} else {
privePemBytes = privPem.Bytes
}
var parsedKey interface{}
if parsedKey, err = x509.ParsePKCS1PrivateKey(privePemBytes); err != nil {
logger.Printf("error one %v\n", err)
if parsedKey, err = x509.ParsePKCS8PrivateKey(privePemBytes); err != nil {
logger.Printf("error on parsing %v\n", err)
if parsedKey, err = x509.ParseECPrivateKey(privePemBytes); err != nil {
return
}
}
}
var privKey *rsa.PrivateKey
var ok bool
privKey, ok = parsedKey.(*rsa.PrivateKey)
if !ok {
err = fmt.Errorf("Unable to parse this private key")
return
}
em.PrivKey = privKey
return
}
func (em *EncryptionManager) ParsePrivKey(privateKey string) (privKey *rsa.PrivateKey, err error) {
key := []byte(privateKey)
block, _ := pem.Decode(key)
b := block.Bytes
privKey, err = x509.ParsePKCS1PrivateKey(b)
if err != nil {
return
}
return
}
func (em *EncryptionManager) SignRequest(privKey, id string) (sig string, err error) {
key, err := em.ParsePrivKey(privKey)
if err != nil {
return
}
msg := []byte(id)
hashed := sha256.Sum256(msg)
signature, err := rsa.SignPKCS1v15(rand.Reader, key, crypto.SHA256, hashed[:])
if err != nil {
return
}
sig = base64.StdEncoding.EncodeToString(signature)
return
}
func (em *EncryptionManager) SignRequestHMAC(id string) string {
h := hmac.New(sha256.New, []byte(NodeToken))
h.Write([]byte(id))
sha := h.Sum(nil)
sig := base64.StdEncoding.EncodeToString(sha)
return sig
}