void setup() { |
// initialize both serial ports: |
Serial.begin(9600); |
Serial1.begin(9600); |
} |
|
void loop() { |
// read from serial port 1, and send to serial monitor on port 0 |
if (Serial1.available()) { |
// returns one byte of unsigned serial data, or -1 if none available |
int16_t inByte = Serial1.read(); |
Serial.write(inByte); |
} |
|
// read from serial monitor on port 0, and send to port 1 |
if (Serial.available()) { |
// returns one byte of unsigned serial data, or -1 if none available |
int16_t inByte = Serial.read(); |
Serial1.write(inByte); |
} |
} |
m' = (m + key) % 256and later decrypt it by doing
m = (m' - key) % 256This is not a very secure encryption algorithm!
gpu.srv.ualberta.ca
and Alice is a student that wants to communicate her password to Bob without the ever-eavesdropping Eve snooping her password. Alice and Bob can do so with this process of secret key generation, all communicated publicly, yet Eve is unaware of their secret. g^0 mod p, g^1 mod p, g^2 mod p, ..., g^(p-1) mod pare all of the unique integers in the range 1, ..., p-1$. The pair (p,g) can be made public or even shared by a group of users.
A = g^a mod p B = g^b mod p
Num Bits | p | g | factors of p-1 |
15 | 19211 | 6 | 2 x 5 x 17 x 113 |
31 | 2147483647 Mersenne 31 |
16807 also 7 |
2 * 3^2 * 7 * 11 * 31 * 151 * 331 |
(b ** e) mod m
where b
is the base, e
is the exponent, and m
is the modulus. M
, to the encrypting exponent, E
, modulo N. Decryption raises the cipher text, C
, to the decrypting (private key) exponent, D
, modulo N. Thus it makes sense to figure out how to do this in general for given b, e, and m. // global state variables |
|
void setup() |
{ |
Serial.begin(9600); |
} |
|
void loop() |
{ |
uint32_t b, e, m; |
char line[128]; |
|
b = readlong(); |
Serial.print(b); |
Serial.print(" "); |
|
e = readlong(); |
Serial.print(e); |
Serial.print(" "); |
|
m = readlong(); |
Serial.print(m); |
Serial.print("\n"); |
|
Serial.print("answer = "); |
Serial.println(pow_mod(b, e, m)); |
} |
|
// common functions and procedures |
|
/* |
Compute and return (b ** e) mod m |
For unsigned b, e, m and m > 0 |
*/ |
uint32_t pow_mod(uint32_t b, uint32_t e, uint32_t m) |
{ |
return 0; |
} |
|
/* |
Read a sequence characters from the serial monitor and interpret |
them as a decimal integer. |
|
The characters can be leading and tailing blanks, a leading '-', |
and the digits 0-9. |
|
Return that number as a 32 bit int. |
*/ |
int32_t readlong() |
{ |
char s[128]; /* 128 characters should be more than enough. */ |
readline(s, 128); |
return atol(s); |
} |
|
/* |
Read a \n terminated line from the serial monitor and store the result |
in string s. |
|
String s has maximum size, including the terminating \0, of bufsize |
characters. If the input line is longer than can be stored in s, then |
it is truncated. bufsize must be at least 1. |
|
s will always be a properly terminted string. |
*/ |
void readline(char *s, int bufsize) |
{ |
uint8_t i = 0; |
|
while( i < bufsize-1 ) { |
// wait for a character |
while (Serial.available() == 0) { } /* Do nothing */ |
|
// grab the character and save in the buffer |
s[i] = Serial.read(); |
|
// if end of line or somehow a \0 got sent, we are done |
if (s[i] == '\n' || s[i] == '\0') break; |
i += 1; |
} |
// \0 teminate the string |
s[i] = '\0'; |
} |
|
loop()
you will see that this program simply reads three unsigned long numbers from the Serial monitor, and then prints the result from calling the procedure pow_mod
with these values. Currently, pow_mod
does nothing. pow_mod
program contains a number of procedures. By default, setup
and loop
are procedures that must be defined for all Arduino programs. Let's look in depth at the procedure pow_mod
, as that is where we will be solving our first subtask. uint32_t pow_mod(uint32_t b, uint32_t e, uint32_t m) {
return 0;
}
Its definition has some key parts: void
. uint32_t
(unsigned long). b
, e
and m
. void
) then the statement return RETURNVALUE;
causes the procedure to finish with the value RETURNVALUE
. 0
. We want this function to compute B
to the exponent E
modulo M
, and return that value. ulong pow_mod(ulong b, ulong e, ulong m) {
ulong r = 1;
for (ulong i=0; i<e; i++) {
r = r * b % m;
}
return r;
}
The notes here are purposefully blank. Think of a procedure for doing modular exponentiation. b
gets large? What about e
? Or m
? How long would it take to answer 7 ** 123456789 mod 13? How can you figure that out? micros()
timing function. We can time a portion of code using: The functionlong time = micros();
... section of code to time ...
time = micros() - time;
Serial.print("time = ");
Serial.println(time);
micros()
returns the number of microseconds since the Arduino was turned on. By recording this in time
we can subtract off the new value after the code executes to find the amount of elapsed time taken to execute the intervening lines of code. Use this formulation to answer the following questions on our exponentiation function. b
affect the computation time? Try small values of b
, e
, and m
. Then double the value of b
. Again. Again. Again. Does its size affect the running time? e
and m
? Which affects the running time? e
and the resulting running time. Have e
range from 2 up to 8192. Plot the results on a graph. pow_mod
is linear in the value of e
. What would the running time graph look like for b
or m
? In such a case, we say the running time is constant in these parameters. unsigned long
). This is essentially true, in fact. Now for each line of code of the algorithm, consider: b
or m
? Does it depend upon e
? What does the formula look like? If we gather terms, we can see it has the same form as the equation of a line. So we can conclude that our algorithm is linear in e
without even running the algorithm! r
to b
and e
at the start of each iteration of the while loop? r = (b ** i) % mWe can prove this by induction. First we start by proving it is true before the loop starts.
i = 0
, so (b ** i) % m = 1 = r
. Now, prove that if the loop invariant holds at some point, that it will hold at the start of the next iteration. So r = (b ** i) % m
. At the end of this iteration r = ((b ** i) * b) % m = (b ** (i + 1)) % m
. But then i
is incremented so r = (b ** i) % m
, thus proving our loop invariant. i = e
(why?). This gives us r = (b ** i) % m = (b ** e) % m
. So returning r
returns the value (b ** e) % m
. e
was a power of 2. In other words, we could write e = 2**k
for some value k. Is there a faster algorithm for pow_mod
for just this case? If you find such an algorithm, think about the case where e
is the addition of two powers of 2, i.e., e = 2**k + 2**j
. Can we always write e
as the addition of some number of powers of 2? Can we use this fact to construct a general algorithm? v = b*b;
. What is v
? It is b**2
. Now consider v = v*v;
. What is v
now? It is b**4
. What if we do this k times? Now go back and read Hint #1 again. 7. Diffie-Hellman Key Exchange Tangible Computing / Version 3.20 2013-03-25 |