use SDK provided encoder, rather than pulling in library
This commit is contained in:
parent
a4220d631d
commit
e63a8c4b75
@ -14,7 +14,7 @@ void ArduinoJsonJWT::setSecret(String secret){
|
||||
* No need to pull in additional crypto libraries - lets use what we already have.
|
||||
*/
|
||||
String ArduinoJsonJWT::sign(String &payload) {
|
||||
unsigned char hmacResult[32];
|
||||
unsigned char hmacResult[33];
|
||||
{
|
||||
#if defined(ESP_PLATFORM)
|
||||
mbedtls_md_context_t ctx;
|
||||
@ -34,43 +34,15 @@ String ArduinoJsonJWT::sign(String &payload) {
|
||||
br_hmac_out(&hmacCtx, hmacResult);
|
||||
#endif
|
||||
}
|
||||
return encode(hmacResult, 32);
|
||||
}
|
||||
|
||||
String ArduinoJsonJWT::decode(unsigned char * value) {
|
||||
// create buffer of approperate length
|
||||
size_t decodedLength = decode_base64_length(value) + 1;
|
||||
char decoded[decodedLength];
|
||||
|
||||
// decode
|
||||
decode_base64(value, (unsigned char *) decoded);
|
||||
decoded[decodedLength-1] = 0;
|
||||
|
||||
// return as arduino string
|
||||
return String(decoded);
|
||||
}
|
||||
|
||||
String ArduinoJsonJWT::encode(unsigned char * value , int length) {
|
||||
int encodedIndex = encode_base64_length(length);
|
||||
|
||||
// encode
|
||||
char encoded[encodedIndex];
|
||||
encode_base64(value, length, (unsigned char *) encoded);
|
||||
|
||||
// trim padding
|
||||
while (encoded[--encodedIndex] == '=') {
|
||||
encoded[encodedIndex] = 0;
|
||||
}
|
||||
|
||||
// return as string
|
||||
return String(encoded);
|
||||
hmacResult[32] = 0;
|
||||
return encode(String((char *) hmacResult));
|
||||
}
|
||||
|
||||
String ArduinoJsonJWT::buildJWT(JsonObject &payload) {
|
||||
// serialize, then encode payload
|
||||
String jwt;
|
||||
serializeJson(payload, jwt);
|
||||
jwt = encode((unsigned char *) jwt.c_str(), jwt.length());
|
||||
jwt = encode(jwt);
|
||||
|
||||
// add the header to payload
|
||||
jwt = JWT_HEADER + '.' + jwt;
|
||||
@ -108,7 +80,7 @@ void ArduinoJsonJWT::parseJWT(String jwt, JsonDocument &jsonDocument) {
|
||||
|
||||
// decode payload
|
||||
jwt = jwt.substring(JWT_HEADER_SIZE + 1);
|
||||
jwt = decode((unsigned char *) jwt.c_str());
|
||||
jwt = decode(jwt);
|
||||
|
||||
// parse payload, clearing json document after failure
|
||||
DeserializationError error = deserializeJson(jsonDocument, jwt);
|
||||
@ -116,3 +88,52 @@ void ArduinoJsonJWT::parseJWT(String jwt, JsonDocument &jsonDocument) {
|
||||
jsonDocument.clear();
|
||||
}
|
||||
}
|
||||
|
||||
String ArduinoJsonJWT::encode(String value) {
|
||||
// prepare encoder
|
||||
base64_encodestate _state;
|
||||
#if defined(ESP8266)
|
||||
base64_init_encodestate_nonewlines(&_state);
|
||||
size_t encodedLength = base64_encode_expected_len_nonewlines(value.length()) + 1;
|
||||
#elif defined(ESP_PLATFORM)
|
||||
base64_init_encodestate(&_state);
|
||||
size_t encodedLength = base64_encode_expected_len(value.length()) + 1;
|
||||
#endif
|
||||
|
||||
// prepare buffer of correct length
|
||||
char buffer[encodedLength];
|
||||
|
||||
// encode to buffer
|
||||
int len = base64_encode_block(value.c_str(), value.length(), &buffer[0], &_state);
|
||||
len += base64_encode_blockend(&buffer[len], &_state);
|
||||
buffer[len] = 0;
|
||||
|
||||
// convert to arduino string
|
||||
value = String(buffer);
|
||||
|
||||
// remove padding and convert to URL safe form
|
||||
while (value.charAt(value.length() - 1) == '='){
|
||||
value.remove(value.length() - 1);
|
||||
}
|
||||
value.replace('+', '-');
|
||||
value.replace('/', '_');
|
||||
|
||||
// return as string
|
||||
return value;
|
||||
}
|
||||
|
||||
String ArduinoJsonJWT::decode(String value) {
|
||||
// convert to standard base64
|
||||
value.replace('-', '+');
|
||||
value.replace( '_', '/');
|
||||
|
||||
// prepare buffer of correct length
|
||||
char buffer[base64_decode_expected_len(value.length()) + 1];
|
||||
|
||||
// decode
|
||||
int len = base64_decode_chars(value.c_str(), value.length(), &buffer[0]);
|
||||
buffer[len] = 0;
|
||||
|
||||
// return as string
|
||||
return String(buffer);
|
||||
}
|
||||
|
@ -1,11 +1,10 @@
|
||||
#ifndef ArduinoJsonJWT_H
|
||||
#define ArduinoJsonJWT_H
|
||||
|
||||
#include "base64.h"
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
#include <libb64/cdecode.h>
|
||||
#include <libb64/cencode.h>
|
||||
#if defined(ESP_PLATFORM)
|
||||
#include <mbedtls/md.h>
|
||||
#else
|
||||
@ -24,8 +23,9 @@ private:
|
||||
const String JWT_HEADER = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9";
|
||||
|
||||
String sign(String &value);
|
||||
String encode(unsigned char * value, int length);
|
||||
String decode(unsigned char * value);
|
||||
|
||||
static String encode(String value);
|
||||
static String decode(String value);
|
||||
|
||||
public:
|
||||
ArduinoJsonJWT(String secret);
|
||||
|
@ -104,8 +104,10 @@ void SecurityManager::testVerification(AsyncWebServerRequest *request, JsonDocum
|
||||
DynamicJsonDocument parsedJwt(MAX_JWT_SIZE);
|
||||
jwtHandler.parseJWT(accessToken, parsedJwt);
|
||||
if (parsedJwt.is<JsonObject>()){
|
||||
String username = parsedJwt["username"];
|
||||
Serial.println(username);
|
||||
// authentication successful
|
||||
AsyncWebServerResponse *response = request->beginResponse(200);
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// authentication failed
|
||||
|
124
src/base64.cpp
124
src/base64.cpp
@ -1,124 +0,0 @@
|
||||
#include "base64.h"
|
||||
|
||||
unsigned char binary_to_base64(unsigned char v) {
|
||||
// Capital letters - 'A' is ascii 65 and base64 0
|
||||
if(v < 26) return v + 'A';
|
||||
|
||||
// Lowercase letters - 'a' is ascii 97 and base64 26
|
||||
if(v < 52) return v + 71;
|
||||
|
||||
// Digits - '0' is ascii 48 and base64 52
|
||||
if(v < 62) return v - 4;
|
||||
|
||||
// '+' is ascii 43 and base64 62
|
||||
if(v == 62) return '-';
|
||||
|
||||
// '/' is ascii 47 and base64 63
|
||||
if(v == 63) return '_';
|
||||
|
||||
return 64;
|
||||
}
|
||||
|
||||
unsigned char base64_to_binary(unsigned char c) {
|
||||
// Capital letters - 'A' is ascii 65 and base64 0
|
||||
if('A' <= c && c <= 'Z') return c - 'A';
|
||||
|
||||
// Lowercase letters - 'a' is ascii 97 and base64 26
|
||||
if('a' <= c && c <= 'z') return c - 71;
|
||||
|
||||
// Digits - '0' is ascii 48 and base64 52
|
||||
if('0' <= c && c <= '9') return c + 4;
|
||||
|
||||
// '+' is ascii 43 and base64 62
|
||||
if(c == '-') return 62;
|
||||
|
||||
// '/' is ascii 47 and base64 63
|
||||
if(c == '_') return 63;
|
||||
|
||||
return 255;
|
||||
}
|
||||
|
||||
unsigned int encode_base64_length(unsigned int input_length) {
|
||||
return (input_length + 2)/3*4;
|
||||
}
|
||||
|
||||
unsigned int decode_base64_length(unsigned char input[]) {
|
||||
unsigned char *start = input;
|
||||
|
||||
while(base64_to_binary(input[0]) < 64) {
|
||||
++input;
|
||||
}
|
||||
|
||||
unsigned int input_length = input - start;
|
||||
|
||||
unsigned int output_length = input_length/4*3;
|
||||
|
||||
switch(input_length % 4) {
|
||||
default: return output_length;
|
||||
case 2: return output_length + 1;
|
||||
case 3: return output_length + 2;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int encode_base64(unsigned char input[], unsigned int input_length, unsigned char output[]) {
|
||||
unsigned int full_sets = input_length/3;
|
||||
|
||||
// While there are still full sets of 24 bits...
|
||||
for(unsigned int i = 0; i < full_sets; ++i) {
|
||||
output[0] = binary_to_base64( input[0] >> 2);
|
||||
output[1] = binary_to_base64((input[0] & 0x03) << 4 | input[1] >> 4);
|
||||
output[2] = binary_to_base64((input[1] & 0x0F) << 2 | input[2] >> 6);
|
||||
output[3] = binary_to_base64( input[2] & 0x3F);
|
||||
|
||||
input += 3;
|
||||
output += 4;
|
||||
}
|
||||
|
||||
switch(input_length % 3) {
|
||||
case 0:
|
||||
output[0] = '\0';
|
||||
break;
|
||||
case 1:
|
||||
output[0] = binary_to_base64( input[0] >> 2);
|
||||
output[1] = binary_to_base64((input[0] & 0x03) << 4);
|
||||
output[2] = '=';
|
||||
output[3] = '=';
|
||||
output[4] = '\0';
|
||||
break;
|
||||
case 2:
|
||||
output[0] = binary_to_base64( input[0] >> 2);
|
||||
output[1] = binary_to_base64((input[0] & 0x03) << 4 | input[1] >> 4);
|
||||
output[2] = binary_to_base64((input[1] & 0x0F) << 2);
|
||||
output[3] = '=';
|
||||
output[4] = '\0';
|
||||
break;
|
||||
}
|
||||
|
||||
return encode_base64_length(input_length);
|
||||
}
|
||||
|
||||
unsigned int decode_base64(unsigned char input[], unsigned char output[]) {
|
||||
unsigned int output_length = decode_base64_length(input);
|
||||
|
||||
// While there are still full sets of 24 bits...
|
||||
for(unsigned int i = 2; i < output_length; i += 3) {
|
||||
output[0] = base64_to_binary(input[0]) << 2 | base64_to_binary(input[1]) >> 4;
|
||||
output[1] = base64_to_binary(input[1]) << 4 | base64_to_binary(input[2]) >> 2;
|
||||
output[2] = base64_to_binary(input[2]) << 6 | base64_to_binary(input[3]);
|
||||
|
||||
input += 4;
|
||||
output += 3;
|
||||
}
|
||||
|
||||
switch(output_length % 3) {
|
||||
case 1:
|
||||
output[0] = base64_to_binary(input[0]) << 2 | base64_to_binary(input[1]) >> 4;
|
||||
break;
|
||||
case 2:
|
||||
output[0] = base64_to_binary(input[0]) << 2 | base64_to_binary(input[1]) >> 4;
|
||||
output[1] = base64_to_binary(input[1]) << 4 | base64_to_binary(input[2]) >> 2;
|
||||
break;
|
||||
}
|
||||
|
||||
return output_length;
|
||||
}
|
77
src/base64.h
77
src/base64.h
@ -1,77 +0,0 @@
|
||||
/**
|
||||
* Adapted from https://github.com/Densaugeo/base64_arduino
|
||||
*/
|
||||
|
||||
/**
|
||||
* Base64 encoding and decoding of strings. Uses '+' for 62, '\' for 63, '=' for padding
|
||||
* This has been modified to use '-' for 62, '_' for 63 as per the JWT specification
|
||||
*/
|
||||
|
||||
#ifndef BASE64_H_INCLUDED
|
||||
#define BASE64_H_INCLUDED
|
||||
|
||||
/* binary_to_base64:
|
||||
* Description:
|
||||
* Converts a single byte from a binary value to the corresponding base64 character
|
||||
* Parameters:
|
||||
* v - Byte to convert
|
||||
* Returns:
|
||||
* ascii code of base64 character. If byte is >= 64, then there is not corresponding base64 character
|
||||
* and 255 is returned
|
||||
*/
|
||||
unsigned char binary_to_base64(unsigned char v);
|
||||
|
||||
/* base64_to_binary:
|
||||
* Description:
|
||||
* Converts a single byte from a base64 character to the corresponding binary value
|
||||
* Parameters:
|
||||
* c - Base64 character (as ascii code)
|
||||
* Returns:
|
||||
* 6-bit binary value
|
||||
*/
|
||||
unsigned char base64_to_binary(unsigned char v);
|
||||
|
||||
/* encode_base64_length:
|
||||
* Description:
|
||||
* Calculates length of base64 string needed for a given number of binary bytes
|
||||
* Parameters:
|
||||
* input_length - Amount of binary data in bytes
|
||||
* Returns:
|
||||
* Number of base64 characters needed to encode input_length bytes of binary data
|
||||
*/
|
||||
unsigned int encode_base64_length(unsigned int input_length);
|
||||
|
||||
/* decode_base64_length:
|
||||
* Description:
|
||||
* Calculates number of bytes of binary data in a base64 string
|
||||
* Parameters:
|
||||
* input - Base64-encoded null-terminated string
|
||||
* Returns:
|
||||
* Number of bytes of binary data in input
|
||||
*/
|
||||
unsigned int decode_base64_length(unsigned char input[]);
|
||||
|
||||
/* encode_base64:
|
||||
* Description:
|
||||
* Converts an array of bytes to a base64 null-terminated string
|
||||
* Parameters:
|
||||
* input - Pointer to input data
|
||||
* input_length - Number of bytes to read from input pointer
|
||||
* output - Pointer to output string. Null terminator will be added automatically
|
||||
* Returns:
|
||||
* Length of encoded string in bytes (not including null terminator)
|
||||
*/
|
||||
unsigned int encode_base64(unsigned char input[], unsigned int input_length, unsigned char output[]);
|
||||
|
||||
/* decode_base64:
|
||||
* Description:
|
||||
* Converts a base64 null-terminated string to an array of bytes
|
||||
* Parameters:
|
||||
* input - Pointer to input string
|
||||
* output - Pointer to output array
|
||||
* Returns:
|
||||
* Number of bytes in the decoded binary
|
||||
*/
|
||||
unsigned int decode_base64(unsigned char input[], unsigned char output[]);
|
||||
|
||||
#endif // ifndef
|
Loading…
Reference in New Issue
Block a user