In the aftermath of time, the world of “smart home” has become closer for novice enthusiasts, thanks to the large number of hardware solutions with a low threshold of entry (of course, about the Arduino platform and a considerable set of modules / sensors for it) and ready-made libraries and frameworks for working with them . As a rule, they have default settings (mac addresses, channels, etc.) that are intact and remain in the hands of these very beginners ... For example, the
MySensors framework mentioned not long ago on Habré has the configuration file “MyConfig.h” which many (my hapless neighbor in particular) do not even rule.
On the one hand, I don’t care that someone in a multi-storey building can “overhear” the temperature in the kitchen (or even call with the question “What are you cooking?”), But on the other hand I don’t want anyone to (at least and theoretically) manage power loads (turn on your favorite coffee machine, for example). I want to be a little more confident that the command comes from my control device, and not from a false one (in cryptography, this is known as “authentication”).
Implementing such an approach is relatively easy ...
The interaction between the control and the actuator is based on the “signature” of a random phrase with an internal key known to both devices. More clearly it can be demonstrated as follows:
')

You can implement using three functions. One to generate a random phrase:
byte alphabet[] = { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a };
The second creation of the MD5 hash itself (
MD5 library for the Arduino ):
#include <MD5.h> byte sessionPhrase[9]; byte salt[] = { 0x4c, 0x39, 0x78, 0x36, 0x73, 0x4c, 0x39, 0x78 }; // L9x6sL9x - void signPhrase(byte *phrase, char *signedPhrase) { byte localPhrase[17]; for (int i = 0; i < 16; i++) { if (i < 8) localPhrase[i] = salt[i]; else localPhrase[i] = sessionPhrase[i - 8]; localPhrase[i + 1] = '\0'; } unsigned char* hash = MD5::make_hash((char *)localPhrase); char *md5str = MD5::make_digest(hash, 16); for (int i = 0; i < 16; i++) { signedPhrase[i] = md5str[i]; signedPhrase[i + 1] = '\0'; } free(hash); free(md5str); }
The third to verify the "signed" phrase of the initiator with the "self-signed" phrase of the performer:
bool compareSignedPhrases(char *signedPhrase) { if (strcmp(signedPhrase, (char *)sessionMD5Phrase) == 0) { return true; } return false; }
A short code to check the operation of the generation of the phrase, its signing and comparison#include <MySensor.h>
#include <SPI.h>
#include <MD5.h>
#define DEBUG 1
byte sessionPhrase [9];
char sessionMD5Phrase [17];
byte salt [] = {0x4c, 0x39, 0x78, 0x36, 0x73, 0x4c, 0x39, 0x78}; // L9x6sL9x - internal key
byte alphabet [] = {0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a}; // a, b, c, d, etc
void setup () {
Serial.begin (115200);
}
void loop () {
/ * Generate a random phrase * /
getPhrase (sessionPhrase);
signPhrase (sessionPhrase, sessionMD5Phrase); // Remember for further comparison
/ * Signing * /
char signedPhrase [17];
signPhrase (sessionPhrase, signedPhrase);
#ifdef DEBUG
Serial.print (“signedPhrase:„);
Serial.println ((char *) signedPhrase);
Serial.print (“copmpare:„);
Serial.println (compareSignedPhrases (signedPhrase));
Serial.println ("");
#endif
delay (1000);
}
void getPhrase (byte * phrase) {
for (int i = 0; i <8; i ++) {
phrase [i] = alphabet [random (0, 26)];
phrase [i + 1] = '\ 0';
}
#ifdef DEBUG
Serial.print (“sessionPhrase:„);
Serial.println ((char *) sessionPhrase);
#endif
}
void signPhrase (byte * phrase, char * signedPhrase) {
byte catPhrase [17];
for (int i = 0; i <16; i ++) {
if (i <8) catPhrase [i] = salt [i];
else catPhrase [i] = sessionPhrase [i - 8];
catPhrase [i + 1] = '\ 0';
}
#ifdef DEBUG
Serial.print (“catPhrase:„);
Serial.println ((char *) catPhrase);
#endif
unsigned char * hash = MD5 :: make_hash ((char *) catPhrase);
char * md5str = MD5 :: make_digest (hash, 16);
for (int i = 0; i <16; i ++) {
signedPhrase [i] = md5str [i];
signedPhrase [i + 1] = '\ 0';
}
free (hash);
free (md5str);
}
bool compareSignedPhrases (char * signedPhrase) {
if (strcmp (signedPhrase, (char *) sessionMD5Phrase) == 0) {
return true;
}
return false;
}
This approach can be performed both in your “bikes” and in other frameworks (such as MySensors) and gives an additional plus to the security of your Internet of Things.
By the way, authentication will be in MySensors, at the moment it is implemented in the development version .PS: If the community is interested, I’ll make update notes using the example of the same MySensors with examples of listings for Serial Gateway and Relay ...