Hello Felix. Thank you for your reply.
Here is the code:
// **********************************************************************************************************
// Garage Door Node
// Ver. 9.0 - 2020-09-14
// **********************************************************************************************************
#include <RFM69.h>
#include <RFM69_OTA.h>
#include <RFM69_ATC.h>
#include <SPIFlash.h>
#define THISNODEID 4//unique for each node on same network
#define GATEWAYID 1//Gateway number on this network
#define BLYNKGATEWAY 10 //Blynk Gateway
#define NETWORKID 100//the same on all nodes that talk to each other
#define FREQUENCY RF69_433MHZ
#define ENCRYPTKEY "XXXXXXXXXXXXXXXX"
#define ATC_RSSI -80
#define ACK_TIME 3000 //max # of ms to wait for an ack
#define LED 9 // Moteinos have LEDs on D9
#define RELAYPIN1 6 // Output pin connected to the relay
#define RELAYPIN2 7 // Output pin connected to the relay
#define POSITIONPOT A1 //Input pin connected to the potentiometer
#define POSITIONPOT_EN 5//Digital output to enable the potentiometer
#define RELAY_PULSE_MS 500 //just enough that the opener will pick it up
#define SERIAL_BAUD 115200
#define PROMISCUOUSMODE false //set to 'true' to sniff all packets on the same network
// Outbound Data Struct
typedef struct
{
char out_nodeType[6]; // Node Type
uint32_t out_data1; // Data 1 << Device Output - 1 = DOOR POSITION SENSOR
uint32_t out_data2; // Data 2 << Door position in %
float out_data3; // Data 3 << NIL
} Payload;
Payload outData;
//Inbound Data Struct
typedef struct
{
uint8_t in_data0; // Node Type
uint32_t in_data1; // Data 1 >> Device Input - 1 = OPEN/STOP/CLOSE RELAY
uint32_t in_data2; // Data 2 >> INPUT A - 1 = OPEN/STOP/CLOSE
float in_data3; // Data 3 >> INPUT B - NIL
} in_Payload;
in_Payload inData;
//Initialize some variables
unsigned long timeNow = 0;
word blinkPeriod = 15000; //transmit a ping to gateway so often (in ms)
int16_t doorPosition = 0;
int16_t olddoorPosition = 0;
// Hardware Init
SPIFlash flash(8, 0xEF30); //EF30 for windbond 4mbit flash
RFM69_ATC radio;
void setup()
{
//Setup the pins
pinMode(LED, OUTPUT);
pinMode(RELAYPIN1, OUTPUT);
pinMode(RELAYPIN2, OUTPUT);
pinMode(POSITIONPOT, INPUT);
pinMode(POSITIONPOT_EN, OUTPUT);
//Turn on the position trim pot
digitalWrite(POSITIONPOT_EN, HIGH);
//Start the Serial port
Serial.begin(SERIAL_BAUD);
//Initialize the radio
radio.initialize(FREQUENCY, THISNODEID, NETWORKID);
radio.setHighPower();
radio.encrypt(ENCRYPTKEY);//Turn encryption ON
radio.promiscuous(PROMISCUOUSMODE);
radio.enableAutoPower(ATC_RSSI);
}
void loop()
{
if (radio.receiveDone())//If some packet was received by the radio, wait for all its contents to come trough
{
CheckForWirelessHEX(radio, flash, true);// Check if it is a OTA upload
//If an ACK (acknowledge) was requested by the data packet transmitter radio, send the ACK back to it
if (radio.ACKRequested())
{
radio.sendACK();
}
//Extract data from the payload
inData = *(in_Payload*)radio.DATA; //assume radio.DATA actually contains our struct and not something else
//Now check what was the instruction sent by the Gateway to this node
if (inData.in_data1 == 1) // If it was a "1", a command was sent from the Gateway to the Output 1 - Garage Door Relay
{
if (inData.in_data2 == 1) // If it was a "1", a command was sent from the Gateway to toggle the relay
{
controlDoor();
}
inData.in_data1 = 0; //Reset the in_data2 Variable content
}
}
sendDoorPos(); // Get the door position from the potenciometer and sent it to the Gateway
}
void controlDoor()
{
digitalWrite(RELAYPIN1, HIGH);//Using two pins to doulbe the current
digitalWrite(RELAYPIN2, HIGH);
delay(RELAY_PULSE_MS);
digitalWrite(RELAYPIN1, LOW);//Using two pins to doulbe the current
digitalWrite(RELAYPIN2, LOW);
Blink(25);//Blink the node led to show a the command was successfully received
}
void sendDoorPos()
{
doorPosition = analogRead(POSITIONPOT); //Read Potenciometer to determine door position
doorPosition = map(doorPosition, 5, 920, 0, 100);
doorPosition = constrain(doorPosition, 0, 100);
//Check if door position has changed and if it did, send new position to the Gateway.
if (millis() / 1000 - timeNow / 1000 > 1)
{
timeNow = millis();
if (doorPosition != olddoorPosition)
{
olddoorPosition = doorPosition;
//fill in the struct with new door position
strcpy(outData.out_nodeType, "GGATE");
outData.out_data1 = 1; // Device output - Potenciometer
outData.out_data2 = doorPosition;
outData.out_data3 = analogRead(POSITIONPOT);
sendData(GATEWAYID);
sendData(BLYNKGATEWAY);
}
}
}
void sendData(byte destinationNode)
{
radio.sendWithRetry(destinationNode, (const void*)(&outData), sizeof(outData), 3, ACK_TIME); //Send new position to the Moteino Gateway
}
void Blink(byte DELAY_MS)//Local led blinking function
{
digitalWrite(LED, HIGH);
delay(DELAY_MS);
digitalWrite(LED, LOW);
}
This is very different than my GarageMote example (https://github.com/LowPowerLab/RFM69/blob/master/Examples/GarageMote/GarageMote.ino). You're using a struct, so Im guessing that's where things go wrong - a stray packet from some other source gets through, gets decrypted as binary data, which then gets picked up into your struct without any checks of whether the data is valid.
You need some more checks in your code, do not just blindly execute stuff that is decoded from an unknown packet into a struct.
if (inData.in_data1 == 1)
The above code is NOT a good check :-\
At a point it opened both my small gate and the garage door at the same time. But not the outer gate.
Here is the code of the small gate>
// **********************************************************************************************************
// Outer Gate Node
// Ver. 4.0
// 2020-09-16
// **********************************************************************************************************
#include <RFM69.h>
#include <RFM69_ATC.h>
#include <RFM69_OTA.h>
#include <SPIFlash.h>
#define NODEID 5 //unique for each node on same network
#define GATEWAYID 1 //Gateway number on this network
#define NETWORKID 100 //the same on all nodes that talk to each other
#define FREQUENCY RF69_433MHZ
#define ENCRYPTKEY "XXXXXXXXXXXXXXXX" //exactly the same 16 characters/bytes on all nodes!
#define ATC_RSSI -80
#define ACK_TIME 3000 // max # of ms to wait for an ack
#define LED 9 // Moteinos have LEDs on D9
#define RELAY1 5 // Output pin connected to the relay
#define RELAY2 7 // Output pin connected to the relay
#define SERIAL_BAUD 115200
#define PROMISCUOUSMODE false //set to 'true' to sniff all packets on the same network
//Initialize some variables
unsigned long timeNow = 0;
// Outbound Data Struct
typedef struct
{
char out_nodeType[6]; // Node Type
uint32_t out_data1; // Data 1 << Device Output - 1 = DOOR POSITION SENSOR
uint32_t out_data2; // Data 2 << Door position in %
float out_data3; // Data 3 << NIL
} Payload;
Payload outData;
//Inbound Data Struct
typedef struct
{
uint8_t in_data0; // Node Id
uint32_t in_data1; // Data 1 >> Device Input - RELAY 1 and 2
uint32_t in_data2; // Data 2 >> INPUT A - 1 = OPEN; 0 = CLOSE
float in_data3; // Data 3 >> INPUT B - NIL
} in_Payload;
in_Payload inData;
// Hardware Init
SPIFlash flash(8, 0xEF30); //EF40 for 16mbit windbond chip
RFM69_ATC radio; // Call the radio
void setup()
{
//Setup the pins
pinMode(LED, OUTPUT);
pinMode(RELAY1, OUTPUT);
pinMode(RELAY2, OUTPUT);
//Start the Serial port
Serial.begin(SERIAL_BAUD);
//Initialize the radio
radio.initialize(FREQUENCY, NODEID, NETWORKID);
radio.setHighPower();
radio.encrypt(ENCRYPTKEY);//Turn encryption ON
radio.promiscuous(PROMISCUOUSMODE);
radio.enableAutoPower(ATC_RSSI);
}
void loop()
{
if (radio.receiveDone())//If some packet was received by the radio, wait for all its contents to come trough
{
CheckForWirelessHEX(radio, flash, true); // set to true for debug. This will check if there is a new wireless program to load
//Extract data from the incoming payload
inData = *(in_Payload*)radio.DATA;
//If an ACK (acknowledge) was requested by the data packet transmitter radio, send the ACK back to it
if (radio.ACKRequested())
{
radio.sendACK();
}
if (inData.in_data1 == 1) //If data is for Relays
{
if (inData.in_data2 == 1)// If a command was sent from the Gateway to toggle RELAY1, a "1" was received
{
digitalWrite(RELAY1, HIGH);
delay(500);
digitalWrite(RELAY1, LOW);
}
else if (inData.in_data2 == 2) // If a command was sent from the Gateway to toggle RELAY2, a "2" was received
{
digitalWrite(RELAY2, HIGH);
delay(500);
digitalWrite(RELAY2, LOW);
}
}
inData.in_data1 = 0; //Reset the in_data Variable content
inData.in_data2 = 0; //Reset the in_data Variable content
Blink(25);//Blink the transmitter led to show the data was successfully received
}
}
void Blink(byte DELAY_MS)//Local led blinking function
{
digitalWrite(LED, HIGH);
delay(DELAY_MS);
digitalWrite(LED, LOW);
}
So I guess I should have something like:
if (radio.SENDERID = GATEWAYID)
{
if (inData.in_data1 == 1) // If it was a "1", a command was sent from the Gateway to the Output 1 - Garage Door Relay
{
if (inData.in_data2 == 1) // If it was a "1", a command was sent from the Gateway to toggle the relay
{
controlDoor();
}
inData.in_data1 = 0; //Reset the in_data2 Variable content
}
}
Still I can't understand how the garbled data can be passed if spyMode is set to false
Read my response again for the explanation. PROMISCUOUS doesn't help you in any way to filter bad data.
Instead of checking 1 bit to trigger a OPEN or CLOSE, you need to check something like:
if (struct.magicToken == "AverySpecialThatWouldGuaranteeThisIsNotGibberishData")
{ all good, open my garage! }
That is pseudocode and grossly exaggerated, but I think you get the idea of what's needed before you release the heaviest moving object in your home without your presence ;)
So I spent some time studying this subject, and I went on and instead of just sending a if (struct.magicToken ==
Averyspecialstringherethattellsmethisisreallyforthegarageandnotsomethingelselikefakedata") { all good, open my garage! }
I decided to implement an Authentication method, using a MD5 HMAC, or keyed-hash message authentication code.
Mind you that I'm a copy/paste programmer, so take this with a bit of salt (pun intended :) ).
The idea is simple:
I have two nodes, one is the Gateway and the other is a node that will control something (like the garage, for instance).
So in order to make sure that the garage node only receives a command from the gateway and from nothing else, the gateway has to be authenticated.
To do this, I assigned a common password (or key, if you wish), that is considered private. This key is known by all the nodes. It is a private key. (Not the encryption type of key, but a key, anyway).
Now imagine that the Gateway wants to send a "OPEN THE GARAGE DOOR" to the garage door node.
First it will request a public key from the garage node, one that can be captured by someone listening to this conversation. But this key is nothing more the the "salt" that will scramble the private key when it is sent over the radio and on its own it is useless.
So the Gateway requests a public key to the garage node.
The garage node will fabricate a random number, of 9 digits in this case, using the millis() as a seed to assure the randomness of this number, and sends it to the gateway.
The gateway receives this public key and adds it to the private key, another 9 digit fixed number, and creates a MD5 Digested Hash, a large hexadecimal number, that is always the same size, no matter the dimension of the numbers used to generate it. This MD5 Hash is created by a very simple library created by TZIKIS (https://github.com/tzikis/ArduinoMD5 (https://github.com/tzikis/ArduinoMD5), trough two commands: one to create the Hash, and the other to create the Digested Hash that will be in a HEX format.
Now the Gateway sends this Digested Hash back to the garage node along with the intended command of "OPEN THE GARAGE DOOR".
The node receives this command and the Digested Hash and does the same process on its side: adds the private key with the public key it has already created and runs this trough the library to create the same Digested Hash, which will be compared with the received one.
If they match, the gateway is authenticated and the command is executed. If not, the node will wait a total of 200ms since it created the public key to receive the correct digested hash. After that that public key is expired and a new one must be requested.
All this takes about 30 to 50 ms.
If someone would receive the public key, not knowing what the private key is, the authentication digested hash cannot be recreated. And if the authenticated digested hash sent by the gateway is captured, it is no longer valid, since the node will only use it once.
So, I think this is a great step in the direction of increasing the security of this data transactions, beyond the AES128 encryption that the radios are already capable of.
I read that MD5 is not very secure compared with SHA256, for instance, but its a first step. I'm starting to look a solution for SHA256, but I'm not sure if the time it takes to create the hash will make it feasible.
Anyway, I leave the codes I use on both nodes here for your appreciation and comment.
In the Gateway Node, the code sends a request to the Garage Node every 5 seconds, for this test.
Below is a screen capture of this transactions.
Gateway node
//*****************************
// Homeseer Moteino Gateway
// Ver. 2G 1.0
// Node 20
//*****************************
#include <RFM69.h>
#include <RFM69_ATC.h>
#include <SPIFlash.h>
#include <MD5.h>
#define THISNODEID 20 //unique for each node on same network
#define NETWORKID 100 //the same on all nodes that talk to each other
#define FREQUENCY RF69_433MHZ //Match with the correct radio frequency
#define ENCRYPTKEY "xxxxxxxxxxxxxxxx" //exactly the same 16 characters/bytes on all nodes!
#define ATC_RSSI -80
#define ACK_TIME 500 // max # of ms to wait for an ack
#define SERIAL_BAUD 115200//Make sure the script comport_open1.txt has the same baud rate
#define FLASH_SS 8 // and FLASH SS on D8
#define SPY false
#define PRIVATEKEY 189578193
//Define Hardware
SPIFlash flash(FLASH_SS, 0xEF30); //EF30 for windbond 4mbit flash
RFM69_ATC radio;
unsigned long last_millis = 0;
unsigned long timeNow = 0;
uint32_t authToken = 0;
uint32_t hash;
String authTokenSt;
char buf[10];
//Inbound Data Struct
typedef struct
{
uint8_t in_data0; // Data 0 - Incoming Node ID
uint8_t in_data1; // Data 1 - 3: Auth token incoming
uint32_t in_data2; // Data 2 - NIL
uint32_t in_data3; // Data 3 - Security Token
}in_Payload;
in_Payload inData;
//Outboud Data Struct
typedef struct
{
uint8_t out_data0; // Data 0 - Destination Node ID
uint8_t out_data1; // Data 1 - 3: Request a Auth Token
uint32_t out_data2; // Data 2 - NIL
char out_data3[33]; // Data 3 - Security Token
}out_Payload;
out_Payload outData;
void setup()
{
//Initialize the Serial port at the specified baud rate
Serial.begin(SERIAL_BAUD);
pinMode(LED_BUILTIN, OUTPUT);
//Initialize the radio
radio.initialize(FREQUENCY, THISNODEID, NETWORKID);//Initialize the radio
radio.setHighPower();//Set the radio to high power
radio.encrypt(ENCRYPTKEY);//Turn the radio Encryption ON
radio.spyMode(SPY);//Turn the radio Promiscuous mode according to what in the promiscuousMode variable
radio.enableAutoPower(ATC_RSSI);
//Initialize FLASH
flash.initialize();
Serial.println("Gateway radio receiving in 433Mhz Mhz...");
Serial.println();
}
void loop()
{
//Every 5 seconds send
if (millis() > last_millis + 5000) //Time to send a new open/close instructions
{
last_millis = millis();
//Struct components to request the Salt
outData.out_data0 = 21;
outData.out_data1 = 3;
outData.out_data2 = 0;
strcpy(outData.out_data3, "");
timeNow = millis(); //Record the time to calculate how much time took the transaction
Serial.println();
Serial.println("Requesting a Auth Token...");
sendData(1);//Request a authentication token
}
if (radio.receiveDone())//If some packet was received by the radio, wait for all its contents to come trough
{
inData = *(in_Payload*)radio.DATA; //assume radio.DATA actually contains our struct and not something else
//If an ACK (acknowledge) was requested by the data packet transmitter radio, send the ACK back to it and display "ACK sent" on the serial monitor
if (radio.ACKRequested())
{
radio.sendACK();
Serial.println("[ACK sent!]");
}
if (inData.in_data1 == 3) //If the data is a Authentication Token
{
authToken = inData.in_data3 + PRIVATEKEY;
authTokenSt = String (authToken);
authTokenSt.toCharArray(buf, 11);
//generate the MD5 hash for our string
unsigned char* hash = MD5::make_hash(buf);
char *md5str = MD5::make_digest(hash, 16);
free(hash);
Serial.print("Auth Token received:");
Serial.println(inData.in_data3);
Serial.print("Elapsed Time:");
Serial.println(millis()-timeNow);// Display how much time it took for the Token to be available
Serial.print("DIGESTED HASH:");
Serial.println(md5str);
outData.out_data0 = radio.SENDERID;
outData.out_data1 = 1;
outData.out_data2 = 1;
strcpy(outData.out_data3, md5str);
free(md5str);
sendData(2);
Blink(50);
}
}
}
void sendData(int type)
{
if (radio.sendWithRetry(outData.out_data0, (const void*)(&outData), sizeof(outData), 5, ACK_TIME))//Send the data to the destinationNode via radio and wait for the ACK to be received
{
if (type == 1)
{
Serial.println("Token request sent and ACK received");
}
else if (type == 2)
{
Serial.println("Command sent and ACK received");
}
}
outData.out_data0 = 0;
outData.out_data1 = 0;
outData.out_data2 = 0;
strcpy(outData.out_data3, "");
}
void Blink(int DELAY_MS)//The led blinking function
{
digitalWrite(LED_BUILTIN, HIGH);
delay(DELAY_MS);
digitalWrite(LED_BUILTIN, LOW);
}
Garage node:
//*****************************
// Homeseer Moteino Gateway
// Ver. 2G 1.0
// Node 21
//*****************************
#include <RFM69.h>
#include <RFM69_ATC.h>
#include <SPIFlash.h>
#include <MD5.h>
#define THISNODEID 21 //unique for each node on same network
#define NETWORKID 100 //the same on all nodes that talk to each other
#define FREQUENCY RF69_433MHZ //Match with the correct radio frequency
#define ENCRYPTKEY "xxxxxxxxxxxxxxxx" //exactly the same 16 characters/bytes on all nodes!
#define ATC_RSSI -80
#define ACK_TIME 500 // max # of ms to wait for an ack
#define SERIAL_BAUD 115200//Make sure the script comport_open1.txt has the same baud rate
#define FLASH_SS 8 // and FLASH SS on D8
#define SPY false
#define PRIVATEKEY 189578193
#define TIMEOUT 200 //Auth Token timeout time in ms
//Define Hardware
SPIFlash flash(FLASH_SS, 0xEF30); //EF30 for windbond 4mbit flash
RFM69_ATC radio;
unsigned long last_millis = 0;
unsigned long int timeNow = 0;
uint32_t authToken = 0;
bool authTokenSent = false;
String authTokenSt;
char buf[10];
//Inbound Data Struct
typedef struct
{
uint8_t in_data0; // Data 0 - Incoming Node ID
uint8_t in_data1; // Data 1 - 3: Auth token incoming
uint32_t in_data2; // Data 2 - Auth Token
char in_data3[33]; // Data 3 - Security Token
}in_Payload;
in_Payload inData;
//Outboud Data Struct
typedef struct
{
uint8_t out_data0; // Data 0 - Sender Node ID
uint8_t out_data1; // Data 1 - 3: Request a Auth Token
uint32_t out_data2; // Data 2 - NIL
uint32_t out_data3; // Data 3 - Security Token
}out_Payload;
out_Payload outData;
void setup()
{
//Initialize the Serial port at the specified baud rate
Serial.begin(SERIAL_BAUD);
pinMode(LED_BUILTIN, OUTPUT);
//Initialize the radio
radio.initialize(FREQUENCY, THISNODEID, NETWORKID);//Initialize the radio
radio.setHighPower();//Set the radio to high power
radio.encrypt(ENCRYPTKEY);//Turn the radio Encryption ON
radio.spyMode(SPY);//Turn the radio Promiscuous mode according to what in the promiscuousMode variable
radio.enableAutoPower(ATC_RSSI);
//Initialize FLASH
flash.initialize();
Serial.println("Garage Node receiving in 433Mhz Mhz...");
Serial.println();
}
void loop()
{
if (radio.receiveDone())//If some packet was received by the radio, wait for all its contents to come trough
{
inData = *(in_Payload*)radio.DATA; //assume radio.DATA actually contains our struct and not something else
//If an ACK (acknowledge) was requested by the data packet transmitter radio, send the ACK back to it and display "ACK sent" on the serial monitor
if (radio.ACKRequested())
{
radio.sendACK();
Serial.println("[ACK sent!]");
}
// If the Auth Token was requested
if (inData.in_data1 == 3)
{
randomSeed(millis());
authToken = random(999999999);
Serial.println();
Serial.println("New request for a Auth Token received.");
Serial.print("New Auth Token:");
Serial.println(authToken);
outData.out_data0 = radio.SENDERID;
outData.out_data1 = 3;
outData.out_data2 = 0;
outData.out_data3 = authToken;
timeNow = millis();
sendData();
}
else if (inData.in_data1 == 1 && millis() - timeNow < TIMEOUT)
{
authToken = authToken + PRIVATEKEY; //Add the Salt to the Auth Token
authTokenSt = String (authToken); //Make the Auth Token a String
authTokenSt.toCharArray(buf, 11); //Convert the String into an array of chars
//generate the MD5 hash for our string
unsigned char* hash = MD5::make_hash(buf);
char *md5str = MD5::make_digest(hash, 16);//Convert the hash into HEX
Serial.print("Generated DIGESTED HASH:");
Serial.println(inData.in_data3);
Serial.print("Received DIGESTED HASH:");
Serial.println(md5str);
free(hash);// Release the hash memory blocks
if (strcmp(inData.in_data3, md5str) == 0)// See if the locally Digested Hash is equal to the remote Digested Hash received
{
free(md5str);//Release the md5str memory block
Serial.println("Command received!");
Serial.print("Elapsed Time:");
Serial.println(millis() - timeNow);// Show how much time passed sinced the requst for a token until a command was received
Blink(50);
authToken = 0;//Reset the Auth Token
}
}
else if (inData.in_data0 == 1 && millis() - timeNow >= TIMEOUT)
{
Serial.println("Auth Token Expired!");
}
}
}
void sendData()
{
if (radio.sendWithRetry(outData.out_data0, (const void*)(&outData), sizeof(outData), 5, ACK_TIME))//Send the data to the destinationNode via radio and wait for the ACK to be received
{
Serial.println("Auth Token sent and ACK received");
}
outData.out_data0 = 0;
outData.out_data1 = 0;
outData.out_data2 = 0;
outData.out_data3 = 0;
}
void Blink(int DELAY_MS)//The led blinking function
{
digitalWrite(LED_BUILTIN, HIGH);
delay(DELAY_MS);
digitalWrite(LED_BUILTIN, LOW);
}
I have managed to create the authentication hash with the strength of SHA256. It takes 21ms to create a digested hash from the concatenation of a PRIVATE key and the PUBLIC KEY (the "salt").
So I guess that makes SHA256 hash authentication a viable solution.
Tomorrow I will create a two way transaction between two Moteinos and see how much time it takes in total for a full transaction to be completed (request PUBLIC KEY, create a one time PUBLIC KEY, send the PUBLIC KEY, concatenate the public key with the PRIVATE KEY, create a digested hash, send a command with the digested hash for authentication, receive the digested hash, create the same digested hash, compare both digested to approve the authentication and finally accept and execute the sent command.
On the MD5 it took about 30 to 50ms in total. Lets see if the difference is significative.
For the SHA256 authentication I'm using the Crypto library for the Arduino, by Dr. Brandon Wiley, available here: https://github.com/OperatorFoundation/Crypto (https://github.com/OperatorFoundation/Crypto)
Just install the library as part of the Arduino libraries. I'm only using the #include <SHA256.h>, which is a part of the Crypto library.
The proof of concept code is this:
#include <SHA256.h>
#define PRIVATEKEY "myprivatekey"
#define HASH_SIZE 32
char data[70] = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
SHA256 sha256;
Hash *hash = &sha256;
char *out = (char*)malloc(33);
void setup()
{
int time = millis();
uint8_t value[HASH_SIZE];
Serial.begin(115200);
strcat(data, PRIVATEKEY);
// do the hash
hash->reset();
hash->update(data, strlen(data));
hash->finalize(value, sizeof(value));
Serial.print("Elapsed time:");
Serial.println(millis() - time);
int count = sizeof(value) / sizeof(value[0]);
for (int i = 0; i < count; i++)
snprintf(&(out[i * 2]), 16 * 2, "%02x", (unsigned int)value[i]);
Serial.println("The digested hash is:");
Serial.print(out);
}
void loop(){}
To check if the result is correct, use this SHA hash generator after concatenating your PUBLIC and PRIVATE KEYS:
https://passwordsgenerator.net/sha256-hash-generator/ (https://passwordsgenerator.net/sha256-hash-generator/)
I need some help, please!
I'm trying to compile my sketch with the SHA256.h from the Crypto library, but I get this error:
LowPower.cpp.o (symbol from plugin)*: In function LowPowerClass::idle(period_t, adc_t, timer2_t, timer1_t, timer0_t, spi_t, usart0_t, twi_t)
(.text+0x0)*: multiple definition of __vector_6
RNG.cpp.o (symbol from plugin)*: (.text+0x0): first defined here
Error linking for board Moteino(-USB)
Build failed for project 'Moteino Auth Gateway Node SHA256 [20]'
collect2.exe*: error: ld returned 1 exit status
I can get rid of it if I comment this in the LowPower.cpp (freshly downloaded from here: https://github.com/LowPowerLab/LowPower (https://github.com/LowPowerLab/LowPower)
ISR (WDT_vect)
{
// WDIE & WDIF is cleared in hardware upon entering this ISR
wdt_disable();
}
First of, why is the LowPower library part of the compilation?
And what can I do to avoid this error without hacking the LowPower library?