Skip to content

Instantly share code, notes, and snippets.

@bshambaugh
Created November 30, 2022 00:29
Show Gist options
  • Save bshambaugh/41683d50c5de91344e724afc585b10fa to your computer and use it in GitHub Desktop.
Save bshambaugh/41683d50c5de91344e724afc585b10fa to your computer and use it in GitHub Desktop.
main.cpp with some string embellishments
#include <Arduino.h>
#include <SparkFun_ATECCX08a_Arduino_Library.h> /// the latest version of this library might work with the ESP32. so you do not need to use Blinky's *-aug26.h
#include <WiFi.h>
#include <WebSocketClient.h>
#include <Wire.h>
#include <concatenateArray.h>
#include <protected.h>
#include <websocketserver_config.h> // defines: path, host, and espport
#include <string>
using namespace std;
#include <parsePacket.h>
//#include "utils.h"
// Declaration for the exteranal cryptographic co-processor class
ATECCX08A atecc;
// Use WiFiClient class to create TCP connections
WiFiClient client;
// const char* ssid = "your ssid"; // defined in protected.h
// const char* password = "your password"; // defined in protected.h
WebSocketClient webSocketClient;
boolean handshakeFailed=0;
String data= "";
string ldata = "";
// some of the variable declarations below could exist in their own file
#define BUFFER_SIZE 30 // Define the payload size here
char txpacket[BUFFER_SIZE];
// set up an array for the signature
char signatureString[129];
char publicKeyString[129];
// uint8_t bufferString[64];
// bool start = true;
const byte MaxByteArraySize = 32;
byte byteArray[MaxByteArraySize] = {0};
//*********************************************************************************************************************
//***************function definitions**********************************************************************************
// source: https://forum.arduino.cc/t/hex-string-to-byte-array/563827
// reply: johnwasser, Dec '18post #4
// this may be able to exist in its own file.
byte nibble(char c)
{
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
return 0; // Not a valid hexadecimal character
}
// this may be able to exist in its own file.
void hexCharacterStringToBytes(byte *byteArray, const char *hexString)
{
bool oddLength = strlen(hexString) & 1;
byte currentByte = 0;
byte byteIndex = 0;
for (byte charIndex = 0; charIndex < strlen(hexString); charIndex++)
{
bool oddCharIndex = charIndex & 1;
if (oddLength)
{
// If the length is odd
if (oddCharIndex)
{
// odd characters go in high nibble
currentByte = nibble(hexString[charIndex]) << 4;
}
else
{
// Even characters go into low nibble
currentByte |= nibble(hexString[charIndex]);
byteArray[byteIndex++] = currentByte;
currentByte = 0;
}
}
else
{
// If the length is even
if (!oddCharIndex)
{
// Odd characters go into the high nibble
currentByte = nibble(hexString[charIndex]) << 4;
}
else
{
// Odd characters go into low nibble
currentByte |= nibble(hexString[charIndex]);
byteArray[byteIndex++] = currentByte;
currentByte = 0;
}
}
}
}
void wsconnect(){
// Connect to the websocket server
if (client.connect(host, espport)) {
Serial.println("Connected");
} else {
Serial.println("Connection failed.");
delay(1000);
if(handshakeFailed){
handshakeFailed=0;
ESP.restart();
}
handshakeFailed=1;
}
// Handshake with the server
webSocketClient.path = path;
webSocketClient.host = host;
if (webSocketClient.handshake(client)) {
Serial.println("Handshake successful");
} else {
Serial.println("Handshake failed.");
delay(4000);
if(handshakeFailed){
handshakeFailed=0;
ESP.restart();
}
handshakeFailed=1;
}
}
void printInfo()
{
// Read all 128 bytes of Configuration Zone
// These will be stored in an array within the instance named: atecc.configZone[128]
atecc.readConfigZone(false); // Debug argument false (OFF)
// Print useful information from configuration zone data
Serial.println();
Serial.print("Serial Number: \t");
for (int i = 0 ; i < 9 ; i++)
{
if ((atecc.serialNumber[i] >> 4) == 0) Serial.print("0"); // print preceeding high nibble if it's zero
Serial.print(atecc.serialNumber[i], HEX);
}
Serial.println();
Serial.print("Rev Number: \t");
for (int i = 0 ; i < 4 ; i++)
{
if ((atecc.revisionNumber[i] >> 4) == 0) Serial.print("0"); // print preceeding high nibble if it's zero
Serial.print(atecc.revisionNumber[i], HEX);
}
Serial.println();
Serial.print("Config Zone: \t");
if (atecc.configLockStatus) Serial.println("Locked");
else Serial.println("NOT Locked");
Serial.print("Data/OTP Zone: \t");
if (atecc.dataOTPLockStatus) Serial.println("Locked");
else Serial.println("NOT Locked");
Serial.print("Data Slot 0: \t");
if (atecc.slot0LockStatus) Serial.println("Locked");
else Serial.println("NOT Locked");
Serial.println();
// if everything is locked up, then configuration is complete, so let's print the public key
if (atecc.configLockStatus && atecc.dataOTPLockStatus && atecc.slot0LockStatus)
{
if(atecc.generatePublicKey() == false)
{
Serial.println("Failure to generate This device's Public Key");
Serial.println();
}
}
}
// Modified https://stackoverflow.com/questions/15050766/comparing-the-values-of-char-arrays-in-c#15050807
// compares two character arrays to see if they have the same sequence of characters
// I might need to modify this to return a pointer or something...
// this may be able to exist in its own file.
bool char_sequence_compare(const char a[],const char b[]){
if(strlen(a) > strlen(b)) {
for(int i=0;a[i]!='\0';i++){
if(a[i]!=b[i])
return false;
}
} else {
for(int i=0;b[i]!='\0';i++){
if(a[i]!=b[i])
return false;
}
}
return true;
}
// verify that the public key matches the key:did you think it is
// this should take the payload as an argument
// this may be able to exist in its own file. Are voidArray and merge Array tested?
/*
bool verifyKeyDID(const String payload) {
// somehow payload which is a string needs to be converted to a char array
const char* payload_str = payload.c_str();
voidArray(129,publicKeyString);
mergeArray(64,atecc.publicKey64Bytes,publicKeyString);
Serial.println("my public key string is");
Serial.println(publicKeyString);
if(char_sequence_compare(payload_str,publicKeyString)) {
voidArray(129,publicKeyString);
return true;
} else {
voidArray(129,publicKeyString);
return false;
}
// if the payload matches the publicKeyString return true
// else return false
// this involves matching two char arrays (they may not be the same length, but they will have the same contents)
}
*/
bool verifyKeyDID(const string payload) {
// somehow payload which is a string needs to be converted to a char array
const char* payload_str = payload.c_str();
voidArray(129,publicKeyString);
mergeArray(64,atecc.publicKey64Bytes,publicKeyString);
Serial.println("my public key string is");
Serial.println(publicKeyString);
if(char_sequence_compare(payload_str,publicKeyString)) {
voidArray(129,publicKeyString);
return true;
} else {
voidArray(129,publicKeyString);
return false;
}
// if the payload matches the publicKeyString return true
// else return false
// this involves matching two char arrays (they may not be the same length, but they will have the same contents)
}
char getPublicKeyPacket() {
Serial.println("Okay, I am getting the Public Key");
Serial.println(atecc.publicKey64Bytes[63]);
voidArray(129,publicKeyString);
mergeArray(64,atecc.publicKey64Bytes,publicKeyString);
sprintf(txpacket+strlen(txpacket),"%s","publicKey"); // add another thing (by bret)
sprintf(txpacket+strlen(txpacket),"%s",","); // add another thing (by bret)
sprintf(txpacket+strlen(txpacket),"%s",publicKeyString); // add another thing (by bret)
// sprintf(txpacket+strlen(txpacket),"%s","\n"); // add another thing (by bret)
voidArray(129,publicKeyString);
return *txpacket;
}
// what happens when the payload is larger than the BUFFER_SIZE ??
/*
void sendStringoverWebSocket(char *payload) {
sprintf(txpacket+strlen(txpacket),"%s",payload);
webSocketClient.sendData(txpacket);
voidArray(BUFFER_SIZE,txpacket);
}
*/
// refactor this with sendStringoverWebSocket
// getthepublicKey
// separate the logic from the sending by websockets, move the logic to its own file
void websocketSendPublicKey() {
*txpacket = getPublicKeyPacket();
Serial.println(txpacket);
webSocketClient.sendData(txpacket);
voidArray(BUFFER_SIZE,txpacket);
}
/*
char getSignaturePacket(String payload) {
Serial.println("Okay, I am getting the Signature");
Serial.println(payload);
const char* payload_str = payload.c_str();
hexCharacterStringToBytes(byteArray, payload_str);
// (String(*payload_str,strlen(payload_str))).getBytes(bufferString,64); /// copies data characters into bufferString as a byteString that can be signed
for (byte i = 0; i < 32; i++)
{
// Serial.println(bufferString[i]);
Serial.println(byteArray[i]);
}
// atecc.createSignature(bufferString);
atecc.createSignature(byteArray);
Serial.println(atecc.signature[63]);
voidArray(129,signatureString);
mergeArray(64,atecc.signature,signatureString);
sprintf(txpacket+strlen(txpacket),"%s","signature"); // add another thing (by bret)
sprintf(txpacket+strlen(txpacket),"%s",","); // add another thing (by bret)
sprintf(txpacket+strlen(txpacket),"%s",signatureString); // add another thing (by bret)
voidArray(129,signatureString);
voidUint8Array(MaxByteArraySize,byteArray);
return *txpacket;
}
*/
char getSignaturePacket(string payload) {
Serial.println("Okay, I am getting the Signature");
// Serial.println(payload);
Serial.println(payload.c_str());
const char* payload_str = payload.c_str();
hexCharacterStringToBytes(byteArray, payload_str);
// (String(*payload_str,strlen(payload_str))).getBytes(bufferString,64); /// copies data characters into bufferString as a byteString that can be signed
for (byte i = 0; i < 32; i++)
{
// Serial.println(bufferString[i]);
Serial.println(byteArray[i]);
}
// atecc.createSignature(bufferString);
atecc.createSignature(byteArray);
Serial.println(atecc.signature[63]);
voidArray(129,signatureString);
mergeArray(64,atecc.signature,signatureString);
sprintf(txpacket+strlen(txpacket),"%s","signature"); // add another thing (by bret)
sprintf(txpacket+strlen(txpacket),"%s",","); // add another thing (by bret)
sprintf(txpacket+strlen(txpacket),"%s",signatureString); // add another thing (by bret)
voidArray(129,signatureString);
voidUint8Array(MaxByteArraySize,byteArray);
return *txpacket;
}
// refactor this with sendStringoverWebSocket
// gettheSignature
// payload should be 64 hex character string (32 bytes)
// separate the logic from the sending by websockets, move the logic to its own file
/*
void websocketSendSignature(String payload) {
*txpacket = getSignaturePacket(payload);
Serial.println(txpacket);
webSocketClient.sendData(txpacket);
voidArray(BUFFER_SIZE,txpacket);
}
*/
void websocketSendSignature(string payload) {
*txpacket = getSignaturePacket(payload);
Serial.println(txpacket);
webSocketClient.sendData(txpacket);
voidArray(BUFFER_SIZE,txpacket);
}
/*
char getMessageASCIIstring(String payload) {
Serial.println("Okay, I am getting the ASCII Message");
Serial.println(payload);
const char* payload_str = payload.c_str();
sprintf(txpacket+strlen(txpacket),"%s","message"); // add another thing (by bret)
sprintf(txpacket+strlen(txpacket),"%s",","); // add another thing (by bret)
sprintf(txpacket+strlen(txpacket),"%s",payload_str); // add another thing (by bret)
return *txpacket;
}
*/
char getMessageASCIIstring(string payload) {
Serial.println("Okay, I am getting the ASCII Message");
// Serial.println(payload);
Serial.println(payload.c_str());
const char* payload_str = payload.c_str();
sprintf(txpacket+strlen(txpacket),"%s","message"); // add another thing (by bret)
sprintf(txpacket+strlen(txpacket),"%s",","); // add another thing (by bret)
sprintf(txpacket+strlen(txpacket),"%s",payload_str); // add another thing (by bret)
return *txpacket;
}
/*
void websocketSendASCIIstring(String payload) {
*txpacket = getMessageASCIIstring(payload);
Serial.println(txpacket);
webSocketClient.sendData(txpacket);
voidArray(BUFFER_SIZE,txpacket);
}
*/
void websocketSendASCIIstring(string payload) {
*txpacket = getMessageASCIIstring(payload);
Serial.println(txpacket);
webSocketClient.sendData(txpacket);
voidArray(BUFFER_SIZE,txpacket);
}
// this can move to it's own file
/*
bool compareString(String s1, String s2)
{
if(s1.compareTo(s2) == 0) {
return true;
} else {
return false;
}
}
*/
bool compareString(string s1, string s2)
{
if(strcmp(s1.c_str(),s2.c_str()) == 0) {
return true;
} else {
return false;
}
}
// this can move to it's own file
/*
void parse_packet(const String *source, String *type, String *curve, String *payload) {
*type = (*source).substring(0,1);
// *curve = (*source).substring(1,4);
*curve = (*source).substring(1,5);
//*payload = (*source).substring(5,(*source).length()-1);
*payload = (*source).substring(5,(*source).length());
}
*/
// void RPC(String &source) {
void RPC(string &source) {
/*
String type = "";
String curve = "";
String payload = "";
*/
string type = "";
string curve = "";
string payload = "";
// .substr(0,1);
if((((source.substr(0,1)).c_str() == "0") || ((source.substr(0,1)).c_str() == "1") || ((source.substr(0,1)).c_str() == "2") || ((source.substr(0,1)).c_str() == "3")) && (source.length() >= 5)) {
// if(((source.charAt(0) == '0') | (source.charAt(0) == '1') | (source.charAt(0) == '2') | (source.charAt(0) == '3')) && (source.length() >= 5)) {
parse_packet(&source,&type,&curve,&payload);
if(compareString("0",type)) {
Serial.println("Match Public Key to stored\n");
// some function that grabs the public key from the cryptochip and matches to what is sent
// actually verifyKeyDID should only take the hex string as an argument, AFAIK this function has not been battle tested
Serial.println("The type is:");
// Serial.println(type);
Serial.println(type.c_str());
Serial.println("The curve is:");
/// Serial.println(curve);
Serial.println(curve.c_str());
Serial.println("The payload is:");
// Serial.println(payload);
Serial.println(payload.c_str());
if(verifyKeyDID(payload)) {
Serial.println("You guessed my name");
// websocketsend 1
// sendStringoverWebSocket("1"); // check to see if this works
websocketSendASCIIstring("1");
// construct a function to send back arbitary data over websockets, follow the pattern in websocketSendPublicKey and websocketGetSignature
} else {
Serial.println("You did not guess my name");
// websocketsend 0
// sendStringoverWebSocket("0"); // check to see if this works
websocketSendPublicKey();
// construct a function to send back arbitary data over websockets, follow the pattern in websocketSendPublicKey and websocketGetSignature
}
}
if(compareString("1",type)) {
Serial.println("Here is the public key of my cryptographic co-processor\n");
websocketSendPublicKey();
}
if(compareString("2",type)) {
if(payload.length() > 0) {
Serial.println("Sign the payload\n");
websocketSendSignature(payload); // this needs to refactored to sign the payload
}
}
if(compareString("3",type)) {
Serial.println("I have a message\n");
websocketSendASCIIstring(payload);
}
} else {
Serial.println("Invalid packet");
}
}
void setupWifi() {
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
delay(1000);
}
void setupCryptoChip() {
// check the ESP
if (atecc.begin() == true)
{
Serial.println("Successful wakeUp(). I2C connections are good.");
}
else
{
Serial.println("Device not found. Check wiring.");
while (1); // stall out forever
}
printInfo(); // see function below for library calls and data handling
}
void setup() {
Wire.begin();
Serial.begin(115200);
setupCryptoChip();
// We start by connecting to a WiFi network
setupWifi();
wsconnect();
}
void loop() {
// delay(1000); /// this delay may need to be changed...
delay(250);
if (client.connected()) {
// the getSignature and getPublicKey will process all of the requests from the Node.js server.
webSocketClient.getData(data);
ldata = data.c_str();
/// only run the code below if 0,1,2 is the first byte...length of string should be at least two
Serial.println("I am a connected client");
RPC(ldata);
}
}
@bshambaugh
Copy link
Author

