mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
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
|
||||
endif
|
||||
|
||||
ifneq (,$(filter base64url,$(USEMODULE)))
|
||||
USEMODULE += base64
|
||||
endif
|
||||
|
||||
ifneq (,$(filter csma_sender,$(USEMODULE)))
|
||||
USEMODULE += random
|
||||
USEMODULE += xtimer
|
||||
|
@ -1,5 +1,6 @@
|
||||
PSEUDOMODULES += at_urc
|
||||
PSEUDOMODULES += at24c%
|
||||
PSEUDOMODULES += base64url
|
||||
PSEUDOMODULES += can_mbox
|
||||
PSEUDOMODULES += can_pm
|
||||
PSEUDOMODULES += can_raw
|
||||
|
@ -18,26 +18,42 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "base64.h"
|
||||
#include "kernel_defines.h"
|
||||
|
||||
#define BASE64_CAPITAL_UPPER_BOUND (25) /**< base64 'Z' */
|
||||
#define BASE64_SMALL_UPPER_BOUND (51) /**< base64 'z' */
|
||||
#define BASE64_NUMBER_UPPER_BOUND (61) /**< base64 '9' */
|
||||
#define BASE64_PLUS (62) /**< base64 '+' */
|
||||
#define BASE64_MINUS (62) /**< base64 '-' */
|
||||
#define BASE64_SLASH (63) /**< base64 '/' */
|
||||
#define BASE64_UNDERLINE (63) /**< base64 '_' */
|
||||
#define BASE64_EQUALS (0xFE) /**< no base64 symbol '=' */
|
||||
#define BASE64_NOT_DEFINED (0xFF) /**< no base64 symbol */
|
||||
|
||||
/*
|
||||
* 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 '/';
|
||||
}
|
||||
|
||||
if (code == BASE64_PLUS) {
|
||||
if (!urlsafe && code == BASE64_PLUS) {
|
||||
return '+';
|
||||
}
|
||||
|
||||
@ -56,8 +72,9 @@ static char getsymbol(unsigned char code)
|
||||
return (char)BASE64_NOT_DEFINED;
|
||||
}
|
||||
|
||||
int base64_encode(const void *data_in, size_t data_in_size,
|
||||
unsigned char *base64_out, size_t *base64_out_size)
|
||||
static int base64_encode_base(const void *data_in, size_t data_in_size,
|
||||
unsigned char *base64_out, size_t *base64_out_size,
|
||||
bool urlsafe)
|
||||
{
|
||||
const unsigned char *in = data_in;
|
||||
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);
|
||||
}
|
||||
|
||||
base64_out[iterate_base64_buffer++] = getsymbol(nNum);
|
||||
base64_out[iterate_base64_buffer++] = getsymbol(nNum, urlsafe);
|
||||
}
|
||||
|
||||
/* The last character is not finished yet */
|
||||
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 */
|
||||
while (iterate_base64_buffer % 4) {
|
||||
@ -122,6 +139,20 @@ int base64_encode(const void *data_in, size_t data_in_size,
|
||||
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
|
||||
*/
|
||||
@ -131,10 +162,18 @@ static int getcode(char symbol)
|
||||
return BASE64_SLASH;
|
||||
}
|
||||
|
||||
if (symbol == '_') {
|
||||
return BASE64_UNDERLINE;
|
||||
}
|
||||
|
||||
if (symbol == '+') {
|
||||
return BASE64_PLUS;
|
||||
}
|
||||
|
||||
if (symbol == '-') {
|
||||
return BASE64_MINUS;
|
||||
}
|
||||
|
||||
if (symbol == '=') {
|
||||
/* indicates a padded base64 end */
|
||||
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,
|
||||
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.
|
||||
* @param[out] base64_in pointer to store the encoded base64 string
|
||||
|
Loading…
Reference in New Issue
Block a user