ECF 1.5
attack.h
1/*
2attack.h
3Written by Walter O. Krawec, Michael Nelson, and Eric Geiss
4Copyright (c) 2017
5
6Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
7
8The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
9
10THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11*/
12
13
14#pragma once
15#include <vector>
16#include "Quantum/Algebra.h"
17
18namespace QKD
19{
20struct Basis
21{
22 std::vector < std::vector < Complex > > B;
23 void orthogonalize();
24
25 Complex innerProduct(std::vector < Complex >& a, std::vector < Complex >& b)
26 {
27 Complex sum = 0;
28
29 for(int i=0; i<a.size(); ++i)
30 sum = sum + a[i] * conj(b[i]);
31
32 return sum;
33 }
34
35 double norm(std::vector <Complex> & a)
36 {
37 double sum = 0;
38 Complex b;
39 for(int i=0; i<a.size(); ++i){
40 b = a[i] * conj(a[i]);
41 sum += creal(b);
42 }
43
44 return sqrt(sum);
45 }
46};
47
48struct Stats
49{
50 double p00, p01, p10, p11;
51 double Qx, Qy; // Qx = 1-paa; Qy = 1-pbb
52 double p0a, p1a, pa0;
53 double p0b, p1b, pb0;
54
55 double BB84Rate();
56 double SafeLog(double x)
57 {
58 if(x < 0.0000001)
59 return 0;
60 return log(x)/log(2.0);
61 }
62 double entropy(double x)
63 {
64 if(x > 1.00001){
65 std::cout << "Entropy error: x = " << x << "\n";
66 return 0;
67 //throw std::string("Entropy Error.");
68 }
69
70 return -x*SafeLog(x) - (1-x)*SafeLog(1-x);
71 }
72 double HAB(double key00, double key01, double key10, double key11)
73 {
74 double first = -key00*SafeLog(key00) - key01*SafeLog(key01) - key10*SafeLog(key10) - key11*SafeLog(key11);
75
76 if(key00+key10 > 1.00001)
77 std::cout << "HAB ERROR!\n";
78 double second = entropy(key00+key10);
79
80 return first-second;
81 }
82
83
84 void cnot();
85 void symmetric(double Q);
86 void testChannel1()
87 {
88 p00 = 0.752;
89 p01 = 1-p00;
90 p10 = .055;
91 p11 = 1-p10;
92
93 Qx = .163;
94 Qy = .115;
95
96 p0a = .435;
97 p1a = .592;
98 pa0 = .507;
99
100 p0b = .660;
101 p1b = .357;
102 pb0 = .322;
103 }
104 void testChannel2()
105 {
106 p00 = 0.790;
107 p01 = 1-p00;
108 p10 = .099;
109 p11 = 1-p10;
110
111 Qx = .121;
112 Qy = .283;
113
114 p0a = .581;
115 p1a = .381;
116 pa0 = .373;
117
118 p0b = .337;
119 p1b = .453;
120 pb0 = .499;
121 }
122
123 void printChannel(std::ostream& f)
124 {
125 f << "CHANNEL STATS:\n";
126 f << "p00 = " << p00 << "\n";
127 f << "p01 = " << p01 << "\n";
128 f << "p10 = " << p10 << "\n";
129 f << "p11 = " << p11 << "\n\n";
130
131 f << "Qx = " << Qx << "\n";
132 f << "Qy = " << Qy << "\n\n";
133
134 f << "p0+ = " << p0a << "\n";
135 f << "p1+ = " << p1a << "\n";
136 f << "p+0 = " << pa0 << "\n\n";
137
138 f << "p0Y = " << p0b << "\n";
139 f << "p1Y = " << p1b << "\n";
140 f << "pY0 = " << pb0 << "\n\n";
141 }
142
143 double randFloat(double small, double large)
144 {
145 int r = rand()%RAND_MAX;
146 double r2 = r / (double)RAND_MAX;
147
148 return (large-small)*r2 + small;
149 }
150
151 void generateRandom(double p01, double p10);
152 void chooseRandomVector(double minScale, double maxScale, std::vector <Complex>& v, int startIndex, int endIndex);
153};
154
156{
157 static const double precision = .01;
158 public:
159 Attack(Stats& _stats) : stats(_stats)
160 {
161 setLocalVars();
162
163 v0.create(4,1);
164 v1.create(4,1);
165 v2.create(4,1);
166 v3.create(4,1);
167
168 v0.zero();
169 v1.zero();
170 v2.zero();
171 v3.zero();
172
173 v0(0,0) = 1;
174 v1(1,0) = 1;
175 v2(2,0) = 1;
176 v3(3,0) = 1;
177 }
178
179 // sets E03 and E12 to their start values
180 void begin()
181 {
182 double im03lb = -SafeSqrt(E00*E33 - ReE03*ReE03);
183 double im12lb = -SafeSqrt(E11*E22 - ReE12*ReE12);
184
185 E03 = creal(E03) + I*im03lb;
186 E12 = creal(E12) + I*im12lb;
187
188 debugStart = true;
189 }
190
191 // gets the next possible attack; returns TRUE when this is the last legal attack; FALSE o/w
192 bool getNext(algebra::mat & e0, algebra::mat& e1, algebra::mat& e2, algebra::mat& e3)
193 {
194 bool done = false;
195 do{
196 //E12 = quantum::Complex(-.0361068, .00601651);
197 //E03 = quantum::Complex(.73823, -.230657);
198
199 done = buildAttackVec(e0, e1, e2, e3);
200
201 // add to E12.imag:
202 E12 = creal(E12) + I*(cimag(E12)+precision);
203 if(creal(E12*conj(E12)) > E11*E22){
204 double im12lb = -SafeSqrt(E11*E22 - ReE12*ReE12);
205 E12 = creal(E12) + I*im12lb;
206
207 E03 = creal(E03) + I*(cimag(E03) + precision);
208 if(creal(E03*conj(E03)) > E00*E33){
209 if(debugStart)
210 throw(std::string("NO ATTACKS"));
211 return true; // no more attacks to consider
212 }
213 }
214 }while(!done);
215
216 debugStart= false;
217 return false;
218 }
219
220 bool debugStart;
221
222 double SafeSqrt(double x)
223 {
224 if(x < -0.00001){
225 std::cout << "\n\nSafeSQRT Error: x = " << x << "\n\n";
226 throw(std::string("SafeSQRT Error; X negative."));
227 }
228 if(x < .00000001)
229 return 0;
230
231 return sqrt(x);
232 }
233
234 bool buildAttackVec(algebra::mat & e0, algebra::mat& e1, algebra::mat& e2, algebra::mat& e3)
235 {
236 // e0:
237 Complex a0 = SafeSqrt(stats.p00);
238
239 // e3:
240 Complex a3 = E03 / creal(a0);
241
242 if(stats.p11 - creal(a3)*creal(a3) - cimag(a3)*cimag(a3) < 0)
243 return false;
244 Complex b3 = SafeSqrt(stats.p11 - creal(a3)*creal(a3) - cimag(a3)*cimag(a3));
245
246
247 // e1:
248 Complex a1 = E01 / creal(a0);
249 Complex b1 = E13 - conj(a1)*a3;
250 b1 = b1 * (1.0/creal(b3));
251 b1 = conj(b1);
252 if(creal(b3) < .0000001){
253 b1 = 0;
254 }
255
256 if(stats.p01 - creal(a1*conj(a1) + b1*conj(b1)) < 0)
257 return false;
258
259 Complex c1 = SafeSqrt(stats.p01 - creal(a1*conj(a1) + b1*conj(b1)));
260
261
262 // e2:
263 Complex a2 = E02/creal(a0);
264 Complex b2 = E23 - conj(a2)*a3;
265 b2 = b2 * (1.0/creal(b3));
266 b2 = conj(b2);
267
268 if(creal(b3) < .0000001){
269 // check to make sure this is a valid solution:
270 Complex check = conj(a1)*a3;
271 if(fabs(creal(check) - creal(E13)) > .0000001 ||
272 fabs(cimag(check) - cimag(E13)) > .0000001){
273 //std::cout << "INVALID\n";
274 return false;
275 }
276 b2 = 0;
277 }
278
279 Complex c2 = E12 - conj(a1)*a2 - conj(b1)*b2;
280
281
282 c2 = c2 * (1.0/creal(c1));
283
284 if(creal(c1) < .0000001){
285 // check:
286 Complex check = conj(a1)*a2 + conj(b1)*b2;
287 if(fabs(creal(check) - creal(E12)) > .0000001 ||
288 fabs(cimag(check) - cimag(E12)) > .0000001){
289 //std::cout << "INVALID12\n";
290 return false;
291 }
292 c2 = 0;
293 }
294
295
296
297 double test = stats.p10 - creal( a2*conj(a2) + b2*conj(b2) + c2*conj(c2) );
298 if(test < 0)
299 return false;
300 Complex d2 = SafeSqrt(test);
301
302
303 /*
304 // a test:
305 std::cout << "\n--test--\n";
306 // e0e2:
307 quantum::Complex t = a0.conj()*a2;
308 std::cout << "E02: ";
309 t.print();
310 //e1e3:
311 t = a1.conj()*a3 + b1.conj()*b3;
312 std::cout << "\nE13: ";
313 t.print();
314 std::cout << "--end test--\n\n";
315 */
316
317 e0.zero();
318 e1.zero();
319 e2.zero();
320 e3.zero();
321
322 e0.add(a0, v0);
323
324 e3.add(a3, v0);
325 e3.add(b3, v1);
326
327 e1.add(a1, v0);
328 e1.add(b1, v1);
329 e1.add(c1, v2);
330
331 e2.add(a2, v0);
332 e2.add(b2, v1);
333 e2.add(c2, v2);
334 e2.add(d2, v3);
335
336 return true;
337 }
338
339 private:
340 void setLocalVars()
341 {
342 E00 = stats.p00;
343 E11 = stats.p01;
344 E22 = stats.p10;
345 E33 = stats.p11;
346
347 E01 = stats.p0a - .5 + I*(stats.p0b-.5);
348 E23 = stats.p1a - .5 + I*(stats.p1b-.5);
349 E02 = stats.pa0 - .5*(E00+E22) + I*(.5*(E00+E22)-stats.pb0);
350 E13 = E02*(-1);
351
352 ReE03 = 1 - stats.Qx - stats.Qy - .5*(creal(E01) + cimag(E01) + creal(E23) + cimag(E23));
353 ReE12 = stats.Qy - stats.Qx + .5*(cimag(E01) - creal(E01) + cimag(E23) - creal(E23));
354
355 E03 = ReE03;
356 E12 = ReE12;
357 }
358
359 Stats stats;
360 algebra::mat v0, v1, v2, v3; // standard basis vectors
361
362 double E00, E11, E22, E33;
363 Complex E01, E23, E02, E13;
364
365 double ReE03, ReE12;
366 Complex E03, E12;
367};
368}