-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
RFC 4648 (https://tools.ietf.org/html/rfc4648) standardizes two
Base-64 alphabets. Nettle currently only supports the traditional
base-64 alphabet from section 4.
There is growing use amongst new protocol definitions and extensions,
particularly in the HTTP area for the URL-safe extension alphabet
instead of the classical Base-64 alphabet.
The attached patch implements a proposed API/ABI extension adding
support for RFC 4648 section 5 "Base 64 Encoding with URL and Filename
Safe Alphabet"
External code simply calls the init() function relevant to the
alphabet it is needing to encode/decode with. The library internally
uses the context to select which lookup table to use for later base64
function calls.
The base64_encode_raw() and base64_encode_group() functions which do
not use contexts are left untouched for now.
Amos Jeffries
Treehouse Networks Ltd.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.22 (MingW32)
iQEcBAEBAgAGBQJUiXerAAoJELJo5wb/XPRjPxEIAJGMXNF0H84kJntKpe1idimr
+x7/xg55GJ2sWEBAbVIHvKvjFZoBIeqNmPeeK+yrqMdA+dtALA37AuezqhiNBtuj
YfGd/DyRvys2O2bQ4XNRHxj6zGQU6tlRHHZzSnWp9ywwN4xk/zfNc5JM0EKYqiuu
8crNPzQxP91N33gkdi9LrOkAA8v+/bTYJgTrT46D/2Ut+8ECAcpjS5jwsJiljETu
uqO50QlhqGC3ZsHKs1kYnjrbl1Peiqw/b/srEnY3shfS9MKrTYe3qLOsvU5CQpnD
A7e8w/SW716D0s4t0SGf85WvUnS6UvDTfAdm3EXAPKNU8PaYpK9D8izq8kgxCP4=
=NgGG
-----END PGP SIGNATURE-----
diff --git a/base64-decode.c b/base64-decode.c
index f622baa..fbaf54f 100644
--- a/base64-decode.c
+++ b/base64-decode.c
@@ -43,7 +43,7 @@
#define TABLE_END -3
static const signed char
-decode_table[0x100] =
+default_decode_table[0x100] =
{
/* White space is HT, VT, FF, CR, LF and SPC */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -2, -2, -2, -2, -1, -1,
@@ -64,10 +64,40 @@ decode_table[0x100] =
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
};
+static const signed char
+urlextended_decode_table[0x100] =
+{
+ /* White space is HT, VT, FF, CR, LF and SPC */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -2, -2, -2, -2, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -3, -1, -1,
+ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63,
+ -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+};
+
void
base64_decode_init(struct base64_decode_ctx *ctx)
{
ctx->word = ctx->bits = ctx->padding = 0;
+ ctx->alphabet = BASE64_ALPHABET;
+}
+
+void
+base64url_decode_init(struct base64_decode_ctx *ctx)
+{
+ ctx->word = ctx->bits = ctx->padding = 0;
+ ctx->alphabet = BASE64URL_ALPHABET;
}
int
@@ -76,8 +106,11 @@ base64_decode_single(struct base64_decode_ctx *ctx,
uint8_t src)
{
int data;
-
- data = decode_table[src];
+
+ if (ctx->alphabet == BASE64URL_ALPHABET)
+ data = urlextended_decode_table[src];
+ else
+ data = default_decode_table[src];
switch(data)
{
diff --git a/base64-encode.c b/base64-encode.c
index 313c512..fcf8546 100644
--- a/base64-encode.c
+++ b/base64-encode.c
@@ -38,11 +38,16 @@
#include "base64.h"
-static const uint8_t encode_table[64] =
+static const uint8_t default_encode_table[64] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
+static const uint8_t urlextended_encode_table[64] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789-_";
+
#define ENCODE(x) (encode_table[0x3F & (x)])
void
@@ -52,6 +57,7 @@ base64_encode_raw(uint8_t *dst, size_t length, const uint8_t
*src)
uint8_t *out = dst + BASE64_ENCODE_RAW_LENGTH(length);
unsigned left_over = length % 3;
+ const uint8_t *encode_table = default_encode_table;
if (left_over)
{
@@ -97,6 +103,7 @@ base64_encode(uint8_t *dst,
unsigned n = src_length / 3;
unsigned left_over = src_length % 3;
unsigned done = 0;
+ const uint8_t *encode_table = default_encode_table;
if (left_over)
{
@@ -134,6 +141,7 @@ base64_encode(uint8_t *dst,
void
base64_encode_group(uint8_t *dst, uint32_t group)
{
+ const uint8_t *encode_table = default_encode_table;
*dst++ = ENCODE(group >> 18);
*dst++ = ENCODE(group >> 12);
*dst++ = ENCODE(group >> 6);
@@ -144,6 +152,14 @@ void
base64_encode_init(struct base64_encode_ctx *ctx)
{
ctx->word = ctx->bits = 0;
+ ctx->alphabet = BASE64_ALPHABET;
+}
+
+void
+base64url_encode_init(struct base64_encode_ctx *ctx)
+{
+ ctx->word = ctx->bits = 0;
+ ctx->alphabet = BASE64URL_ALPHABET;
}
/* Encodes a single byte. */
@@ -155,6 +171,7 @@ base64_encode_single(struct base64_encode_ctx *ctx,
unsigned done = 0;
unsigned word = ctx->word << 8 | src;
unsigned bits = ctx->bits + 8;
+ const uint8_t *encode_table = (ctx->alphabet == BASE64URL_ALPHABET ?
urlextended_encode_table : default_encode_table);
while (bits >= 6)
{
@@ -182,6 +199,7 @@ base64_encode_update(struct base64_encode_ctx *ctx,
size_t left = length;
unsigned left_over;
size_t bulk;
+ const uint8_t *encode_table = (ctx->alphabet == BASE64URL_ALPHABET ?
urlextended_encode_table : default_encode_table);
while (ctx->bits && left)
{
@@ -221,6 +239,7 @@ base64_encode_final(struct base64_encode_ctx *ctx,
{
unsigned done = 0;
unsigned bits = ctx->bits;
+ const uint8_t *encode_table = (ctx->alphabet == BASE64URL_ALPHABET ?
urlextended_encode_table : default_encode_table);
if (bits)
{
diff --git a/base64.h b/base64.h
index a6fb823..4f6d5e3 100644
--- a/base64.h
+++ b/base64.h
@@ -42,12 +42,14 @@ extern "C" {
/* Name mangling */
#define base64_encode_init nettle_base64_encode_init
+#define base64url_encode_init nettle_base64url_encode_init
#define base64_encode_single nettle_base64_encode_single
#define base64_encode_update nettle_base64_encode_update
#define base64_encode_final nettle_base64_encode_final
#define base64_encode_raw nettle_base64_encode_raw
#define base64_encode_group nettle_base64_encode_group
#define base64_decode_init nettle_base64_decode_init
+#define base64url_decode_init nettle_base64url_decode_init
#define base64_decode_single nettle_base64_decode_single
#define base64_decode_update nettle_base64_decode_update
#define base64_decode_final nettle_base64_decode_final
@@ -55,6 +57,10 @@ extern "C" {
#define BASE64_BINARY_BLOCK_SIZE 3
#define BASE64_TEXT_BLOCK_SIZE 4
+/* which alphabet to use */
+#define BASE64_ALPHABET 0
+#define BASE64URL_ALPHABET 1
+
/* Base64 encoding */
/* Maximum length of output for base64_encode_update. NOTE: Doesn't
@@ -73,11 +79,17 @@ struct base64_encode_ctx
{
unsigned word; /* Leftover bits */
unsigned bits; /* Number of bits, always 0, 2, or 4. */
+ unsigned alphabet; /* which alphabet to use for encoding */
};
+/* initialize encoding context for base-64 */
void
base64_encode_init(struct base64_encode_ctx *ctx);
+/* initialize encoding context for base-64 with URL safe extended alphabet */
+void
+base64url_encode_init(struct base64_encode_ctx *ctx);
+
/* Encodes a single byte. Returns amount of output (always 1 or 2). */
size_t
base64_encode_single(struct base64_encode_ctx *ctx,
@@ -123,11 +135,17 @@ struct base64_decode_ctx
/* Number of padding characters encountered */
unsigned padding;
+ unsigned alphabet; /* which alphabet to use for encoding */
};
+/* initialize encoding context for base-64 */
void
base64_decode_init(struct base64_decode_ctx *ctx);
+/* initialize encoding context for base-64 with URL safe extended alphabet */
+void
+base64url_decode_init(struct base64_decode_ctx *ctx);
+
/* Decodes a single byte. Returns amount of output (0 or 1), or -1 on
* errors. */
int
_______________________________________________
nettle-bugs mailing list
[email protected]
http://lists.lysator.liu.se/mailman/listinfo/nettle-bugs