diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..cfa4370189676c011d73d45d4111e383ea8f3b27
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+bin/
+vendor/
+Gopkg.lock
+
diff --git a/Gopkg.toml b/Gopkg.toml
new file mode 100644
index 0000000000000000000000000000000000000000..6e4954b45287512568d441b89e2ef45c00efcee1
--- /dev/null
+++ b/Gopkg.toml
@@ -0,0 +1,27 @@
+[[constraint]]
+  branch = "master"
+  name = "code.vereign.com/code/viam-apis"
+
+[[constraint]]
+  branch = "master"
+  name = "code.vereign.com/code/data-storage-agent"
+
+[[constraint]]
+  name = "github.com/golang/protobuf"
+  version = "1.1.0"
+
+[[constraint]]
+  name = "github.com/grpc-ecosystem/grpc-gateway"
+  version = "1.4.1"
+
+[[constraint]]
+  branch = "master"
+  name = "golang.org/x/net"
+
+[[constraint]]
+  name = "google.golang.org/grpc"
+  version = "1.13.0"
+
+[prune]
+  go-tests = true
+  unused-packages = true
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..e84137fd9f75576cddc61728006ea28dc499862f
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,15 @@
+
+Copyright (c) 2018 Vereign AG [https://www.vereign.com]
+
+This is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
\ No newline at end of file
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..d95e1e5cec40a31c8f4fee3b276f5e0c0d439673
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,19 @@
+SERVER_OUT := "bin/server"
+PKG := "code.vereign.com/code/key-storage-agent"
+SERVER_PKG_BUILD := "${PKG}"
+PKG_LIST := $(shell go list ${PKG}/... | grep -v /vendor/)
+
+.PHONY: all api server
+
+all: server
+
+dep: ## Get the dependencies
+	dep ensure -update
+server: dep ## Build the binary file for server
+	@go build -i -v -o $(SERVER_OUT) $(SERVER_PKG_BUILD)
+
+clean: ## Remove previous builds
+	@rm $(SERVER_OUT)
+
+help: ## Display this help screen
+	@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
diff --git a/cert/server.crt b/cert/server.crt
new file mode 100644
index 0000000000000000000000000000000000000000..ffc52d260e9fac51405c58e02317690c9e79cfa2
--- /dev/null
+++ b/cert/server.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDPjCCAiYCCQDpx954xyvbgjANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJG
+UjEMMAoGA1UECAwDaWRmMQ4wDAYDVQQHDAVQYXJpczESMBAGA1UECgwJUGFudG9t
+YXRoMQwwCgYDVQQLDANub2MxEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0xNzEwMDUx
+NTI5MzZaFw0yNzEwMDMxNTI5MzZaMGExCzAJBgNVBAYTAkZSMQwwCgYDVQQIDANp
+ZGYxDjAMBgNVBAcMBVBhcmlzMRIwEAYDVQQKDAlQYW50b21hdGgxDDAKBgNVBAsM
+A25vYzESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEA9UFeeiJ5Gyi5MZGEI0ME8v4IikVByiBgwqn6PH/bYuJwRoR3acZg
+tiiMS1pyfUBSQ2iTLRzrkvFd5rXByXWK4+6MeqYdAzAyQzgk6/1U58oPzGrZCRYe
+b3Bm7QvS9rl00keO37gE8ETpatL8rCQt9Qsl88ah1BfCVuDdFtBdOW2Qz1i6qGUv
+pkTSJDZBmE3gjWGHIp4UjcdshFlTEjmFfcKtNJtMuhnKZIgo6KZcN1Trvyf4aUUM
+zQbPFm2jGd5lUFZJQvSQ00k+TF4YrbuDVfhozoxBrbsoaRXkVWVYC1fYey89FY1n
+9zFyxB6OF32EIry4Kn5Tu6AG9+9z/CU3gwIDAQABMA0GCSqGSIb3DQEBCwUAA4IB
+AQDUeByNiVS/XZgc4BXO5JPXY98orVZKfXEEWKzMfzPDxW925k2IpnnCpT4WkAe4
+sUR7C5efGPyv0TMTzNeXGrkB7lK/9WGWRrlR/bI0kdad7/p7Qx+5hC/nE2HWZYQo
+5JYj8tEfetY3aV64rFllcq2hfI71dMML05GwoVaKaMc9Q1ccwIZAbkXR2Sifwsn9
++UNNsP5hR+7kQh+Dqd/+qEySp1+0ZJ1LmRmRes37MlJI9KSoC1uANwcB5+4ZFrba
+LHrkszk9nxk09Y/tLGYlvvf23y1BdhcqT2EbUZX7jD/jEDC0kZ5yxDE1UDk+pnZp
+UaEcVsgg/b9dMESt38f6ICK/
+-----END CERTIFICATE-----
diff --git a/cert/server.csr b/cert/server.csr
new file mode 100644
index 0000000000000000000000000000000000000000..5662bf115417fa8cc05a5c987aa46e4bfbb229dd
--- /dev/null
+++ b/cert/server.csr
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIICpjCCAY4CAQAwYTELMAkGA1UEBhMCRlIxDDAKBgNVBAgMA2lkZjEOMAwGA1UE
+BwwFUGFyaXMxEjAQBgNVBAoMCVBhbnRvbWF0aDEMMAoGA1UECwwDbm9jMRIwEAYD
+VQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQD1
+QV56InkbKLkxkYQjQwTy/giKRUHKIGDCqfo8f9ti4nBGhHdpxmC2KIxLWnJ9QFJD
+aJMtHOuS8V3mtcHJdYrj7ox6ph0DMDJDOCTr/VTnyg/MatkJFh5vcGbtC9L2uXTS
+R47fuATwROlq0vysJC31CyXzxqHUF8JW4N0W0F05bZDPWLqoZS+mRNIkNkGYTeCN
+YYcinhSNx2yEWVMSOYV9wq00m0y6GcpkiCjoplw3VOu/J/hpRQzNBs8WbaMZ3mVQ
+VklC9JDTST5MXhitu4NV+GjOjEGtuyhpFeRVZVgLV9h7Lz0VjWf3MXLEHo4XfYQi
+vLgqflO7oAb373P8JTeDAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAQEAES8c7EOs
+rU0eu3whtUumllhotNvvqBP4x46arQQE2ud0GkLkxvxqbUuGQxLWi5KCcdads+Cx
+EramC/UAUgAFFj8Ll1EuSZxy1+sb5GL00uJMxatpDBHwr78fhllAWkM7jiZbh2ad
+FHOg9kQcDtdfFB6XP7JM7uiXluEQRyxIutoOzIkhZZva6zg/7iWE+u6DGz3r8dWQ
+WNH8gsWA3D85ZyTDVrCvp6omGx35pzwuQOoWH6nO3dCsR2smf58ShnMtE+c6uLbF
+qoZRTXGAiCaH3/Cn3TXkcrclZdneCCOWidHG2ICTsTqfujDYz/CCYM23AGkqQb1Y
+QMQl0LGZ+k+HAQ==
+-----END CERTIFICATE REQUEST-----
diff --git a/cert/server.key b/cert/server.key
new file mode 100644
index 0000000000000000000000000000000000000000..e4633619d4877c9d199a723e3334cf887dece536
--- /dev/null
+++ b/cert/server.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpgIBAAKCAQEA9UFeeiJ5Gyi5MZGEI0ME8v4IikVByiBgwqn6PH/bYuJwRoR3
+acZgtiiMS1pyfUBSQ2iTLRzrkvFd5rXByXWK4+6MeqYdAzAyQzgk6/1U58oPzGrZ
+CRYeb3Bm7QvS9rl00keO37gE8ETpatL8rCQt9Qsl88ah1BfCVuDdFtBdOW2Qz1i6
+qGUvpkTSJDZBmE3gjWGHIp4UjcdshFlTEjmFfcKtNJtMuhnKZIgo6KZcN1Trvyf4
+aUUMzQbPFm2jGd5lUFZJQvSQ00k+TF4YrbuDVfhozoxBrbsoaRXkVWVYC1fYey89
+FY1n9zFyxB6OF32EIry4Kn5Tu6AG9+9z/CU3gwIDAQABAoIBAQDcQdXAaD9NRdh0
+DNSX+nNyavRugV5hUYy0poTmWolDmEru+b5oj1GBpo7Aib0ygVaf1UYACO4D7KLB
+NNCRxe9zXmRpLc/2cg1h0wVNrxjWheCEXB0IjQXOXSsCjlDrZYjl5IAKqTA+PBVI
+660iR+fCHz35XZUubhwJfC7yczSWAe8nlnFHrcUzSeqLctI18JGsq3hDf5Fy+97+
+4uuJFPwQ0mLsgOdzKvCB79ecSZdQ18hkidgpnARaM1sI501b1Tp/uUQOLUmdVnvh
+/MFEWndm1th3i+gMotsBwrBCyPPeWVrcvKI2sf0LJmgaMl4/sBB0UsSKLhcbBLsj
+jvABikmJAoGBAP1z/WeNDaEaypXBSOKZlMu9YuPOemS2DY5GEc204Fi0dYNDlMEh
+CAu7mEsEvH66hwKn+xMnpb5hIuxQv3/2hUFTME9au2htj2MX0+qk1bqMQMlDEdda
+WWybxy+jW1mYJFMVHFwAAE7hXS5peH9ZCihAu/szYt8zPdZ4X3EEEqqfAoGBAPe4
+Slp2GVd742ZA3VBpfv6802C/DA98gIdHqWNF5vJzi1HU29m+2zY6mMGl9CP3ICeX
+gLL6a3bqIc8aPgJ8ULAhegKOcFqruhGFIjmd+FPRtwjiYC9jJRXbMUSmTrR0XsxG
+GkK2UmBNxVNGUj++1hwji39OfsMnf6OvfVhnmOydAoGBAJk5OgUUHR08WSTXyPxU
+5MOXJuWZuhyQgvl0GudFZiu6TSCiBpgLJBYTvyn7HwluMpjEfOFDosvJZZd/6YWu
+vziS1i3jKFEliv3ZNeAw7pTsnW4PAgYzNMSYGH8QPvWXKL6hkJd92LHXRMH+OT6j
+0aQsHnjqw+czzzqNYwWr9Kz5AoGBAKvxBeLuUD6x5jAGW9dBsn08MXfYg5WINGox
+qngWf+vPmWdOWN81o1BrsbXP67q/AFmaxiD0wnzCnH701w/Am/z074wws/mrcrZQ
+c2YMqN39FY+cGWkq5wXZo8Pjr4N/toERM48Un+7qbEmV6OcIHfNgFKZjpIbutqC1
+4UnodnPdAoGBANzcLKz99NXBBuAiYHgmOckh6I2RCcORgE6WDbj57qrdMco0NToU
+wU9ute0SBEm6VEnBf9i3jlrPZr69f3VT4OFWeo9RoHkVmVDD+LEY5P7xqftj/XZy
+2r+uvgkqZWBC3rpAORGq3F7MgD4nFcyssFKwylEGyCVCfyGIsv5+ZKMr
+-----END RSA PRIVATE KEY-----
diff --git a/handler/handler.go b/handler/handler.go
new file mode 100644
index 0000000000000000000000000000000000000000..5184a9d1190891328b552d9b1342ae907834e724
--- /dev/null
+++ b/handler/handler.go
@@ -0,0 +1,142 @@
+/*
+Copyright (c) 2018 Vereign AG [https://www.vereign.com]
+
+This is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+package handler
+
+import (
+	"strings"
+
+	"code.vereign.com/code/viam-apis/versions"
+	"github.com/golang/protobuf/proto"
+
+	"code.vereign.com/code/viam-apis/authentication"
+	"code.vereign.com/code/viam-apis/data-storage-agent/client"
+	"code.vereign.com/code/viam-apis/key-storage-agent/api"
+	"code.vereign.com/code/viam-apis/utils"
+	"golang.org/x/net/context"
+	"google.golang.org/grpc/metadata"
+)
+
+// Server represents the gRPC server
+type KeyStorageServerImpl struct {
+	DataStorageUrl string
+	CertPath       string
+}
+
+func (s *KeyStorageServerImpl) CreateAuthentication(ctx context.Context) *authentication.Authentication {
+	if md, ok := metadata.FromIncomingContext(ctx); ok {
+		uuid := strings.Join(md["uuid"], "")
+		session := strings.Join(md["session"], "")
+
+		auth := &authentication.Authentication{
+			Uuid:    uuid,
+			Session: session,
+		}
+
+		return auth
+	}
+
+	return nil
+}
+
+func (s *KeyStorageServerImpl) GetPrivateKey(ctx context.Context, in *api.GetPrivateKeyRequest) (*api.GetPrivateKeyResponse, error) {
+	auth := s.CreateAuthentication(ctx)
+
+	client := &client.DataStorageClientImpl{}
+	client.SetUpClient(auth, s.DataStorageUrl, s.CertPath)
+	defer client.CloseClient()
+
+	data, _ := client.DoGetDataCall("privatekeys", in.Name)
+
+	getPrivateKeyResponse := &api.GetPrivateKeyResponse{}
+
+	if data.Errors != "" {
+		getPrivateKeyResponse.Key = nil
+		getPrivateKeyResponse.StatusList = utils.AddStatus(getPrivateKeyResponse.StatusList, "500", "Internal server error", data.Errors)
+	} else {
+		key := &api.PrivateKey{}
+		proto.Unmarshal(data.Data.Data, key)
+		getPrivateKeyResponse.Key = key
+	}
+
+	return getPrivateKeyResponse, nil
+}
+
+func (s *KeyStorageServerImpl) GetPublicKey(ctx context.Context, in *api.GetPublicKeyRequest) (*api.GetPublicKeyResponse, error) {
+	auth := s.CreateAuthentication(ctx)
+
+	client := &client.DataStorageClientImpl{}
+	client.SetUpClient(auth, s.DataStorageUrl, s.CertPath)
+	defer client.CloseClient()
+
+	data, _ := client.DoGetDataCall("publickeys", in.Name)
+
+	getPublicKeyResponse := &api.GetPublicKeyResponse{}
+
+	if data.Errors != "" {
+		getPublicKeyResponse.Key = nil
+		getPublicKeyResponse.StatusList = utils.AddStatus(getPublicKeyResponse.StatusList, "500", "Internal server error", data.Errors)
+	} else {
+		key := &api.PublicKey{}
+		proto.Unmarshal(data.Data.Data, key)
+		getPublicKeyResponse.Key = key
+	}
+
+	return getPublicKeyResponse, nil
+}
+
+func (s *KeyStorageServerImpl) SetPrivateKey(ctx context.Context, in *api.SetPrivateKeyRequest) (*api.SetPrivateKeyResponse, error) {
+	auth := s.CreateAuthentication(ctx)
+
+	client := &client.DataStorageClientImpl{}
+	client.SetUpClient(auth, s.DataStorageUrl, s.CertPath)
+	defer client.CloseClient()
+
+	result, errors, err := client.DoPutDataCall("privatekeys", in.Key.Name, in.Key, versions.EntitiesManagementAgentApiVersion)
+
+	setPrivateKeyResponse := &api.SetPrivateKeyResponse{}
+	if err != nil {
+		setPrivateKeyResponse.StatusList = utils.AddStatus(setPrivateKeyResponse.StatusList, "500", "error", err.Error())
+	} else if errors != "" {
+		setPrivateKeyResponse.StatusList = utils.AddStatus(setPrivateKeyResponse.StatusList, "500", "error", errors)
+	} else {
+		setPrivateKeyResponse.StatusList = utils.AddStatus(setPrivateKeyResponse.StatusList, "200", "info", result)
+	}
+
+	return setPrivateKeyResponse, nil
+}
+
+func (s *KeyStorageServerImpl) SetPublicKey(ctx context.Context, in *api.SetPublicKeyRequest) (*api.SetPublicKeyResponse, error) {
+	auth := s.CreateAuthentication(ctx)
+
+	client := &client.DataStorageClientImpl{}
+	client.SetUpClient(auth, s.DataStorageUrl, s.CertPath)
+	defer client.CloseClient()
+
+	result, errors, err := client.DoPutDataCall("publickeys", in.Key.Name, in.Key, versions.EntitiesManagementAgentApiVersion)
+
+	setPublicKeyResponse := &api.SetPublicKeyResponse{}
+	if err != nil {
+		setPublicKeyResponse.StatusList = utils.AddStatus(setPublicKeyResponse.StatusList, "500", "error", err.Error())
+	} else if errors != "" {
+		setPublicKeyResponse.StatusList = utils.AddStatus(setPublicKeyResponse.StatusList, "500", "error", errors)
+	} else {
+		setPublicKeyResponse.StatusList = utils.AddStatus(setPublicKeyResponse.StatusList, "200", "info", result)
+	}
+
+	return setPublicKeyResponse, nil
+}
diff --git a/kill.sh b/kill.sh
new file mode 100755
index 0000000000000000000000000000000000000000..40d73ddc80314f22e053c5dd8353dc5c8b233579
--- /dev/null
+++ b/kill.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+PIDFILE="$HOME/tmp/key-storage-agent.pid"
+kill -9 `cat $PIDFILE`
diff --git a/main.go b/main.go
new file mode 100644
index 0000000000000000000000000000000000000000..8cadaaafeb8faa93c0a0383cadb741b23c9a615a
--- /dev/null
+++ b/main.go
@@ -0,0 +1,64 @@
+/*
+Copyright (c) 2018 Vereign AG [https://www.vereign.com]
+
+This is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+package main
+
+import (
+	"fmt"
+	"log"
+
+	"code.vereign.com/code/key-storage-agent/server"
+	"code.vereign.com/code/viam-apis/utils"
+)
+
+// main start a gRPC server and waits for connection
+func main() {
+
+	// TODO this should be done via configuration or even a certificate repository
+	certDir := utils.GetCertDirFromFlags()
+	if certDir == "" {
+		log.Printf("cert-dir cannot be empty")
+		return
+	}
+
+	grpcAddress := fmt.Sprintf("%s:%d", "localhost", 7877)
+	restAddress := fmt.Sprintf("%s:%d", "localhost", 7878)
+	dataStorageAddress := fmt.Sprintf("%s:%d", "localhost", 7777)
+
+	certFile := certDir + "/server.crt"
+	keyFile := certDir + "/server.key"
+
+	// fire the gRPC server in a goroutine
+	go func() {
+		err := server.StartGRPCServer(grpcAddress, certFile, keyFile, dataStorageAddress)
+		if err != nil {
+			log.Fatalf("failed to start gRPC server: %s", err)
+		}
+	}()
+
+	// fire the REST server in a goroutine
+	go func() {
+		err := server.StartRESTServer(restAddress, grpcAddress, certFile)
+		if err != nil {
+			log.Fatalf("failed to start gRPC server: %s", err)
+		}
+	}()
+
+	// infinite loop
+	log.Printf("Entering infinite loop")
+	select {}
+}
diff --git a/run.sh b/run.sh
new file mode 100755
index 0000000000000000000000000000000000000000..ddfaeae8a956962a9c11ff73a110f88f18893a07
--- /dev/null
+++ b/run.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+mkdir -p "$HOME/tmp"
+PIDFILE="$HOME/tmp/key-storage-agent.pid"
+
+if [ -e "${PIDFILE}" ] && (ps -u $(whoami) -opid= |
+                           grep -P "^\s*$(cat ${PIDFILE})$" &> /dev/null); then
+  echo "Already running."
+  exit 99
+fi
+
+PATH=$PATH:/usr/local/bin
+
+nohup $GOPATH/src/code.vereign.com/code/key-storage-agent/bin/server --cert-dir $GOPATH/src/code.vereign.com/code/key-storage-agent/cert > $HOME/key-storage-agent.log 2>&1 &
+
+echo $! > "${PIDFILE}"
+chmod 644 "${PIDFILE}"
diff --git a/server/server.go b/server/server.go
new file mode 100644
index 0000000000000000000000000000000000000000..fa6892a8ba25068b898872887bdca0f0940a8d20
--- /dev/null
+++ b/server/server.go
@@ -0,0 +1,174 @@
+package server
+
+/*
+Copyright (c) 2018 Vereign AG [https://www.vereign.com]
+
+This is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+import (
+	"fmt"
+	"log"
+	"net"
+	"net/http"
+	"strings"
+
+	"github.com/grpc-ecosystem/grpc-gateway/runtime"
+
+	"golang.org/x/net/context"
+
+	"code.vereign.com/code/key-storage-agent/handler"
+	"code.vereign.com/code/key-storage-agent/session"
+	"code.vereign.com/code/viam-apis/authentication"
+	"code.vereign.com/code/viam-apis/data-storage-agent/client"
+	api "code.vereign.com/code/viam-apis/key-storage-agent/api"
+	"google.golang.org/grpc"
+	"google.golang.org/grpc/credentials"
+	"google.golang.org/grpc/metadata"
+)
+
+// private type for Context keys
+type contextKey int
+
+const (
+	clientIDKey contextKey = iota
+)
+
+var pkgCertFile string
+
+func credMatcher(headerName string) (mdName string, ok bool) {
+	if headerName == "Session" {
+		return headerName, true
+	}
+	return "", false
+}
+
+// authenticateAgent check the client credentials
+func authenticateClient(ctx context.Context, s *handler.KeyStorageServerImpl, invokedMethod string) (string, error) {
+	if md, ok := metadata.FromIncomingContext(ctx); ok {
+
+		clientAuth := &authentication.Authentication{
+			Uuid:    strings.Join(md["uuid"], ""),
+			Session: strings.Join(md["session"], ""),
+		}
+
+		viamAuth := &authentication.Authentication{
+			Uuid:    "viam-system",
+			Session: "viam-session",
+		}
+
+		sessionClient := &client.DataStorageClientImpl{}
+		sessionClient.SetUpClient(viamAuth, "localhost:7777", pkgCertFile)
+		defer sessionClient.CloseClient()
+
+		if clientAuth.Uuid == viamAuth.Uuid {
+			if clientAuth.Session != viamAuth.Session {
+				return "", fmt.Errorf("bad session %s", clientAuth.Session)
+			}
+		} else {
+			if session.CheckSession(clientAuth.Uuid, clientAuth.Session, sessionClient) == false {
+				return "", fmt.Errorf("bad session %s", clientAuth.Session)
+			}
+		}
+
+		log.Printf("authenticated uuid: %s", clientAuth.Uuid)
+
+		return clientAuth.Uuid, nil
+	}
+	return "", fmt.Errorf("missing credentials")
+}
+
+// unaryInterceptor call authenticateClient with current context
+func unaryInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler1 grpc.UnaryHandler) (interface{}, error) {
+	s, ok := info.Server.(*handler.KeyStorageServerImpl)
+	fmt.Println("Invoked method: " + info.FullMethod)
+	if !ok {
+		return nil, fmt.Errorf("unable to cast server")
+	}
+	clientID, err := authenticateClient(ctx, s, info.FullMethod)
+	if err != nil {
+		return nil, err
+	}
+
+	ctx = context.WithValue(ctx, clientIDKey, clientID)
+
+	return handler1(ctx, req)
+}
+
+func StartGRPCServer(address, certFile, keyFile, dataStorageAddress string) error {
+	pkgCertFile = certFile
+
+	// create a listener on TCP port
+	lis, err := net.Listen("tcp", address)
+	if err != nil {
+		return fmt.Errorf("failed to listen: %v", err)
+	}
+
+	// create a server instance
+	s := handler.KeyStorageServerImpl{
+		DataStorageUrl: dataStorageAddress,
+		CertPath:       certFile,
+	}
+
+	// Create the TLS credentials
+	creds, err := credentials.NewServerTLSFromFile(certFile, keyFile)
+	if err != nil {
+		return fmt.Errorf("could not load TLS keys: %s", err)
+	}
+
+	// Create an array of gRPC options with the credentials
+	opts := []grpc.ServerOption{grpc.Creds(creds),
+		grpc.UnaryInterceptor(unaryInterceptor)}
+
+	// create a gRPC server object
+	grpcServer := grpc.NewServer(opts...)
+
+	// attach the CalcMinimumDistance service to the server
+	api.RegisterKeyStorageServer(grpcServer, &s)
+
+	// start the server
+	log.Printf("starting HTTP/2 gRPC server on %s", address)
+	if err := grpcServer.Serve(lis); err != nil {
+		return fmt.Errorf("failed to serve: %s", err)
+	}
+
+	return nil
+}
+
+func StartRESTServer(address, grpcAddress, certFile string) error {
+	ctx := context.Background()
+	ctx, cancel := context.WithCancel(ctx)
+	defer cancel()
+
+	mux := runtime.NewServeMux(runtime.WithIncomingHeaderMatcher(credMatcher))
+
+	creds, err := credentials.NewClientTLSFromFile(certFile, "")
+	if err != nil {
+		return fmt.Errorf("could not load TLS certificate: %s", err)
+	}
+
+	// Setup the client gRPC options
+	opts := []grpc.DialOption{grpc.WithTransportCredentials(creds)}
+
+	// Register RedisStorageServer
+	err = api.RegisterKeyStorageHandlerFromEndpoint(ctx, mux, grpcAddress, opts)
+	if err != nil {
+		return fmt.Errorf("could not register service RedisStorageServer: %s", err)
+	}
+
+	log.Printf("starting HTTP/1.1 REST server on %s", address)
+	http.ListenAndServe(address, mux)
+
+	return nil
+}
diff --git a/server/server_test.go b/server/server_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..1c0fda7aef278d34358541a5655ee47faaf6c305
--- /dev/null
+++ b/server/server_test.go
@@ -0,0 +1,132 @@
+/*
+Copyright (c) 2018 Vereign AG [https://www.vereign.com]
+
+This is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+package server
+
+import (
+	"log"
+	"os"
+	"testing"
+	"time"
+
+	dataStorageServer "code.vereign.com/code/data-storage-agent/server"
+	"code.vereign.com/code/data-storage-agent/utils"
+	"code.vereign.com/code/viam-apis/authentication"
+	ksapi "code.vereign.com/code/viam-apis/key-storage-agent/api"
+	ksclient "code.vereign.com/code/viam-apis/key-storage-agent/client"
+)
+
+const (
+	dataStorageGrpcAddress = "localhost:7777"
+	keyStorageGrpcAddress  = "localhost:7877"
+	certFile               = "../cert/server.crt"
+	keyFile                = "../cert/server.key"
+)
+
+func TestSetAndGetKeys(t *testing.T) {
+	dataStorageClient := utils.CreateClientFromUuidAndSession("viam-system", "viam-session", dataStorageGrpcAddress, certFile)
+
+	keyStorageAuth := &authentication.Authentication{
+		Uuid:    "some-uuid",
+		Session: "some-session",
+	}
+
+	_, _, _ = dataStorageClient.RenewSession(keyStorageAuth.Uuid, keyStorageAuth.Session)
+
+	keyStorageClient := &ksclient.KeyStorageClientImpl{}
+	keyStorageClient.SetUpClient(keyStorageAuth, keyStorageGrpcAddress, certFile)
+	defer keyStorageClient.CloseClient()
+
+	privateKey := &ksapi.PrivateKey{
+		Name:               "privkey1",
+		PublicKeyReference: "pubkey1",
+		Content:            []byte{0, 1, 4},
+	}
+
+	statusList, _ := keyStorageClient.DoSetPrivateKey(privateKey)
+	for _, status := range statusList {
+		if status.StatusType == "error" {
+			t.Errorf("DoSetPrivateKey, returned error: %s.", status.Code+":"+status.Description)
+		}
+	}
+
+	privateKeyResult, statusList, _ := keyStorageClient.DoGetPrivateKey("privkey1")
+	for _, status := range statusList {
+		if status.StatusType == "error" {
+			t.Errorf("DoGetPrivateKey, returned error: %s.", status.Code+":"+status.Description)
+		}
+	}
+	if privateKeyResult.Content == nil || !utils.CompareByteArrays(privateKeyResult.Content, []byte{0, 1, 4}) {
+		t.Errorf("DoGetPrivateKey, incorrect keyResult.Content, expected: %v, but was: %v",
+			[]byte{0, 1, 2}, privateKeyResult.Content)
+	}
+
+	publicKey := &ksapi.PublicKey{
+		Name:        "pubkey1",
+		Content:     []byte{3, 4, 2},
+		Certificate: []byte{5, 1, 6},
+	}
+
+	statusList, _ = keyStorageClient.DoSetPublicKey(publicKey)
+	for _, status := range statusList {
+		if status.StatusType == "error" {
+			t.Errorf("DoSetPublicKey, returned error: %s.", status.Code+":"+status.Description)
+		}
+	}
+
+	publicKeyResult, statusList, _ := keyStorageClient.DoGetPublicKey("pubkey1")
+	for _, status := range statusList {
+		if status.StatusType == "error" {
+			t.Errorf("DoGetPublicKey, returned error: %s.", status.Code+":"+status.Description)
+		}
+	}
+	if publicKeyResult.Content == nil || !utils.CompareByteArrays(publicKeyResult.Content, []byte{3, 4, 2}) {
+		t.Errorf("DoGetPublicKey, incorrect publicKeyResult.Content, expected: %v, but was: %v",
+			[]byte{3, 4, 2}, publicKeyResult.Content)
+	}
+	if publicKeyResult.Certificate == nil || !utils.CompareByteArrays(publicKeyResult.Certificate, []byte{5, 1, 6}) {
+		t.Errorf("DoGetPublicKey, incorrect publicKeyResult.Certificate, expected: %v, but was: %v",
+			[]byte{5, 1, 6}, publicKeyResult.Certificate)
+	}
+}
+
+func TestMain(m *testing.M) {
+	// fire the gRPC server in a goroutine
+	go func() {
+		err := dataStorageServer.StartGRPCServer(dataStorageGrpcAddress, certFile, keyFile)
+		if err != nil {
+			log.Fatalf("failed to start gRPC server: %s", err)
+		}
+	}()
+
+	// wait a second for the server to start
+	time.Sleep(time.Duration(1) * time.Second)
+
+	// fire the gRPC server in a goroutine
+	go func() {
+		err := StartGRPCServer(keyStorageGrpcAddress, certFile, keyFile, dataStorageGrpcAddress)
+		if err != nil {
+			log.Fatalf("failed to start gRPC server: %s", err)
+		}
+	}()
+
+	// wait a second for the server to start
+	time.Sleep(time.Duration(1) * time.Second)
+
+	retCode := m.Run()
+	os.Exit(retCode)
+}
diff --git a/session/session.go b/session/session.go
new file mode 100644
index 0000000000000000000000000000000000000000..14793a89303df97561b0e64975fe40ab0a22ee2a
--- /dev/null
+++ b/session/session.go
@@ -0,0 +1,31 @@
+/*
+Copyright (c) 2018 Vereign AG [https://www.vereign.com]
+
+This is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+package session
+
+import (
+	client "code.vereign.com/code/viam-apis/data-storage-agent/client"
+)
+
+func CheckSession(uuid string, session string, sessionClient *client.DataStorageClientImpl) bool {
+	hasSession, _, err := sessionClient.HasSession(uuid, session)
+	if err != nil {
+		return false
+	}
+
+	return hasSession
+}