diff --git a/security/filesystem.go b/security/filesystem.go new file mode 100644 index 0000000..e59bd40 --- /dev/null +++ b/security/filesystem.go @@ -0,0 +1,105 @@ +package security + +import ( + "os" + "path/filepath" + + "git.qowevisa.me/Qowevisa/gotell/errors" +) + +func findInStore(name string) KeyPair { + return KeyPair{} +} + +const ( + _int_FSPath = "./key-store" + _int_FSPairsPath = _int_FSPath + "/pairs" + _int_PrivateKeyAddon = "private.Key" + _int_PublicKeyAddon = "public.key" +) + +func initFS() error { + var err error + err = os.Mkdir(_int_FSPath, os.ModePerm) + if err != nil { + return errors.WrapErr("Mkdir:initFSPath", err) + } + + err = os.Mkdir(_int_FSPairsPath, os.ModePerm) + if err != nil { + return errors.WrapErr("Mkdir:initFSPairsPath", err) + } + return nil +} + +func fs_checkIfPairExists(name string) (bool, error) { + var err error + privateKeyPath := filepath.Join(_int_FSPairsPath, name+_int_PrivateKeyAddon) + _, err = os.Stat(privateKeyPath) + if err != nil { + if os.IsNotExist(err) { + return false, nil + } else { + return false, errors.WrapErr(privateKeyPath, err) + } + } + publicKeyPath := filepath.Join(_int_FSPairsPath, name+_int_PublicKeyAddon) + _, err = os.Stat(publicKeyPath) + if err != nil { + if os.IsNotExist(err) { + return false, nil + } else { + return false, errors.WrapErr(publicKeyPath, err) + } + } + return true, nil +} + +// TODO: add encryption +func fs_savePair(keyPair KeyPair) error { + var err error + err = os.WriteFile(keyPair.baseName+_int_PrivateKeyAddon, keyPair.privateKey, 0644) + if err != nil { + return errors.WrapErr("WriteFile:privateKey", err) + } + err = os.WriteFile(keyPair.baseName+_int_PublicKeyAddon, keyPair.publicKey, 0644) + if err != nil { + return errors.WrapErr("WriteFile:publicKey", err) + } + return nil +} + +// TODO: add encryption +func fs_readPair(name string, keyPair *KeyPair) error { + var err error + privateKeyPath := filepath.Join(_int_FSPairsPath, name+_int_PrivateKeyAddon) + _, err = os.Stat(privateKeyPath) + if err != nil { + if os.IsNotExist(err) { + return errors.WrapErr(privateKeyPath, errors.NOT_FOUND) + } else { + return errors.WrapErr(privateKeyPath, err) + } + } + privKey, err := os.ReadFile(privateKeyPath) + if err != nil { + return errors.WrapErr("os.ReadFile:private", err) + } + publicKeyPath := filepath.Join(_int_FSPairsPath, name+_int_PublicKeyAddon) + _, err = os.Stat(publicKeyPath) + if err != nil { + if os.IsNotExist(err) { + return errors.WrapErr(publicKeyPath, errors.NOT_FOUND) + } else { + return errors.WrapErr(publicKeyPath, err) + } + } + pubKey, err := os.ReadFile(publicKeyPath) + if err != nil { + return errors.WrapErr("os.ReadFile:publicKey", err) + } + keyPair.baseName = name + keyPair.privateKey = privKey + keyPair.publicKey = pubKey + return nil +} diff --git a/security/store.go b/security/store.go new file mode 100644 index 0000000..c864a08 --- /dev/null +++ b/security/store.go @@ -0,0 +1,69 @@ +package security + +import ( + "crypto/rand" + "fmt" + + "git.qowevisa.me/Qowevisa/gotell/errors" + "git.qowevisa.me/Qowevisa/gotell/types" + "golang.org/x/crypto/curve25519" +) + +func generateKeyPair(cfg types.ECDHConfig) ([]byte, []byte, error) { + var private [32]byte + if _, err := rand.Read(private[:]); err != nil { + return nil, nil, errors.WrapErr("rand.Read", err) + } + + public, err := curve25519.X25519(private[:], curve25519.Basepoint) + if err != nil { + return nil, nil, errors.WrapErr("curve25519.X25519", err) + } + + return private[:], public, nil +} + +type KeyPair struct { + baseName string + privateKey []byte + publicKey []byte +} + +type Store struct { + Pairs map[string]KeyPair +} + +func InitStorage() (*Store, error) { + err := initFS() + if err != nil { + return nil, errors.WrapErr("initFS", err) + } + var newStore Store + newStore.Pairs = make(map[string]KeyPair) + + return &newStore, nil +} + +func (s *Store) AddNewPair(name string, ecdhCfg types.ECDHConfig) error { + _, exists := s.Pairs[name] + if exists { + return errors.WrapErr(fmt.Sprintf("Store.Pairs[%s]", name), errors.ALREADY_SET) + } + fileExists, err := fs_checkIfPairExists(name) + if fileExists { + return errors.WrapErr(fmt.Sprintf("Store.Pairs[%s]. FS found but in store", name), errors.NOT_SET) + } + if err != nil { + return errors.WrapErr("fs_checkIfPairExists", err) + } + private, public, err := generateKeyPair(ecdhCfg) + if err != nil { + return errors.WrapErr("generateKeyPair", err) + } + s.Pairs[name] = KeyPair{ + baseName: name, + privateKey: private, + publicKey: public, + } + return nil +}