Path: ...!eternal-september.org!feeder3.eternal-september.org!i2pn.org!i2pn2.org!.POSTED!not-for-mail From: Stefan Claas Newsgroups: sci.crypt Subject: Putting encrypted data in an X-Face Header :-) Date: Sat, 22 Mar 2025 12:53:51 +0100 Organization: i2pn2 (i2pn.org) Message-ID: <640286bde8850f22227e92c0156e382704f6e916@i2pn2.org> MIME-Version: 1.0 Injection-Date: Sat, 22 Mar 2025 11:53:51 -0000 (UTC) Injection-Info: i2pn2.org; logging-data="1265485"; mail-complaints-to="usenet@i2pn2.org"; posting-account="ieSrCjSDShpZNyqIW52mlwIkg76Hsp+TOOO6KTdfCN8"; User-Agent: flnews/1.3.0pre29 (for GNU/Linux) Cancel-Lock: sha1:rQ/6hLTGFpAi3+hXRuoDW+cW+SE= X-Date: It's Sat Sep 11526 12:53:51 PM CET 1993, the September that never ends. X-Spam-Checker-Version: SpamAssassin 4.0.0 X-Ed25519-Sig: 42eb9641913c28a5c063925bd9dbf0b8d24c34701d01489fb8ed5d9b8f0a60e7 f68d0b93e306a720b0d66263ffc6374c4b0950b8d7d77357272ef5844f0adf0a X-Ed25519-Pub: c0ffee5a36e581eb10f60b2831b3cdb955d2e7ef680dd282a8d43ad8b84b357a Bytes: 7449 Lines: 185 Hi all, just for fun. You can put up to 288 bytes in an X-Face header. If the message is shorter than 288 bytes it will be padded with a checkerboard pattern. https://www.dairiki.org/xface/ $ echo "Hello sci.crypt community. :-)" | d2x #define image_width 48 #define image_height 48 static unsigned char image_bits[] = { 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x73, 0x63, 0x69, 0x2e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x2e, 0x20, 0x3a, 0x2d, 0x29, 0x0a, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff }; Here is the C source code: // d2x - data to xbm #include #include #include #include #define IMAGE_WIDTH 48 #define IMAGE_HEIGHT 48 #define IMAGE_SIZE (IMAGE_WIDTH * IMAGE_HEIGHT / 8) // 288 Bytes #define INPUT_SIZE IMAGE_SIZE // 288 Bytes // Function to embed data into an image with checkerboard padding void encode(uint8_t *image, const uint8_t *data, size_t bytesRead) { for (size_t i = 0; i < bytesRead; i++) { image[i] = data[i]; } // Checkerboard padding for (size_t i = bytesRead; i < IMAGE_SIZE; i++) { // Alternate between 0xFF and 0x00 based on row and column if ((i / IMAGE_WIDTH) % 2 == (i % IMAGE_WIDTH) % 2) { image[i] = 0xFF; // White } else { image[i] = 0x00; // Black } } } // Function to extract data from an image void decode(const uint8_t *image, uint8_t *data) { for (int i = 0; i < INPUT_SIZE; i++) { data[i] = image[i]; } } // Function to write the XBM format void write_xbm(const uint8_t *image, FILE *out) { fprintf(out, "#define image_width %d\n", IMAGE_WIDTH); fprintf(out, "#define image_height %d\n", IMAGE_HEIGHT); fprintf(out, "static unsigned char image_bits[] = {\n"); for (int i = 0; i < IMAGE_SIZE; i++) { // Single space before the first hex value on each line if (i % 12 == 0) { fprintf(out, " "); } // Write the hex value fprintf(out, "0x%02x", image[i]); // Add a comma unless it's the last value if (i < IMAGE_SIZE - 1) { fprintf(out, ","); } // Add a space after each value fprintf(out, " "); // Add a newline after every 12 values if ((i + 1) % 12 == 0 || i == IMAGE_SIZE - 1) { fprintf(out, "\n"); } } fprintf(out, "};\n"); } // Function to read the XBM format int read_xbm(FILE *input, uint8_t *image) { char line[256]; int index = 0; while (fgets(line, sizeof(line), input)) { // Skip lines that do not contain hex values if (!strstr(line, "0x")) { continue; } // Parse hex values char *token = strtok(line, ","); while (token != NULL) { if (sscanf(token, " 0x%02hhx", &image[index]) == 1) { index++; } token = strtok(NULL, ","); } } return index; } // Main function int main(int argc, char *argv[]) { int mode = 0; // 0 = Encode, 1 = Decode // Argument check if (argc > 1) { if (strcmp(argv[1], "-d") == 0) { mode = 1; // Decode mode } else { fprintf(stderr, "Usage:\n"); fprintf(stderr, " sx Put data (max. 288 bytes) from stdin into XBM format and write to stdout\n"); fprintf(stderr, " sx -d Decode XBM image from stdin and write data to stdout\n"); return 1; } } if (mode == 1) { // Decode mode uint8_t image[IMAGE_SIZE] = {0}; int bytesRead = read_xbm(stdin, image); if (bytesRead != IMAGE_SIZE) { fprintf(stderr, "Error: Invalid image size (expected %d bytes, got %d)\n", IMAGE_SIZE, bytesRead); return 1; } uint8_t data[INPUT_SIZE] = {0}; decode(image, data); fwrite(data, 1, INPUT_SIZE, stdout); } else { // Encode mode uint8_t data[INPUT_SIZE] = {0}; size_t bytesRead = fread(data, 1, INPUT_SIZE, stdin); if (bytesRead > INPUT_SIZE) { fprintf(stderr, "Error: Input data too large\n"); return 1; } uint8_t image[IMAGE_SIZE] = {0}; encode(image, data, bytesRead); write_xbm(image, stdout); } return 0; } ========== REMAINDER OF ARTICLE TRUNCATED ==========