diff --git a/internal/api/gen/proto/go/kmsetsi/kmsetsiproto.pb.go b/internal/api/gen/proto/go/kmsetsi/kmsetsiproto.pb.go
index 80cf822b317b6a457997549b0dd6b7342046b459..af7a507c7f40823c4620e0881f2e02cf744ee169 100644
--- a/internal/api/gen/proto/go/kmsetsi/kmsetsiproto.pb.go
+++ b/internal/api/gen/proto/go/kmsetsi/kmsetsiproto.pb.go
@@ -27,7 +27,7 @@ type QuantumElementInfo struct {
 	unknownFields protoimpl.UnknownFields
 
 	Timestamp int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
-	QleID     uint64 `protobuf:"varint,2,opt,name=qleID,proto3" json:"qleID,omitempty"`
+	QleID     string `protobuf:"bytes,2,opt,name=qleID,proto3" json:"qleID,omitempty"`
 	UdpAddr   string `protobuf:"bytes,3,opt,name=udpAddr,proto3" json:"udpAddr,omitempty"`
 }
 
@@ -70,11 +70,11 @@ func (x *QuantumElementInfo) GetTimestamp() int64 {
 	return 0
 }
 
-func (x *QuantumElementInfo) GetQleID() uint64 {
+func (x *QuantumElementInfo) GetQleID() string {
 	if x != nil {
 		return x.QleID
 	}
-	return 0
+	return ""
 }
 
 func (x *QuantumElementInfo) GetUdpAddr() string {
@@ -305,7 +305,7 @@ type ETSIKMSPeerRequest struct {
 
 	Timestamp     int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
 	KmsPeerSocket string `protobuf:"bytes,2,opt,name=kmsPeerSocket,proto3" json:"kmsPeerSocket,omitempty"`
-	KmsLocalQLEId uint32 `protobuf:"varint,3,opt,name=kmsLocalQLEId,proto3" json:"kmsLocalQLEId,omitempty"`
+	KmsLocalQLEId string `protobuf:"bytes,3,opt,name=kmsLocalQLEId,proto3" json:"kmsLocalQLEId,omitempty"`
 }
 
 func (x *ETSIKMSPeerRequest) Reset() {
@@ -354,11 +354,11 @@ func (x *ETSIKMSPeerRequest) GetKmsPeerSocket() string {
 	return ""
 }
 
-func (x *ETSIKMSPeerRequest) GetKmsLocalQLEId() uint32 {
+func (x *ETSIKMSPeerRequest) GetKmsLocalQLEId() string {
 	if x != nil {
 		return x.KmsLocalQLEId
 	}
-	return 0
+	return ""
 }
 
 type ETSIKMSPeerReply struct {
@@ -912,7 +912,7 @@ var file_kmsetsi_kmsetsiproto_proto_rawDesc = []byte{
 	0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1c, 0x0a, 0x09, 0x74,
 	0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09,
 	0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x71, 0x6c, 0x65,
-	0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x71, 0x6c, 0x65, 0x49, 0x44, 0x12,
+	0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x6c, 0x65, 0x49, 0x44, 0x12,
 	0x18, 0x0a, 0x07, 0x75, 0x64, 0x70, 0x41, 0x64, 0x64, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
 	0x52, 0x07, 0x75, 0x64, 0x70, 0x41, 0x64, 0x64, 0x72, 0x22, 0x55, 0x0a, 0x17, 0x45, 0x54, 0x53,
 	0x49, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71,
@@ -945,7 +945,7 @@ var file_kmsetsi_kmsetsiproto_proto_rawDesc = []byte{
 	0x65, 0x72, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d,
 	0x6b, 0x6d, 0x73, 0x50, 0x65, 0x65, 0x72, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x24, 0x0a,
 	0x0d, 0x6b, 0x6d, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x51, 0x4c, 0x45, 0x49, 0x64, 0x18, 0x03,
-	0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x6b, 0x6d, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x51, 0x4c,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6b, 0x6d, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x51, 0x4c,
 	0x45, 0x49, 0x64, 0x22, 0x52, 0x0a, 0x10, 0x45, 0x54, 0x53, 0x49, 0x4b, 0x4d, 0x53, 0x50, 0x65,
 	0x65, 0x72, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73,
 	0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65,
diff --git a/internal/api/kmsetsi/kmsetsi/kmsetsiproto.proto b/internal/api/kmsetsi/kmsetsi/kmsetsiproto.proto
index 261dd51b19f928ed0d9bb1ce6ab05da8b500ab6f..0c2e19616074c7f60c2bad21491d1d43a7a0a5a6 100644
--- a/internal/api/kmsetsi/kmsetsi/kmsetsiproto.proto
+++ b/internal/api/kmsetsi/kmsetsi/kmsetsiproto.proto
@@ -18,7 +18,7 @@ service KmsETSI{
 // NB for myself: this be used to link QLE mit KMS-Session!
 message QuantumElementInfo {
 	int64 timestamp = 1;
-    uint64 qleID = 2;
+    string qleID = 2;
     string udpAddr = 3;
 }
 
@@ -46,7 +46,7 @@ message ETSIKMSQuantumInterfaceListReply {
 message ETSIKMSPeerRequest {
 	int64 timestamp = 1;
     string kmsPeerSocket = 2;
-    uint32 kmsLocalQLEId = 3;
+    string kmsLocalQLEId = 3;
 }
 
 message ETSIKMSPeerReply {
diff --git a/internal/docs/run.sh b/internal/docs/run.sh
index 1d8c279948e159d298295bc764eb17be891ec018..a48acc17a8cfcff54b5a2db34d74c1d59ddc85ca 100755
--- a/internal/docs/run.sh
+++ b/internal/docs/run.sh
@@ -1,3 +1,3 @@
 grpcurl -d '{"pathId" : "f6a575e5-c7f9-4765-8890-134ae5b8f451", "nextHop" : "", "prevHop" : "[::1]:50932"}' --import-path ../api/kmsetsi/kmsetsi --proto kmsetsiproto.proto  --plaintext [::1]:50901  kmsetsi.KmsETSI.ETSIAssignForwarding
-grpcurl -d '{"pathId" : "f6a575e5-c7f9-4765-8890-134ae5b8f451", "nextHop" : "[::1]:50931", "prevHop": "[::1]:50930"}' --import-path ../api/kmsetsi//kmsetsi --proto kmsetsiproto.proto  --plaintext [::1]:50902  kmsetsi.KmsETSI.ETSIAssignForwarding
-grpcurl -d '{"pathId" : "f6a575e5-c7f9-4765-8890-134ae5b8f451", "nextHop" : "[::1]:50932"}' --import-path ../api/kmsetsi//kmsetsi --proto kmsetsiproto.proto  --plaintext [::1]:50900  kmsetsi.KmsETSI.ETSIAssignForwarding
+grpcurl -d '{"pathId" : "f6a575e5-c7f9-4765-8890-134ae5b8f451", "nextHop" : "[::1]:50931", "prevHop": "[::1]:50930"}' --import-path ../api/kmsetsi/kmsetsi --proto kmsetsiproto.proto  --plaintext [::1]:50902  kmsetsi.KmsETSI.ETSIAssignForwarding
+grpcurl -d '{"pathId" : "f6a575e5-c7f9-4765-8890-134ae5b8f451", "nextHop" : "[::1]:50932"}' --import-path ../api/kmsetsi/kmsetsi --proto kmsetsiproto.proto  --plaintext [::1]:50900  kmsetsi.KmsETSI.ETSIAssignForwarding
diff --git a/internal/kms/kms-keystore.go b/internal/kms/kms-keystore.go
index b3f3de46da4c1fdfe58d8012539f4ee2729ab939..93a29b740a1f4da5ff0077ab8365e54a41f5b7bc 100644
--- a/internal/kms/kms-keystore.go
+++ b/internal/kms/kms-keystore.go
@@ -1,7 +1,6 @@
 package kms
 
 import (
-	"errors"
 	"fmt"
 	"sync"
 
@@ -32,19 +31,18 @@ type kmsKSElement struct {
 }
 
 type kmsKeyStore struct {
-	keyStoreMutex    sync.Mutex
-	underlyingBulkId int64
-	keyStore         map[uint64]*kmsKSElement
-	keySingleSize    uint // the size of a single key, given as unit of bits
-	indexCounter     uint64
+	keyStoreMutex sync.Mutex
+	keyStore      map[uint64]*kmsKSElement
+	keySingleSize uint // the size of a single key, given as unit of bits
+	indexCounter  uint64
 }
 
 func NewKmsKeyStore(desiredkeySingleSizeLength uint) *kmsKeyStore {
 	return &kmsKeyStore{
-		underlyingBulkId: 0,
-		keyStore:         make(map[uint64]*kmsKSElement),
-		keySingleSize:    desiredkeySingleSizeLength,
-		indexCounter:     0,
+		// NOTE: could be useful to use something like a ordered map here
+		keyStore:      make(map[uint64]*kmsKSElement),
+		keySingleSize: desiredkeySingleSizeLength,
+		indexCounter:  0,
 	}
 }
 
@@ -54,7 +52,7 @@ func (ks *kmsKeyStore) addKey(keyId uint64, keyToadd []byte) {
 
 	// test for collisions
 	if _, notThere := ks.keyStore[keyId]; notThere {
-		log.Errorf("Whop: addKey collission of key id %s for bulkKeyID %d", keyId, ks.underlyingBulkId)
+		log.Errorf("Whop: addKey collission of key id %s", keyId)
 		return
 	}
 
@@ -86,37 +84,27 @@ func (ks *kmsKeyStore) GetKey() (*kmsKSElement, error) {
 	return nil, fmt.Errorf("Key with index: %d is already reserved.", ks.indexCounter)
 }
 
-// Takes a bulk of keys and chops them in chopFactor keys each
-// Any remainder is discarded
-func (ks *kmsKeyStore) KeyChopper(bulkKey *quantumlayer.QuantumLayerBulkKey) (err error) {
-	if ks.keySingleSize == 0 {
-		err = errors.New("KeyChopper: no  keySingleSize set")
-		return err
-	}
-	// TODO check if multiple of 8 (1 Byte)
+func (ks *kmsKeyStore) GetKeyWithID(id uint64) (*kmsKSElement, error) {
+	ks.keyStoreMutex.Lock()
+	defer ks.keyStoreMutex.Unlock()
 
-	if bulkKey.BulkKeyLength != len(*bulkKey.BulkKey) {
-		err = errors.New("bulkKey length mismatch")
-		return err
+	key, ok := ks.keyStore[id]
+	if !ok {
+		return nil, fmt.Errorf("Could not find a key for id: %d", ks.indexCounter)
 	}
+	if key.status == AVAILABLE {
+		// change status of key to reserved
+		key.status = RESERVED
+		// increase index counter
+		ks.indexCounter = ks.indexCounter + 1
 
-	// Store underlying bulkID
-	ks.underlyingBulkId = bulkKey.BulkKeyId
-	// reset indexCounter
-	ks.indexCounter = 0
-
-	var keyId uint64
-	keyId = 0
-
-	// Let's chop!
-	chopFactor := ks.keySingleSize >> 3
-	key := *bulkKey.BulkKey
-	for len(key) > int(chopFactor) {
-		tmpkey := key[:chopFactor]
-		ks.addKey(keyId, tmpkey)
-		keyId++
-		// shorten the key storage
-		key = key[chopFactor:]
+		return key, nil
 	}
-	return nil
+	return nil, fmt.Errorf("Key with index: %d is already reserved.", ks.indexCounter)
+}
+
+func (ks *kmsKeyStore) DeleteKey(keyId uint64) {
+	ks.keyStoreMutex.Lock()
+	delete(ks.keyStore, keyId)
+	ks.keyStoreMutex.Unlock()
 }
diff --git a/internal/kms/kms.go b/internal/kms/kms.go
index 6b7c925d59dd02eff1d1f203024e62f2dc1371b6..696c0ea328b726c56edd220280fb94ca07625231 100644
--- a/internal/kms/kms.go
+++ b/internal/kms/kms.go
@@ -5,31 +5,27 @@
 package kms
 
 import (
-	"crypto/rand"
-	"encoding/binary"
 	"fmt"
 	"io"
 	"sync"
-	"time"
 
 	log "github.com/sirupsen/logrus"
 
 	pbETSI "code.fbi.h-da.de/danet/proto-kms/api/gen/proto/go/kmsetsi"
 	pbIC "code.fbi.h-da.de/danet/proto-kms/api/gen/proto/go/kmsintercom"
-	"code.fbi.h-da.de/danet/proto-kms/quantumlayer"
 	"github.com/google/uuid"
 )
 
-type Qkdnkms interface {
-	//AddExternalNotifierGeneral(chan bool)   // used to indicate unspecific changes
-	AddExternalNotifierQLE(chan uint32)     // used to indicate changes to specific Quantum Link Element (QLE)
-	AddExternalNotifierKMSPeer(chan string) // used to indicate changes to specific KMSPeer
-	AddQuantumElement() *QuantumElement
-	GlobalKeyHandler(time.Duration) error
-	AddPeer(kmsPeerSocket string, servingQLE *QuantumElement)
-	RemovePeer(kmsPeerSocket string)
-	FindPeerUuid(uuid.UUID) *kmsPeer
-}
+//type Qkdnkms interface {
+//	//AddExternalNotifierGeneral(chan bool)   // used to indicate unspecific changes
+//	AddExternalNotifierQLE(chan uint32)     // used to indicate changes to specific Quantum Link Element (QLE)
+//	AddExternalNotifierKMSPeer(chan string) // used to indicate changes to specific KMSPeer
+//	AddQuantumElement() *EmulatedQuantumModule
+//	GlobalKeyHandler(time.Duration) error
+//	AddPeer(kmsPeerSocket string, servingQLE *EmulatedQuantumModule)
+//	RemovePeer(kmsPeerSocket string)
+//	FindPeerUuid(uuid.UUID) *kmsPeer
+//}
 
 type Route struct {
 	Previous *kmsPeer
@@ -50,7 +46,8 @@ type EKMS struct {
 	kmsUUID             uuid.UUID
 	interComAddr        string
 	qleMapMutex         sync.Mutex
-	QuantumElements     map[uint32]*QuantumElement
+	quantumModules      map[uuid.UUID]QuantumModule
+	quantumModulesMutex sync.RWMutex
 	externalNotifierQLE chan uint32
 	kmsPeersMutex       sync.Mutex
 	// TODO(maba): find a better name for this
@@ -71,15 +68,6 @@ type QuantumElementInterface interface {
 	GetQlID() qlElementId
 }*/
 
-type QuantumElement struct {
-	QlID               uint32
-	QuantumElementLink *quantumlayer.QuantumlayerEmuPRNG // contains information about the quantum links
-	//key stores of unchopped bulk keys go here
-	rawBulkKeysMutex sync.Mutex
-	rawBulkKeys      map[int64]*quantumlayer.QuantumLayerBulkKey
-	keyStorePeer     *kmsKeyStore // the keys used between two peers.
-}
-
 func NewEKMS(kmsName string, kmsUUID uuid.UUID, logOutput io.Writer, logLevel log.Level, logInJson bool, interComAddr string) (newEKMS *EKMS) {
 	/*
 	 * Setup logging
@@ -105,7 +93,7 @@ func NewEKMS(kmsName string, kmsUUID uuid.UUID, logOutput io.Writer, logLevel lo
 		kmsName:                 kmsName,
 		kmsUUID:                 kmsUUID,
 		interComAddr:            interComAddr,
-		QuantumElements:         make(map[uint32]*QuantumElement),
+		quantumModules:          make(map[uuid.UUID]QuantumModule),
 		routingTable:            make(map[uuid.UUID]*Route),
 		KmsPeers:                make(map[string]*kmsPeer),
 		externalNotifierQLE:     nil, // just be surely set to nil!
@@ -121,86 +109,14 @@ func NewEKMS(kmsName string, kmsUUID uuid.UUID, logOutput io.Writer, logLevel lo
 	return createdEKMS
 }
 
-func (kms *EKMS) AddQuantumElement(kmsUDPAddrr string, generateKeys bool, logOutput io.Writer, logLevel log.Level, logInJson bool) *QuantumElement {
-
-	//Get an emulated Quantumlayer
-	ql := quantumlayer.NewQuantumlayerEmuPRNG(logOutput, logLevel, logInJson)
-	ql.Configure(kmsUDPAddrr)
-	ql.PowerOn(generateKeys)
-
-	qle := QuantumElement{
-		QuantumElementLink: ql,
-		rawBulkKeys:        make(map[int64]*quantumlayer.QuantumLayerBulkKey),
-		// keyStorePeer:   not set, will be set later on, if key size is negotiated.
-	}
-
-	// generate a ID for this quantum element that is unique locally
-	var randError error
-	qle.QlID, randError = kms.GenerateNewQleID()
-	if randError != nil {
-		log.Fatalf("%s: GenerateNewQleID: %s", kms.kmsName, randError)
-		return nil
-	}
-
-	kms.QuantumElements[qle.QlID] = &qle
-
-	return &qle
-}
-
-// TODO: Name of this function is misleading, as it only reads the bulk keys, but nothing more else
-func (kms *EKMS) GlobalKeyHandler(waitTime time.Duration) error {
-	// periodically walk through QuantumElements and retrieve the
-	// - key bulk buffer for each peer
-	// feed this into the corresponding key buffers of the kmss
-	for {
-		for currentQE := range kms.QuantumElements {
-			log.Debugf("%s GlobalKeyHandler reading...\n", kms.kmsName)
-
-			bulkKeys, err := kms.QuantumElements[currentQE].QuantumElementLink.GetKeyBulkPeer()
-			if err != nil {
-				log.Errorf("%s failed to retrieve bulkkeys with error %s", kms.kmsName, err)
-			} else {
-				// Add to the slice, but not process yet.
-				log.Debugf("%s produced %d bytes of key", kms.kmsName, bulkKeys.BulkKeyLength)
-				kms.QuantumElements[currentQE].rawBulkKeysMutex.Lock()
-				//kms.QuantumElements[currentQE].rawBulkKeys = append(kms.QuantumElements[currentQE].rawBulkKeys, &bulkKeys)
-				kms.QuantumElements[currentQE].rawBulkKeys[bulkKeys.BulkKeyId] = &bulkKeys
-				kms.QuantumElements[currentQE].rawBulkKeysMutex.Unlock()
-
-				//kms.QuantumElements[currentQE].keyStorePeer.KeyChopper256Bit(&bulkKeys)
-
-			}
-		}
-		// TODO: Better approach required than a sleep timer!
-		time.Sleep(waitTime)
-	}
-}
-
-// This has a design flaw, as the generated ID is returned to the calling function and used there.
-// However, when being used a potential other caller might received the same qlElementId
-// TODO/XXX: This would be collision and must be eventually avoided
-func (kms *EKMS) GenerateNewQleID() (uint32, error) {
-	for { // this needs a condition to stop!
-		// create buffer for uint32, so reserve 4 bytes
-		buf := make([]byte, 4)
-
-		// fill the buffer from rand
-		_, err := rand.Read(buf)
-		if err != nil {
-			return 0, err
-		}
-
-		propopsedQlElementID := binary.BigEndian.Uint32(buf)
-
-		// check if ID is already taken
-		if kms.QuantumElements[propopsedQlElementID] == nil {
-			return propopsedQlElementID, nil
-		}
-		//keep going....
-	}
+func (kms *EKMS) AddQuantumElement(qm QuantumModule) error {
+	kms.quantumModulesMutex.Lock()
+	kms.quantumModules[qm.ID()] = qm
+	kms.quantumModulesMutex.Unlock()
+	return nil
 }
 
-func (kms *EKMS) AddPeer(kmsPeerSocket string, servingQLE *QuantumElement) (*kmsPeer, error) {
+func (kms *EKMS) AddPeer(kmsPeerSocket string, servingQLE QuantumModule) (*kmsPeer, error) {
 	//check if peer exists
 	if _, there := kms.KmsPeers[kmsPeerSocket]; there {
 		log.Errorf("Trying to add existing peer %s", kmsPeerSocket)
diff --git a/internal/kms/kmsetsi.go b/internal/kms/kmsetsi.go
index 8dc0e4f79910eabdd55fa373dea405411700be93..689611937e19ad2bea90bfdb6d47c73c1c853098 100644
--- a/internal/kms/kmsetsi.go
+++ b/internal/kms/kmsetsi.go
@@ -2,7 +2,6 @@ package kms
 
 import (
 	"context"
-	"encoding/json"
 	"errors"
 	"flag"
 	"fmt"
@@ -40,10 +39,10 @@ func (es *etsiServer) ETSIGetQuantumInterfaces(ctx context.Context, in *pb.ETSIK
 	qleList := make([]*pb.QuantumElementInfo, 1)
 
 	// Walk through QuantumLayerInterfaces and return their information
-	for _, qlWorks := range es.handlingEkms.QuantumElements {
+	for _, qlWorks := range es.handlingEkms.quantumModules {
 		qleElement := pb.QuantumElementInfo{
-			QleID:   uint64(qlWorks.QlID),
-			UdpAddr: fmt.Sprintf("%s:%d", qlWorks.QuantumElementLink.GetLocalQLPort().IP.String(), qlWorks.QuantumElementLink.GetLocalQLPort().Port),
+			QleID:   qlWorks.ID().String(),
+			UdpAddr: qlWorks.Address().String(),
 		}
 		qleList = append(qleList, &qleElement)
 	}
@@ -57,8 +56,8 @@ func (es *etsiServer) ETSIAddKMSPeer(ctx context.Context, in *pb.ETSIKMSPeerRequ
 	log.Debugf("AddKMSPeer called.")
 
 	// Check first if KmsLocalQLEId is actually one of ours...
-	qleID := in.KmsLocalQLEId
-	servingQLE, _ := es.handlingEkms.QuantumElements[qleID]
+	qleID := uuid.MustParse(in.KmsLocalQLEId)
+	servingQLE, _ := es.handlingEkms.quantumModules[qleID]
 	if servingQLE == nil {
 		//no such element!
 		err := errors.New(fmt.Sprintf("Unknown local quantum element with ID %d", qleID))
@@ -146,19 +145,19 @@ func (es *etsiServer) ETSISendPayload(ctx context.Context, in *pb.ETSISendPayloa
 	}
 
 	// NOTE: For demo purpose only
-	json, err := json.Marshal(KMSInfo{
-		Name:             es.handlingEkms.kmsName,
-		EncryptedMessage: in.Payload,
-		DecryptedMessage: in.Payload,
-	})
-	if err != nil {
-		log.Println("Failed to marshal: ", err)
-	}
-
-	err = sendKmsInfoMessage("http://172.20.10.21:4000/kmsinfo", json)
-	if err != nil {
-		log.Println("Failed to send KMS info message: ", err)
-	}
+	//json, err := json.Marshal(KMSInfo{
+	//	Name:             es.handlingEkms.kmsName,
+	//	EncryptedMessage: in.Payload,
+	//	DecryptedMessage: in.Payload,
+	//})
+	//if err != nil {
+	//	log.Println("Failed to marshal: ", err)
+	//}
+
+	//err = sendKmsInfoMessage("http://172.20.10.21:4000/kmsinfo", json)
+	//if err != nil {
+	//	log.Println("Failed to send KMS info message: ", err)
+	//}
 
 	if err := route.Next.SendPayload([]byte(in.GetPayload()), pathId); err != nil {
 		return nil, status.Errorf(codes.Internal, "Failed to send payload: ", err)
@@ -169,42 +168,6 @@ func (es *etsiServer) ETSISendPayload(ctx context.Context, in *pb.ETSISendPayloa
 	}, nil
 }
 
-//func (es *etsiServer) ETSIGetEncryptKeys256Bit(ctx context.Context, in *pb.ETSIGetEncryptKeys256BitRequest) (*pb.ETSIGetEncryptKeys256BitReply, error) {
-//	log.Printf("Received request for n=%d keys", in.GetAmount())
-//
-//	var randomKey *kmsKSElement
-//	var err error
-//	// NOTE: change change change!
-//	for _, qe := range es.handlingEkms.QuantumElements {
-//		quantumElementLocalKeyStore := qe.keyStorePeer
-//		randomKey, err = randomItemFromMap[uint64, *kmsKSElement](quantumElementLocalKeyStore.keyStore, es.visitedKeys)
-//		if err != nil {
-//			return nil, status.Errorf(codes.Internal, "%v", err)
-//		}
-//		es.visitedKeys[randomKey] = true
-//	}
-//
-//	// TODO: Remove/move ssh-kind prototype code below
-//	keyAsString := base64.StdEncoding.EncodeToString(randomKey.key)
-//	// push the key to the encryptor via ssh
-//	ssh := "ssh"
-//	complexArg := fmt.Sprintf("(rc=$(sed \"12 c PresharedKey = %s\" /etc/wireguard/wg0.conf); echo \"$rc\" > /etc/wireguard/wg0.conf)", keyAsString)
-//	args := []string{"root@172.20.0.5", "-oStrictHostKeyChecking=no", complexArg}
-//
-//	cmd := exec.Command(ssh, args...)
-//	err = cmd.Run()
-//	if err != nil {
-//		log.Errorf("could not execute ssh command with parameters")
-//		return nil, status.Errorf(codes.Internal, "%v", err)
-//	}
-//
-//	// Construct any response
-//	return &pb.ETSIGetEncryptKeys256BitReply{
-//		KeyID: randomKey.keyID,
-//		Key:   randomKey.key,
-//	}, nil
-//}
-
 func StartETSI(listenAddr string, callingKMS *EKMS) {
 	flag.Parse()
 
diff --git a/internal/kms/kmsintercom.go b/internal/kms/kmsintercom.go
index 42670803e1bc5eb6264a2f1e8740b84bf3f889f0..78cd85502e2d52c17534f794e26bad77a36ad27e 100644
--- a/internal/kms/kmsintercom.go
+++ b/internal/kms/kmsintercom.go
@@ -3,7 +3,6 @@ package kms
 import (
 	"context"
 	"encoding/base64"
-	"encoding/json"
 	"flag"
 	"net"
 	"time"
@@ -39,6 +38,8 @@ func (s *kmsTalkerServer) InterComCapabilities(ctx context.Context, in *pb.Inter
 	}, nil
 }
 
+// TODO: should be removed as soon as the emulated quantum module has been
+// changed; is specific for emulated quantum module
 func (s *kmsTalkerServer) SyncQkdBulk(ctx context.Context, in *pb.SyncQkdBulkRequest) (*pb.SyncQkdBulkResponse, error) {
 	// NOTE: with "google.golang.org/grpc/peer" it would be possible to get the client ip directly
 
@@ -49,19 +50,24 @@ func (s *kmsTalkerServer) SyncQkdBulk(ctx context.Context, in *pb.SyncQkdBulkReq
 		return nil, status.Errorf(codes.Internal, "peer does not exist")
 	}
 
+	eqm, ok := peer.servingQuantumModul.(*EmulatedQuantumModule)
+	if !ok {
+		return nil, status.Errorf(codes.Internal, "expected emulated quantum module")
+	}
+
 	for _, bulkId := range in.BulkId {
-		rawBulkKeyIds := keysOfMap[int64](peer.servingQLE.rawBulkKeys)
+		rawBulkKeyIds := keysOfMap[int64](eqm.rawBulkKeys)
 		log.Info("PEER BULK KEYS: ", rawBulkKeyIds)
-		if bulk, ok := peer.servingQLE.rawBulkKeys[bulkId]; ok {
-			peer.servingQLE.keyStorePeer = NewKmsKeyStore(256)
-			if err := peer.servingQLE.keyStorePeer.KeyChopper(bulk); err != nil {
+		if bulk, ok := eqm.rawBulkKeys[bulkId]; ok {
+			eqm.keyStore = NewKmsKeyStore(256)
+			if err := eqm.KeyChopper(bulk); err != nil {
 				//TODO: proper error message
 				return nil, status.Errorf(codes.Internal, "chopping failed")
 			}
 
-			peer.servingQLE.rawBulkKeysMutex.Lock()
-			delete(peer.servingQLE.rawBulkKeys, bulkId)
-			peer.servingQLE.rawBulkKeysMutex.Unlock()
+			eqm.rawBulkKeysMutex.Lock()
+			delete(eqm.rawBulkKeys, bulkId)
+			eqm.rawBulkKeysMutex.Unlock()
 
 			return &pb.SyncQkdBulkResponse{
 				Timestamp: time.Now().Unix(),
@@ -101,13 +107,14 @@ func (s *kmsTalkerServer) InterComTransportKeyNegotiation(ctx context.Context, i
 	//	return nil, status.Errorf(codes.Internal, "A transport key for pathID: %s has already been negotiated.", in.PathID)
 	//}
 
-	quantumElementRemoteKeyStore := route.Previous.servingQLE.keyStorePeer
+	quantumModuleKeyStore := route.Previous.servingQuantumModul.KeyStore()
 
-	key, ok := quantumElementRemoteKeyStore.keyStore[keyID]
-	if !ok {
-		return nil, status.Errorf(codes.Internal, "Key with ID: %s could not be found.", keyID)
+	key, err := quantumModuleKeyStore.GetKeyWithID(keyID)
+	if err != nil {
+		return nil, status.Errorf(codes.Internal, "%v", err)
 	}
 
+	// TODO: mutex
 	s.keyNegotiationMap[pathId] = key
 
 	return &pb.InterComTransportKeyNegotiationResponse{Timestamp: time.Now().Unix()}, nil
@@ -148,21 +155,21 @@ func (s *kmsTalkerServer) KeyForwarding(ctx context.Context, in *pb.KeyForwardin
 		log.Infof("%s received the final payload: ", s.eKMS.kmsName, string(decryptedPayload))
 	}
 
-	// NOTE: For demo purpose only
-	json, err := json.Marshal(KMSInfo{
-		Name:             s.eKMS.kmsName,
-		EncryptedMessage: in.Payload,
-		DecryptedMessage: string(decryptedPayload),
-		Key:              base64.StdEncoding.EncodeToString(decryptKey.key),
-	})
-	if err != nil {
-		log.Println("Failed to marshal: ", err)
-	}
+	//// NOTE: For demo purpose only
+	//json, err := json.Marshal(KMSInfo{
+	//	Name:             s.eKMS.kmsName,
+	//	EncryptedMessage: in.Payload,
+	//	DecryptedMessage: string(decryptedPayload),
+	//	Key:              base64.StdEncoding.EncodeToString(decryptKey.key),
+	//})
+	//if err != nil {
+	//	log.Println("Failed to marshal: ", err)
+	//}
 
-	err = sendKmsInfoMessage("http://172.20.10.21:4000/kmsinfo", json)
-	if err != nil {
-		log.Println("Failed to send KMS info message: ", err)
-	}
+	//err = sendKmsInfoMessage("http://172.20.10.21:4000/kmsinfo", json)
+	//if err != nil {
+	//	log.Println("Failed to send KMS info message: ", err)
+	//}
 
 	return &pb.KeyForwardingResponse{Timestamp: time.Now().Unix()}, nil
 }
diff --git a/internal/kms/kmspeers.go b/internal/kms/kmspeers.go
index 6e42f8f78e47394572c9be6ab3e22affd27ff930..494cb3b1d62b3b70e68b498d27d4f71d92d6510c 100644
--- a/internal/kms/kmspeers.go
+++ b/internal/kms/kmspeers.go
@@ -9,7 +9,6 @@ import (
 
 	pbIC "code.fbi.h-da.de/danet/proto-kms/api/gen/proto/go/kmsintercom"
 	"github.com/google/uuid"
-	"github.com/sirupsen/logrus"
 	log "github.com/sirupsen/logrus"
 	"google.golang.org/grpc"
 	"google.golang.org/grpc/credentials/insecure"
@@ -36,7 +35,7 @@ type kmsPeer struct {
 	peerClient              pbIC.KmsTalkerClient
 	peerStatus              KmsPeerStatus
 	interComAddr            string
-	servingQLE              *QuantumElement
+	servingQuantumModul     QuantumModule
 	tcpSocket               net.TCPAddr // the IP address and TCP port (aka socket) of the kms peer
 	tcpSocketStr            string      // string rep. of tcpSocket
 	et                      CryptoAlgorithm
@@ -45,178 +44,42 @@ type kmsPeer struct {
 	quit                    chan bool // cancel the peer goroutine
 }
 
-func NewKmsPeer(servQLE *QuantumElement, tcpSocketStr string, interComAddr string, in chan string) (peer *kmsPeer, err error) {
+func NewKmsPeer(servQM QuantumModule, tcpSocketStr string, interComAddr string, in chan string) (*kmsPeer, error) {
+	if servQM.Peer() != nil {
+		return nil, fmt.Errorf("QuantumModule with ID: , already has a peer", servQM.ID())
+	}
 	newPeerConn, err := grpc.Dial(tcpSocketStr, grpc.WithTransportCredentials(insecure.NewCredentials()))
 	if err != nil {
 		return nil, err
 	}
 	peerClient := pbIC.NewKmsTalkerClient(newPeerConn)
 
-	return &kmsPeer{
+	peer := &kmsPeer{
 		externalNotifierKMSPeer: in,
-		peerClient:              peerClient,
+		// TODO: rename to client
+		peerClient: peerClient,
 		// TODO: change this, only for demo purposes
 		peerStatus: KmsPeerUp,
 		// TODO: move this into a config
-		interComAddr: interComAddr,
-		servingQLE:   servQLE,
-		tcpSocketStr: tcpSocketStr,
-		et:           NewAES(),
-		id:           uuid.New(),
-		quit:         make(chan bool),
-	}, nil
-}
-
-// Handles everything with respect to a specific KMS peer
-//func (ph *kmsPeer) PeerHandler(kmsName string) {
-//	//	log.Infof("%s started PeerHandler for %s:", kmsName, ph.tcpSocketStr)
-//
-//	// contact peer
-//	newPeerConn, err := grpc.Dial(ph.tcpSocketStr, grpc.WithTransportCredentials(insecure.NewCredentials()))
-//	if err != nil {
-//		log.Errorf("%s: did not connect: %v", kmsName, err)
-//		ph.peerStatus = KmsPeerDown
-//		return
-//	}
-//	defer newPeerConn.Close()
-//
-//	c := pb.NewKmsETSIClient(newPeerConn)
-//
-//	// Contact the server and print out its response.
-//	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
-//	defer cancel()
-//	r, err := c.ETSICapabilities(ctx, &pb.ETSICapabilitiesRequest{MyKmsName: kmsName})
-//	if err != nil {
-//		log.Errorf("%s: could not greet: %v", kmsName, err)
-//		ph.peerStatus = KmsPeerDown
-//		// Send notification about change
-//		if ph.externalNotifierKMSPeer != nil {
-//			ph.externalNotifierKMSPeer <- ph.tcpSocketStr
-//		}
-//	}
-// // NOTE: If a session is created, we also request a encryption key for now
-//	//quantumElementRequest, err := c.ETSIGetQuantumInterfaces(ctx, &pb.ETSIKMSQuantumInterfaceListRequest{})
-//	//if err != nil {
-//	//	log.Println("Could not request quantum elements: ", err)
-//	//	ph.peerStatus = KmsPeerDown
-//	//	// Send notification about change
-//	//	if ph.externalNotifierKMSPeer != nil {
-//	//		ph.externalNotifierKMSPeer <- ph.tcpSocketStr
-//	//	}
-//	//	return
-//	//}
-//
-//	//if quantumElementRequest.QlElementInfo != nil {
-//	//	peerQuantumElement := quantumElementRequest.QlElementInfo[0].QleID
-//	//} else {
-//	//	// return error?!
-//	//}
-//
-//	// Works and peer moves to kmsPeerUp
-//	ph.peerStatus = KmsPeerUp
-//
-//	encryptKeyRequest, err := c.ETSIGetEncryptKeys256Bit(ctx, &pb.ETSIGetEncryptKeys256BitRequest{Amount: 1})
-//	if err != nil {
-//		log.Errorf("%s: could not request a encryption key: %s", kmsName, err)
-//		ph.peerStatus = KmsPeerDown
-//		// Send notification about change
-//		if ph.externalNotifierKMSPeer != nil {
-//			ph.externalNotifierKMSPeer <- ph.tcpSocketStr
-//		}
-//		return
-//	}
-//
-//	// check if key is in KeyStore
-//	if key, ok := ph.servingQLE.keyStorePeer.keyStore[encryptKeyRequest.KeyID]; ok {
-//		keyAsString := base64.StdEncoding.EncodeToString(key.key)
-//		log.Debugf("Agreed Key: %s", keyAsString)
-//
-//		// TODO: Remove/move ssh-kind prototype code below
-//		// push the key to the encryptor via ssh
-//		ssh := "ssh"
-//		complexArg := fmt.Sprintf("(rc=$(sed \"12 c PresharedKey = %s\" /etc/wireguard/wg0.conf); echo \"$rc\" > /etc/wireguard/wg0.conf)", keyAsString)
-//		args := []string{"root@172.20.0.4", "-oStrictHostKeyChecking=no", complexArg}
-//
-//		cmd := exec.Command(ssh, args...)
-//		err := cmd.Run()
-//		if err != nil {
-//			log.Errorf("%s: could not execute ssh command with parameters", kmsName)
-//			return
-//		}
-//	}
-//
-//	// Send notification about change
-//	if ph.externalNotifierKMSPeer != nil {
-//		ph.externalNotifierKMSPeer <- ph.tcpSocketStr
-//	}
-//
-//	log.Printf("Greeting: %s which is now in peerStatus %d", r.GetPeerKmsName(), ph.peerStatus)
-//
-//	// NOTE: should be possible to cancel!
-//	// By now, do check only the liveliness of the peer, nothing else.
-//	//for {
-//	//	select {
-//	//	case <-ph.quit:
-//	//		return
-//	//	default:
-//	//		// Contact the server and print out its response.
-//	//		ctx, cancel := context.WithTimeout(context.Background(), time.Second)
-//	//		defer cancel()
-//	//		_, err := c.ETSICapabilities(ctx, &pb.ETSICapabilitiesRequest{MyKmsName: kmsName})
-//	//		if err != nil {
-//	//			log.Printf("could not greet: %v", err)
-//	//			ph.peerStatus = KmsPeerDown
-//	//			// Send notification about change
-//	//			if ph.externalNotifierKMSPeer != nil {
-//	//				ph.externalNotifierKMSPeer <- ph.tcpSocketStr
-//	//			}
-//	//		}
-//	//		time.Sleep(30 * time.Second)
-//	//	}
-//	//}
-//}
-
-func (ph *kmsPeer) SyncBulkKeys() error {
-	rawBulkKeyIds := keysOfMap[int64](ph.servingQLE.rawBulkKeys)
-	logrus.Info("Found the following bulk key ids for usage: ", rawBulkKeyIds)
-
-	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
-	defer cancel()
-	initialPeerSetupResponse, err := ph.peerClient.SyncQkdBulk(ctx, &pbIC.SyncQkdBulkRequest{
-		Timestamp:    time.Now().Unix(),
-		InterComAddr: ph.interComAddr,
-		BulkId:       rawBulkKeyIds,
-	})
-	if err != nil {
-		return err
+		interComAddr:        interComAddr,
+		servingQuantumModul: servQM,
+		tcpSocketStr:        tcpSocketStr,
+		et:                  NewAES(),
+		id:                  uuid.New(),
+		quit:                make(chan bool),
 	}
 
-	bulkKey, ok := ph.servingQLE.rawBulkKeys[initialPeerSetupResponse.BulkId]
-	if !ok {
-		// TODO: add proper error message
-		return fmt.Errorf("Could not find raw bulk key with id: %d", initialPeerSetupResponse.BulkId)
-	}
-
-	// TODO: Initially the peer partners should discuss about the key length,
-	// for now it is hardcoded.
-	ph.servingQLE.keyStorePeer = NewKmsKeyStore(256)
+	servQM.SetPeer(peer)
 
-	if err := ph.servingQLE.keyStorePeer.KeyChopper(bulkKey); err != nil {
-		return err
+	if err := servQM.Initialize(); err != nil {
+		return nil, err
 	}
 
-	ph.servingQLE.rawBulkKeysMutex.Lock()
-	delete(ph.servingQLE.rawBulkKeys, initialPeerSetupResponse.BulkId)
-	ph.servingQLE.rawBulkKeysMutex.Unlock()
-
-	// update the peer status to up
-	ph.peerStatus = KmsPeerUp
-	// Send notification about change
-	if ph.externalNotifierKMSPeer != nil {
-		ph.externalNotifierKMSPeer <- ph.tcpSocketStr
-	}
+	return peer, nil
+}
 
-	return nil
+func (ph *kmsPeer) SyncBulkKeys() error {
+	return ph.servingQuantumModul.Sync()
 }
 
 // TransportKeyNegotiation sends a request for a transport key negotiation to
@@ -229,7 +92,9 @@ func (ph *kmsPeer) TransportKeyNegotiation() error {
 }
 
 func (ph *kmsPeer) SendPayload(payload []byte, pathId uuid.UUID) error {
-	if len(ph.servingQLE.keyStorePeer.keyStore) <= int(ph.servingQLE.keyStorePeer.indexCounter) {
+	// NOTE: It should be assumed that there are keys available if we try to
+	// send.
+	if len(ph.servingQuantumModul.KeyStore().keyStore) <= int(ph.servingQuantumModul.KeyStore().indexCounter) {
 		log.Debug("Syncing bulk keys before sending the payload")
 		err := ph.SyncBulkKeys()
 		if err != nil {
@@ -237,11 +102,10 @@ func (ph *kmsPeer) SendPayload(payload []byte, pathId uuid.UUID) error {
 		}
 	}
 
-	// TODO: Remove; for demo purposes only
-	time.Sleep(5 * time.Second)
+	// TODO: Return a message if keys are empty
 
 	// select a key from key store
-	key, err := ph.servingQLE.keyStorePeer.GetKey()
+	key, err := ph.servingQuantumModul.KeyStore().GetKey()
 	if err != nil {
 		return err
 	}
@@ -292,7 +156,3 @@ func (ph *kmsPeer) GetKmsPeerStatus() KmsPeerStatus {
 func (ph *kmsPeer) GetKmsPeerId() uuid.UUID {
 	return ph.id
 }
-
-func (ph *kmsPeer) GetKmsPeerQkdiId() uint32 {
-	return uint32(ph.servingQLE.QlID)
-}
diff --git a/internal/kms/module.go b/internal/kms/module.go
new file mode 100644
index 0000000000000000000000000000000000000000..0b170ba5e3b24d410c16d87e1cd6977efdbfb73c
--- /dev/null
+++ b/internal/kms/module.go
@@ -0,0 +1,179 @@
+package kms
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"io"
+	"net"
+	"sync"
+	"time"
+
+	pbIC "code.fbi.h-da.de/danet/proto-kms/api/gen/proto/go/kmsintercom"
+	"code.fbi.h-da.de/danet/proto-kms/quantumlayer"
+	"github.com/google/uuid"
+	"github.com/sirupsen/logrus"
+	log "github.com/sirupsen/logrus"
+)
+
+// QuantumModule ...
+type QuantumModule interface {
+	ID() uuid.UUID
+	Initialize() error
+	// NOTE: Sync will be removed as soon as the emulated quantum module has been
+	// changed to push a constant byte stream.
+	Sync() error
+	Manufacturer() string
+	KeyStore() *kmsKeyStore
+	Peer() *kmsPeer
+	SetPeer(*kmsPeer)
+	Address() net.Addr
+}
+
+type EmulatedQuantumModule struct {
+	QlID               uuid.UUID
+	QuantumElementLink *quantumlayer.QuantumlayerEmuPRNG // contains information about the quantum links
+	//key stores of unchopped bulk keys go here
+	rawBulkKeysMutex sync.Mutex
+	rawBulkKeys      map[int64]*quantumlayer.QuantumLayerBulkKey
+	keyStore         *kmsKeyStore // the keys used between two peers.
+	peer             *kmsPeer
+}
+
+func NewEmulatedQuantumModule(kmsUDPAddr string, generateKeys bool, logOutput io.Writer, logLevel log.Level, logInJson bool) *EmulatedQuantumModule {
+	// create an emulated quantum layer
+	ql := quantumlayer.NewQuantumlayerEmuPRNG(logOutput, logLevel, logInJson)
+	ql.Configure(kmsUDPAddr)
+	ql.PowerOn(generateKeys)
+
+	return &EmulatedQuantumModule{
+		QlID:               uuid.New(),
+		QuantumElementLink: ql,
+		rawBulkKeys:        make(map[int64]*quantumlayer.QuantumLayerBulkKey),
+		keyStore:           NewKmsKeyStore(256),
+		peer:               nil,
+	}
+}
+
+func (eqe *EmulatedQuantumModule) ID() uuid.UUID {
+	return eqe.QlID
+}
+
+func (eqe *EmulatedQuantumModule) Manufacturer() string {
+	return "danet"
+}
+
+func (eqe *EmulatedQuantumModule) Initialize() error {
+	// TODO: error handling
+	go eqe.keyHandler()
+	return nil
+}
+
+func (eqe *EmulatedQuantumModule) Address() net.Addr {
+	return eqe.QuantumElementLink.GetLocalQLPort()
+}
+
+func (eqe *EmulatedQuantumModule) KeyStore() *kmsKeyStore {
+	return eqe.keyStore
+}
+
+func (eqe *EmulatedQuantumModule) Sync() error {
+	rawBulkKeyIds := keysOfMap[int64](eqe.rawBulkKeys)
+	logrus.Info("Found the following bulk key ids for usage: ", rawBulkKeyIds)
+
+	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
+	defer cancel()
+	initialPeerSetupResponse, err := eqe.peer.peerClient.SyncQkdBulk(ctx, &pbIC.SyncQkdBulkRequest{
+		Timestamp:    time.Now().Unix(),
+		InterComAddr: eqe.peer.interComAddr,
+		BulkId:       rawBulkKeyIds,
+	})
+	if err != nil {
+		return err
+	}
+
+	bulkKey, ok := eqe.rawBulkKeys[initialPeerSetupResponse.BulkId]
+	if !ok {
+		// TODO: add proper error message
+		return fmt.Errorf("Could not find raw bulk key with id: %d", initialPeerSetupResponse.BulkId)
+	}
+
+	// TODO: Initially the peer partners should discuss about the key length,
+	// for now it is hardcoded.
+	eqe.keyStore = NewKmsKeyStore(256)
+
+	if err := eqe.KeyChopper(bulkKey); err != nil {
+		return err
+	}
+
+	eqe.rawBulkKeysMutex.Lock()
+	delete(eqe.rawBulkKeys, initialPeerSetupResponse.BulkId)
+	eqe.rawBulkKeysMutex.Unlock()
+
+	// update the peer status to up
+	eqe.peer.peerStatus = KmsPeerUp
+	// Send notification about change
+	if eqe.peer.externalNotifierKMSPeer != nil {
+		eqe.peer.externalNotifierKMSPeer <- eqe.peer.tcpSocketStr
+	}
+
+	return nil
+}
+
+func (eqe *EmulatedQuantumModule) Peer() *kmsPeer {
+	return eqe.peer
+}
+
+func (eqe *EmulatedQuantumModule) SetPeer(peer *kmsPeer) {
+	eqe.peer = peer
+}
+
+func (eqe *EmulatedQuantumModule) keyHandler() {
+	// periodically walk through quantum element and retrieve the key bulk buffer
+	for {
+		log.Debugf("%s: KeyHandler reading...\n", eqe.ID())
+		bulkKeys, err := eqe.QuantumElementLink.GetKeyBulkPeer()
+		if err != nil {
+			log.Errorf("%s: failed to retrieve bulkkeys with error %s", eqe.ID(), err)
+		} else {
+			// Add to the slice, but not process yet.
+			log.Debugf("%s: produced %d bytes of key", eqe.ID(), bulkKeys.BulkKeyLength)
+			eqe.rawBulkKeysMutex.Lock()
+			eqe.rawBulkKeys[bulkKeys.BulkKeyId] = &bulkKeys
+			eqe.rawBulkKeysMutex.Unlock()
+		}
+		// TODO: hardcoded
+		time.Sleep(5 * time.Second)
+	}
+}
+
+// Takes a bulk of keys and chops them in chopFactor keys each
+// Any remainder is discarded
+func (eqe *EmulatedQuantumModule) KeyChopper(bulkKey *quantumlayer.QuantumLayerBulkKey) error {
+	if eqe.keyStore.keySingleSize == 0 {
+		return errors.New("KeyChopper: no  keySingleSize set")
+	}
+	// TODO check if multiple of 8 (1 Byte)
+
+	if bulkKey.BulkKeyLength != len(*bulkKey.BulkKey) {
+		return errors.New("bulkKey length mismatch")
+	}
+
+	// reset indexCounter
+	eqe.keyStore.indexCounter = 0
+
+	var keyId uint64
+	keyId = 0
+
+	// Let's chop!
+	chopFactor := eqe.keyStore.keySingleSize >> 3
+	key := *bulkKey.BulkKey
+	for len(key) > int(chopFactor) {
+		tmpkey := key[:chopFactor]
+		eqe.keyStore.addKey(keyId, tmpkey)
+		keyId++
+		// shorten the key storage
+		key = key[chopFactor:]
+	}
+	return nil
+}
diff --git a/internal/main_test.go b/internal/main_test.go
index 9775621673bd106c66a1683bcfaf70ca9cd95423..3c59b5c785224bdc0879d45e616c86ed4f8d8bce 100644
--- a/internal/main_test.go
+++ b/internal/main_test.go
@@ -64,8 +64,14 @@ func emulatedKMS(myName, myUDPAddr, myInterComAddr, peerUDPAddr, peerInterComAdd
 	// Attach to eKMS
 	emuKMS := kms.NewEKMS(myName, uuid.New(), os.Stdout, log.TraceLevel, false, myInterComAddr)
 
+	eqm := kms.NewEmulatedQuantumModule(myUDPAddr, false, os.Stdout, log.TraceLevel, false)
+
 	// Fire up Quantum LinK
-	myQL := emuKMS.AddQuantumElement(myUDPAddr, false, os.Stdout, log.TraceLevel, false)
+	err := emuKMS.AddQuantumElement(eqm)
+	if err != nil {
+		log.Println("failed to create emulated quantum module")
+		return
+	}
 
 	udpQL2Addr, err := net.ResolveUDPAddr("udp", peerUDPAddr)
 	if err != nil {
@@ -73,9 +79,9 @@ func emulatedKMS(myName, myUDPAddr, myInterComAddr, peerUDPAddr, peerInterComAdd
 		return
 	}
 
-	myQL.QuantumElementLink.AddPeer(udpQL2Addr)
+	eqm.QuantumElementLink.AddPeer(udpQL2Addr)
 
-	_, err = emuKMS.AddPeer(peerInterComAddr, myQL)
+	_, err = emuKMS.AddPeer(peerInterComAddr, eqm)
 	if err != nil {
 		log.Println("PEERERROR: ", err)
 	}
@@ -83,8 +89,8 @@ func emulatedKMS(myName, myUDPAddr, myInterComAddr, peerUDPAddr, peerInterComAdd
 	// Start the SDN/management and key retrieval interface
 	go kms.StartETSI(myUDPAddr, emuKMS)
 
-	// TODO/XXX catch errors!
-	emuKMS.GlobalKeyHandler(7 * time.Second)
+	// // TODO/XXX catch errors!
+	// emuKMS.GlobalKeyHandler(7 * time.Second)
 }
 
 func middleKMS(myName, myUDPAddr, myInterComAddr, leftUDPAddr, leftInterComAddr, rightUDPAddr, rightInterComAddr string) {
@@ -92,8 +98,8 @@ func middleKMS(myName, myUDPAddr, myInterComAddr, leftUDPAddr, leftInterComAddr,
 	emuKMS := kms.NewEKMS(myName, uuid.New(), os.Stdout, log.TraceLevel, false, myInterComAddr)
 
 	// create two quantum modules that generate keys
-	qlForLeft := emuKMS.AddQuantumElement("[::1]:50910", true, os.Stdout, log.TraceLevel, false)
-	qlForRight := emuKMS.AddQuantumElement("[::1]:50911", true, os.Stdout, log.TraceLevel, false)
+	qlForLeft := kms.NewEmulatedQuantumModule("[::1]:50910", true, os.Stdout, log.TraceLevel, false)
+	qlForRight := kms.NewEmulatedQuantumModule("[::1]:50911", true, os.Stdout, log.TraceLevel, false)
 
 	netLeftUDPAddr, err := net.ResolveUDPAddr("udp", leftUDPAddr)
 	if err != nil {
@@ -107,6 +113,19 @@ func middleKMS(myName, myUDPAddr, myInterComAddr, leftUDPAddr, leftInterComAddr,
 		return
 	}
 
+	// Fire up Quantum LinK
+	err = emuKMS.AddQuantumElement(qlForLeft)
+	if err != nil {
+		log.Println("failed to create emulated quantum module")
+		return
+	}
+
+	err = emuKMS.AddQuantumElement(qlForRight)
+	if err != nil {
+		log.Println("failed to create emulated quantum module")
+		return
+	}
+
 	qlForLeft.QuantumElementLink.AddPeer(netLeftUDPAddr)
 	qlForRight.QuantumElementLink.AddPeer(netRightUDPAddr)
 
@@ -123,9 +142,6 @@ func middleKMS(myName, myUDPAddr, myInterComAddr, leftUDPAddr, leftInterComAddr,
 	// Start the SDN/management and key retrieval interface
 	go kms.StartETSI(myUDPAddr, emuKMS)
 
-	// TODO/XXX catch errors!
-	go emuKMS.GlobalKeyHandler(7 * time.Second)
-
 	time.Sleep(time.Second * 15)
 	if err := peerLeft.SyncBulkKeys(); err != nil {
 		log.Println("SYNC ERROR: ", err)
diff --git a/internal/quantumlayer/quantumlayer-emu-prng.go b/internal/quantumlayer/quantumlayer-emu-prng.go
index b2a2013b144d2adcdc94aee94dfcfed3d3d84a3d..76dcd1dfb268c61a2039e2011dd7eac747ad24c6 100644
--- a/internal/quantumlayer/quantumlayer-emu-prng.go
+++ b/internal/quantumlayer/quantumlayer-emu-prng.go
@@ -137,6 +137,7 @@ func (qlemuprng *QuantumlayerEmuPRNG) PowerOn(enableKeyGeneration bool) {
 			// Retrieve local UDP address and store it for further actions.
 			qlemuprng.qlLocalPort = qlemuprng.udpSrvConn.LocalAddr().(*net.UDPAddr)
 
+			// TODO: This does not seem to be necessary if the gle is not generating rands
 			log.Infof("QuantumlayerEmuPRNG: started server, waiting for incoming rands on port %s \n", qlemuprng.udpSrvConn.LocalAddr().(*net.UDPAddr).String())
 			inBuffer := make([]byte, 1500)
 			for {
@@ -248,8 +249,8 @@ func (qlemuprng *QuantumlayerEmuPRNG) RemovePeer() {
 	qlemuprng.qlPeerMutex.Unlock()
 }
 
-func (qlemuprng *QuantumlayerEmuPRNG) GetLocalQLPort() (myAddr net.UDPAddr) {
-	return *qlemuprng.qlLocalPort
+func (qlemuprng *QuantumlayerEmuPRNG) GetLocalQLPort() (myAddr *net.UDPAddr) {
+	return qlemuprng.qlLocalPort
 }
 
 func (qlemuprng *QuantumlayerEmuPRNG) GenerateRandomNumbers() (randNums []byte) {