sys/base64: Implement Base 64 Encoding with URL Safe Alphabet
RFC4648 specifies an alternate alphabet for base64 encoding / decoding where '+' and '/' are exchanged for '-' and '-' to make the resulting string safe to use in filenames and URLs. This adds a base64url_encode() function that uses the alternate alphabet. The base64_decode() function is extended to accept both alphabets.
This commit is contained in:
parent
e738508308
commit
fc89531c61
@ -42,6 +42,10 @@ ifneq (,$(filter auto_init_saul,$(USEMODULE)))
|
|||||||
USEMODULE += saul_init_devs
|
USEMODULE += saul_init_devs
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifneq (,$(filter base64url,$(USEMODULE)))
|
||||||
|
USEMODULE += base64
|
||||||
|
endif
|
||||||
|
|
||||||
ifneq (,$(filter csma_sender,$(USEMODULE)))
|
ifneq (,$(filter csma_sender,$(USEMODULE)))
|
||||||
USEMODULE += random
|
USEMODULE += random
|
||||||
USEMODULE += xtimer
|
USEMODULE += xtimer
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
PSEUDOMODULES += at_urc
|
PSEUDOMODULES += at_urc
|
||||||
PSEUDOMODULES += at24c%
|
PSEUDOMODULES += at24c%
|
||||||
|
PSEUDOMODULES += base64url
|
||||||
PSEUDOMODULES += can_mbox
|
PSEUDOMODULES += can_mbox
|
||||||
PSEUDOMODULES += can_pm
|
PSEUDOMODULES += can_pm
|
||||||
PSEUDOMODULES += can_raw
|
PSEUDOMODULES += can_raw
|
||||||
|
|||||||
@ -18,26 +18,42 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
#include "base64.h"
|
#include "base64.h"
|
||||||
|
#include "kernel_defines.h"
|
||||||
|
|
||||||
#define BASE64_CAPITAL_UPPER_BOUND (25) /**< base64 'Z' */
|
#define BASE64_CAPITAL_UPPER_BOUND (25) /**< base64 'Z' */
|
||||||
#define BASE64_SMALL_UPPER_BOUND (51) /**< base64 'z' */
|
#define BASE64_SMALL_UPPER_BOUND (51) /**< base64 'z' */
|
||||||
#define BASE64_NUMBER_UPPER_BOUND (61) /**< base64 '9' */
|
#define BASE64_NUMBER_UPPER_BOUND (61) /**< base64 '9' */
|
||||||
#define BASE64_PLUS (62) /**< base64 '+' */
|
#define BASE64_PLUS (62) /**< base64 '+' */
|
||||||
|
#define BASE64_MINUS (62) /**< base64 '-' */
|
||||||
#define BASE64_SLASH (63) /**< base64 '/' */
|
#define BASE64_SLASH (63) /**< base64 '/' */
|
||||||
|
#define BASE64_UNDERLINE (63) /**< base64 '_' */
|
||||||
#define BASE64_EQUALS (0xFE) /**< no base64 symbol '=' */
|
#define BASE64_EQUALS (0xFE) /**< no base64 symbol '=' */
|
||||||
#define BASE64_NOT_DEFINED (0xFF) /**< no base64 symbol */
|
#define BASE64_NOT_DEFINED (0xFF) /**< no base64 symbol */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* returns the corresponding ascii symbol value for the given base64 code
|
* returns the corresponding ascii symbol value for the given base64 code
|
||||||
*/
|
*/
|
||||||
static char getsymbol(unsigned char code)
|
static char getsymbol(unsigned char code, bool urlsafe)
|
||||||
{
|
{
|
||||||
if (code == BASE64_SLASH) {
|
if (!IS_ACTIVE(MODULE_BASE64URL)) {
|
||||||
|
urlsafe = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (urlsafe && code == BASE64_UNDERLINE) {
|
||||||
|
return '_';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (urlsafe && code == BASE64_MINUS) {
|
||||||
|
return '-';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!urlsafe && code == BASE64_SLASH) {
|
||||||
return '/';
|
return '/';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (code == BASE64_PLUS) {
|
if (!urlsafe && code == BASE64_PLUS) {
|
||||||
return '+';
|
return '+';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,8 +72,9 @@ static char getsymbol(unsigned char code)
|
|||||||
return (char)BASE64_NOT_DEFINED;
|
return (char)BASE64_NOT_DEFINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
int base64_encode(const void *data_in, size_t data_in_size,
|
static int base64_encode_base(const void *data_in, size_t data_in_size,
|
||||||
unsigned char *base64_out, size_t *base64_out_size)
|
unsigned char *base64_out, size_t *base64_out_size,
|
||||||
|
bool urlsafe)
|
||||||
{
|
{
|
||||||
const unsigned char *in = data_in;
|
const unsigned char *in = data_in;
|
||||||
size_t required_size = base64_estimate_encode_size(data_in_size);
|
size_t required_size = base64_estimate_encode_size(data_in_size);
|
||||||
@ -103,14 +120,14 @@ int base64_encode(const void *data_in, size_t data_in_size,
|
|||||||
nLst = tmpval & ((1 << njump * 2) - 1);
|
nLst = tmpval & ((1 << njump * 2) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
base64_out[iterate_base64_buffer++] = getsymbol(nNum);
|
base64_out[iterate_base64_buffer++] = getsymbol(nNum, urlsafe);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The last character is not finished yet */
|
/* The last character is not finished yet */
|
||||||
njump++;
|
njump++;
|
||||||
|
|
||||||
nNum = nLst << (8 - 2 * njump);
|
nNum = nLst << (8 - 2 * njump);
|
||||||
base64_out[iterate_base64_buffer++] = getsymbol(nNum);
|
base64_out[iterate_base64_buffer++] = getsymbol(nNum, urlsafe);
|
||||||
|
|
||||||
/* if required we append '=' for the required dividability */
|
/* if required we append '=' for the required dividability */
|
||||||
while (iterate_base64_buffer % 4) {
|
while (iterate_base64_buffer % 4) {
|
||||||
@ -122,6 +139,20 @@ int base64_encode(const void *data_in, size_t data_in_size,
|
|||||||
return BASE64_SUCCESS;
|
return BASE64_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int base64_encode(const void *data_in, size_t data_in_size,
|
||||||
|
unsigned char *base64_out, size_t *base64_out_size)
|
||||||
|
{
|
||||||
|
return base64_encode_base(data_in, data_in_size, base64_out, base64_out_size, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if IS_ACTIVE(MODULE_BASE64URL)
|
||||||
|
int base64url_encode(const void *data_in, size_t data_in_size,
|
||||||
|
unsigned char *base64_out, size_t *base64_out_size)
|
||||||
|
{
|
||||||
|
return base64_encode_base(data_in, data_in_size, base64_out, base64_out_size, true);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* returns the corresponding base64 code for the given ascii symbol
|
* returns the corresponding base64 code for the given ascii symbol
|
||||||
*/
|
*/
|
||||||
@ -131,10 +162,18 @@ static int getcode(char symbol)
|
|||||||
return BASE64_SLASH;
|
return BASE64_SLASH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (symbol == '_') {
|
||||||
|
return BASE64_UNDERLINE;
|
||||||
|
}
|
||||||
|
|
||||||
if (symbol == '+') {
|
if (symbol == '+') {
|
||||||
return BASE64_PLUS;
|
return BASE64_PLUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (symbol == '-') {
|
||||||
|
return BASE64_MINUS;
|
||||||
|
}
|
||||||
|
|
||||||
if (symbol == '=') {
|
if (symbol == '=') {
|
||||||
/* indicates a padded base64 end */
|
/* indicates a padded base64 end */
|
||||||
return BASE64_EQUALS;
|
return BASE64_EQUALS;
|
||||||
|
|||||||
@ -76,6 +76,32 @@ static inline size_t base64_estimate_encode_size(size_t data_in_size)
|
|||||||
int base64_encode(const void *data_in, size_t data_in_size,
|
int base64_encode(const void *data_in, size_t data_in_size,
|
||||||
unsigned char *base64_out, size_t *base64_out_size);
|
unsigned char *base64_out, size_t *base64_out_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Encodes a given datum to base64 with URL and Filename Safe Alphabet
|
||||||
|
* and save the result to the given destination.
|
||||||
|
*
|
||||||
|
* @see [RFC 4648, section 5](https://tools.ietf.org/html/rfc4648#section-5)
|
||||||
|
*
|
||||||
|
* @note Requires the use of the `base64url` module.
|
||||||
|
*
|
||||||
|
* @param[in] data_in pointer to the datum to encode
|
||||||
|
* @param[in] data_in_size the size of `data_in`
|
||||||
|
* @param[out] base64_out pointer to store the encoded base64 string
|
||||||
|
* @param[in,out] base64_out_size pointer to the variable containing the size of `base64_out.`
|
||||||
|
This value is overwritten with the estimated size used for
|
||||||
|
the encoded base64 string on BASE64_ERROR_BUFFER_OUT_SIZE.
|
||||||
|
This value is overwritten with the actual used size for the
|
||||||
|
encoded base64 string on BASE64_SUCCESS.
|
||||||
|
|
||||||
|
* @returns BASE64_SUCCESS on success,
|
||||||
|
BASE64_ERROR_BUFFER_OUT_SIZE on insufficient size for encoding to `base64_out`,
|
||||||
|
BASE64_ERROR_BUFFER_OUT if `base64_out` equals NULL
|
||||||
|
but the `base64_out_size` is sufficient,
|
||||||
|
BASE64_ERROR_DATA_IN if `data_in` equals NULL.
|
||||||
|
*/
|
||||||
|
int base64url_encode(const void *data_in, size_t data_in_size,
|
||||||
|
unsigned char *base64_out, size_t *base64_out_size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Decodes a given base64 string and save the result to the given destination.
|
* @brief Decodes a given base64 string and save the result to the given destination.
|
||||||
* @param[out] base64_in pointer to store the encoded base64 string
|
* @param[out] base64_in pointer to store the encoded base64 string
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user