diff --git a/quantumlayer-emu-prng.go b/quantumlayer-emu-prng.go index c1ff93295465377387b8d141a5b0179ed28e0657..8bb321a8f3b2dca4250dd080541b758888aaca53 100644 --- a/quantumlayer-emu-prng.go +++ b/quantumlayer-emu-prng.go @@ -32,7 +32,8 @@ type QuantumPayloadElement struct { type QuantumlayerEmuPRNG struct { configured bool - poweron bool + poweron bool // set to yes if operation, i.e., generating keys + generateKeys bool // set to yes, if this qle should generate random number. incomingRandNums chan QuantumPayloadElement outgoingRandNums chan QuantumPayloadElement peerNumbers *NumberStore @@ -74,6 +75,7 @@ func NewQuantumlayerEmuPRNG(logOutput io.Writer, logLevel logi.Level, logInJson return &QuantumlayerEmuPRNG{ configured: false, poweron: false, + generateKeys: false, incomingRandNums: make(chan QuantumPayloadElement), outgoingRandNums: make(chan QuantumPayloadElement), peerNumbers: NewNumberStore(40000), @@ -101,8 +103,8 @@ func (qlemuprng *QuantumlayerEmuPRNG) Configure(localQLAddress ...string) { // Power on the quantum layer, i.e., open up the communication ports for the // other quantum module -func (qlemuprng *QuantumlayerEmuPRNG) PowerOn() { - if qlemuprng.configured == false { +func (qlemuprng *QuantumlayerEmuPRNG) PowerOn(enableKeyGeneration bool) { + if !qlemuprng.configured { // nothing do here move on log.Errorf("QuantumlayerEmuPRNG: Sorry, the quantum layer is not configured for action. You've missed Configure()") return @@ -110,6 +112,11 @@ func (qlemuprng *QuantumlayerEmuPRNG) PowerOn() { //qlemuprng.poweron = false log.Infof("QuantumlayerEmuPRNG: is powering on...charging.") + if enableKeyGeneration { + log.Infof("QuantumlayerEmuPRNG: will GENERATE random keys") + } + qlemuprng.generateKeys = enableKeyGeneration + // serve UDP incoming if qlemuprng.udpSrvConn == nil { go func() { @@ -181,7 +188,7 @@ func (qlemuprng *QuantumlayerEmuPRNG) PowerOff() { } func (qlemuprng *QuantumlayerEmuPRNG) AddPeer(addr *net.UDPAddr) { - if qlemuprng.poweron == false { + if !qlemuprng.poweron { return } //TODO/XXX check the incoming addr @@ -191,40 +198,43 @@ func (qlemuprng *QuantumlayerEmuPRNG) AddPeer(addr *net.UDPAddr) { qlemuprng.qlPeer = addr.String() qlemuprng.qlPeerMutex.Unlock() - ctx, cancel := context.WithCancel(context.Background()) - qlemuprng.qlPeerCancel = cancel + // generate only keys if requested to do so. + if qlemuprng.generateKeys { + ctx, cancel := context.WithCancel(context.Background()) + qlemuprng.qlPeerCancel = cancel - // Start the generation and shipping of random numbers - go func(ctx context.Context) { - for { - select { - case <-ctx.Done(): - return - default: - if qlemuprng.poweron == true { - // retrieve a new back of random numbers - newNumberBatch := qlemuprng.GenerateRandomNumbers() - // TODO: Replace this by some generic encapsulation reader and not just JSON - //Get JSON for transmission ready - qpe := QuantumPayloadElement{time.Now().UnixNano(), len(newNumberBatch), &newNumberBatch} - - // XXX/TODO: error must be handled - jsonPayload, err := json.Marshal(qpe) - if err != nil { - log.Errorf("QuantumlayerEmuPRNG: json.Marshal error %s", err) - } + // Start the generation and shipping of random numbers + go func(ctx context.Context) { + for { + select { + case <-ctx.Done(): + return + default: + if qlemuprng.poweron { + // retrieve a new back of random numbers + newNumberBatch := qlemuprng.GenerateRandomNumbers() + // TODO: Replace this by some generic encapsulation reader and not just JSON + //Get JSON for transmission ready + qpe := QuantumPayloadElement{time.Now().UnixNano(), len(newNumberBatch), &newNumberBatch} + + // XXX/TODO: error must be handled + jsonPayload, err := json.Marshal(qpe) + if err != nil { + log.Errorf("QuantumlayerEmuPRNG: json.Marshal error %s", err) + } - _, _, err = qlemuprng.udpSrvConn.WriteMsgUDP(jsonPayload, nil, addr) - if err != nil { - log.Fatalf("QuantumlayerEmuPRNG: WriteMsgUDPAddrPort failed: %s", err) + _, _, err = qlemuprng.udpSrvConn.WriteMsgUDP(jsonPayload, nil, addr) + if err != nil { + log.Fatalf("QuantumlayerEmuPRNG: WriteMsgUDPAddrPort failed: %s", err) + } + qlemuprng.outgoingRandNums <- qpe } - qlemuprng.outgoingRandNums <- qpe + // TODO: This sleep timer has to replaced by something for clever. + time.Sleep(5 * time.Second) } - // TODO: This sleep timer has to replaced by something for clever. - time.Sleep(5 * time.Second) } - } - }(ctx) + }(ctx) + } } func (qlemuprng *QuantumlayerEmuPRNG) RemovePeer() { diff --git a/quantumlayer-emu-prng_test.go b/quantumlayer-emu-prng_test.go index 502377abd7c2564449749ebe78f38bbe611ceba7..42e01717bb5712c6f8569def24e060bb42cb3f36 100644 --- a/quantumlayer-emu-prng_test.go +++ b/quantumlayer-emu-prng_test.go @@ -5,22 +5,17 @@ package quantumlayer import ( "fmt" "net" + "os" "testing" "time" + + logrus "github.com/sirupsen/logrus" ) func TestQuantumLayer(t *testing.T) { - ql1 := NewQuantumlayerEmuPRNG() - ql1.PowerOn() - defer ql1.PowerOff() - - ql2 := NewQuantumlayerEmuPRNG() - ql2.PowerOn() - defer ql2.PowerOff() - // Generate UDPAddr for ql1 peer - udpQL2AddrString := fmt.Sprintf("127.0.0.1:%d", ql2.GetLocalQLPort().Port) + udpQL2AddrString := fmt.Sprintf("127.0.0.1:%d", 5002) udpQL2Addr, err := net.ResolveUDPAddr("udp", udpQL2AddrString) if err != nil { t.Fatalf("QuantumlayerEmuPRNG UDP failure: %s", err) @@ -28,34 +23,55 @@ func TestQuantumLayer(t *testing.T) { } // Generate UDPAddr for ql2 peer - udpQL1AddrString := fmt.Sprintf("127.0.0.1:%d", ql1.GetLocalQLPort().Port) + udpQL1AddrString := fmt.Sprintf("127.0.0.1:%d", 5001) udpQL1Addr, err := net.ResolveUDPAddr("udp", udpQL1AddrString) if err != nil { t.Fatalf("QuantumlayerEmuPRNG UDP failure: %s", err) return } + ql1 := NewQuantumlayerEmuPRNG(os.Stdout, logrus.DebugLevel, false) + ql1.Configure(udpQL1AddrString) + ql1.PowerOn(true) // this one generates keys + defer ql1.PowerOff() + + ql2 := NewQuantumlayerEmuPRNG(os.Stdout, logrus.DebugLevel, false) + ql2.Configure(udpQL2AddrString) + ql2.PowerOn(false) // this one does NOT generate keys + defer ql2.PowerOff() + ql1.AddPeer(udpQL2Addr) ql2.AddPeer(udpQL1Addr) + // Wait for key gen to get up and running + time.Sleep(5 * time.Second) + for n := 0; n < 2; n++ { - resultQl1, err := ql1.GetKeyBatchPeer() + resultQl1, err := ql1.GetKeyBatchLocal() if err == nil { t.Logf("run %d, *ql1* keyid %d \t keylen %d", n, resultQl1.BulkKeyId, resultQl1.BulkKeyLength) + } else { + t.Fatalf("Couldn't read local ql1 batch with error %s", err) } //resultQl2 := ql2.GetBatchPeer() resultQl2, err := ql2.GetKeyBatchPeer() if err == nil { - t.Logf("*ql2* keyid %d \t keylen %d", resultQl2.BulkKeyId, resultQl1.BulkKeyLength) + t.Logf("*ql2* keyid %d \t keylen %d", resultQl2.BulkKeyId, resultQl2.BulkKeyLength) + } else { + t.Fatalf("Couldn't read local ql2 batch with error %s", err) } - resultQL2Local, err := ql2.GetKeyBatchLocal() - if err == nil { - t.Logf("Current key IDs are for ql2 local %d and for peer ql1 %d", resultQL2Local.BulkKeyId, resultQl1.BulkKeyId) + if resultQl1.BulkKeyId != resultQl2.BulkKeyId { + log.Fatalf("Mismatching BulkKeyIds ql1 (%d) != ql2 (%d)", resultQl1.BulkKeyId, resultQl2.BulkKeyId) + } + if resultQl1.BulkKeyLength != resultQl2.BulkKeyLength { + log.Fatalf("Mismatching BulkKeyLengths ql1 (%d) != ql2 (%d)", resultQl1.BulkKeyLength, resultQl2.BulkKeyLength) } + // TODO: Calculate checksum of BulkKey + time.Sleep(5 * time.Second) } diff --git a/quantumlayer.go b/quantumlayer.go index fc31056d9ffb37684e59ce2365bbb92c287f1ca4..87e2589cb24a304b63b961e80a12f76dc2c8b16c 100644 --- a/quantumlayer.go +++ b/quantumlayer.go @@ -12,7 +12,7 @@ type QuantumLayerBulkKey struct { type QuantumLayer interface { Configure(...string) // configure the interface, e.g., used IP/Port config if emulated - PowerOn() // switch on the quantum layer element + PowerOn(enableKeyGeneration bool) // switch on the quantum layer element PowerOff() // switch off the quantum layer element GetStatus() (poweredOn bool) // returns true if quantum layer element is powered on AddPeer() // Adds a Quantum Layer Peer to the peer list