diff --git a/README.md b/README.md index 1a613d8..c4b4615 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,14 @@ As usual, you can customize the destination with `DESTDIR` and `prefix`. ## Usage + $ echo -n JBSWY3DPEHPK3PXP | base32 -d | totp + $ 123456 + +Or + + $ echo JBSWY3DPEHPK3PXP | totp -b + $ 123456 + It has been thought for [secret](https://github.com/angt/secret), maybe it will be directly integrated in a future version, in the meantime: diff --git a/totp.c b/totp.c index c1d614f..3850542 100644 --- a/totp.c +++ b/totp.c @@ -1,6 +1,7 @@ // Copyright (c) 2020 by angt // Don't try to reuse the HMAC-SHA1 implementation of this project, // you will suffer unproductively :P +// base32 ignores non-alphabet, doesn't enforce canonical zeros or padding #include #include @@ -98,17 +99,39 @@ erase(void *buf, size_t len) x[i] = 0; } +static size_t +base32_decode(uint8_t *inout, size_t len) +{ + uint8_t *in = inout, *out = inout; + const char *b32 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567", *p; + unsigned v = 0, bits = 0; + + for (; len--; in++) { + if (*in && (p = strchr(b32, *in))) { + v = (v << 5) | (unsigned)(p - b32); + if ((bits += 5) >= 8) + *out++ = (uint8_t)(v >> (bits -= 8)); + } + } + + return (size_t)(out - inout); +} + int main(int argc, char **argv) { uint8_t h[20]; - uint8_t ki[64 + 8] = {0}; + uint8_t ki[64 + 8]; uint8_t ko[64 + 20] = {0}; ssize_t len = read(0, ki, 64); + if (len > 0 && argc > 1 && argv[1][0] == '-' && argv[1][1] == 'b') + len = (ssize_t)base32_decode(ki, (size_t)len); + if (len <= 0) return -1; + memset(ki + len, 0, sizeof(ki) - (size_t)len); memcpy(ko, ki, len); for (int i = 0; i < 64; i++) {