Skip to content

Commit b7569ca

Browse files
committed
feat: change to aes-cbc encryption
1 parent 892fd10 commit b7569ca

File tree

3 files changed

+73
-80
lines changed

3 files changed

+73
-80
lines changed

debug.sh

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
arduino-cli compile \
2+
--build-property "build.partitions=min_spiffs" \
3+
--build-property "upload.maximum_size=1966080" \
4+
--library ./libraries/TFT_eSPI \
5+
--library ./libraries/QRCode \
6+
--build-path build --fqbn esp32:esp32:ttgo-lora32 lnpos && \
7+
arduino-cli upload --input-dir build --fqbn esp32:esp32:ttgo-lora32 -p /dev/ttyACM0 && \
8+
arduino-cli monitor -p /dev/ttyACM0 -c baudrate=115200

lnpos/100_config.ino

+1-2
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,6 @@ void readFiles()
145145
secretPoS = getValue(lnurlPoS, ',', 1);
146146
currencyPoS = getValue(lnurlPoS, ',', 2);
147147
Serial.println("");
148-
Serial.println("lnurlPoS used");
149148
Serial.println("lnurlPoS: " + lnurlPoS);
150149
if (secretPoS != "")
151150
{
@@ -164,7 +163,7 @@ void readFiles()
164163
secretATM = getValue(lnurlATM, ',', 1);
165164
currencyATM = getValue(lnurlATM, ',', 2);
166165
Serial.println("");
167-
Serial.println("lnurlATM: " + lnurlATM);
166+
Serial.println("lnurlATM: " + baseURLATM);
168167
if (secretATM != "")
169168
{
170169
menuItemCheck[3] = 1;

lnpos/lnpos.ino

+64-78
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ fs::SPIFFSFS &FlashFS = SPIFFS;
99
#include <stdio.h>
1010
#include "qrcoded.h"
1111
#include <WiFiClientSecure.h>
12+
#include "mbedtls/aes.h"
1213

1314
// ArduinoJson, Keypad and uBitcoin should be installed using the Arduino Library Manager.
1415
// The latest versions should work, verified with ArduinoJson 7.2.1, Keypad 3.1.1 and uBitcoin 0.2.0
@@ -23,7 +24,6 @@ fs::SPIFFSFS &FlashFS = SPIFFS;
2324
#define USB_POWER 1000 // battery percentage sentinel value to indicate USB power
2425

2526
//////////SET TO TRUE TO WIPE MEMORY//////////////
26-
2727
bool format = false;
2828

2929
////////////////////////////////////////////////////////
@@ -80,7 +80,7 @@ const char currencyItems[3][5] = {"sat", "USD", "EUR"};
8080
char decimalplacesOutput[20];
8181
int menuItemCheck[5] = {0, 0, 0, 0, 1};
8282
int menuItemNo = 0;
83-
int randomPin;
83+
String randomPin;
8484
int calNum = 1;
8585
int sumFlag = 0;
8686
int converted = 0;
@@ -931,9 +931,9 @@ void qrShowCodeln()
931931
qrData.toUpperCase();
932932
const char *qrDataChar = qrData.c_str();
933933
QRCode qrcoded;
934-
uint8_t qrcodeData[qrcode_getBufferSize(20)];
934+
uint8_t qrcodeData[qrcode_getBufferSize(32)];
935935

936-
qrcode_initText(&qrcoded, qrcodeData, 11, 0, qrDataChar);
936+
qrcode_initText(&qrcoded, qrcodeData, 32, 0, qrDataChar);
937937

938938
for (uint8_t y = 0; y < qrcoded.size; y++)
939939
{
@@ -1011,20 +1011,24 @@ void qrShowCodeLNURL(String message)
10111011
qrData.toUpperCase();
10121012
const char *qrDataChar = qrData.c_str();
10131013
QRCode qrcoded;
1014-
uint8_t qrcodeData[qrcode_getBufferSize(20)];
1015-
qrcode_initText(&qrcoded, qrcodeData, 6, 0, qrDataChar);
1014+
uint8_t qrcodeData[qrcode_getBufferSize(11)];
1015+
qrcode_initText(&qrcoded, qrcodeData, 11, 0, qrDataChar);
1016+
1017+
unsigned int pixSize = 2;
1018+
unsigned int offsetTop = 3;
1019+
unsigned int offsetLeft = 65;
10161020

10171021
for (uint8_t y = 0; y < qrcoded.size; y++)
10181022
{
10191023
for (uint8_t x = 0; x < qrcoded.size; x++)
10201024
{
10211025
if (qrcode_getModule(&qrcoded, x, y))
10221026
{
1023-
tft.fillRect(65 + 3 * x, 5 + 3 * y, 3, 3, TFT_BLACK);
1027+
tft.fillRect(offsetLeft + pixSize * x, offsetTop + pixSize * y, pixSize, pixSize, TFT_BLACK);
10241028
}
10251029
else
10261030
{
1027-
tft.fillRect(65 + 3 * x, 5 + 3 * y, 3, 3, qrScreenBgColour);
1031+
tft.fillRect(offsetLeft + pixSize * x, offsetTop + pixSize * y, pixSize, pixSize, qrScreenBgColour);
10281032
}
10291033
}
10301034
}
@@ -1579,43 +1583,68 @@ void to_upper(char *arr)
15791583

15801584
bool makeLNURL()
15811585
{
1582-
if (amountToShow.toFloat() == 0)
1586+
if (amountToShow.toFloat() <= 0)
15831587
{
1584-
error("ZERO VALUE");
1588+
error("ZERO AMOUNT");
15851589
delay(3000);
15861590
return false;
15871591
}
15881592

1589-
randomPin = random(1000, 9999);
1590-
byte nonce[8];
1591-
for (int i = 0; i < 8; i++)
1592-
{
1593-
nonce[i] = random(256);
1594-
}
1595-
15961593
int multipler = pow(10, 2);
1597-
15981594
if (currencyPoS == "sat")
15991595
{
16001596
multipler = 1;
16011597
}
16021598

16031599
float total = amountToShow.toFloat() * multipler;
16041600

1605-
byte payload[51]; // 51 bytes is max one can get with xor-encryption
1601+
//const char* key = "Yq3t6w9z$C&F)J@M";
1602+
1603+
unsigned char iv_init[16];
1604+
unsigned char iv[16];
1605+
1606+
for (int i = 0; i < 16; i++) {
1607+
iv[i] = random(0, 255);
1608+
iv_init[i] = iv[i];
1609+
}
1610+
16061611
if (selection == "Offline PoS")
16071612
{
1608-
size_t payload_len = xor_encrypt(payload, sizeof(payload), (uint8_t *)secretPoS.c_str(), secretPoS.length(), nonce, sizeof(nonce), randomPin, total);
1609-
preparedURL = baseURLPoS + "?p=";
1610-
preparedURL += toBase64(payload, payload_len, BASE64_URLSAFE | BASE64_NOPADDING);
1613+
randomPin = String(random(1000, 9999));
1614+
preparedURL = baseURLATM;
16111615
}
16121616
else // ATM
16131617
{
1614-
size_t payload_len = xor_encrypt(payload, sizeof(payload), (uint8_t *)secretATM.c_str(), secretATM.length(), nonce, sizeof(nonce), randomPin, total);
1615-
preparedURL = baseURLATM + "?atm=1&p=";
1616-
preparedURL += toBase64(payload, payload_len, BASE64_URLSAFE | BASE64_NOPADDING);
1618+
randomPin = String("FFFF");
1619+
preparedURL = baseURLATM + "/atm/";
1620+
}
1621+
preparedURL += "?p=";
1622+
1623+
String payload = randomPin + String(":") + String(total);
1624+
Serial.print("payload: ");
1625+
Serial.println(payload);
1626+
size_t payload_len = payload.length();
1627+
int padding = 16 - (payload_len % 16);
1628+
unsigned char encrypted[payload_len + padding] = {0};
1629+
String s = "";
1630+
encrypt(secretATM.c_str(), iv, payload_len + padding, payload.c_str(), encrypted);
1631+
for (int i = 0; i < sizeof(encrypted); i++) {
1632+
s = String(encrypted[i], HEX);
1633+
if (s.length() == 1) {
1634+
s = "0" + s;
1635+
}
1636+
preparedURL += s;
1637+
}
1638+
// append iv to the url
1639+
preparedURL += "&iv=";
1640+
for (int i = 0; i < sizeof(iv_init); i++) {
1641+
s = String(iv_init[i], HEX);
1642+
if (s.length() == 1) {
1643+
s = "0" + s;
1644+
}
1645+
preparedURL += s;
16171646
}
1618-
1647+
Serial.println();
16191648
Serial.println(preparedURL);
16201649
char Buf[200];
16211650
preparedURL.toCharArray(Buf, 200);
@@ -1632,58 +1661,6 @@ bool makeLNURL()
16321661
return true;
16331662
}
16341663

1635-
int xor_encrypt(uint8_t *output, size_t outlen, uint8_t *key, size_t keylen, uint8_t *nonce, size_t nonce_len, uint64_t pin, uint64_t amount_in_cents)
1636-
{
1637-
// check we have space for all the data:
1638-
// <variant_byte><len|nonce><len|payload:{pin}{amount}><hmac>
1639-
if (outlen < 2 + nonce_len + 1 + lenVarInt(pin) + 1 + lenVarInt(amount_in_cents) + 8)
1640-
{
1641-
return 0;
1642-
}
1643-
1644-
int cur = 0;
1645-
output[cur] = 1; // variant: XOR encryption
1646-
cur++;
1647-
1648-
// nonce_len | nonce
1649-
output[cur] = nonce_len;
1650-
cur++;
1651-
memcpy(output + cur, nonce, nonce_len);
1652-
cur += nonce_len;
1653-
1654-
// payload, unxored first - <pin><currency byte><amount>
1655-
int payload_len = lenVarInt(pin) + 1 + lenVarInt(amount_in_cents);
1656-
output[cur] = (uint8_t)payload_len;
1657-
cur++;
1658-
uint8_t *payload = output + cur; // pointer to the start of the payload
1659-
cur += writeVarInt(pin, output + cur, outlen - cur); // pin code
1660-
cur += writeVarInt(amount_in_cents, output + cur, outlen - cur); // amount
1661-
cur++;
1662-
1663-
// xor it with round key
1664-
uint8_t hmacresult[32];
1665-
SHA256 h;
1666-
h.beginHMAC(key, keylen);
1667-
h.write((uint8_t *)"Round secret:", 13);
1668-
h.write(nonce, nonce_len);
1669-
h.endHMAC(hmacresult);
1670-
for (int i = 0; i < payload_len; i++)
1671-
{
1672-
payload[i] = payload[i] ^ hmacresult[i];
1673-
}
1674-
1675-
// add hmac to authenticate
1676-
h.beginHMAC(key, keylen);
1677-
h.write((uint8_t *)"Data:", 5);
1678-
h.write(output, cur);
1679-
h.endHMAC(hmacresult);
1680-
memcpy(output + cur, hmacresult, 8);
1681-
cur += 8;
1682-
1683-
// return number of bytes written to the output
1684-
return cur;
1685-
}
1686-
16871664
unsigned int getBatteryPercentage()
16881665
{
16891666
const float batteryMaxVoltage = 4.2;
@@ -1900,3 +1877,12 @@ void printSleepAnimationFrame(String text, int wait)
19001877
tft.println(text);
19011878
delay(wait);
19021879
}
1880+
1881+
//////////ENCRYPTION///////////////
1882+
void encrypt(const char* key, unsigned char* iv, int length, const char* plainText, unsigned char* outputBuffer){
1883+
mbedtls_aes_context aes;
1884+
mbedtls_aes_init(&aes);
1885+
mbedtls_aes_setkey_enc(&aes, (const unsigned char*)key, strlen(key)*8);
1886+
mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_ENCRYPT, length, iv, (const unsigned char*)plainText, outputBuffer);
1887+
mbedtls_aes_free(&aes);
1888+
}

0 commit comments

Comments
 (0)