mirror of
https://github.com/postgres/postgres.git
synced 2025-12-19 17:02:53 +03:00
Add support for base64url encoding and decoding
This adds support for base64url encoding and decoding, a base64 variant which is safe to use in filenames and URLs. base64url replaces '+' in the base64 alphabet with '-' and '/' with '_', thus making it safe for URL addresses and file systems. Support for base64url was originally suggested by Przemysław Sztoch. Author: Florents Tselai <florents.tselai@gmail.com> Reviewed-by: Aleksander Alekseev <aleksander@timescale.com> Reviewed-by: David E. Wheeler <david@justatheory.com> Reviewed-by: Masahiko Sawada <sawada.mshk@gmail.com> Reviewed-by: Daniel Gustafsson <daniel@yesql.se> Reviewed-by: Chao Li (Evan) <li.evan.chao@gmail.com> Discussion: https://postgr.es/m/70f2b6a8-486a-4fdb-a951-84cef35e22ab@sztoch.pl
This commit is contained in:
@@ -2517,6 +2517,156 @@ SELECT decode(encode('\x1234567890abcdef00', 'escape'), 'escape');
|
||||
\x1234567890abcdef00
|
||||
(1 row)
|
||||
|
||||
--
|
||||
-- base64url encoding/decoding
|
||||
--
|
||||
SET bytea_output TO hex;
|
||||
-- Simple encoding/decoding
|
||||
SELECT encode('\x69b73eff', 'base64url'); -- abc-_w
|
||||
encode
|
||||
--------
|
||||
abc-_w
|
||||
(1 row)
|
||||
|
||||
SELECT decode('abc-_w', 'base64url'); -- \x69b73eff
|
||||
decode
|
||||
------------
|
||||
\x69b73eff
|
||||
(1 row)
|
||||
|
||||
-- Round-trip: decode(encode(x)) = x
|
||||
SELECT decode(encode('\x1234567890abcdef00', 'base64url'), 'base64url'); -- \x1234567890abcdef00
|
||||
decode
|
||||
----------------------
|
||||
\x1234567890abcdef00
|
||||
(1 row)
|
||||
|
||||
-- Empty input
|
||||
SELECT encode('', 'base64url'); -- ''
|
||||
encode
|
||||
--------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT decode('', 'base64url'); -- ''
|
||||
decode
|
||||
--------
|
||||
\x
|
||||
(1 row)
|
||||
|
||||
-- 1 byte input
|
||||
SELECT encode('\x01', 'base64url'); -- AQ
|
||||
encode
|
||||
--------
|
||||
AQ
|
||||
(1 row)
|
||||
|
||||
SELECT decode('AQ', 'base64url'); -- \x01
|
||||
decode
|
||||
--------
|
||||
\x01
|
||||
(1 row)
|
||||
|
||||
-- 2 byte input
|
||||
SELECT encode('\x0102'::bytea, 'base64url'); -- AQI
|
||||
encode
|
||||
--------
|
||||
AQI
|
||||
(1 row)
|
||||
|
||||
SELECT decode('AQI', 'base64url'); -- \x0102
|
||||
decode
|
||||
--------
|
||||
\x0102
|
||||
(1 row)
|
||||
|
||||
-- 3 byte input (no padding needed)
|
||||
SELECT encode('\x010203'::bytea, 'base64url'); -- AQID
|
||||
encode
|
||||
--------
|
||||
AQID
|
||||
(1 row)
|
||||
|
||||
SELECT decode('AQID', 'base64url'); -- \x010203
|
||||
decode
|
||||
----------
|
||||
\x010203
|
||||
(1 row)
|
||||
|
||||
-- 4 byte input (results in 6 base64 chars)
|
||||
SELECT encode('\xdeadbeef'::bytea, 'base64url'); -- 3q2-7w
|
||||
encode
|
||||
--------
|
||||
3q2-7w
|
||||
(1 row)
|
||||
|
||||
SELECT decode('3q2-7w', 'base64url'); -- \xdeadbeef
|
||||
decode
|
||||
------------
|
||||
\xdeadbeef
|
||||
(1 row)
|
||||
|
||||
-- Round-trip test for all lengths from 0–4
|
||||
SELECT encode(decode(encode(E'\\x', 'base64url'), 'base64url'), 'base64url');
|
||||
encode
|
||||
--------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT encode(decode(encode(E'\\x00', 'base64url'), 'base64url'), 'base64url');
|
||||
encode
|
||||
--------
|
||||
AA
|
||||
(1 row)
|
||||
|
||||
SELECT encode(decode(encode(E'\\x0001', 'base64url'), 'base64url'), 'base64url');
|
||||
encode
|
||||
--------
|
||||
AAE
|
||||
(1 row)
|
||||
|
||||
SELECT encode(decode(encode(E'\\x000102', 'base64url'), 'base64url'), 'base64url');
|
||||
encode
|
||||
--------
|
||||
AAEC
|
||||
(1 row)
|
||||
|
||||
SELECT encode(decode(encode(E'\\x00010203', 'base64url'), 'base64url'), 'base64url');
|
||||
encode
|
||||
--------
|
||||
AAECAw
|
||||
(1 row)
|
||||
|
||||
-- Invalid inputs (should ERROR)
|
||||
-- invalid character '@'
|
||||
SELECT decode('QQ@=', 'base64url');
|
||||
ERROR: invalid symbol "@" found while decoding base64url sequence
|
||||
-- missing characters (incomplete group)
|
||||
SELECT decode('QQ', 'base64url'); -- ok (1 byte)
|
||||
decode
|
||||
--------
|
||||
\x41
|
||||
(1 row)
|
||||
|
||||
SELECT decode('QQI', 'base64url'); -- ok (2 bytes)
|
||||
decode
|
||||
--------
|
||||
\x4102
|
||||
(1 row)
|
||||
|
||||
SELECT decode('QQIDQ', 'base64url'); -- ERROR: invalid base64url end sequence
|
||||
ERROR: invalid base64url end sequence
|
||||
HINT: Input data is missing padding, is truncated, or is otherwise corrupted.
|
||||
-- unexpected '=' at start
|
||||
SELECT decode('=QQQ', 'base64url');
|
||||
ERROR: unexpected "=" while decoding base64url sequence
|
||||
-- valid base64 padding in base64url (optional, but accepted)
|
||||
SELECT decode('abc-_w==', 'base64url'); -- should decode to \x69b73eff
|
||||
decode
|
||||
------------
|
||||
\x69b73eff
|
||||
(1 row)
|
||||
|
||||
--
|
||||
-- get_bit/set_bit etc
|
||||
--
|
||||
|
||||
@@ -799,6 +799,60 @@ SELECT decode(encode(('\x' || repeat('1234567890abcdef0001', 7))::bytea,
|
||||
SELECT encode('\x1234567890abcdef00', 'escape');
|
||||
SELECT decode(encode('\x1234567890abcdef00', 'escape'), 'escape');
|
||||
|
||||
--
|
||||
-- base64url encoding/decoding
|
||||
--
|
||||
SET bytea_output TO hex;
|
||||
|
||||
-- Simple encoding/decoding
|
||||
SELECT encode('\x69b73eff', 'base64url'); -- abc-_w
|
||||
SELECT decode('abc-_w', 'base64url'); -- \x69b73eff
|
||||
|
||||
-- Round-trip: decode(encode(x)) = x
|
||||
SELECT decode(encode('\x1234567890abcdef00', 'base64url'), 'base64url'); -- \x1234567890abcdef00
|
||||
|
||||
-- Empty input
|
||||
SELECT encode('', 'base64url'); -- ''
|
||||
SELECT decode('', 'base64url'); -- ''
|
||||
|
||||
-- 1 byte input
|
||||
SELECT encode('\x01', 'base64url'); -- AQ
|
||||
SELECT decode('AQ', 'base64url'); -- \x01
|
||||
|
||||
-- 2 byte input
|
||||
SELECT encode('\x0102'::bytea, 'base64url'); -- AQI
|
||||
SELECT decode('AQI', 'base64url'); -- \x0102
|
||||
|
||||
-- 3 byte input (no padding needed)
|
||||
SELECT encode('\x010203'::bytea, 'base64url'); -- AQID
|
||||
SELECT decode('AQID', 'base64url'); -- \x010203
|
||||
|
||||
-- 4 byte input (results in 6 base64 chars)
|
||||
SELECT encode('\xdeadbeef'::bytea, 'base64url'); -- 3q2-7w
|
||||
SELECT decode('3q2-7w', 'base64url'); -- \xdeadbeef
|
||||
|
||||
-- Round-trip test for all lengths from 0–4
|
||||
SELECT encode(decode(encode(E'\\x', 'base64url'), 'base64url'), 'base64url');
|
||||
SELECT encode(decode(encode(E'\\x00', 'base64url'), 'base64url'), 'base64url');
|
||||
SELECT encode(decode(encode(E'\\x0001', 'base64url'), 'base64url'), 'base64url');
|
||||
SELECT encode(decode(encode(E'\\x000102', 'base64url'), 'base64url'), 'base64url');
|
||||
SELECT encode(decode(encode(E'\\x00010203', 'base64url'), 'base64url'), 'base64url');
|
||||
|
||||
-- Invalid inputs (should ERROR)
|
||||
-- invalid character '@'
|
||||
SELECT decode('QQ@=', 'base64url');
|
||||
|
||||
-- missing characters (incomplete group)
|
||||
SELECT decode('QQ', 'base64url'); -- ok (1 byte)
|
||||
SELECT decode('QQI', 'base64url'); -- ok (2 bytes)
|
||||
SELECT decode('QQIDQ', 'base64url'); -- ERROR: invalid base64url end sequence
|
||||
|
||||
-- unexpected '=' at start
|
||||
SELECT decode('=QQQ', 'base64url');
|
||||
|
||||
-- valid base64 padding in base64url (optional, but accepted)
|
||||
SELECT decode('abc-_w==', 'base64url'); -- should decode to \x69b73eff
|
||||
|
||||
--
|
||||
-- get_bit/set_bit etc
|
||||
--
|
||||
|
||||
Reference in New Issue
Block a user