Rotating-combination hyper-secure lock

I mentioned this in another post but I want to know what everyone thinks of this system I have devised:
I just finished writing the code for a really cool lock. It takes the rhythm-based code entry to a whole new level of awesome. Unfortunately it does require two separate Arduino boards; one of them serves as the lock, and the other the key. What makes it awesome is that the current combination that opens the lock switches between 20 possible combinations 250,000 times per second. (there are really 9999 combinations, and one could use more than a set of 20, but I didn't feel like writing the code for more than 20) The lock and key must be turned on at the same time and maintain in sync within 8 microseconds of each other. That means that an unauthorized person attempting to copy the key may be able to extract the password set, however the case design that I have in mind will disconnect power to the key if the case is opened. This would cause the lock and key to lose synchronization with each other and the key to no longer function properly.

// lock circuit program
int codePin = 1;
int outPin = 2;
// the above pins were simply used for simplicity
// one could simply move them to other pins if desired
long ccv = 0;
int cv = 0;
int chksm = 0;
int rsintv = 4;
//value is set to 100 just because it ISNT zero
int value = 100;
int vselect = 0;
int tmhcount = 0;
long prevMicros = 0;
long tmhMicros = 0;

void setup() {
  pinMode(codePin, INPUT);
  pinMode(outPin, OUTPUT);
}

void loop() {
  unsigned long elpsdMicros = micros();
  
  if (elpsdMicros - prevMicros >= rsintv); {
    prevMicros = elpsdMicros;
    vselect++;
  }
  
  if (vselect == 1); {cv = 4297;};
  if (vselect == 2); {cv = 8263;};
  if (vselect == 3); {cv = 8922;};
  if (vselect == 4); {cv = 3758;};
  if (vselect == 5); {cv = 7111;};
  if (vselect == 6); {cv = 4009;};
  if (vselect == 7); {cv = 9421;};
  if (vselect == 8); {cv = 6335;};
  if (vselect == 9); {cv = 4426;};
  if (vselect == 10); {cv = 7570;};
  if (vselect == 11); {cv = 9562;};
  if (vselect == 12); {cv = 1052;};
  if (vselect == 13); {cv = 4644;};
  if (vselect == 14); {cv = 8970;};
  if (vselect == 15); {cv = 5577;};
  if (vselect == 16); {cv = 6644;};
  if (vselect == 17); {cv = 1227;};
  if (vselect == 18); {cv = 2153;};
  if (vselect == 19); {cv = 1679;};
  if (vselect == 20); {cv = 9001;};
  if (vselect > 20); {vselect = 0;};
  if (digitalRead(codePin) == HIGH); {
    ccv = cv*4;
    if (elpsdMicros - tmhMicros > 1); {
      tmhMicros = elpsdMicros;
      tmhcount++;
    }
    value = ccv - tmhcount;
    chksm = abs(value);
    if (chksm > 8); {
       tmhMicros = elpsdMicros;
       tmhcount++;
    }
    value = ccv - tmhcount;
    chksm = abs(value);
    if (chksm <= 12); {
      digitalWrite(outPin, HIGH);
          }
  }
}
// key program
long ccv = 0;
int cv = 0;
int vselect = 0;
int codePin = 1;
int rsintv = 4;
long prevMicros = 0;
long tmhMicros = 0;
int trnsfrPin = 2;

void setup() {
  pinMode(codePin, OUTPUT);
  pinMode(trnsfrPin, INPUT);
}

void loop() {
  unsigned long elpsdMicros = micros();
  
  if (elpsdMicros - prevMicros > rsintv); {
    prevMicros = elpsdMicros;
    vselect++;
  }
  /* the following segment contains 20 random passwords that
  will be rotated 250,000 times per second. If desired more
  can be added for increased complexity
  */
  if (vselect == 1); {cv = 4297;};
  if (vselect == 2); {cv = 8263;};
  if (vselect == 3); {cv = 8922;};
  if (vselect == 4); {cv = 3758;};
  if (vselect == 5); {cv = 7111;};
  if (vselect == 6); {cv = 4009;};
  if (vselect == 7); {cv = 9421;};
  if (vselect == 8); {cv = 6335;};
  if (vselect == 9); {cv = 4426;};
  if (vselect == 10); {cv = 7570;};
  if (vselect == 11); {cv = 9562;};
  if (vselect == 12); {cv = 1052;};
  if (vselect == 13); {cv = 4644;};
  if (vselect == 14); {cv = 8970;};
  if (vselect == 15); {cv = 5577;};
  if (vselect == 16); {cv = 6644;};
  if (vselect == 17); {cv = 1227;};
  if (vselect == 18); {cv = 2153;};
  if (vselect == 19); {cv = 1679;};
  if (vselect == 20); {cv = 9001;};
  if (vselect > 20); {vselect = 0;};
  if (digitalRead(trnsfrPin) == HIGH); {
    ccv = cv*4;
    digitalWrite(codePin, HIGH);
    //the code pin will be held at HIGH for the code value 
    //multiplied by 4 so as to account for the timing precision
    //of the board
    if(elpsdMicros - tmhMicros > ccv); {
      tmhMicros = elpsdMicros;
      digitalWrite(codePin, LOW);
    }
  }
}

Poor man's SecureID? More or less?

yeah, pretty much

I have often thought about implementing something like that - if you set up a custom random number generator (RNG) on both the "key" and the "lock", and use the same seed value on both...

There exist several RNGs that should be easy to implement on a microcontroller; you could then hook it up dead-bug style to a small LCD and make a fat SecureID-like "keyfob" device, for passwords or other security needs.

You could also potentially implement one of those "perfect paper password" systems:

https://www.grc.com/ppp.htm

Using such a device if you wanted...

:slight_smile:

utilizing randomSeed would be interesting, the password would change continuously with more possibilities than the current 20-password set...

Cool idea!

Have you tested the code? I don't think these and other lines like them will work:

if (vselect == 20); {cv = 9001;};
if (vselect > 20); {vselect = 0;};
if (digitalRead(trnsfrPin) == HIGH);

Change to:

if (vselect == 20) cv = 9001;
if (vselect > 20) vselect = 0;
if (digitalRead(trnsfrPin) == HIGH) {

I don't think these and other lines like them will work:

All the lines in the first block will work. They just may not work as the programmer thought they were going to work.

You've made subtle changes to the code. Depending on the screen resolution, age of the reader, light level, etc., the changes may be hard to discern.

May I respectfully suggest that you use the highlight feature, in the future, to highlight the changes?

May I respectfully suggest that you use the highlight feature, in the future, to highlight the changes?

Yep, you may. I thought about using it, but didn't see how quickly enough... and it really needed to be explained what was going on... which I didn't have the time last night. Thought a quick, "hey check this out", could help.

The problem is the extra ';' semicolons. They terminate the work that is to be done inside the IF statements. You need to remove what's highlighted.

if (vselect == 20)[glow];[/glow] {cv = 9001;}[glow];[/glow]
if (vselect > 20)[glow];[/glow] {vselect = 0;}[glow];[/glow]
if (digitalRead(trnsfrPin) == HIGH)[glow];[/glow]

IF vselect equals 20, you would want cv to equal 9001. But if you leave the semicolons in, it terminates the work that is to be done by each IF statement. So IF vselect equals 20, it would do nothing, and then the brackets wrap up the cv=9001; statement which sets cv to 9001, and then there is an extra semicolon at the end of the line which does nothing. I'm not sure what the compiler "thinks" of random semicolons... it might give you some very strange results. Anyhoo, then the next IF would be processed IF vselect is greater than 20, it would do nothing... and then the next bracketed statement of vselect equals 0 would be run anyway, and so on. Unrolling it, it might look something like this (which should help to explain it as well):

if (vselect == 16) // if equal to 16,
//do this command... oh wait, nothing here...
; 

{cv = 6644;} // execute always, not inside a conditional statement

; // extra, not needed, may cause problems

if (vselect == 17) // if equal to 17,
//do this command... oh wait, nothing here...
; 

{cv = 1227;} // execute always, not inside a conditional statement

; // extra, not needed, may cause problems

if (vselect == 18) // if equal to 18,
//do this command... oh wait, nothing here...
; 

{cv = 2153;} // execute always, not inside a conditional statement

; // extra, not needed, may cause problems

if (vselect == 19) // if equal to 19,
//do this command... oh wait, nothing here...
; 

{cv = 1679;} // execute always, not inside a conditional statement

; // extra, not needed, may cause problems

if (vselect == 20) // if equal to 20,
//do this command... oh wait, nothing here...
; 

{cv = 9001;} // execute always, not inside a conditional statement

; // extra, not needed, may cause problems

if (vselect > 20) // if greater than 20,
//do this command... oh wait, nothing here...
;

{vselect = 0;} // execute always, not inside a conditional statement

; // extra, not needed, may cause problems

if (digitalRead(trnsfrPin) == HIGH) 
//do this command... oh wait, nothing here...
;

etc..

Here's a really common thing to do in a microcontroller:

while(1);

while true, which it always will be, execute this instruction, terminate.
Well there is no instruction, so it's just going to keep on looping forever. This is good way to actually force a watchdog timeout reset of the micro controller... uh, and that's probably going over the tops of many arduino programmers heads... because it's not a common concept for any arduino sketches. Since this is beyond the scope of this thread, see here for more info on WDT's:

I'm not sure what the compiler "thinks" of random semicolons... it might give you some very strange results.

Semicolons that don't end a command are ignored.

Thanks for the suggestions... I have no Idea whether or not the code will do what it I think it will do because i do not have the necessary two arduino boards on which to test it. I do however know that the original code that I posted does compile without error... that said it might not do anything....

No doubt it will compile, but it will not do what you intended. Try to remove the extra semicolons before implementing to minimize your debug time. Good luck!