From c01062beadca35d065088d397bbad1afd01c4b7e Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Thu, 7 Oct 2010 19:27:29 +0200 Subject: [PATCH] [MINOR] add encode/decode function for 30-bit integers from/to base64 These functions only require 5 chars to encode 30 bits, and don't expect any padding. They will be used to encode dates in cookies. (cherry picked from commit a7e2b5fc4612994c7b13bcb103a4a2c3ecd6438a) --- include/common/base64.h | 4 +++- src/base64.c | 49 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/include/common/base64.h b/include/common/base64.h index e668001f4..2f52ac745 100644 --- a/include/common/base64.h +++ b/include/common/base64.h @@ -2,7 +2,7 @@ * include/common/base64.h * Ascii to Base64 conversion as described in RFC1421. * - * Copyright 2006 Willy Tarreau + * Copyright 2006-2010 Willy Tarreau * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -18,6 +18,8 @@ int a2base64(char *in, int ilen, char *out, int olen); int base64dec(const char *in, size_t ilen, char *out, size_t olen); +const char *s30tob64(int in, char *out); +int b64tos30(const char *in); extern const char base64tab[]; diff --git a/src/base64.c b/src/base64.c index ea244a25f..594ab456a 100644 --- a/src/base64.c +++ b/src/base64.c @@ -1,7 +1,7 @@ /* * ASCII <-> Base64 conversion as described in RFC1421. * - * Copyright 2006-2008 Willy Tarreau + * Copyright 2006-2010 Willy Tarreau * Copyright 2009-2010 Krzysztof Piotr Oledzki * * This program is free software; you can redistribute it and/or @@ -135,3 +135,50 @@ int base64dec(const char *in, size_t ilen, char *out, size_t olen) { return convlen; } + + +/* Converts the lower 30 bits of an integer to a 5-char base64 string. The + * caller is responsible for ensuring that the output buffer can accept 6 bytes + * (5 + the trailing zero). The pointer to the string is returned. The + * conversion is performed with MSB first and in a format that can be + * decoded with b64tos30(). This format is not padded and thus is not + * compatible with usual base64 routines. + */ +const char *s30tob64(int in, char *out) +{ + int i; + for (i = 0; i < 5; i++) { + out[i] = base64tab[(in >> 24) & 0x3F]; + in <<= 6; + } + out[5] = '\0'; + return out; +} + +/* Converts a 5-char base64 string encoded by s30tob64() into a 30-bit integer. + * The caller is responsible for ensuring that the input contains at least 5 + * chars. If any unexpected character is encountered, a negative value is + * returned. Otherwise the decoded value is returned. + */ +int b64tos30(const char *in) +{ + int i, out; + signed char b; + + out = 0; + for (i = 0; i < 5; i++) { + b = (signed char)in[i] - B64CMIN; + if ((unsigned char)b > (B64CMAX - B64CMIN)) + return -1; /* input character out of range */ + + b = base64rev[b] - B64BASE - 1; + if (b < 0) /* invalid character */ + return -1; + + if (b == B64PADV) /* padding not allowed */ + return -1; + + out = (out << 6) + b; + } + return out; +}