wowana.me
website source
commit 8a89605017f86042f36777e65c41cdb31a582960 parent ae45281eb1cd8f5c0607e2e8052c86a61a4ae860 Author: opal hart <opal@wowana.me> Date: Tue, 24 Nov 2020 04:26:01 +0000 add fp.c -- fingerprint colourisation tool used to generate coloured fingerprints on <https://wowana.me/pages/omemo.xht>, uses openkeychain / dino algorithm so people can easily compare fingerprints manually Diffstat:
M | .gitignore | | | 1 | + |
M | Makefile | | | 11 | ++++++++--- |
A | src/fp.c | | | 146 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
3 files changed, 155 insertions(+), 3 deletions(-)
diff --git a/.gitignore b/.gitignore @@ -1,3 +1,4 @@ +/scripts/fp /out/** !/out/.well-known/ !/out/cloudflare-warning.svg diff --git a/Makefile b/Makefile @@ -1,8 +1,9 @@ .PHONY := all check clean upload BLOGSRC := $(wildcard src/blog/*.md) -SRC := $(wildcard src/*.md src/mirrors/*.md) $(BLOGSRC) -OBJ := $(SRC:%.md=%.part.xht) src/blog/index.part.xht -FINAL := $(OBJ:src/%.part.xht=out/%.xht) out/blog/index.xht out/blog/feed.atom +SRC := $(wildcard src/*.md src/pages/*.md src/mirrors/*.md) $(BLOGSRC) +XHT_OBJ := $(SRC:%.md=%.part.xht) src/blog/index.part.xht +OBJ := $(XHT_OBJ) +FINAL := $(XHT_OBJ:src/%.part.xht=out/%.xht) out/blog/index.xht out/blog/feed.atom MARKDOWN := hoedown --xhtml .INTERMEDIATE: $(OBJ) @@ -36,3 +37,7 @@ out/%.xht: src/%.part.xht src/header.inc src/footer.inc out/blog/feed.atom: $(BLOGSRC:%.md=%.part.xht) ./scripts/feed $$(ls -1t $^) > $@ + +scripts/fp: CFLAGS += -Wno-implicit-int +scripts/fp: src/fp.c + $(CC) -o $@ $< $(CFLAGS) -lcrypto diff --git a/src/fp.c b/src/fp.c @@ -0,0 +1,146 @@ +#include <errno.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <openssl/sha.h> + +struct colour { + unsigned char r; + unsigned char g; + unsigned char b; +}; + +int main (int, char**); +static usage (const char*, int); +static html_format_fp (const char*); +bool take_four (char*, const char*); +static from_hex (const char*); +struct colour get_colour (int); +unsigned char uchar_min (unsigned char, unsigned char); + +int main (int argc, char** argv) +{ + if (argc < 2) + return usage(argv[0], 1); + int ret; + while (--argc && !( ret = html_format_fp(argv[1]) )) + ++argv; + if (!ret) + puts(""); + return ret; +} + +usage (const char* arg0, int exit) +{ + fputs("Usage: ", stdout); + fputs(arg0, stdout); + puts(" <fingerprint>"); + return exit; +} + +html_format_fp (const char* fp) +{ + const char* ptr = fp; + bool insert_space = false; + while (*ptr) { + char buf[5]; + if (!take_four(buf, ptr)) + return 1; + int val = from_hex(buf); + if (val < 0) + return 1; + struct colour c = get_colour(val); + fputs("<span style='color:#", stdout); + printf("%02x%02x%02x", c.r, c.g, c.b); + fputs("'>", stdout); + fputs(buf, stdout); + fputs("</span>", stdout); + if (insert_space) + fputs(" ", stdout); + insert_space = !insert_space; + ptr += 4; + } + return 0; +} + +bool take_four (char* buf, const char* str) +{ + if (strlen(str) < 4) { + fputs("string length of value `", stderr); + fputs(str, stderr); + fputs("' is not divisible by four\n", stderr); + return false; + } + strncpy(buf, str, 4); + return true; +} + +/* expects 'str' in range of 0x0000 ~ 0xFFFF. + * returns negative value on error + */ +from_hex (const char* str) +{ + errno = 0; + long val = strtol(str, NULL, 16); + if (errno) { + perror("in from_hex(): strtol"); + return -1; + } + else if (val > 0xFFFF) { + fputs("BUG: value `", stderr); + fputs(str, stderr); + fputs("' is greater than 0xFFFF\n", stderr); + return -1; + } + else if (val < 0x0000) { + fputs("BUG: value `", stderr); + fputs(str, stderr); + fputs("' is negative\n", stderr); + return -1; + } + else return (int) val; +} + +/* algorithm stolen from Dino, in turn stolen from OpenKeyChain */ +struct colour get_colour (int val) +{ + unsigned char bytes[2] = { + (unsigned char) ((val >> 8) & 0xff - 128), + (unsigned char) (val & 0xff - 128), + }; + unsigned char* hash = SHA1(bytes, sizeof bytes, NULL); + struct colour c = { + .r = hash[0], + .g = hash[1], + .b = hash[2], + }; + if (0 == (c.r | c.g | c.b)) + c.r = c.g = c.b = 1; + double brightness = + (.2126 * c.r) + + (.7152 * c.g) + + (.0722 * c.b); + if (brightness < 80.) { + double factor = 80. / brightness; +#define brighten(which) which = uchar_min(255, (unsigned char) (which * factor)) + brighten(c.r); + brighten(c.g); + brighten(c.b); +#undef brighten + } + else if (brightness > 180) { + double factor = 180. / brightness; +#define darken(which) which = (unsigned char) (which * factor) + darken(c.r); + darken(c.g); + darken(c.b); +#undef darken + } + return c; +} + +unsigned char uchar_min (unsigned char a, unsigned char b) +{ + return (a<b)? a : b; +}