KeyStore interface to keep secrets

File KeyStore implementation to keep secrets in a json file
diff --git a/libs/keystore/filestore.go b/libs/keystore/filestore.go
new file mode 100644
index 0000000..5491563
--- /dev/null
+++ b/libs/keystore/filestore.go
@@ -0,0 +1,111 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package keystore
+
+import (
+	"encoding/json"
+	"io/ioutil"
+	"os"
+	"sync"
+
+	"github.com/pkg/errors"
+)
+
+// FileStore is the key Store implementation storing the keys in a file
+type FileStore struct {
+	sync.RWMutex
+	filePath string
+	keys     map[string][]byte
+}
+
+// NewFileStore creates a new FileStore
+func NewFileStore(filePath string) (Store, error) {
+	fs := &FileStore{
+		filePath: filePath,
+		keys:     map[string][]byte{},
+	}
+
+	if err := fs.loadKeys(); err != nil {
+		return nil, err
+	}
+
+	return fs, nil
+}
+
+// Set stores multiple keys at once
+func (f *FileStore) Set(name string, key []byte) error {
+	f.Lock()
+	defer f.Unlock()
+
+	f.keys[name] = make([]byte, len(key))
+	copy(f.keys[name], key)
+
+	return f.storeKeys()
+}
+
+// Get retrieves multiple keys
+func (f *FileStore) Get(name string) ([]byte, error) {
+	f.RLock()
+	defer f.RUnlock()
+
+	key, ok := f.keys[name]
+	if !ok {
+		return nil, ErrKeyNotFound
+	}
+
+	return key, nil
+}
+
+// TODO: Lock the file
+
+func (f *FileStore) loadKeys() error {
+	rawKeys, err := ioutil.ReadFile(f.filePath)
+	if err != nil {
+		if os.IsNotExist(err) {
+			return nil
+		}
+		return errors.Wrap(err, "Load keys")
+	}
+
+	return json.Unmarshal(rawKeys, &(f).keys)
+}
+
+func (f *FileStore) storeKeys() error {
+	rawKeys, err := json.Marshal(f.keys)
+	if err != nil {
+		return err
+	}
+
+	// Get the file permissions
+	var perm os.FileMode
+	fi, err := os.Stat(f.filePath)
+	if err != nil {
+		if !os.IsNotExist(err) {
+			return errors.Wrap(err, "Get key file permissions")
+		}
+		perm = 0600
+	} else {
+		perm = fi.Mode().Perm()
+	}
+
+	if err := ioutil.WriteFile(f.filePath, rawKeys, perm); err != nil {
+		return errors.Wrap(err, "Store keys")
+	}
+
+	return nil
+}
diff --git a/libs/keystore/filestore_test.go b/libs/keystore/filestore_test.go
new file mode 100644
index 0000000..7e946dd
--- /dev/null
+++ b/libs/keystore/filestore_test.go
@@ -0,0 +1,85 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package keystore
+
+import (
+	"bytes"
+	"crypto/rand"
+	"fmt"
+	"os"
+	"path/filepath"
+	"testing"
+	"time"
+)
+
+func TestFileStore(t *testing.T) {
+	keys := map[string][]byte{"key1": []byte{1}, "key2": []byte{1, 2}, "key3": []byte{1, 2, 3}}
+
+	fn := tmpFileName()
+	defer func() {
+		if err := os.Remove(fn); err != nil {
+			t.Logf("Warning! Temp file could not be deleted (%v): %v", err, fn)
+		}
+	}()
+
+	fs, err := NewFileStore(fn)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// Set keys
+	for k, v := range keys {
+		fs.Set(k, v)
+	}
+
+	// Get Keys
+	for name, v := range keys {
+		key, err := fs.Get(name)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if !bytes.Equal(v, key) {
+			t.Errorf("Key not match: %v. Expected: %v, Found: %v", name, v, key)
+		}
+
+	}
+
+	fs1, err := NewFileStore(fn)
+	if err != nil {
+		t.Fatal(err)
+	}
+	// Get Keys
+	for name, v := range keys {
+		key, err := fs1.Get(name)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if !bytes.Equal(v, key) {
+			t.Errorf("Key not match: %v. Expected: %v, Found: %v", name, v, key)
+		}
+
+	}
+}
+
+func tmpFileName() string {
+	rnd := make([]byte, 8)
+	rand.Read(rnd)
+	ts := time.Now().UnixNano()
+
+	return filepath.Join(os.TempDir(), fmt.Sprintf("keystore-%v-%x.tmp", ts, rnd))
+}
diff --git a/libs/keystore/keystore.go b/libs/keystore/keystore.go
new file mode 100644
index 0000000..8b321c7
--- /dev/null
+++ b/libs/keystore/keystore.go
@@ -0,0 +1,36 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+/*
+Package keystore - keep secrets
+*/
+package keystore
+
+import "github.com/pkg/errors"
+
+var (
+	// ErrKeyNotFound is returned when a key is not found in the store
+	ErrKeyNotFound = errors.New("Key not found")
+)
+
+// Store is the keystore interface
+type Store interface {
+	// Set stores multiple keys at once
+	Set(name string, key []byte) error
+	// Get retrieves multiple keys
+	Get(name string) ([]byte, error)
+}
diff --git a/libs/keystore/memorystore.go b/libs/keystore/memorystore.go
new file mode 100644
index 0000000..484a45f
--- /dev/null
+++ b/libs/keystore/memorystore.go
@@ -0,0 +1,59 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package keystore
+
+import (
+	"sync"
+)
+
+// MemoryStore is the in-memory implementation of key store
+type MemoryStore struct {
+	sync.RWMutex
+	keys map[string][]byte
+}
+
+// NewMemoryStore creates a new MemoryStore
+func NewMemoryStore() (Store, error) {
+	return &MemoryStore{
+		keys: map[string][]byte{},
+	}, nil
+}
+
+// Set stores multiple keys at once
+func (f *MemoryStore) Set(name string, key []byte) error {
+	f.Lock()
+	defer f.Unlock()
+
+	f.keys[name] = make([]byte, len(key))
+	copy(f.keys[name], key)
+
+	return nil
+}
+
+// Get retrieves multiple keys
+func (f *MemoryStore) Get(name string) ([]byte, error) {
+	f.RLock()
+	defer f.RUnlock()
+
+	key, ok := f.keys[name]
+	if !ok {
+		return nil, ErrKeyNotFound
+	}
+
+	return key, nil
+}
diff --git a/libs/keystore/memorystore_test.go b/libs/keystore/memorystore_test.go
new file mode 100644
index 0000000..5dd92a2
--- /dev/null
+++ b/libs/keystore/memorystore_test.go
@@ -0,0 +1,46 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package keystore
+
+import (
+	"bytes"
+	"testing"
+)
+
+func TestMemoryStore(t *testing.T) {
+	keys := map[string][]byte{"key1": []byte{1}, "key2": []byte{1, 2}, "key3": []byte{1, 2, 3}}
+
+	ms, err := NewMemoryStore()
+	if err != nil {
+		t.Fatal(err)
+	}
+	for k, v := range keys {
+		ms.Set(k, v)
+	}
+
+	for name, v := range keys {
+		key, err := ms.Get(name)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if !bytes.Equal(v, key) {
+			t.Errorf("Key not match: %v. Expected: %v, Found: %v", name, v, key)
+		}
+
+	}
+}