Advertisement
Guest User

Untitled

a guest
Oct 9th, 2015
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.84 KB | None | 0 0
  1. /*
  2. * Assignment 1 part I
  3. * Created by: Gaylord Mbuyi and James Yurick
  4. * LBL A2
  5. */
  6.  
  7. #include <Arduino.h>
  8.  
  9. uint32_t mul_mod(uint32_t a, uint32_t b, uint32_t m) {
  10. uint32_t result = 0;
  11. uint32_t x = b % m;
  12.  
  13. for (int i = 0; i < 32; ++i) {
  14. uint32_t myBit = 31 - i;
  15. //Serial.print(i);
  16. //Serial.print(": ");
  17. //Serial.println(((a << myBit) >> 31));
  18. if (((a << myBit) >> 31) == 1) {
  19. result = (result + x) % m;
  20. }
  21. x = (x << 1) % m;
  22. }
  23.  
  24. return result;
  25. }
  26.  
  27. /** Calculates base^power mod m */
  28. uint32_t pow_mod(uint32_t base, uint32_t power, uint32_t m) {
  29. uint32_t result = 1;
  30. uint32_t x = base % m;
  31. for (int i = 0; i < 32; ++i ) {
  32. if ((power & (1 << i)) != 0) {
  33. result = mul_mod(result, x, m);
  34. }
  35. x = mul_mod(x, x, m);
  36. }
  37.  
  38. return result;
  39. }
  40.  
  41. /** Converts zero-terminated string into an unsigned long */
  42. int str2int( char* buf ) {
  43. return atoi(buf);
  44. }
  45.  
  46. /** Reads a number from the keyboard by using the Serial port */
  47. int get_number() {
  48. const int LINE_LENGTH = 128;
  49. int ret = 0; // number to be returned
  50. char line[LINE_LENGTH+1];
  51. int i = 0;
  52. while (i<LINE_LENGTH) {
  53. int byte = Serial.read();
  54. if (byte!=-1) {
  55. if (byte==10 || byte==13) { // <ENTER> was received
  56. break;
  57. }
  58. line[i] = byte;
  59. i = i + 1;
  60. Serial.print( (char) byte );
  61. }
  62. }
  63. line[i] = 0;
  64. // calculate ret
  65. ret = str2int(line);
  66. Serial.println();
  67.  
  68. return ret;
  69. }
  70.  
  71. /** Generates random private key using analog port 1 */
  72. int generate_key() {
  73. uint32_t result = 0;
  74. uint32_t base2 = 1;
  75. // generate 32-bit random number
  76. for (int i = 0; i < 32; ++i) {
  77. uint16_t keybit = analogRead(1); // get number from analog port 1
  78. keybit = (keybit << 15) >> 15; // get least significant bit
  79. // convert bits into integer
  80. if (keybit == 1) {
  81. result = result + base2;
  82. }
  83. base2 = base2 * 2;
  84.  
  85. delay(50);
  86. }
  87. return result;
  88. }
  89.  
  90. void print_status(){
  91. typedef enum { client, server } client_serv;
  92. client_serv status;
  93. if (digitalRead(13) == HIGH) {
  94. status= server;
  95. Serial.println("I'm a server");
  96. }
  97. else {
  98. status= client;
  99. Serial.println("I'm a client");
  100. }
  101. Serial.println(status);
  102. }
  103.  
  104. /** Waits for a certain number of bytes on Serial3 or timeout
  105. * @param nbytes: the number of bytes we want
  106. * @param timeout: timeout period (ms); specifying a negative number
  107. * turns off timeouts (the function waits indefinitely
  108. * if timeouts are turned off).
  109. * @return True if the required number of bytes have arrived.
  110. */
  111. bool wait_on_serial3( uint8_t nbytes, long timeout ) {
  112. unsigned long deadline = millis() + timeout;//wraparound not a problem
  113. while (Serial3.available()<nbytes && (timeout<0 || millis()<deadline))
  114. {
  115. delay(1); // be nice, no busy loop
  116. }
  117. return Serial3.available()>=nbytes;
  118. }
  119.  
  120. /** Writes an uint32_t to Serial3, starting from the least-significant
  121. * and finishing with the most significant byte.
  122. */
  123. void uint32_to_serial3(uint32_t num) {
  124. Serial3.write((char) (num >> 0));
  125. Serial3.write((char) (num >> 8));
  126. Serial3.write((char) (num >> 16));
  127. Serial3.write((char) (num >> 24));
  128. }
  129.  
  130. /** Reads an uint32_t from Serial3, starting from the least-significant
  131. * and finishing with the most significant byte.
  132. */
  133. uint32_t uint32_from_serial3() {
  134. uint32_t num = 0;
  135. num = num | ((uint32_t) Serial3.read()) << 0;
  136. num = num | ((uint32_t) Serial3.read()) << 8;
  137. num = num | ((uint32_t) Serial3.read()) << 16;
  138. num = num | ((uint32_t) Serial3.read()) << 24;
  139. return num;
  140. }
  141.  
  142. uint32_t server_mod(uint32_t our_public_key) {
  143. Serial.println("The func server_mod is called");
  144. // choose private key
  145.  
  146. //~ Serial.print("Our public key: "); Serial.println(our_public_key);
  147. //~ Serial.print("Their public key: ");
  148. //~ int their_public_key = get_number(); // get from other computer (was B)
  149. //uint32_t shared_key = (pow_mod(their_public_key, private_key,prime)) % 256; // B^a % p and convert it to klow
  150. uint32_t ckey;
  151. //~ Serial.print("Shared key: "); Serial.println(shared_key);
  152.  
  153. typedef enum {
  154. listen, waitingForKey, waitForAck, dataExchange
  155. } Status;
  156. Status myStatus = listen;
  157.  
  158. Serial.print("My status before while is:"); Serial.println(myStatus);
  159. while (myStatus != dataExchange) {
  160. if (myStatus == listen) {
  161. Serial.println("My status is listen");
  162. if ((wait_on_serial3(5, 1000) == true) && (Serial3.read() == 'C')) {
  163. Serial.print("My status in first if is:"); Serial.println(myStatus);
  164. myStatus = waitingForKey;
  165. }
  166. }
  167. else if ((wait_on_serial3(4, 1000) == true) && (myStatus == waitingForKey)) {
  168. Serial.println("My status is waitingForKey");
  169. ckey = uint32_from_serial3();
  170. Serial.print("Just read ckey: "); Serial.println(ckey);
  171. Serial3.write('A');
  172. Serial.println("Just wrote A: ");
  173. uint32_to_serial3(our_public_key);
  174. Serial.print("Our_public_key: "); Serial.println(our_public_key);
  175. myStatus = waitForAck;
  176. }
  177. else if ((wait_on_serial3(1, 1000) == true) && (myStatus == waitForAck)) {
  178. Serial.println("My status is waitForACK");
  179. char a = Serial3.read();
  180. if (a == 'C') {
  181. Serial.println("Just read C");
  182. myStatus = waitingForKey;
  183. }
  184. else if (a == 'A') {
  185. myStatus = dataExchange;
  186. Serial.println("My status is dataExchange in else if");
  187. }
  188. }
  189. else {
  190. myStatus = listen;
  191. }
  192. }
  193. Serial.println("My status is dataExchange");
  194. Serial.print("Our public key (skey): "); Serial.println(our_public_key);
  195. Serial.print("ckey: "); Serial.println(ckey);
  196. return ckey;
  197. }
  198.  
  199. /** Implements the Park-Miller algorithm with 32 bit integer arithmetic
  200. * @return ((current_key * 48271)) mod (2^31 - 1);
  201. * This is linear congruential generator, based on the multiplicative
  202. * group of integers modulo m = 2^31 - 1.
  203. * The generator has a long period and it is relatively efficient.
  204. * Most importantly, the generator's modulus is not a power of two
  205. * (as is for the built-in rng),
  206. * hence the keys mod 2^{s} cannot be obtained
  207. * by using a key with s bits.
  208. * Based on:
  209. * http://www.firstpr.com.au/dsp/rand31/rand31-park-miller-carta.cc.txt
  210. */
  211. uint32_t next_key(uint32_t current_key) {
  212. const uint32_t modulus = 0x7FFFFFFF; // 2^31-1
  213. const uint32_t consta = 48271; // we use that this is <=15 bits
  214. uint32_t lo = consta*(current_key & 0xFFFF);
  215. uint32_t hi = consta*(current_key >> 16);
  216. lo += (hi & 0x7FFF)<<16;
  217. lo += hi>>15;
  218. if (lo > modulus) lo -= modulus;
  219. return lo;
  220. }
  221.  
  222. int main() {
  223. // Initialize Arduino functionality
  224. init();
  225.  
  226. // Attach USB for applicable processors
  227. #ifdef USBCON
  228. USBDevice.attach();
  229. #endif
  230.  
  231. Serial.begin(9600); // Serial0: communication with the PC
  232. Serial3.begin(9600); // Serial3: communication with the other Arduino
  233.  
  234. //~ print_status();
  235.  
  236. uint32_t prime = 2147483647; // prime in Diffie-Hellman
  237. uint32_t generator = 16807; // generator in Diffie-Hellman
  238. uint32_t private_key = generate_key(); // generate random key
  239. uint32_t our_public_key = pow_mod(generator, private_key, prime ); // A = g^a % p
  240. uint32_t their_public_key = server_mod(our_public_key);
  241. uint32_t shared_key = (pow_mod(their_public_key, private_key, prime)); // B^a % p and convert it to klow
  242. Serial.print("share_key before while: "); Serial.println(shared_key);
  243. Serial.println("*******");
  244.  
  245. // chatting starts here
  246. int incomingByte = 0;
  247. uint32_t shared_key_received = shared_key;
  248. uint32_t shared_key_send = shared_key;
  249. while (true) {
  250. // grab byte from other Arduino
  251. if (Serial3.available() > 0) {
  252. incomingByte = Serial3.read();
  253. shared_key_received = (next_key(shared_key_received) << 24) >> 24;
  254. //Serial.print("shared_key in first if: "); Serial.println(shared_key);
  255. uint32_t decryptedByte =
  256. incomingByte ^ shared_key;
  257. if (decryptedByte == 10 || decryptedByte == 13) { // Enter received
  258. Serial.write('\n'); // LF
  259. Serial.write('\r'); // CR
  260. }
  261. else
  262. Serial.write((char)decryptedByte); // print to the PC screen
  263. }
  264. // grab byte from the PC
  265. if (Serial.available() > 0) {
  266. incomingByte = Serial.read();
  267. shared_key_send = (next_key(shared_key_send) << 24) >> 24;
  268. //Serial.print("shared_key in scnd if: "); Serial.println(shared_key);
  269. uint32_t byteToSend = incomingByte ^ shared_key;
  270. //Serial.print("The char is: "); Serial.println((char)byteToSend);
  271. Serial3.write((char)byteToSend); // send byte to other Arduino
  272. }
  273.  
  274. //Serial.println(shared_key);
  275. }
  276.  
  277. Serial.end();
  278. Serial3.end();
  279.  
  280. return 0;
  281. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement