/** Test base32 decoding. */ static void test_crypto_base32_decode(void) { char plain[60], encoded[96 + 1], decoded[60]; int res; crypto_rand(plain, 60); /* Encode and decode a random string. */ base32_encode(encoded, 96 + 1, plain, 60); res = base32_decode(decoded, 60, encoded, 96); test_eq(res, 0); test_memeq(plain, decoded, 60); /* Encode, uppercase, and decode a random string. */ base32_encode(encoded, 96 + 1, plain, 60); tor_strupper(encoded); res = base32_decode(decoded, 60, encoded, 96); test_eq(res, 0); test_memeq(plain, decoded, 60); /* Change encoded string and decode. */ if (encoded[0] == 'A' || encoded[0] == 'a') encoded[0] = 'B'; else encoded[0] = 'A'; res = base32_decode(decoded, 60, encoded, 96); test_eq(res, 0); test_memneq(plain, decoded, 60); /* Bad encodings. */ encoded[0] = '!'; res = base32_decode(decoded, 60, encoded, 96); test_assert(res < 0); done: ; }
ya_result output_stream_decode_base32(output_stream* os, const char * string, u32 length) { char buffer[64]; u8 buffer_bin[40]; u32 needle = 0; ya_result return_code = OK; /* ------------------------------------------------------------ */ while(length-- > 0) { char c = *string++; if(isspace(c)) { continue; } buffer[needle++] = c; if(needle == sizeof (buffer)) { if(FAIL(return_code = base32_decode(buffer, needle, buffer_bin))) { return return_code; } if(FAIL(return_code = output_stream_write(os, buffer_bin, return_code))) { return return_code; } needle = 0; } } if(needle > 0) { if((needle & 7) != 0) { return PARSEB32_ERROR; } if(FAIL(return_code = base32_decode(buffer, needle, buffer_bin))) { return return_code; } if(FAIL(return_code = output_stream_write(os, buffer_bin, return_code))) { return return_code; } } return return_code; }
/** * Extract the TTH out of a "urn:tree:tiger" URN. * Note that the TTH is expected to be solely base32-encoded here. * * @return whether TTH was successfully extracted. */ bool urn_get_tth(const char *buf, size_t size, struct tth *tth) { static const char prefix[] = "urn:tree:tiger"; size_t len; const char *p; g_assert(0 == size || NULL != buf); g_assert(tth); if (size < CONST_STRLEN(prefix) + 1 /* ":" */ + TTH_BASE32_SIZE) { return FALSE; } p = is_strcaseprefix(buf, prefix); if (NULL == p) { return FALSE; } if ('/' == *p) { /* RAZA puts a slash after "tiger" */ if (size < CONST_STRLEN(prefix) + 2 /* "/:" */ + TTH_BASE32_SIZE){ return FALSE; } p++; } if (':' != *p++) { return FALSE; } len = base32_decode(tth->data, TTH_RAW_SIZE, p, TTH_BASE32_SIZE); if (len != TTH_RAW_SIZE) { return FALSE; } return TRUE; }
enum nssync_error nssync_crypto_synckey_decode(const char *key, uint8_t **key_out) { uint8_t *synckey; char key32[BASE32_SYNCKEY_LENGTH + 1]; int key32idx = 0; int keyidx = 0; int ret; synckey = malloc(SYNCKEY_LENGTH); if (synckey == NULL) { return NSSYNC_ERROR_NOMEM; } while ((key32idx < BASE32_SYNCKEY_LENGTH) && (key[keyidx] != 0)) { key32[key32idx] = fromfriendly(key[keyidx++]); if (key32[key32idx] != 0) { key32idx++; } } key32[key32idx] = 0; ret = base32_decode(synckey, SYNCKEY_LENGTH, key32, BASE32_SYNCKEY_LENGTH); if (ret != SYNCKEY_LENGTH) { free(synckey); return -2; } *key_out = synckey; return NSSYNC_ERROR_OK; }
int main(int argc, char **argv) { uint8_t a[128]; unsigned alen = sizeof(a); if (!base32_encode(a, &alen, (unsigned char *) argv[1], strlen(argv[1]))) { perror("encode"); return 1; } write(1, a, alen); write(1, "\n", 1); uint8_t b[128]; unsigned blen = sizeof(b); if (!base32_decode(b, &blen, a, alen, 0)) { perror("decode"); return 1; } write(1, b, blen); write(1, "\n", 1); return 0; }
bool huge_tth_extract32(const char *buf, size_t len, struct tth *tth, const gnutella_node_t *n) { if (len != TTH_BASE32_SIZE) goto bad; if (TTH_RAW_SIZE != base32_decode(tth->data, sizeof tth->data, buf, len)) goto bad; return TRUE; bad: if (GNET_PROPERTY(share_debug)) { if (is_printable(buf, len)) { g_warning("%s has bad TTH (len=%u): %.*s", gmsg_node_infostr(n), (unsigned) len, (int) MIN(len, (size_t) INT_MAX), buf); } else { g_warning("%s has bad TTH (len=%u", gmsg_node_infostr(n), (unsigned) len); if (len) dump_hex(stderr, "Base32 TTH", buf, len); } } return FALSE; }
bool ADC::CID::load() { QDBG("Loading CID from configuration file..."); QuickDC::Preferences* config = QuickDC::Core::getInstance()->config; config->setGroup("User"); pid = new char[HASH+1]; cid = new char[HASH+1]; char* x_pid = strdup(config->getString("Private ID", "")); strncpy(pid, x_pid, HASH); free(x_pid); if (!verify(pid)) { delete[] pid; pid = 0; delete[] cid; cid = 0; return false; } uint8_t pid_decoded[TIGERSIZE] = { 0, }; base32_decode(pid, (unsigned char*) pid_decoded, TIGERSIZE); Samurai::Crypto::Digest::Tiger tiger; Samurai::Crypto::Digest::HashValue* value; tiger.update(pid_decoded, TIGERSIZE); value = tiger.digest(); value->getFormattedString(Samurai::Crypto::Digest::HashValue::FormatBase32, cid, HASH); QDBG("CID loaded: %s (pid=%s)", cid, pid); store(); return true; }
void ADC::HubSession::onRequestPasword(char* token) { if (userState != QuickDC::HubSession::StateIdentify) { QERR("Unexpected state transition. Current state=%d. Ignoring.", userState); return; } userState = QuickDC::HubSession::StateVerify; char password_encoded[40] = { 0, }; if (!token) return; size_t tok_size = (strlen(token) * 5) >> 3; size_t size = strlen(password) + tok_size; uint8_t* tok_decoded = new uint8_t[tok_size]; uint8_t* str = new uint8_t[size]; base32_decode(token, tok_decoded, tok_size); memcpy(&str[0], password, strlen(password)); memcpy(&str[strlen(password)], tok_decoded, tok_size); Samurai::Crypto::Digest::Tiger tiger; tiger.update(str, size); Samurai::Crypto::Digest::HashValue* value = tiger.digest(); value->getFormattedString(Samurai::Crypto::Digest::HashValue::FormatBase32, password_encoded, 40); ADC::Command* cmd = new ADC::Command(FOURCC('H','P','A','S')); cmd->addArgument(password_encoded); send(cmd); delete[] tok_decoded; delete[] str; }
// validate a str is a base32 hashname uint8_t hashname_valid(char *str) { static uint8_t buf[32]; if(!str) return 0; if(strlen(str) != 52) return 0; if(base32_decode(str,52,buf,32) != 32) return 0; return 1; }
// these all create a new hashname hashname_t hashname_str(char *str) { hashname_t hn; if(!hashname_valid(str)) return NULL; hn = hashname_new(NULL); base32_decode(str,52,hn->bin,32); base32_encode(hn->bin,32,hn->hashname,53); return hn; }
static void test_util_format_base32_decode(void *arg) { (void) arg; int ret; size_t real_dstlen = 32; char *dst = tor_malloc_zero(real_dstlen); /* Basic use case. */ { /* Length of 10 bytes. */ const char *expected = "blahbleh12"; /* Expected result encoded base32. */ const char *src = "mjwgc2dcnrswqmjs"; ret = base32_decode(dst, strlen(expected), src, strlen(src)); tt_int_op(ret, ==, 0); tt_str_op(expected, OP_EQ, dst); } /* Non multiple of 5 for the source buffer length. */ { /* Length of 8 bytes. */ const char *expected = "blahbleh"; const char *src = "mjwgc2dcnrswq"; ret = base32_decode(dst, strlen(expected), src, strlen(src)); tt_int_op(ret, ==, 0); tt_mem_op(expected, OP_EQ, dst, strlen(expected)); } /* Invalid values. */ { /* Invalid character '#'. */ ret = base32_decode(dst, real_dstlen, "#abcde", 6); tt_int_op(ret, ==, -1); /* Make sure the destination buffer has been zeroed even on error. */ tt_int_op(tor_mem_is_zero(dst, real_dstlen), ==, 1); } done: tor_free(dst); }
static int int_decode (hpgs_reader *reader, int *value, int b32) { unsigned uval; if (b32) { if (base32_decode(reader,&uval)) return -1; } else { if (base64_decode(reader,&uval)) return -1; } if (uval & 1) *value = - (uval >> 1); else
static chunk_t * b32_dec(const chunk_t *inp) { chunk_t *ch = chunk_new(inp->len);//XXXX int r = base32_decode((char *)ch->buf, ch->len, (char *)inp->buf, inp->len); if (r >= 0) { ch->len = r; } else { chunk_free(ch); } return ch; }
/** * Locate the start of "urn:bitprint:" indications and extract * the SHA1 and TTH out of it, placing them in the supplied buffers. * * @return whether we successfully extracted the bitprint, i.e. the two * hashes. */ bool urn_get_bitprint(const char *buf, size_t size, struct sha1 *sha1, struct tth *tth) { static const char prefix[] = "urn:bitprint:"; size_t len; const char *p; bool base16_tth = FALSE; g_assert(0 == size || NULL != buf); g_assert(sha1); g_assert(tth); /* * Because some clueless sites list magnets with hexadecimal-encoded * values, we attempt to parse both base32 and base16 encoded hashes. * * Note that we expect both hashes to be similarily encoded. */ if (size < CONST_STRLEN(prefix) + BITPRINT_BASE32_SIZE) return FALSE; p = is_strcaseprefix(buf, prefix); if (NULL == p) return FALSE; if (!parse_base32_sha1(p, SHA1_BASE32_SIZE, sha1)) { if ( size >= CONST_STRLEN(prefix) + BITPRINT_BASE16_SIZE && parse_base16_sha1(p, SHA1_BASE16_SIZE, sha1) ) { p += SHA1_BASE16_SIZE; base16_tth = TRUE; /* SHA1 was hexa, expects TTH as hexa */ } else { return FALSE; } } else { p += SHA1_BASE32_SIZE; } if ('.' != *p++) { return FALSE; } if (base16_tth) { len = base16_decode(tth, sizeof *tth, p, TTH_BASE16_SIZE); } else { len = base32_decode(tth, sizeof *tth, p, TTH_BASE32_SIZE); } if (len != TTH_RAW_SIZE) { return FALSE; } return TRUE; }
// intermediate hashes in the json, if id is given it is attached as BODY instead lob_t hashname_im(lob_t keys, uint8_t id) { uint32_t i; size_t len; uint8_t *buf, hash[32]; char *key, *value, hex[3]; lob_t im; if(!keys) return LOG("bad args"); // loop through all keys and create intermediates im = lob_new(); buf = NULL; util_hex(&id,1,hex); for(i=0;(key = lob_get_index(keys,i));i+=2) { value = lob_get_index(keys,i+1); if(strlen(key) != 2 || !value) continue; // skip non-csid keys len = base32_decode_floor(strlen(value)); // save to body raw or as a base32 intermediate value if(id && util_cmp(hex,key) == 0) { lob_body(im,NULL,len); if(base32_decode(value,strlen(value),im->body,len) != len) continue; lob_set_raw(im,key,0,"true",4); }else{ buf = util_reallocf(buf,len); if(!buf) return lob_free(im); if(base32_decode(value,strlen(value),buf,len) != len) continue; // store the hash intermediate value e3x_hash(buf,len,hash); lob_set_base32(im,key,hash,32); } } if(buf) free(buf); return im; }
int main(int argc, char **argv) { const char *str = " *" "* Copyright 2005 Martin Hedenfalk <*****@*****.**>" "*" "* This file is part of ShakesPeer." "*" "* ShakesPeer is free software; you can redistribute it and/or modify" "* it under the terms of the GNU General Public License as published by" "* the Free Software Foundation; either version 2 of the License, or" "* (at your option) any later version." "*" "* ShakesPeer is distributed in the hope that it will be useful," "* but WITHOUT ANY WARRANTY; without even the implied warranty of" "* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the" "* GNU General Public License for more details." "*" "* You should have received a copy of the GNU General Public License" "* along with ShakesPeer; if not, wite to the Free Software" "* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA" "*/"; char *tmp = base32_encode(str, strlen(str)); char *data = base32_decode(tmp, NULL); fail_unless(memcmp(data, str, base32_decode_length(strlen(tmp))) == 0); const char *b = "RF354FEUIXRYFO4O372SXJLKJDIQ2XKIO3XU37OPKEOUEQ7OACWYRFLWDZU5E2QEMESWOS56BIL65HRBFQJHPF4HGWFD6F4E5EJWSA5NZYSHJJP6UZXPUTA5DGOIRIBJILKE65QPP6WBB3I54JRPHUG3XH6NRQTCTLHWAL73NAQ2BCBPKBL3FCZPCAWYNZ7ZN3OHFX2FOZ277IPPLBEZCP6SHDTKJ3CP6SUF2Q6PGZOBFDRFKOX6ERXQADLK6RH4BCOAVRBRQ3S4BTZWLQJI4JKTV7REN4AA22XUJ7AITQFMIMMG4XAA"; unsigned outlen = 0; void *data2 = base32_decode(b, &outlen); fail_unless(data2); fail_unless(outlen % 24 == 0); fail_unless(outlen == 192); return 0; }
/** * Validate `len' bytes starting from `buf' as a proper base32 encoding * of a SHA1 hash, and write decoded value in `sha1'. * Also make sure that the SHA1 is not an improbable value. * * `n' is the node receiving the packet where we found the SHA1, so that we * may trace errors if needed. * * When `check_old' is true, check the encoding against an earlier version * of the base32 alphabet. * * @return TRUE if the SHA1 was valid and properly decoded, FALSE on error. */ bool huge_sha1_extract32(const char *buf, size_t len, struct sha1 *sha1, const gnutella_node_t *n) { if (len != SHA1_BASE32_SIZE || huge_improbable_sha1(buf, len)) goto bad; if (SHA1_RAW_SIZE != base32_decode(sha1->data, sizeof sha1->data, buf, len)) goto bad; /* * Make sure the decoded value in `sha1' is "valid". */ if (huge_improbable_sha1(sha1->data, sizeof sha1->data)) { if (GNET_PROPERTY(share_debug)) { if (is_printable(buf, len)) { g_warning("%s has improbable SHA1 (len=%lu): %.*s, hex: %s", gmsg_node_infostr(n), (unsigned long) len, (int) MIN(len, (size_t) INT_MAX), buf, data_hex_str(sha1->data, sizeof sha1->data)); } else goto bad; /* SHA1 should be printable originally */ } return FALSE; } return TRUE; bad: if (GNET_PROPERTY(share_debug)) { if (is_printable(buf, len)) { g_warning("%s has bad SHA1 (len=%u): %.*s", gmsg_node_infostr(n), (unsigned) len, (int) MIN(len, (size_t) INT_MAX), buf); } else { g_warning("%s has bad SHA1 (len=%u)", gmsg_node_infostr(n), (unsigned) len); if (len) dump_hex(stderr, "Base32 SHA1", buf, len); } } return FALSE; }
/* * call-seq: * Base32.decode(encoded_string) -> string * * Decodes a string that is encoded in base32. Will throw an ArgumentError if * it cannot successfully decode it. */ static VALUE b32_decode (VALUE self, VALUE value) { value = StringValue (value); if (RSTRING (value)->len == 0) return value; VALUE result = rb_str_new (0, base32_decode_buffer_size (RSTRING (value)->len)); size_t length = base32_decode ((uint8_t *) RSTRING (result)->ptr, RSTRING (result)->len, (uint8_t *) RSTRING (value)->ptr, RSTRING (value)->len); if (length == 0) rb_raise(rb_eRuntimeError, "Value provided not base32 encoded"); RSTRING (result)->len = length; return result; }
static int check_hash_tiger(const char* cid, const char* pid) { char x_pid[64]; char raw_pid[64]; uint64_t tiger_res[3]; memset(x_pid, 0, MAX_CID_LEN+1); base32_decode(pid, (unsigned char*) raw_pid, MAX_CID_LEN); tiger((uint64_t*) raw_pid, TIGERSIZE, (uint64_t*) tiger_res); base32_encode((unsigned char*) tiger_res, TIGERSIZE, x_pid); x_pid[MAX_CID_LEN] = 0; if (strncasecmp(x_pid, cid, MAX_CID_LEN) == 0) return 1; return 0; }
bool ADC::CID::verifyCIDandPID(const char* cid, const char* pid) { if (!verify(cid) || !verify(pid)) return false; char x_cid[HASH]; uint8_t raw_pid[TIGERSIZE]; base32_decode(pid, (unsigned char*) raw_pid, TIGERSIZE); Samurai::Crypto::Digest::Tiger tiger; Samurai::Crypto::Digest::HashValue* value; tiger.update(raw_pid, TIGERSIZE); value = tiger.digest(); value->getFormattedString(Samurai::Crypto::Digest::HashValue::FormatBase32, x_cid, HASH); return (strcasecmp(x_cid, cid) == 0); }
static int generateCode(const char *key, unsigned long tm) { uint8_t challenge[8]; for (int i = 8; i--; tm >>= 8) { challenge[i] = tm; } // Estimated number of bytes needed to represent the decoded secret. Because // of white-space and separators, this is an upper bound of the real number, // which we later get as a return-value from base32_decode() int secretLen = (strlen(key) + 7)/8*BITS_PER_BASE32_CHAR; // Sanity check, that our secret will fixed into a reasonably-sized static // array. if (secretLen <= 0 || secretLen > 100) { return -1; } // Decode secret from Base32 to a binary representation, and check that we // have at least one byte's worth of secret data. uint8_t secret[100]; if ((secretLen = base32_decode((const uint8_t *)key, secret, secretLen))<1) { return -1; } // Compute the HMAC_SHA1 of the secrete and the challenge. uint8_t hash[SHA1_DIGEST_LENGTH]; hmac_sha1(secret, secretLen, challenge, 8, hash, SHA1_DIGEST_LENGTH); // Pick the offset where to sample our hash value for the actual verification // code. int offset = hash[SHA1_DIGEST_LENGTH - 1] & 0xF; // Compute the truncated hash in a byte-order independent loop. unsigned int truncatedHash = 0; for (int i = 0; i < 4; ++i) { truncatedHash <<= 8; truncatedHash |= hash[offset + i]; } // Truncate to a smaller number of digits. truncatedHash &= 0x7FFFFFFF; truncatedHash %= VERIFICATION_CODE_MODULUS; return truncatedHash; }
static uint8_t *get_shared_secret( request_rec *r, const char *buf, int *secretLen) { // Decode secret key int base32Len = strlen(buf); *secretLen = (base32Len*5 + 7)/8; unsigned char *secret = apr_palloc(r->pool,base32Len + 1); memcpy(secret, buf, base32Len); secret[base32Len] = '\000'; if ((*secretLen = base32_decode(secret, secret, base32Len)) < 1) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Could not find a valid BASE32 encoded secret"); memset(secret, 0, base32Len); return NULL; } memset(secret + *secretLen, 0, base32Len + 1 - *secretLen); return secret; }
/** * Validate SHA1 starting in NUL-terminated `buf' as a proper base32 encoding * of a SHA1 hash, and write decoded value in `retval'. * * The SHA1 typically comes from HTTP, in a X-Gnutella-Content-URN header. * * @return TRUE if the SHA1 was valid and properly decoded, FALSE on error. */ bool parse_base32_sha1(const char *buf, size_t size, struct sha1 *sha1) { struct sha1 raw; size_t len; if (!sha1) { sha1 = &raw; } if (size < SHA1_BASE32_SIZE) return FALSE; len = base32_decode(sha1, sizeof *sha1, buf, SHA1_BASE32_SIZE); if (SHA1_RAW_SIZE != len) return FALSE; return TRUE; }
// get paths from host and query lob_t util_uri_paths(lob_t uri) { uint32_t i; uint16_t port; uint8_t *buf; size_t len; char *key, *value; lob_t paths, query = lob_linked(uri); if(!query) return NULL; paths = NULL; // gen paths from host/port if((port = lob_get_uint(uri,"port"))) { key = lob_get(uri,"host"); paths = lob_chain(paths); lob_set(paths,"type","upd4"); lob_set(paths,"ip",key); lob_set_uint(paths,"port",port); paths = lob_chain(paths); lob_set(paths,"type","tcp4"); lob_set(paths,"ip",key); lob_set_uint(paths,"port",port); } // loop through all keyval pairs to find paths buf = NULL; for(i=0;(key = lob_get_index(query,i));i+=2) { value = lob_get_index(query,i+1); if(util_cmp(key,"paths") != 0 || !value) continue; len = base32_decode_floor(strlen(value)); buf = util_reallocf(buf,len); if(!buf) continue; if(base32_decode(value,strlen(value),buf,len) < len) continue; paths = lob_link(lob_parse(buf,len), paths); } free(buf); return paths; }
// create hashname from intermediate values as hex/base32 key/value pairs hashname_t hashname_key(lob_t key, uint8_t csid) { unsigned int i, start; uint8_t hash[64]; char *id, *value, hexid[3]; hashname_t hn = NULL; if(!key) return LOG("invalid args"); util_hex(&csid, 1, hexid); // get in sorted order lob_sort(key); // loop through all keys rolling up for(i=0;(id = lob_get_index(key,i));i+=2) { value = lob_get_index(key,i+1); if(strlen(id) != 2 || !util_ishex(id,2) || !value) continue; // skip non-id keys // hash the id util_unhex(id,2,hash+32); start = (i == 0) ? 32 : 0; // only first one excludes previous rollup e3x_hash(hash+start,(32-start)+1,hash); // hash in place // get the value from the body if matching csid arg if(util_cmp(id, hexid) == 0) { if(key->body_len == 0) return LOG("missing key body"); // hash the body e3x_hash(key->body,key->body_len,hash+32); }else{ if(strlen(value) != 52) return LOG("invalid value %s %d",value,strlen(value)); if(base32_decode(value,52,hash+32,32) != 32) return LOG("base32 decode failed %s",value); } e3x_hash(hash,64,hash); } if(!i || i % 2 != 0) return LOG("invalid keys %d",i); hn = hashname_new(hash); return hn; }
int acl_password_verify(struct hub_info* hub, struct hub_user* user, const char* password) { char buf[1024]; struct auth_info* access; const char* challenge; char raw_challenge[64]; char password_calc[64]; uint64_t tiger_res[3]; size_t password_len; if (!password || !user || strlen(password) != MAX_CID_LEN) return 0; access = acl_get_access_info(hub, user->id.nick); if (!access) return 0; challenge = acl_password_generate_challenge(hub, user); base32_decode(challenge, (unsigned char*) raw_challenge, MAX_CID_LEN); password_len = strlen(access->password); memcpy(&buf[0], access->password, password_len); memcpy(&buf[password_len], raw_challenge, TIGERSIZE); tiger((uint64_t*) buf, TIGERSIZE+password_len, (uint64_t*) tiger_res); base32_encode((unsigned char*) tiger_res, TIGERSIZE, password_calc); password_calc[MAX_CID_LEN] = 0; #ifdef PLUGIN_SUPPORT hub_free(access); #endif if (strcasecmp(password, password_calc) == 0) { return 1; } return 0; }
static void test_base32_random(void) { string_t *str, *dest; char buf[10]; unsigned int i, j, max; str = t_str_new(256); dest = t_str_new(256); test_begin("padded base32 encode/decode with random input"); for (i = 0; i < 1000; i++) { max = rand() % sizeof(buf); for (j = 0; j < max; j++) buf[j] = rand(); str_truncate(str, 0); str_truncate(dest, 0); base32_encode(TRUE, buf, max, str); test_assert(base32_decode(str_data(str), str_len(str), NULL, dest) >= 0); test_assert(str_len(dest) == max && memcmp(buf, str_data(dest), max) == 0); } test_end(); test_begin("padded base32hex encode/decode with random input"); for (i = 0; i < 1000; i++) { max = rand() % sizeof(buf); for (j = 0; j < max; j++) buf[j] = rand(); str_truncate(str, 0); str_truncate(dest, 0); base32hex_encode(TRUE, buf, max, str); test_assert(base32hex_decode(str_data(str), str_len(str), NULL, dest) >= 0); test_assert(str_len(dest) == max && memcmp(buf, str_data(dest), max) == 0); } test_end(); }
static void test_base32_decode(void) { static const char *input[] = { "ORXWKZDFNRSWI33LNFSSCII=", "MJ4WKIDCPFSSA53POJWGI===", "NBXWK5TFMVWCA33OPJUW4IDLOVXCA2TFEB2GK43UMVXD6PZ7H47Q====", "MMTWK43UEBYGC4ZAOZZGC2JBEA======", "MRUXIIDJOMQGQZLUEBSWS3TEMUQHMYLOEBSGK6TFEB2GK43U" }; static const struct test_base32_decode_output output[] = { { "toedeledokie!!", 0, 24 }, { "bye bye world", 0, 24 }, { "hoeveel onzin kun je testen?????", 0, 56 }, { "c'est pas vrai! ", 0, 32 }, { "dit is het einde van deze test", 1, 48 }, }; string_t *str; unsigned int i; size_t src_pos; int ret; test_begin("base32_decode()"); str = t_str_new(256); for (i = 0; i < N_ELEMENTS(input); i++) { str_truncate(str, 0); src_pos = 0; ret = base32_decode(input[i], strlen(input[i]), &src_pos, str); test_assert(output[i].ret == ret && strcmp(output[i].text, str_c(str)) == 0 && (src_pos == output[i].src_pos || (output[i].src_pos == UINT_MAX && src_pos == strlen(input[i])))); } test_end(); }
int main(int argc, char **argv) { global_urandom_fd = open("/dev/urandom", O_RDONLY); if (global_urandom_fd < 0) { perror("Opening /dev/urandom"); return 1; } if (argc != 4) return usage(argv[0]); uint32_t target_ip; if (!ip_parse(&target_ip, argv[1])) return usage(argv[0]); const unsigned portnum = strtoul(argv[2], NULL, 10); uint8_t server_pk[32]; unsigned server_pk_len = sizeof(server_pk); if (!base32_decode(server_pk, &server_pk_len, (const uint8_t *) argv[3], strlen(argv[3]), 1)) { perror("base32_decode"); return 1; } if (server_pk_len != 32) { fprintf(stderr, "Invalid server public key\n"); return 1; } static const uint8_t query[] = "\xab\xcd\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x03www\x06google\x03org\x00\x00\x02\x00\x01"; uint8_t pk[32]; crypto_box_curve25519xsalsa20poly1305_keypair(pk, global_secret_key); uint8_t nonce[24]; uint8_t nonce_and_box[4096]; randombytes(nonce, 12); memset(nonce + 12, 0, 12); memset(nonce_and_box, 0, 32); memcpy(nonce_and_box + 32, query, sizeof(query) - 1); crypto_box_curve25519xsalsa20poly1305 (nonce_and_box, nonce_and_box, 32 + sizeof(query) - 1, nonce, server_pk, global_secret_key); memcpy(nonce_and_box + 4, nonce, 12); write(1, pk, 32); write(1, nonce_and_box + 4, 12 + 16 + sizeof(query) - 1); uint8_t request[4096]; unsigned requestlen = sizeof(request) - 2; if (!dns_curve_request_build(request + 2, &requestlen, nonce_and_box + 4, 12 + 16 + sizeof(query) - 1, pk, (unsigned char *) "\x06google\x03org\x00")) { perror("dns_curve_request_build"); return 1; } requestlen += 2; const int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); if (fd < 0) { perror("socket"); return 1; } struct sockaddr_in sin; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = target_ip; sin.sin_port = htons(portnum); ssize_t n; do { n = sendto(fd, request, requestlen, 0, (struct sockaddr *) &sin, sizeof(sin)); } while (n == -1 && errno == EINTR); if (n < 0) { perror("sendto"); return 1; } return 0; }
int main (void) { const char *in = "abcdefghijklmnop"; const char *b32in = "MFRGGZDFMZTWQ2LKNNWG23TPOA======"; char out[255]; size_t len; bool ok; char *p; memset (out, 0x42, sizeof (out)); base32_encode (in, 0, out, 0); ASSERT (out[0] == '\x42'); memset (out, 0x42, sizeof (out)); base32_encode (in, 1, out, 10); ASSERT (memcmp (out, "ME======", 1) == 0); memset (out, 0x42, sizeof (out)); base32_encode (in, 1, out, 2); ASSERT (memcmp (out, "ME======", 2) == 0); memset (out, 0x42, sizeof (out)); base32_encode (in, 1, out, 3); ASSERT (memcmp (out, "ME======", 3) == 0); memset (out, 0x42, sizeof (out)); base32_encode (in, 1, out, 4); ASSERT (memcmp (out, "ME======", 4) == 0); memset (out, 0x42, sizeof (out)); base32_encode (in, 1, out, 8); ASSERT (memcmp (out, "ME======", 8) == 0); memset (out, 0x42, sizeof (out)); base32_encode (in, 2, out, 8); ASSERT (memcmp (out, "MFRA====", 8) == 0); memset (out, 0x42, sizeof (out)); base32_encode (in, 3, out, 8); ASSERT (memcmp (out, "MFRGG===", 8) == 0); memset (out, 0x42, sizeof (out)); base32_encode (in, 4, out, 8); ASSERT (memcmp (out, "MFRGGZA=", 8) == 0); memset (out, 0x42, sizeof (out)); base32_encode (in, 5, out, 8); ASSERT (memcmp (out, "MFRGGZDF", 8) == 0); memset (out, 0x42, sizeof (out)); base32_encode (in, 6, out, 16); ASSERT (memcmp (out, "MFRGGZDFMY======", 16) == 0); memset (out, 0x42, sizeof (out)); base32_encode (in, 6, out, 100); ASSERT (memcmp (out, "MFRGGZDFMY======", 16) == 0); /* Decode. */ memset (out, 0x42, sizeof (out)); len = 0; ok = base32_decode (b32in, 8, out, &len); ASSERT (ok); ASSERT (len == 0); memset (out, 0x42, sizeof (out)); len = 1; ok = base32_decode (b32in, 8, out, &len); ASSERT (ok); ASSERT (len == 1); ASSERT (memcmp (out, "abcdefghijklmnop", 1) == 0); memset (out, 0x42, sizeof (out)); len = 2; ok = base32_decode (b32in, 8, out, &len); ASSERT (ok); ASSERT (len == 2); ASSERT (memcmp (out, "abcdefghijklmnop", 2) == 0); memset (out, 0x42, sizeof (out)); len = 3; ok = base32_decode (b32in, 8, out, &len); ASSERT (ok); ASSERT (len == 3); ASSERT (memcmp (out, "abcdefghijklmnop", 3) == 0); memset (out, 0x42, sizeof (out)); len = 4; ok = base32_decode (b32in, 8, out, &len); ASSERT (ok); ASSERT (len == 4); ASSERT (memcmp (out, "abcdefghijklmnop", 4) == 0); memset (out, 0x42, sizeof (out)); len = 5; ok = base32_decode (b32in, 8, out, &len); ASSERT (ok); ASSERT (len == 5); ASSERT (memcmp (out, "abcdefghijklmnop", 5) == 0); memset (out, 0x42, sizeof (out)); len = 6; ok = base32_decode (b32in, 8, out, &len); ASSERT (ok); ASSERT (len == 5); ASSERT (memcmp (out, "abcdefghijklmnop", 5) == 0); memset (out, 0x42, sizeof (out)); len = 100; ok = base32_decode (b32in, strlen (b32in), out, &len); ASSERT (ok); ASSERT (len == 16); ASSERT (memcmp (out, "abcdefghijklmnop", 16) == 0); /* Allocating encode */ len = base32_encode_alloc (in, strlen (in), &p); ASSERT (len == 32); ASSERT (strcmp (p, "MFRGGZDFMZTWQ2LKNNWG23TPOA======") == 0); free (p); len = base32_encode_alloc (in, SIZE_MAX - 5, &p); ASSERT (len == 0); /* Decode context function */ { struct base32_decode_context ctx; base32_decode_ctx_init (&ctx); len = sizeof (out); ok = base32_decode_ctx (&ctx, b32in, strlen (b32in), out, &len); ASSERT (ok); ASSERT (len == 16); ASSERT (memcmp (out, "abcdefghijklmnop", len) == 0); } /* Allocating decode context function */ ok = base32_decode_alloc_ctx (NULL, b32in, strlen (b32in), &p, &len); ASSERT (ok); ASSERT (len == 16); ASSERT (memcmp (out, "abcdefghijklmnop", len) == 0); free (p); { struct base32_decode_context ctx; const char *newlineb32 = "MFRG\nGZDFMZTWQ2LKNNW\nG23TPOA======"; base32_decode_ctx_init (&ctx); ok = base32_decode_alloc_ctx (&ctx, newlineb32, strlen (newlineb32), &p, &len); ASSERT (ok); ASSERT (len == strlen (in)); ASSERT (memcmp (p, in, len) == 0); free (p); } { struct base32_decode_context ctx; base32_decode_ctx_init (&ctx); ok = base32_decode_alloc_ctx (&ctx, "MFRGGZDFM\nZTWQ2LK", 17, &p, &len); ASSERT (ok); ASSERT (len == 10); ASSERT (memcmp (p, "abcdefghij", len) == 0); free (p); base32_decode_ctx_init (&ctx); ok = base32_decode_alloc_ctx (&ctx, "MF\n", 3, &p, &len); ASSERT (ok); ASSERT (len == 0); free (p); ok = base32_decode_alloc_ctx (&ctx, "RGGZDFMZ", 8, &p, &len); ASSERT (ok); ASSERT (len == 5); ASSERT (memcmp (p, "abcde", len) == 0); free (p); ok = base32_decode_alloc_ctx (&ctx, "TWQ2LK", 6, &p, &len); ASSERT (ok); ASSERT (len == 5); ASSERT (memcmp (p, "fghij", len) == 0); free (p); ok = base32_decode_alloc_ctx (&ctx, "", 0, &p, &len); ASSERT (ok); free (p); } { struct base32_decode_context ctx; const char *newlineb32 = "\n\n\n\n\n"; base32_decode_ctx_init (&ctx); ok = base32_decode_alloc_ctx (&ctx, newlineb32, strlen (newlineb32), &p, &len); ASSERT (ok); ASSERT (len == 0); free (p); } ok = base32_decode_alloc_ctx (NULL, " ! ", 3, &p, &len); ASSERT (!ok); ok = base32_decode_alloc_ctx (NULL, "ABC\nDEF", 7, &p, &len); ASSERT (!ok); ok = base32_decode_alloc_ctx (NULL, "AA", 2, &p, &len); ASSERT (!ok); ok = base32_decode_alloc_ctx (NULL, "AA=", 3, &p, &len); ASSERT (!ok); ok = base32_decode_alloc_ctx (NULL, "AABBAAxx", 8, &p, &len); ASSERT (!ok); ok = base32_decode_alloc_ctx (NULL, "AABBAA=X", 8, &p, &len); ASSERT (!ok); ok = base32_decode_alloc_ctx (NULL, "AABBAA=X", 8, &p, &len); ASSERT (!ok); ok = base32_decode_alloc_ctx (NULL, "AABBAA=A", 8, &p, &len); ASSERT (!ok); return 0; }