base64url_vectors.c (3422B)
1 /* 2 This file is part of paivana tests. 3 Copyright (C) 2026 Taler Systems SA 4 5 Paivana is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Affero General Public License 7 as published by the Free Software Foundation; either version 8 3, or (at your option) any later version. 9 10 Paivana is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty 12 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 13 the GNU Affero General Public License for more details. 14 15 You should have received a copy of the GNU Affero General Public 16 License along with Paivana; see the file COPYING. If not, 17 write to the Free Software Foundation, Inc., 51 Franklin 18 Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 */ 20 21 /** 22 * @file base64url_vectors.c 23 * @brief Print base64url test vectors as the daemon produces them, for 24 * `test_base64url.sh' to check the paywall's JavaScript against. 25 * 26 * The paivana ID is `<expiration>-<base64url(sha256(...))>', and 27 * the browser recomputes it from the same inputs to recognise 28 * the payment it just made. Nothing forces the two encoders to 29 * agree, and they have already disagreed twice: once on the 30 * decode side, where the daemon emitted the RFC 4648 section 5 31 * alphabet and the browser fed it to atob(), which only knows 32 * section 4; and once on the encode side, where the browser 33 * used a method older engines do not have. Both broke the 34 * payment path and neither was visible from either side alone. 35 * 36 * Output is one vector per line, `<hex-input> <expected>', with 37 * an empty input written as `-'. 38 */ 39 #include "platform.h" 40 #include <gnunet/gnunet_util_lib.h> 41 42 43 /** 44 * Print one vector for the @a len bytes at @a buf. 45 */ 46 static void 47 emit (const unsigned char *buf, 48 size_t len) 49 { 50 char *out = NULL; 51 size_t n; 52 53 if (0 == len) 54 printf ("-"); 55 for (size_t i = 0; i < len; i++) 56 printf ("%02x", buf[i]); 57 n = GNUNET_STRINGS_base64url_encode (buf, 58 len, 59 &out); 60 printf (" %.*s\n", 61 (int) n, 62 out); 63 GNUNET_free (out); 64 } 65 66 67 int 68 main (int argc, 69 char **argv) 70 { 71 unsigned char buf[96] = { 0 }; 72 73 (void) argc; 74 (void) argv; 75 /* Every length from 0 to 96, which crosses the three-byte group 76 boundary in all its phases and so exercises both amounts of 77 padding as well as none. */ 78 for (size_t len = 0; len <= sizeof (buf); len++) 79 { 80 for (size_t i = 0; i < len; i++) 81 buf[i] = (unsigned char) ((i * 37 + len * 11) & 0xFF); 82 emit (buf, 83 len); 84 } 85 /* Every single byte value, so no corner of the alphabet is missed -- 86 '-' and '_' are only reachable from particular high bit patterns, 87 and they are exactly the two characters the section 4 alphabet 88 spells differently. */ 89 for (unsigned int v = 0; v < 256; v++) 90 { 91 unsigned char b = (unsigned char) v; 92 93 emit (&b, 94 1); 95 } 96 /* And a 32-byte block, which is the size that actually occurs: the 97 ID is a SHA-256 digest. */ 98 for (unsigned int round = 0; round < 16; round++) 99 { 100 for (size_t i = 0; i < 32; i++) 101 buf[i] = (unsigned char) ((i * 101 + round * 251) & 0xFF); 102 emit (buf, 103 32); 104 } 105 return 0; 106 } 107 108 109 /* end of base64url_vectors.c */