bshambaugh commented Nov 30, 2022

void RPD(string &source) {
      string type = "";
      string curve = "";
      string payload = "";
      string s = "0";
      string r = "1";
      string t = "2";

      /*
      char arr[source.c_str().length() + 1]; 
      *(source.substr(0,1).c_str().length()
      strcpy(arr, source.c_str()); 
      */
      if(source.substr(0,1) == s) {
         Serial.println("You have a zero");
      }

      if(source.substr(0,1) == r) {
         Serial.println("You have a one");
      }

      if(source.substr(0,1) == t) {
         Serial.println("You have a two");
      }

@bshambaugh
Copy link
Author

void loop() {
 // delay(1000); /// this delay may need to be changed...
 delay(250);

  if (client.connected()) {
 
    // the getSignature and getPublicKey will process all of the requests from the Node.js server.
    webSocketClient.getData(data); 

    /// only run the code below if 0,1,2 is the first byte...length of string should be at least two
    Serial.println("I am a connected client"); 

   RPC(data);

  // std::string s(data.c_str());
  string s = data.c_str();
  RPD(s);

   websocketSendASCIIstring("1");

   // I am not sure this is needed, or if this is the place to clear the array .. I'm guessing 
   // try commenting this out since it may not be used
   /*
   voidArray(5,type);
   voidArray(5,curve);
   voidArray(200,payload);
   */

   }
}

@bshambaugh
Copy link
Author

#include <string>
using namespace std;

void parse_packetz(const string *source, string *type, string *curve, string *payload);

#include "parsePacket.h"

void parse_packetz(const string *source, string *type, string *curve, string *payload) {
  *type = (*source).substr(0,1);
 // *curve = (*source).substring(1,4);
  *curve = (*source).substr(1,5);
  //*payload = (*source).substring(5,(*source).length()-1);
  *payload = (*source).substr(5,(*source).length());
}

@bshambaugh
Copy link
Author

void RPC(String &Source) {
   string source = "";
   source = Source.c_str();
   
   if(((source.substr(0,1) == "0") || (source.substr(0,1) == "1") ||  (source.substr(0,1) == "2") )  &&  (source.length() >= 5)) {
   
   }
}

@bshambaugh
Copy link
Author

bshambaugh commented Nov 30, 2022

#include` <Arduino.h>
#include <Wire.h>
#include <string>
using namespace std;


String data= "hello";
// char a[6];
String binary = "010101";


string b = "";

void RPC(String &Source) {
   string source = "";
   source = Source.c_str();
   String payload = "";
   String datum = "";
   
   if(((source.substr(0,1) == "0") || (source.substr(0,1) == "1") ||  (source.substr(0,1) == "2") )  &&  (source.length() >= 5)) {
      Serial.println("I match them all!");
      Serial.println(String(source.substr(0,2).c_str()));
      payload = String(source.substr(0,2).c_str());
      Serial.println(payload);
      datum = String(source.c_str());
      Serial.println(datum);
   }
   // do not need due to automatically declared descructor ...
   /*
   delete &datum;
   delete &payload;
   */
}


void setup() {
  Wire.begin();
  Serial.begin(115200);
 // data.toCharArray(a,6);
  b = data.c_str();
  if(b == "helo") {
    Serial.println("hody");
  } else {
    Serial.println("not hody");
  }
  if(b.substr(0,1) == "h") {
    Serial.println("I have an h");
  }
  if(b.length() >= 6) {
    Serial.println("I am longer than 6");
  } else {
    Serial.println("I am not longer than 6");
  }

  if((b.substr(0,1) == "h") && (b.length() >= 5)) {
    Serial.println("My first letter is h, and I have a length of at least 5");
  } else {
    Serial.println("Failed on all accounts sir");
  }

  RPC(binary);

}

void loop() {
 // delay(1000); /// this delay may need to be changed...
 delay(250);
// Serial.println(a);
 Serial.println(data);

}

@bshambaugh
Copy link
Author

bshambaugh commented Nov 30, 2022

void RPC(string &source) {
   string source = "";
   String payload = "";
   // String datum = "";
   
   if(((source.substr(0,1) == "0") || (source.substr(0,1) == "1") ||  (source.substr(0,1) == "2") )  &&  (source.length() >= 5)) {
      source.substr(0,2).c_str();
      // datum = String(source.c_str());
   }
}

@bshambaugh
Copy link
Author

bshambaugh commented Nov 30, 2022

void RPC(string &source) {
   string source = "";
   string type = "";
   string curve = "";
   string payload = "";
   
   if(((source.substr(0,1) == "0") || (source.substr(0,1) == "1") ||  (source.substr(0,1) == "2") )  &&  (source.length() >= 5)) {
         parse_packetz(&source, &type, &curve, &payload);
   }
}
void parse_packetz(const string *source, string *type, string *curve, string *payload) {
  *type = (*source).substr(0,1);
  *curve = (*source).substr(1,5);
  *payload = (*source).substr(5,(*source).length());
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment