[tor-dev] [RFC] Proposal for the encoding of prop224 onion addresses
Taylor R Campbell
campbell+tor-dev at mumble.net
Sun Feb 5 07:44:00 UTC 2017
> Date: Sat, 04 Feb 2017 20:14:00 -0600
> From: Vi Grey <vigrey at riseup.net>
>
> Wouldn't SHA3 be computational overkill if we're just worrying about the
> checksum making sure the .onion address wasn't mistyped? My suggestion
> would be to use something like this for the checksum:
>
> checksum = HMAC-CRC32(".onion checksum", version + pubkey)[2:]
> (with the HMAC key as its first argument)
>
> HMAC-CRC16 could be used as well instead of a truncated HMAC-CRC32, but
> CRC16 is a lot less standard than CRC32.
It depends on what you're trying to accomplish. There are thousands
of possible 16-bit CRCs and billions of possible 32-bit CRCs, of which
a dozen or two are in widespread use for various applications. If you
simply want a k-bit checksum to detect all errors of up to t bits in
n-bit words, it's not too hard to find a polynomial that does this,
subject to some constraints[1].
The software cost of replacing the polynomial is negligible -- change
a single constant in a program like the attached one, which implements
a 16-bit CRC that detects all 3-bit errors in up to 2048-bit words and
all 4-bit errors in up to 108-bit words.
All that said, I'm not sure I can easily imagine applications that
(a) can tolerate the computational cost of public-key cryptography and
the latency of the Tor network, yet
(b) can't tolerate the cost of one or two blocks of SHA-3 to validate
a .onion address checksum.
It is harder to *prove* that k-bit truncation of SHA-3 will detect all
t-bit errors in n-bit words because it lacks the convenient structure
of a CRC, but it is reasonable to estimate a probability 2^-k of no
bit flips in the checksum under any error.
(I don't think there's anything birthday-related here -- this is a
preimage attack by an adversary of random fat-fingerings or lens
prescriptions in need of replacement.)
> Also, should we consider including a Version option eventually in the
> ADD_ONION control port command when using a KeyBlob? It wouldn't matter
> much for this new version and probably wouldn't matter much for a while,
> but it might be good to keep this in mind for the future.
Versioning onion addresses and versioning network-internal service
descriptors need not be done the same way.
Addresses are likely to be long-term, and should really change only if
the meaning of the encoded public key has changed incompatibly but
otherwise imperceptibly -- e.g., if for some reason Tor switched from
Edwards coordinates to Montgomery coordinates on Curve25519. (That
would be a silly thing to do -- it is just an example of a change that
could still interpret existing addresses, but differently.)
Services are periodically restarted and their descriptors republished
to the directory anyway, and implementation details may change when
you upgrade to a new version of Tor -- Tor has already gone through a
few versions of the HS descriptors, which doesn't necessarily require
changing the onion address.
[1] Philip Koopman and Tridib Chakravarty, `Cyclic Redundancy Check
(CRC) Polynomial Selection For Embedded Networks', Proceedings of the
International Conference on Dependable Systems and Networks, 2004.
http://repository.cmu.edu/cgi/viewcontent.cgi?article=1672&context=isr
-------------- next part --------------
#include <stddef.h>
#include <stdint.h>
/*
* ONIONCRC_POLY
*
* A degree-16 polynomial that detects all 3-bit errors in up to
* 2048-bit words and all 4-bit errors up to 108-bit words, from
* Koopman & Chakravarty, `Cyclic Redundancy Code (CRC) Polynomial
* Selection For Embedded Networks', International Conference on
* Dependable Systems and Networks, 2004.
* http://repository.cmu.edu/cgi/viewcontent.cgi?article=1672&context=isr
*
* x^16 + x^14 + x^13 + x^12 + x^10 + x^8 + x^6 + x^4 + x^3 + x^1 + 1
*
* The paper describes this as 0xbaad, but uses a quirky
* representation with explicit high-degree term and implicit
* constant term taken to be 1.
*
* Of course, for prop224 onion names, we have exactly 262-bit
* words (256-bit public key + 8-bit version), so performance on
* 2048-bit words is irrelevant. There may be a better choice for
* exactly 262-bit words, but it requires some calculation to
* choose.
*/
#define ONIONCRC_POLY UINT16_C(0x755b)
/*
* onioncrc_compute_step(crc, o)
*
* Given crc = m_0 x^k (mod g) and o = m_1 of degree 7, compute
* and return
*
* crc' = (m_0 x^8 + m_1) x^k (mod g)
*
* using bit-by-bit operations.
*/
static uint16_t
onioncrc_compute_step(uint16_t crc, uint8_t o)
{
unsigned i;
crc ^= o << 8;
for (i = 0; i < 8; i++)
crc = ((crc << 1) & UINT16_C(0xffff)) ^
(ONIONCRC_POLY & -(crc >> 15));
return crc;
}
/*
* onioncrc_table[o]
*
* Precomputed table of batch CRC reduction steps for octet o.
*/
static uint16_t onioncrc_table[0x100];
/*
* onioncrc_init()
*
* Initialize onioncrc_table.
*/
void
onioncrc_init(void)
{
uint8_t o = 0;
do {
onioncrc_table[o] = onioncrc_compute_step(0, o);
} while (++o != 0);
}
/*
* onioncrc_step(crc, o)
*
* Given crc = m_0 x^k (mod g) and o = m_1 of degree 7, compute
* and return
*
* crc' = (m_0 x^8 + m_1) x^k (mod g)
*
* using table lookup.
*/
uint16_t
onioncrc_step(uint16_t crc, uint8_t o)
{
return (crc << 8) ^ onioncrc_table[(crc >> 8) ^ o];
}
/*
* onioncrc_buf(crc, p, n)
*
* Given crc = m_0 x^k (mod g) and the degree-(8*n - 1) polynomial
* m_1 = p[0], p[1], ..., p[n - 1], compute and return
*
* crc' = (m_0 x^(8*n) + m_1) x^k (mod g)
*
* using table lookup.
*/
uint16_t
onioncrc_buf(uint16_t crc, const void *buf, size_t len)
{
const uint8_t *p = buf;
size_t n = len;
while (n --> 0)
crc = onioncrc_step(crc, *p++);
return crc;
}
#include <err.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
unsigned char buf[BUFSIZ];
int
main(int argc, char **argv)
{
ssize_t nread;
uint16_t crc = 0;
(void)argc;
(void)argv;
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
err(1, "signal");
onioncrc_init();
while ((nread = read(STDIN_FILENO, buf, sizeof buf)) != 0) {
if (nread == -1)
err(1, "read");
crc = onioncrc_buf(crc, buf, (size_t)nread);
}
if (printf("%04hx\n", crc) < 0)
err(1, "printf");
return 0;
}
More information about the tor-dev
mailing list