How can I HMAC a byte array on an Arduino? I've found this library for SHA1 HMACs, but it appears to be used only for strings.
I've passed it bytes in a null-terminated byte array. This does give me the correct result. But doesn't work so well for byte arrays that contain zeros!
uint8_t hmacKey1[]={ 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x21, 0xde, 0xad, 0xbe, 0xef };
uint8_t time[]={ 0xb2, 0x00 };
Sha1.initHmac(hmacKey1, 10);
Sha1.print((char*)time);
Either I need to find another another library (crypto-arduino-library looks promising, but doesn't include any examples for what I'm doing), or hack up the Cathedrow library to do what I'm after.
Does anyone know of another way?
Adding my own method appears to have done the trick:
void Sha1Class::writebytes(const uint8_t* data, int length) {
for (int i=0; i<length; i++)
{
write(data[i]);
}
}
If you don't want to change sha1.cpp you can just loop and print each single byte, the trick is to use Sha1.print((char) basestring[i]);, like so:
#include <avr/pgmspace.h>
#include <sha1.h>
char key[] = "testKey";
uint8_t basestring[] = { 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67 }; // testing
void printHash(uint8_t* hash) {
for (int i=0; i<20; i++) {
Serial.print("0123456789abcdef"[hash[i]>>4]);
Serial.print("0123456789abcdef"[hash[i]&0xf]);
}
Serial.println();
}
void setup() {
Serial.begin(115200);
Serial.print("Input: ");
for (int i=0; i<sizeof(basestring); i++) {
Serial.print((char) basestring[i]);
}
Serial.println();
Serial.print("Key: ");
Serial.println(key);
Serial.print("Hmac-sha1 (hex): ");
Sha1.initHmac((uint8_t*)key, strlen(key));
for (int i=0; i<sizeof(basestring); i++) {
Sha1.print((char) basestring[i]);
}
uint8_t *hash;
hash = Sha1.resultHmac();
printHash(hash);
}
void loop() { }
Output
Input: testing
Key: testKey
Hmac-sha1 (hex): 60d41271d43b875b791e2d54c34bf3f018a29763
Related
my esp8266 seems to be printing out a ton of memory locations to the serial monitor on arduino. my code mainly takes a post request from an android app and uses the string to execute respective blocks of code like setting and entering password.
this is my code
*i initialized some declarations for testing so i dont have to use my android phone and can just test my functions by setting variables.
#include <base64.h>
#include <xbase64.h>
#include <AES.h>
#include <AESLib.h>
#include <AES_config.h>
#include <base64.h>
#include <ESP8266WebServer.h>
#include <Servo.h>
#include <Keypad.h>
#define SOUND_VELOCITY 0.034
#define CM_TO_INCH 0.393701
const byte ROWS = 3;
const byte COLS = 3;
char keys[ROWS][COLS] = {
{'1','2','3'},
{'4','5','6'},
{'7','8','9'}
};
byte rowPins[ROWS] = { D3, D2, D1};
byte colPins[COLS] = { D7, D6, D5};
const char* ssid = "ESP8266-AP";
const char* passwordd = "password";
const int trigPin=D4;
const int echoPin=D0;
const float DISTANCE_THRESHOLD = 20;
long duration;
float distanceCm;
float distanceInch;
String tempString;
String pass;
char keyp;
String newString = "1020"; //change to 0102 to test other case
Keypad pad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
String password = "0000"; //variable to store the password, default=0000
String input = ""; //variable to store the input
bool setPass = false; //variable to track if the user is setting the password
bool passwordSet = false; //variable to track if the password has been set
bool unlocked = false; //variable to track if the system is unlocked
bool doorOpen = false;
bool isPostHandled = true;
int openClose = 0;
const byte key[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
ESP8266WebServer server(80);
AES aes;
Servo myservo;
void handlePost() {
String val = server.arg("data");
int decodedLength = base64_dec_len(val.c_str(), val.length());
char decodedData[decodedLength];
base64_decode(decodedData, val.c_str(), val.length());
byte decrypted[decodedLength];
aes.set_key(key, sizeof(key));
aes.decrypt((byte*)decodedData, decrypted);
String decryptedVal = String((char*)decrypted);
for(int i=0; i<4; i++){
tempString[i]=decryptedVal[i];
}
newString = String(tempString);
//Serial.println("Encrypted value: " + val);
//Serial.println("Decrypted value: " + decryptedVal);
server.send(200, "text/plain", "Value Received");
isPostHandled = true;
}
/*void moveServo() {
myservo.write(0);
delay(1000);
int count = 0;
myservo.write(180);
} */
//move servo, pass argument to control degrees
void moveServo(int position) {
myservo.write(position);
delay(1000);
}
float calculateDistance() {
// Trigger the ultrasonic sensor
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
// Measure the echo return time and calculate the distance
duration = pulseIn(echoPin, HIGH);
float distanceCm = (duration / 2) * SOUND_VELOCITY;
float distanceInch = distanceCm * CM_TO_INCH;
return distanceInch;
}
void setup() {
float duration, distanceCm, distanceInch;
//esp declaration
Serial.begin(9600);
WiFi.mode(WIFI_AP);
WiFi.softAP(ssid, passwordd);
server.begin();
server.on("/post", HTTP_POST, handlePost);
Serial.println("Server started");
//servo motor declaration
pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
pinMode(echoPin, INPUT); // Sets the echoPin as an Input
myservo.attach(D8);
myservo.write(180); // set the servo to 0 degrees
}
void loop() {
server.handleClient();
float distance = calculateDistance();
if((distance < 20) && (openClose == 0)){
doorOpen = true;
}
if ((distance < 20) && (openClose == 1)) {
doorOpen = false;
}
if(isPostHandled){
if(newString == "0102"){
do{
password = ""; //set password to a null string
Serial.println("Please set 4 digit passcode");
for(int i=0; i<4; i++){
keyp = pad.getKey();
if (keyp != NO_KEY) {
password += keyp; //add the key press to the password
Serial.print("*"); //print a * to indicate a key press
}
if (password.length() == 4) { //if the password is the same length as desired
Serial.println("Password set: " + password);
passwordSet = true;
moveServo(0);
break;
}
}
}while(!passwordSet);
newString = "";
}
else if(newString == "1020"){
input = "";
Serial.println("Please enter passcode");
do{
for(int i=0; i<4; i++){
keyp = pad.getKey();
if (keyp != NO_KEY) {
input += keyp; //add the key press to the input
Serial.print("*"); //print a * to indicate a key press
}
}
}while(!unlocked && (input.length() != 4));
if (input == password) { //if the input is the same length as the password
delay(1000);
Serial.println("Unlocked");
moveServo(0); //unlock
unlocked = true;
}else{
Serial.println("Access Denied, Wrong password");
return;
}
}
}
else{
Serial.print("isPostHandled = false");
return;
}
}
and this is the output
3fffff40: 00000000 00001113 39999999 0013be3a
3fffff50: 3ffe8a32 fffffffc 3fff019c 3ffefe98
3fffff60: 3ffeffc0 00000002 3ffefeb0 40205875
3fffff70: 3fffdad0 00000002 3ffefeb0 402058be
3fffff80: 3fffdad0 00000000 3fff001c 40203919
3fffff90: 3ffefc68 3ffefff8 00000001 40205522
3fffffa0: 00000000 00000000 3ffefc68 3fff0108
3fffffb0: 3fffdad0 00000000 3fff00dc 40208560
3fffffc0: feefeffe feefeffe 3fffdab0 401012b9
<<<stack<<<
--------------- CUT HERE FOR EXCEPTION DECODER ---------------
���u�����Server started
Please enter passcode
i tried changing serial baud rate and i cant really find anything related to what i am facing on the internet
I have the following Arduino function:
void SendCommandToDisplay(byte message[], byte size)
{
byte header[] = {0x5A, 0xA5};
byte result[] = {};
memcpy(result, header, sizeof(header));
memcpy(result+sizeof(header), message, size);
for (byte i=0; i<sizeof(result); i++)
{
Serial.print(result[i], HEX);
Serial.print(' ');
}
}
Then I call this function as follows:
byte test[]={0x82, 0x20, 0x10, 0x00, 0x03};
SendCommandToDisplay(test, sizeof(test) / sizeof(byte));
And seems is not working, I'm doing something wrong or maybe I have to do a reference or pointer. Any clue?
You are not allocating memory for the result variable - in your case try this:
void SendCommandToDisplay(byte message[], byte size)
{
byte header[] = {0x5A, 0xA5};
byte result[sizeof(header)+size];
memcpy(result, header, sizeof(header));
memcpy(result+sizeof(header), message, size);
for (byte i=0; i<sizeof(result); i++)
{
Serial.print(result[i], HEX);
Serial.print(' ');
}
}
Once simple approach to inserting the byte count (of message) following header is to change how the header is initialized:
byte header[] = {0x5A, 0xA5, size};
Note: a prior edit added an alternative to use the sizeof(message) but that was incorrect and removed - sizeof(message) where message is a parameter returns the sizeof of a pointer which is 2 on an arduino.
How i can convert a MAC string, like "5D:41:8F:32:34:H2" to byte array like {0x5D, 0x41, 0x8F, 0x32, 0x34, 0xH2}
I'm using an Arduino WOL library and it requires the MAC to pass it as an array of bytes, but I keep them as strings separated by ":" and I have no idea how that conversion could be done.
I can not put more details if you try because I do not even know where to start trying.
void arrancarPC(String strMac) {
byte mac[] = {0x5D, 0x41, 0x8F, 0x32, 0x34, 0xH2};
WakeOnLan::sendWOL(broadcast_ip, UDP, mac, sizeof mac);
}
the bytes in array must be in reverse order then printed.
H2 is not a valid hex value.
void str2mac(const char* str, uint8_t* mac) {
char buffer[20];
strcpy(buffer, str);
const char* delims = ":";
char* tok = strtok(buffer, delims);
for (int i = 5; i >= 0; i--) {
mac[i] = strtol(tok, NULL, 16);
tok = strtok(NULL, delims);
}
}
void setup() {
Serial.begin(115200);
const char* str = "5D:41:8F:32:34:F2";
uint8_t mac[6];
Serial.println(str);
str2mac(str, mac);
for (int i = 5; i >= 0; i--) {
if (i < 5) {
Serial.print(':');
}
Serial.print(mac[i], HEX);
}
Serial.println();
}
void loop() {
}
I have Arduino + Ethenet shield. I want to dynamically change the ip depending on that will come at the input com-port.
The main problem is - input string has a String type, and Ethernet.begin method accepts a byte array. In general, I can not understand how to convert this string correctly. Tried to make a bicycle(crutch) by moving the string in the char array, and then in the byte array. Did not work out. How convert string to byte[]?
#include <SPI.h>
#include <Ethernet.h>
String readString;
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address
byte myserver[] = { 208, 104, 2, 86 }; // zoomkat web page server IP address
EthernetClient client;
void initEthernetConfig(byte ip[])
{
Ethernet.begin(mac, ip);
Serial.begin(9600);
Serial.println("Better client test 12/01/11"); // so I can keep track of what is loaded
Serial.println("Send an e in serial monitor to test"); // what to do to test
}
void setup(){
byte ip[] = { 10, 28, 33, 4 };
// initEthernetConfig(ip);
}
void loop(){
// check for serial input
while (Serial.available()) {
char c = Serial.read(); //gets one byte from serial buffer
readString += c; //makes the String readString
delay(2); //slow looping to allow buffer to fill with next character
}
if (readString.length() >0) {
byte inArray[4];
char * tokens;
int i = 0;
tokens = strtok(readString, ".");
while (tokens != NULL) {
inArray[i] = atoi(tokens);
tokens = strtok(NULL, ".");
i++;
}
initEthernetConfig(inArray);
}
}
This is a possible solution, it parses, dumps and sets an IPv4:
#include <SPI.h>
#include <Ethernet.h>
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address
byte myserver[] = { 208, 104, 2, 86 }; // zoomkat web page server IP address
EthernetClient client;
/**
* help functions declaration
*/
void get_ip(byte ip[4]);
void dump_ip(byte ip[4]);
void initEthernetConfig(byte ip[]);
/**
* setup && loop
*/
void setup(){
Serial.begin(9600);
}
void loop()
{
byte ip[4];
get_ip(ip);
dump_ip(ip);
initEthernetConfig(ip);
}
/**
* help function implementation
*/
void get_ip(byte ip[4])
{
for (byte i = 0; i < 4; ++i) {
while (Serial.available() <= 0) { };
ip[i] = (byte) Serial.parseInt();
if (i < 3) { Serial.read(); } // throw away dot
}
};
void dump_ip(byte ip[4]) {
for (byte i = 0; i < 4; ++i) {
Serial.print(ip[i]);
if (i < 3) {
Serial.print('.');
} else {
Serial.println();
}
}
};
void initEthernetConfig(byte ip[])
{
Ethernet.begin(mac, ip);
Serial.println("Better client test 12/01/11"); // so I can keep track of what is loaded
Serial.println("Send an e in serial monitor to test"); // what to do to test
};
Obviously, outside this testing application you should ensure that the Serial input is ready for sending an IPv4 in the first place, otherwise the function will likely return 0.0.0.0. An idea would be to enrich your communication protocol with string-based commands, e.g. ip: would signal the start of an IPv4 input.
Try this:
while (tokens != NULL) {
inArray[i++] = atoi(tokens) & 0xFF;
tokens = strtok(NULL, ".");
}
Which will get only the last byte of the integer, but that is all you want in the case of values 0-255.
But then again why not just read it in as bytes...
void loop(){
byte inArray[4];
int i = 0;
// check for serial input
while (Serial.available()) {
inArray[i++] = (byte) Serial.read(); //gets one byte from serial buffer
delay(2); //slow looping to allow buffer to fill with next character
}
initEthernetConfig(inArray);
}
I'm doing a project where I need to randomly generate Hash numbers.
The code has to work as follows.
A random function generates a random number, these numbers are concatenated with a String to then generate the Hash of this String, ie each time a number is generated, the Hash of that number is also generated, this must be looped. To generate the hash I'm using a library called SpritzCipher.
The problem with this code is that it generates the hash of the word "random" instead of the hash of the concatenation of the value with String (salt).
Here is the code I did:
#include <SpritzCipher.h>
String salt = "fkllrnjnfd";
int randNumber;
String valorConcat;
void randomico() {
//Serial.begin(9600);
randomSeed(analogRead(0)); // Starts the list of random values
randNumber = random(100); // Draw a number from 0 to 99
valorConcat = String(randNumber) + salt;
//Serial.println(valorConcat); // Sends the value of randNumber to the serial
delay(500); // espera 500 ms
}
/* Data to input */
const byte testData[12] = {randomico};
/* Test vectors */
/* Data = 'testData' hash test vectors */
const byte testVector[32] =
{ 0xff, 0x8c, 0xf2, 0x68, 0x09, 0x4c, 0x87, 0xb9,
0x5f, 0x74, 0xce, 0x6f, 0xee, 0x9d, 0x30, 0x03,
0xa5, 0xf9, 0xfe, 0x69, 0x44, 0x65, 0x3c, 0xd5,
0x0e, 0x66, 0xbf, 0x18, 0x9c, 0x63, 0xf6, 0x99
};
void testFunc(const byte ExpectedOutput[32], const byte *data, byte dataLen)
{
byte hashLen = 32; /* 256-bit */
byte digest[hashLen]; /* Output buffer */
byte digest_2[hashLen]; /* Output buffer for chunk by chunk API */
spritz_ctx hash_ctx; /* the CTX for chunk by chunk API */
unsigned int i;
/* Print input */
for (i = 0; i < dataLen; i++) {
Serial.write(data[i]);
}
Serial.println();
spritz_hash_setup(&hash_ctx);
/* For easy test: code add a byte each time */
for (i = 0; i < dataLen; i++) {
spritz_hash_update(&hash_ctx, data + i, 1);
}
spritz_hash_final(&hash_ctx, digest_2, hashLen);
spritz_hash(digest, hashLen, data, dataLen);
for (i = 0; i < sizeof(digest); i++) {
if (digest[i] < 0x10) { /* To print "0F" not "F" */
Serial.write('0');
}
Serial.print(digest[i], HEX);
}
/* Check the output */
if (spritz_compare(digest, ExpectedOutput, sizeof(digest)) || spritz_compare(digest_2, ExpectedOutput, sizeof(digest_2))) {
/* If the output is wrong "Alert" */
digitalWrite(LED_BUILTIN, HIGH); /* Turn pin LED_BUILTIN On (Most boards have this LED connected to digital pin 13) */
Serial.println("\n** WARNING: Output != Test_Vector **");
}
Serial.println();
}
void setup() {
/* Initialize serial and wait for port to open */
Serial.begin(9600);
while (!Serial) {
; /* Wait for serial port to connect. Needed for Leonardo only */
}
/* initialize digital pin LED_BUILTIN (Most boards have this LED connected to digital pin 13) as an output */
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
}
void loop() {
Serial.println("[Spritz spritz_hash*() test]\n");
/* Data: arcfour */
testFunc(testVector, testData, sizeof(testData));
delay(5000); /* Wait 5s */
Serial.println();
}
A lot of your hashing code is just and example of two different options of hashing an array of bytes and comparing it to a known hash.
Since you only need to calculate the hash you only need to call spritz_hash.
As for your string generation, a more efficient way would be to use low level C++ functions, since the String object is using dynamic memory allocation and that can cause memory problems.
#include <SpritzCipher.h>
#define hex_char(n) ((n) < 10 ? '0' + (n) : 'A' + ((n)-10))
const char salt[] = "fkllrnjnfd";
char string[13] = "";
byte hash[32]; // byte hash
char hash_string[65]; // hex string hash
void randomico(char *string)
{
int randNumber = random(100); // Draw a number from 0 to 99
itoa(randNumber, string, 10); // convert int into char array
strcat(string, salt); // concatenate salt
}
void bytes_to_hexstr(char *string, byte *bytes, int size)
{
for (int i = 0; i < size; i++)
{
string[i*2] = bytes[i] < 16 ? '0' : hex_char((bytes[i] >> 4) & 0xF);
string[i*2+1] = hex_char(bytes[i] & 0xF);
}
string[size*2] = 0;
}
void setup()
{
Serial.begin(115200);
while (!Serial);
randomSeed(analogRead(0)); // Starts the list of random values
}
void loop()
{
randomico(string); // generate random salted string into 'string' variable
spritz_hash(hash, 32, (byte*)string, strlen(string)); // hash 'string' into 'hash' variable (hash only the character inside the string not the full char array)
bytes_to_hexstr(hash_string, hash, 32); // convert byte hash into printable hex string
// print out string and hash
Serial.print(string);
Serial.print(" -> ");
Serial.println(hash_string);
delay(1000);
}
But if you really want to use String you can do it as such:
String str = String(random(100))+salt;
spritz_hash(hash, 32, (byte*)str.c_str(), str.length());