codegroup-19981025/0000755000175000017500000000000010111773457013411 5ustar vlmvlm00000000000000codegroup-19981025/Makefile0000644000175000017500000000147406615151566015064 0ustar vlmvlm00000000000000 PROGS = codegroup CFLAGS = -O all: $(PROGS) clean: rm -f $(PROGS) *.o *.bak *.zip core *.out codegroup: codegroup.o $(CC) codegroup.o -o codegroup $(CFLAGS) # Create zipped archive RELFILES = Makefile codegroup.1 codegroup.c \ codegroup.html codegroup.jpg codegroup.man codegrp.exe release: rm -f codegroup.zip zip codegroup.zip $(RELFILES) # View manual page manpage: nroff -man codegroup.1 | $(PAGER) # Print manual page printman: ptroff -man codegroup.1 # Test it test: codegroup codegroup -e /tmp/codegroup1.bak codegroup -d /tmp/codegroup2.bak cmp codegroup /tmp/codegroup2.bak codegroup -e codegroup /tmp/codegroup1.bak codegroup -d /tmp/codegroup1.bak /tmp/codegroup2.bak cmp codegroup /tmp/codegroup2.bak # rm /tmp/codegroup1.bak /tmp/codegroup2.bak codegroup-19981025/codegroup.10000644000175000017500000001447206615153710015470 0ustar vlmvlm00000000000000.TH CODEGROUP 1 "26 OCT 1998" .UC 4 .SH NAME codegroup \- encode / decode binary file as five letter codegroups .SH SYNOPSIS .B codegroup .BR \-d | \-e [ .B \-u ] [ .I infile [ .I outfile ] ] .SH DESCRIPTION For decades, spies have written their encoded messages in groups of five letters. .PP .B codegroup encodes any binary file into this form, allowing it to be transmitted through any medium, and decodes files containing codegroups into the original input. Encoded files contain a 16-bit cyclical redundancy check (CRC) and file size to verify, when decoded, that the message is complete and correct. Files being decoded may contain other information before and after the codegroups, allowing in-the-clear annotations to be included. .PP .B codegroup makes no attempt, on its own, to prevent your message from being read. Cryptographic security should be delegated to a package intended for that purpose, such as .BR pgp . .B codegroup can then be applied to the encrypted binary output, transforming it into easily transmitted text. Text created by .B codegroup uses only upper case ASCII letters and spaces. Unlike files encoded with .B uuencode or .BR pgp 's ``ASCII armour'' facility, the output of .B codegroup can be easily (albeit tediously) read over the telephone, broadcast on shortwave radio to agents in the field, or sent by telegram, telex, or Morse code. .PP To illustrate the difference, here are the first few lines of a binary file encoded by: .PP .TP 5 .B base64: .CS R 24 .nf H4sICFJ9MzYAA2EudGFyAOxba3faSNKer+lf0SezO3YmgLnY2I6TyQIGgwOGBTtOYjuJEMJo DJJGF1+ys//9rarulpqLHRi/mdk9G84JIKGuqq579eNkNn745q9sNru9tcXhs5gtFPAzm83l xad88WyxmNssbhe3sps8m8ttZ/M/8K1vL9oPP0RBaPggypU1vrad+59zosj0HqAj9xF//pe8 WsaVNbTH1rfkAfoobm7ea//cZn4rtv/mNtq/kM9t/cCz31Io9foftz9nnW77oMdfcdMdWJe+ .CS R .fi .TP .B uuencode: .CS R 24 .nf begin 644 data.bin M'XL("&7._R\\ VUO;V\\ /9U+FN2XSF3G6H5OA1(?HOB<=/<7__X7TNXJ^&PI/\\[?7-7U]KU=]SSWQ? .CS R .fi .TP .B pgp: .CS R 24 .nf -----BEGIN PGP MESSAGE----- Version: 2.6.2i hIwCCb8iTku3pBUBA/9oSDlfk/On9bwjmTnB98Eejr6agkPSi3n6hd8JkAtJd33f kzFq18Jo0xzRUWZ7Di6Jq/FXpeI1yztVDqispbcYOP0aDv4JZOSF1kRsmJ9xK9Bo Cv4a967IXPkkRsjIAkx0B39dYxCzf8kHUn4THmyV/b2qLUZ0cc+mr8hxFfFpuYSM .CS R .fi .TP .B codegroup: .CS R 24 .nf ZZZZZ YBPIL AIAIG FMOPP CPAAA DGNGP GPGPA ADNJN ELJKO ELIMO GEOHF KIFGP IFBCB PKCPI YJMHE PHBHP PPOBH NCOHD AKLLL AGHFP DEGEF LKELC EAIJI ABAGP AHPPO IHHPH OHPDF YNFPB ALEPO KMPKP NGCHI GFPBI CBDML PFGHL LIHPC BOOBB HOLDO FJNHP OLHLL OPNIL .CS R .fi .PP Only .B codegroup conforms to the telegraphic convention of all upper case letters, and passes the ``telephone test'' of being readable without any modifiers such as ``capital'' and ``lower-case''. Avoiding punctuation marks and lower case letters makes the output of .B codegroup much easier to transmit over a voice or traditional telegraphic link. .SH OPTIONS .TP 12 .B \-decode Decodes the input, previously created by .BR codegroup , to recover the original input file, and verifies it to detect truncation or corruption of the contents. .TP .BI \-encode Encodes the input into an output text file containing five letter code groups (default). .TP .B \-usage Print how-to-call information. .PP All options may be abbreviated to a single letter. .SH "APPLICATION NOTES" Encoding a binary file as ASCII characters inevitably increases its size. When used in conjunction with existing compression and encryption tools, the resulting growth in file size is usually acceptable. For example, a random extract of electronic mail 32768 bytes in length was chosen as a test sample. Compression with .B gzip compacted the file to 15062 bytes. It was then encrypted for transmission to a single recipient with .BR pgp , which resulted in a 15233 byte file. (Even though .B pgp has its own compression, smaller files usually result from initial compression with .BR gzip . In this case, .B pgp alone would have produced a file of 15420 bytes.) .PP .B codegroup transforms the encrypted file into a 37296 byte text file. Thus, due to compression, the code groups for the encrypted file are only a little larger than the original cleartext. .PP Restricting the character set and including spaces between groups results in substantially larger output files than those produced by .B uuencode and .BR pgp . Files encoded with .B codegroup are about 2.5 times the size of the input file, while .B uuencode and .B pgp expand the file only about 35%. .B codegroup is thus preferable only for applications where its limited character set is an advantage. .SH FILES If no .I infile is specified or .I infile is a single ``\-'', .B codegroup reads from standard input; if no .I outfile is given, or .I outfile is a single ``\-'', output is sent to standard output. The input and output are processed strictly serially; consequently .B codegroup may be used in pipelines. .SH BUGS When a CRC error is detected, no indication is given of the location in the file where the error(s) occurred. When sending large files, you may want to break them into pieces with the .B splits utility (available from the Web page cited below) so, in case of error, only the erroneous pieces have to be re-sent. .PP It might be nice to embed the original file name and modes in the encoded output, but this opens the door to all kinds of system-dependent problems. You can always include this information as text before the first codegroup, or send an archive created with .B tar or .BR zip . .SH "SEE ALSO" .PD .BR base64 (1), .BR gzip (1), .BR pgp (1), .BR splits (1), .BR tar (1), .BR uuencode (1), .BR zip (1) .ne 5 .SH EXIT STATUS .B codegroup returns status 0 if processing was completed without errors, 1 if errors were detected in decoding a file which indicate the output is incorrect or incomplete, and 2 if processing could not be performed at all due, for example, to a nonexistent input file or no codegroups found in the input. .SH AUTHOR .RS 5 .nf John Walker .fi .RE .PD .PP This software is in the public domain. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, without any conditions or restrictions. This software is provided ``as is'' without express or implied warranty. codegroup-19981025/codegroup.c0000644000175000017500000004041406615153672015554 0ustar vlmvlm00000000000000/* Encode or decode file as five letter code groups by John Walker http://www.fourmilab.ch/ This program is in the public domain. December 1986: Original version July 1995: Unified encoder and decoder in one program, replaced ad-hoc checksum with CRC-16. October 1998: HTML documentation, Zipped distribution archive including ready-to-run MS-DOS program. */ #define REVDATE "25th October 1998" #include #include #include #include #ifdef _WIN32 #include #include #endif #define TRUE 1 #define FALSE 0 typedef unsigned char byte; /* Byte type */ #define EOS '\0' #define GROUPLEN 5 /* Code group type */ #define LINELEN 64 /* Maximum line length */ #define ERRMAX 10 /* Maximum data lost messages to print */ static FILE *fi = stdin; /* Input file */ static FILE *fo = stdout; /* Output file */ static char groupbuf[GROUPLEN + 1]; /* Group assembly buffer */ static char linebuf[LINELEN + 4]; /* Line editing buffer */ static byte iobuf[256]; /* I/O buffer */ static byte obuf[32]; /* Output assembly buffer */ static long gcount = 0L; /* Groups sent count */ static long cksum = 0L; /* Data checksum */ static int gblen = 0; /* Group bytes used count */ static int linelen = 0; /* Bytes used in line */ static int gprefix; /* Prefix for data block group */ static int iolen = 0; /* Bytes left in I/O buffer */ static int iocp = 256; /* Character removal pointer */ static int ateof = FALSE; /* EOF encountered */ static int obnib = 0; /* Output nybble index */ static int obbyte = 0; /* Output byte index */ static int exitstat = 0; /* Exit status */ /* This is the precomputed remainder table for generating and checking cyclic redundancy check characters. */ static byte low8[] = { 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0, 0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41, 0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0, 0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40, 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1, 0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41, 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1, 0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41, 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0, 0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40, 0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1, 0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40, 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0, 0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40, 0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0, 0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40, 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0, 0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41, 0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0, 0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41, 0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0, 0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40, 0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1, 0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41, 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0, 0x80,0x41,0x00,0xC1,0x81,0x40 }; static byte high8[] = { 0x00,0xC0,0xC1,0x01,0xC3,0x03,0x02,0xC2,0xC6,0x06, 0x07,0xC7,0x05,0xC5,0xC4,0x04,0xCC,0x0C,0x0D,0xCD, 0x0F,0xCF,0xCE,0x0E,0x0A,0xCA,0xCB,0x0B,0xC9,0x09, 0x08,0xC8,0xD8,0x18,0x19,0xD9,0x1B,0xDB,0xDA,0x1A, 0x1E,0xDE,0xDF,0x1F,0xDD,0x1D,0x1C,0xDC,0x14,0xD4, 0xD5,0x15,0xD7,0x17,0x16,0xD6,0xD2,0x12,0x13,0xD3, 0x11,0xD1,0xD0,0x10,0xF0,0x30,0x31,0xF1,0x33,0xF3, 0xF2,0x32,0x36,0xF6,0xF7,0x37,0xF5,0x35,0x34,0xF4, 0x3C,0xFC,0xFD,0x3D,0xFF,0x3F,0x3E,0xFE,0xFA,0x3A, 0x3B,0xFB,0x39,0xF9,0xF8,0x38,0x28,0xE8,0xE9,0x29, 0xEB,0x2B,0x2A,0xEA,0xEE,0x2E,0x2F,0xEF,0x2D,0xED, 0xEC,0x2C,0xE4,0x24,0x25,0xE5,0x27,0xE7,0xE6,0x26, 0x22,0xE2,0xE3,0x23,0xE1,0x21,0x20,0xE0,0xA0,0x60, 0x61,0xA1,0x63,0xA3,0xA2,0x62,0x66,0xA6,0xA7,0x67, 0xA5,0x65,0x64,0xA4,0x6C,0xAC,0xAD,0x6D,0xAF,0x6F, 0x6E,0xAE,0xAA,0x6A,0x6B,0xAB,0x69,0xA9,0xA8,0x68, 0x78,0xB8,0xB9,0x79,0xBB,0x7B,0x7A,0xBA,0xBE,0x7E, 0x7F,0xBF,0x7D,0xBD,0xBC,0x7C,0xB4,0x74,0x75,0xB5, 0x77,0xB7,0xB6,0x76,0x72,0xB2,0xB3,0x73,0xB1,0x71, 0x70,0xB0,0x50,0x90,0x91,0x51,0x93,0x53,0x52,0x92, 0x96,0x56,0x57,0x97,0x55,0x95,0x94,0x54,0x9C,0x5C, 0x5D,0x9D,0x5F,0x9F,0x9E,0x5E,0x5A,0x9A,0x9B,0x5B, 0x99,0x59,0x58,0x98,0x88,0x48,0x49,0x89,0x4B,0x8B, 0x8A,0x4A,0x4E,0x8E,0x8F,0x4F,0x8D,0x4D,0x4C,0x8C, 0x44,0x84,0x85,0x45,0x87,0x47,0x46,0x86,0x82,0x42, 0x43,0x83,0x41,0x81,0x80,0x40 }; static unsigned int crc1, crc2; /* CRC accumulation cells */ /* CRCCHAR -- Include byte in CRC. */ static void crcchar(byte b) { unsigned int c; crc1 = low8[c = 0xFF & (b ^ crc1)] ^ crc2; crc2 = high8[c]; } /* CRCINIT -- Initialise CRC computation. */ static void crcinit(void) { crc1 = crc2 = 0; crcchar(1); /* Guarantee no leading zeroes */ } /* OUTLINE -- Output next line */ static void outline(void) { linebuf[linelen++] = '\n'; fwrite(linebuf, linelen, 1, fo); linelen = 0; } /* OUTGROUP -- Output next group to line buffer */ static void outgroup(void) { if ((linelen + GROUPLEN + 1) > LINELEN) { outline(); } if (linelen > 0) { linebuf[linelen++] = ' '; } strcpy(linebuf + linelen, groupbuf); linelen += GROUPLEN; gblen = 0; gcount++; /* Increment groups sent */ } /* OUTCHAR -- Output next character to group */ static void outchar(int c) { groupbuf[gblen++] = c; if (gblen >= GROUPLEN) { outgroup(); } } /* OUTBYTE -- Output next encoded byte as two group characters */ static void outbyte(int b) { crcchar(b); outchar('A' + ((b & 0xF0) >> 4)); outchar('A' + (b & 0xF)); } /* OUT32 -- Output 32 byte data block */ static void out32(int code, byte dbuf[32]) { int i; outchar(code); for (i = 0; i < 32; i++) { outbyte((int) dbuf[i]); } } /* STORELONG -- Store long value in I/O buffer (byte-order independent) */ static void storelong(byte *cp, long l) { int i; for (i = 0; i < 4; i++) { *cp++ = l & 0xFF; l >>= 8; } } /* ENGROUP -- Encode binary file into code groups. */ static void engroup(void) { int i, l; strcpy(groupbuf, "ZZZZZ"); /* Place start sentinel */ outgroup(); while (TRUE) { l = fread(iobuf + 1, 1, 32, fi); if (l <= 0) { break; } if (l < 32) { iobuf[0] = (byte) l; out32('V', iobuf); } else { out32('Y', iobuf + 1); } } /* Emit ending record with group count and checksum. */ storelong(iobuf, gcount); cksum = (crc1 << 16) | crc2; storelong(iobuf + 4, cksum); for (i = 8; i < 32; i += 4) { storelong(iobuf + i, cksum = (gcount ^ cksum) ^ (cksum >> 3) ^ (cksum << 3)); } out32('U', iobuf); strcpy(groupbuf, "WWWWW"); /* Place end sentinel */ outgroup(); outline(); } /* INBUF -- Fill input buffer with data */ static int inbuf(void) { int l; if (ateof) { return FALSE; } l = fread(iobuf, 1, 256, fi); /* Read input buffer */ if (l <= 0) { ateof = TRUE; return FALSE; } iolen = l; iocp = 0; return TRUE; } /* INCHAR -- Return next character from input */ static int inchar(void) { if (iocp >= iolen) { if (!inbuf()) { return EOF; } } return iobuf[iocp++]; } /* INSIG -- Return next significant input */ static int insig(void) { int c; static int skipws = FALSE; /* Skip white space flag */ if (skipws) { while (TRUE) { c = inchar(); if (c == EOF || (c > ' ')) { skipws = FALSE; return c; } } } c = inchar(); if (c <= ' ') { c = ' '; skipws = TRUE; } return c; } /* INSKERR -- Skip error. Ignores input until next white space or end of file. */ static void inskerr(void) { int ch; while (TRUE) { ch = insig(); if (ch == EOF || ch == ' ') { break; } } } /* INGROUP -- Scan next code group into group buffer. Returns FALSE if an error is detected in the code group, EOF if the end of file is hit, and TRUE if a valid group is assembled. */ static int ingroup(void) { int gp = 0; /* Group data pointer */ int ch; while (TRUE) { ch = insig(); if (ch == EOF) { return EOF; } if (ch != ' ') { if (ch < 'A' || ch > 'Z') { inskerr(); return FALSE; } groupbuf[gp++] = ch; break; } } while (TRUE) { ch = insig(); if (ch == EOF || ch == ' ') { if (gp < 5) { return FALSE; /* Short groups got no reason to live */ } gcount++; /* Increment valid groups received */ return TRUE; } if (ch < 'A' || ch > 'Z') { inskerr(); return FALSE; } if (gp >= 5) { inskerr(); /* Group is too long */ return FALSE; } groupbuf[gp++] = ch; } /* NOTREACHED */ } /* OSTORE -- Store data group starting at specified offset. Verifies that this is not a control group being misinterpreted. */ static int ostore(int x) { int i, j; for (i = x; i < 5; i++) { if (groupbuf[i] < 'A' || groupbuf[i] > ('A' + 15)) { return FALSE; } j = groupbuf[i] - 'A'; if (obnib) { obuf[obbyte++] |= j; obnib = FALSE; } else { obuf[obbyte] = j << 4; obnib = TRUE; } } return TRUE; } /* IN32 -- Input data record. Returns EOF if 'WWWWWW' terminator group found, FALSE if an error is detected, and TRUE if a valid group was decoded. If a valid group was found, its data is stored in OBUF, with the prefix letter in GPREFIX. If an error was previously reported, all data is ignored until a valid start of record group is found. */ static int in32(void) { int inerr = FALSE; int i, j; if (inerr) { while (TRUE) { i = ingroup(); if (i == EOF) { return EOF; } if (i == TRUE) { if (groupbuf[0] == 'Y' || groupbuf[0] == 'V' || (strcmp(groupbuf, "WWWWW") == 0)) { inerr = FALSE; break; } } } } else { i = ingroup(); } if (i == EOF || i == FALSE) { inerr = TRUE; return FALSE; } if (strcmp(groupbuf, "WWWWW") == 0) { return EOF; } gprefix = groupbuf[0]; if (gprefix == 'Y' || gprefix == 'V' || gprefix == 'U') { obnib = 0; obbyte = 0; i = ostore(1); if (i == FALSE) { inerr = TRUE; return FALSE; } for (j = 0; j < 12; j++) { i = ingroup(); if (i == EOF || i == FALSE) { inerr = TRUE; return FALSE; } if (!ostore(0)) { inerr = TRUE; return FALSE; } } for (j = 0; j < 32; j++) { crcchar(obuf[j]); } return TRUE; } else { inerr = TRUE; return FALSE; } } /* GETLONG -- Load LONG from a byte stream in an order-independent fashion. */ static long getlong(byte *cp) { int i; long l; for (l = 0L, i = 0; i < 4; i++) { l |= ((long) (*cp++)) << (i * 8); } return l; } /* UNGROUP -- Decode codegroups. */ static void ungroup(void) { int i, l, nerrs = 0; long savegc, savecs; groupbuf[GROUPLEN] = EOS; /* Set group terminator */ /* Ignore all text before initial ZZZZZ group. */ l = 0; while (TRUE) { i = insig(); if (i == EOF) { break; } if (i == 'Z') { l++; if (l == 5) { i = insig(); if (i == EOF) { break; } if (i == ' ') { break; } else { l = (i == 'Z' ? 5 : 0); } } } else { l = 0; } } /* If we hit end of file before finding the first code group, issue an error message. */ if (i == EOF) { fprintf(stderr, "No code groups found in input.\n"); exitstat = 2; return; } gcount = 1; /* Account for initial sentinel group */ while (TRUE) { savegc = gcount; cksum = (crc1 << 16) | crc2; savecs = cksum; i = in32(); if (i == EOF) { fprintf(stderr, "Warning: count and checksum missing.\n"); fprintf(stderr, " File may be incomplete.\n"); exitstat = 1; return; } if (i == FALSE) { if (++nerrs <= ERRMAX) { fprintf(stderr, "Error: skipping to next group. Data lost.\n"); exitstat = 1; } } else { if (gprefix == 'U') { if (nerrs > ERRMAX) { nerrs = nerrs - ERRMAX; fprintf(stderr, "Too many errors. %d additional data lost message%s suppressed.\n", nerrs, nerrs > 1 ? "s" : ""); } gcount = getlong(obuf); cksum = getlong(obuf + 4); if (gcount > savegc) { fprintf(stderr, "Warning: groups missing from file.\n"); fprintf(stderr, " Groups sent: %ld, Groups received %ld.\n", gcount, savegc); exitstat = 1; } else if (gcount < savegc) { fprintf(stderr, "Warning: extraneous groups in file.\n"); fprintf(stderr, " Groups sent: %ld, Groups received %ld.\n", gcount, savegc); exitstat = 1; } if (cksum != savecs) { fprintf(stderr, "Warning: checksum error on file contents.\n"); #ifdef DUMPCKSUM fprintf(stderr, " Checksum sent: %lX, received: %lX\n", cksum, savecs); #endif exitstat = 1; } if (in32() != EOF) { fprintf(stderr, "Warning: extraneous material after final data block.\n"); exitstat = 1; } return; } else if (gprefix == 'Y') { fwrite(obuf, 32, 1, fo); } else { fwrite(obuf + 1, 1, obuf[0], fo); } } } } /* Main program */ int main(int argc, char *argv[]) { int i, f = 0, decode = FALSE; char *cp, opt; for (i = 1; i < argc; i++) { cp = argv[i]; if (*cp == '-') { opt = *(++cp); if (islower(opt)) { opt = toupper(opt); } switch (opt) { case 'D': decode = TRUE; break; case 'E': decode = FALSE; break; case 'U': case '?': fprintf(stderr,"\n%s -- Encode/decode file as code groups. Call:", argv[0]); fprintf(stderr, "\n %s [-e[ncode] / -d[ecode]] [infile] [outfile]", argv[0]); fprintf(stderr,"\n"); return 0; } } else { switch (f) { /** Warning! On systems which distinguish text mode and binary I/O (MS-DOS, Macintosh, etc.) the modes in these open statements will have to be made conditional based upon whether an encode or decode is being done, which will have to be specified earlier. But it's worse: if input or output is from standard input or output, the mode will have to be changed on the fly, which is generally system and compiler dependent. 'Twasn't me who couldn't conform to Unix CR/LF convention, so don't ask me to write the code to work around Apple and Microsoft's incompatible standards. This file contains code, conditional on _WIN32, which sets binary mode using the method prescribed by Microsoft Visual C 1.52 ("Monkey C"); this may require modification if you're using a different compiler or release of Monkey C. */ case 0: if (strcmp(cp, "-") != 0) { if ((fi = fopen(cp, "r")) == NULL) { fprintf(stderr, "Cannot open input file %s\n", cp); return 2; } } f++; break; case 1: if (strcmp(cp, "-") != 0) { if ((fo = fopen(cp, "w")) == NULL) { fprintf(stderr, "Cannot open output file %s\n", cp); return 2; } } f++; break; default: fprintf(stderr, "Too many file names specified.\n"); return 2; } } } crcinit(); if (decode) { #ifdef _WIN32 _setmode(_fileno(fo), _O_BINARY); #endif ungroup(); } else { #ifdef _WIN32 _setmode(_fileno(fi), _O_BINARY); #endif engroup(); } return exitstat; } codegroup-19981025/codegroup.html0000644000175000017500000002051606615150642016271 0ustar vlmvlm00000000000000 CODEGROUP: Five-Letter Codegroup Filter

CODEGROUP

Five-Letter Codegroup Filter


This page describes a program, codegroup, which encodes and decodes arbitrary binary data in five-letter code groups, just like spies use.

NAME

codegroup - encode / decode binary file as five letter codegroups

SYNOPSIS

codegroup -d|-e [ -u ] [ infile [ outfile ] ]

DESCRIPTION

For decades, spies have written their encoded messages in groups of five letters.

codegroup encodes any file into this form, allowing it to be transmitted through any medium, and decodes files containing codegroups into the original input. Encoded files contain a 16-bit cyclical redundancy check (CRC) and file size to verify, when decoded, that the message is complete and correct. Files being decoded may contain other information before and after the codegroups, allowing in-the-clear annotations to be included.

codegroup makes no attempt, on its own, to prevent your message from being read. Cryptographic security should be delegated to a package intended for that purpose, such as pgp. codegroup can then be applied to the encrypted binary output, transforming it into easily transmitted text. Text created by codegroup uses only upper case ASCII letters and spaces. Unlike files encoded with uuencode or pgp's "ASCII armour" facility, the output of codegroup can be easily (albeit tediously) read over the telephone, broadcast by shortwave radio to agents in the field, or sent by telegram, telex, or Morse code.

To illustrate the difference, here are the first few lines of a binary file encoded by:

base64:
H4sICFJ9MzYAA2EudGFyAOxba3faSNKer+lf0SezO3YmgLnY2I6TyQIGgwOGBTtOYjuJEMJo
DJJGF1+ys//9rarulpqLHRi/mdk9G84JIKGuqq579eNkNn745q9sNru9tcXhs5gtFPAzm83l
xad88WyxmNssbhe3sps8m8ttZ/M/8K1vL9oPP0RBaPggypU1vrad+59zosj0HqAj9xF//pe8
WsaVNbTH1rfkAfoobm7ea//cZn4rtv/mNtq/kM9t/cCz31Io9foftz9nnW77oMdfcdMdWJe+
uuencode:
begin 644 data.bin
M'XL("&7._R  VUO;V /9U+FN2XSF3G6H5OA1(?HOB<=/<7__X7TN<PJ[L&
M=?-&1;I+) B8 0;P?_Z'?WY_-=7Q"T_JSZ_6)X9?&"$OU9[N'A[A%^L^6=
M?^M[OOV+:9=UM9J^] MAS_ ;X0O]U];(Z?<WWE9_[/]ZMMOO[CG'^2MM
M_G(+,US/LWKZE1#C^YO?D_;O#G[7][2R^+0>XJ^&PI/[?7-7U]KU=]SSWQ?
pgp:
-----BEGIN PGP MESSAGE-----
Version: 2.6.2i

hIwCCb8iTku3pBUBA/9oSDlfk/On9bwjmTnB98Eejr6agkPSi3n6hd8JkAtJd33f
kzFq18Jo0xzRUWZ7Di6Jq/FXpeI1yztVDqispbcYOP0aDv4JZOSF1kRsmJ9xK9Bo
Cv4a967IXPkkRsjIAkx0B39dYxCzf8kHUn4THmyV/b2qLUZ0cc+mr8hxFfFpuYSM
codegroup:
ZZZZZ YBPIL AIAIG FMOPP CPAAA DGNGP GPGPA ADNJN ELJKO ELIMO
GEOHF KIFGP IFBCB PKCPI YJMHE PHBHP PPOBH NCOHD AKLLL AGHFP
DEGEF LKELC EAIJI ABAGP AHPPO IHHPH OHPDF YNFPB ALEPO KMPKP
NGCHI GFPBI CBDML PFGHL LIHPC BOOBB HOLDO FJNHP OLHLL OPNIL
Only codegroup conforms to the telegraphic convention of all upper case letters, and passes the "telephone test" of being readable without any modifiers such as "capital" and "lower-case". Avoiding punctuation marks and lower case letters makes the output of codegroup much easier to transmit over a voice or traditional telegraphic link.

OPTIONS

-d
Decodes the input, previously created by codegroup, to recover the original input file, and verifies it to detect truncation or corruption of the contents.

-e
Encodes the input into codegroups.

-u
Print how-to-call information.

APPLICATION NOTES

Encoding a binary file as ASCII characters inevitably increases its size. When used in conjunction with existing compression and encryption tools, the resulting growth in file size is usually acceptable. For example, a random extract of electronic mail 32768 bytes in length was chosen as a test sample. Compression with gzip compacted the file to 15062 bytes. It was then encrypted for transmission to a single recipient with pgp, which resulted in a 15233 byte file. (Even though pgp has its own compression, smaller files usually result from initial compression with gzip. In this case, pgp alone would have produced a file of 15420 bytes.)

codegroup transforms the encrypted file into a 37296 byte text file. Thus, due to compression, the code groups for the encrypted file are only a little larger than the original cleartext.

Restricting the character set to upper case letters and including spaces between groups results in substantially larger output files than those produced by uuencode and pgp. Files encoded with codegroup are about 2.5 times the size of the input file, while uuencode and pgp expand the file only about 35%. codegroup is thus preferable only for applications where its limited character set is an advantage.

FILES

If no infile is specified or infile is a single "-", codegroup reads from standard input; if no outfile is given, or outfile is a single "-", output is sent to standard output. Input and output are processed strictly serially; consequently codegroup may be used in pipelines.

BUGS

When a CRC error is detected, no indication is given of the location in the file where the error(s) occurred. When sending large files, you may want to break them into pieces with the splits utility so, in case of error, only the erroneous pieces need to be re-sent.

It might be nice to embed the original file name and modes in the encoded output, but this opens the door to all kinds of system-dependent problems. You can always include this information as text before the first codegroup, or send an archive created with tar or zip.

Download codegroup.zip (Zipped archive)

The program is provided as codegroup.zip, a Zipped archive containing an ready-to-run WIN32 command-line executable program, codegrp.exe (compiled using Microsoft Visual C++ 5.0), and in source code form along with a Makefile to build the program under Unix.

SEE ALSO

base64(1), gzip(1), pgp(1), splits(1), tar(1), uuencode(1), zip(1)

EXIT STATUS

codegroup returns status 0 if processing was completed without errors, 1 if errors were detected in decoding a file which indicate the output is incorrect or incomplete, and 2 if processing could not be performed at all due, for example, to a nonexistent input file or no codegroups found in the input.

COPYING

This software is in the public domain. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, without any conditions or restrictions. This software is provided "as is" without express or implied warranty.

by John Walker
October 26th, 1998
codegroup-19981025/codegroup.jpg0000444000175000017500000010403606615141550016101 0ustar vlmvlm00000000000000JFIFC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222|" dH pkۀjqF"hp{DRN\,j$jppBpp6D%Pu0_Dݭ=iARp]ǫk=l|[Uw*w'us=kųe[%8%zXĞqt5}/q%?O}6<<=+uo<}\']ձt|njx.ʿ[sp{q/87ÎplZ5>-pvz;Ϧmxy],xٍDD#տIҠqnn8Pg\|ΜYk+[E}W txru_]Eqؗk__u<7vÿus]:?(N Lgmx7/g m/qlNzFxٗ;<2p8W}tfy=0vz-jx]=9gzCs~A>M|'qoEw4r~~t9s~pyh|>V==gWO/s[zL+{M=C3r^3v9 37Ϲx]_#cީwאz_{rW}yvz?O_徹|ǣzsÿ(3?Mña' mjjԑ?\OQ=[} mβ>#zD9.2Ѡv86= ?G3jzػ^x_B>x#ղxzbU3GĻ5[!O=>O̬ks󽼅{KhysoM[jWfiݗ5s^sgRw7FUfv-Ҵ ye?T\-T0FƗ+A4XcpΚ*n rb{q:-6 >WD AFuG˶3ޗkb|3/drgE.ϓRx$ 'lC#j,Y=S1j=)Zb뢓h-29[M,'U"Wʩ6(]<0cDfKzC_\Pm`4UEO T?W7)ݳ.fPFnJ~dj:Hքl-׊Bƭ ` ̸Xi>"}3?yl}pFM_ŎoxdsG+S{pouߎ ÌPf9$R-f)fhs>g';m:[&k֬2[l?c~ϳpt<>x'n66,SxT9j2wGv٧!qf qmA{DwaGOa}0 Y$?o8GdO@ݬBMF}ͩ\+bFH#b5Kaa]' DFT&\+*#Ru<3*n> u=gjt:k4i7 Vmnp`hVaDEEW6E[1 ݰ'{ 4,. yzpƠWoʏwax]V2wBS99e`az3-*mq~%_YQ?m,1j! d{%N(ԍsw׿Bʯ>Hck!:s ]yLbɭ}PC4p*> `4aip_q-ĹRw=?QMUG*;$mժDVu6)0 f.xԅ #sHڱ3{Lt*sCx@-+\vz_:ZU08yuo4Sru9#7f̩UQ1es˩ M~a;ö>$,xVM%T)a+ʘ؇?=_F BTӕ7UsɜJJR φ+fyߤ%cUP3U`[j*TkZ?KT~lb>F܉A"Uc&Z=EHpbX0}{|miI+QxժV~ WUQb8XX.Pe;DBpib)Nx L;,V$冯~UN7mFӱ>AkV/rֹi9U\,͵kž[Oχ7ԩb޶ O97ڨ J (LOS-wV)V2銼ŬV=vkV" 9QPuEU2}nUʪ-6U*PKR)dfu:NjO#oʗZMfg7"p%xyLQ=j.Q567þQl6_u8D_SITcSΜ~'E&fh<l6 >1"PG ӎD`GYF:QJ`U!(˃3Pj<[QIvg BTjOQӚB@|*!'IK1VQhᦟ c6μżN0]!ՋuȔ1C%YWgm4%OԴ2 E;-&B Me*j0[jM; j悉:*YpVY$eENmJFhIaW3Fj9G"]KFgxH>-6SӦB ti"le8H\k;әSy7GIU6z8MXtd#qӓБvALCB8lpN@;c8H(Ba[kp#oK 3amVaHXeXeB,j/c2,2k,2p [Emde[YaɅaa݅[YcaXdΰ̰k"!{"K#E#.t{ӻ2;q;1xhc1;1tβ. 8!v&&R^x"RO;bNB(hB)73x32 @RNѠ;ssɁK8#6dt[@-1!l y,A1jf+*@gd[2\,)ɠ(1Us0n<^^ ݟE9E+V C^~Y4Y<8>ax&;d-MJ)Gl٘%LaL[!yf CN;G QEˍm6%3-Gq;ǾGLdgk^"l`4uIӼNN4#0.R[~\a@1cgSV͈4O" YY-oQ)ŲQ<c#1!A 0BpQ?E-fѲ͢lZfѲ6BxţeJVh8vN_d> YX%CA8dEY<[4.ɑ?a%C]?R> t|#l_FTn K:L1]3tu|!7Dec^qpJEb>|Ԃ9W%\P3Li.7*V^{5Sj oE- 3M)|1uYZ& p3*!w]f蓚v7HݕLgܪY/8jt0&꺱6(]ڴ# 1Y_pWV@畲V+8"yW%Y Ü:!eнiWW(OWUB[]_'+t2#+ed2* @"V@ld+/ f~>Uaoo@1!"2AQa q3BR#0b@r$CP`sc?2GoKXaçC[M[R77ͤը,'{vMzJ Mo:ڐeg9oYF-xo^&Ņ5_Q-٭ur>E`-WE_8͸kfl!+pn 53wMky_>3w_Nw@kYzOԣQ+[tag|Ok/cgJK ɝVbo{]s2uA;촲qS=5ÆʢY"OT*~#JNF<׼"\tWlւt麉ctQFa~Վ#wm8k j]:\,ѭ>VƙW[fH>@7r]Χ5t9PgM`l@B{㇢;Y/ERG R4u*㟔C~hϛfZ>רd檹9fM624Zs];߿LQsXvϮ_ΦR J.⛞]T+TwJPb o tڙ(Y6˛0$TUEke"eʮWw*FS 0@NveϘf9|J<1cz4?dm4ڏl1aMWWU]څ@B<>KE:貲".K{;=BkV2.q{k){ҶcT"- 7Ncc{CAƦ` iuPp;.[+f:UېÀ57AZP\`ןu^ys@Jw ab:aR9 ^$My-0ɭ9p(թaNZ|0ѥjӄF7VֈÁE sq~)qy}0IV-Apr.)¤XœkznU2 \'ƱBNjTې-pz"&|wHi 0Y ;Oco.YA@ЩOU(3(Y%g@IQ jF|c ]P<ޑ96faJ?D 5>pKxݠ^a BmFP ߦ^{QTFy}Sl쪴.ѳm tkȢƒ%= HM@Tc83 {(y^ѿBu&С߳w a1djsO[FVPG 5@X8HԢ$ :Qәm R]N 4 U=rPy<+/`1uS~a'@~4m h$Lv̓Z:15BgU:_'~9dgh4MFlwȎn79H̾2{cXA}g=V7bZr`n4зvuOU)5f^(sIUw8w̘ߛ{ WT+p>9je")0p%Jܹ4< e׉'k6UC@aiޝ2 k';1NڑշO *Vq'EgODq'pр4657e9)꣞a`b~"9ܕQ}TYaeSh ].O!궊Ԩa~9qfM`)G ʋ=N |hĦ##{?{?{4 "ppAUcn搡]p;#R 7e5ߪz-N38|o`za_}VNKBV~j4^$aPFjSbP~xϟoj֧|> x\ `aYYYYop pk eToGHs$PUժEXcic:[t1 `(ӿ ̎&uJBno9|ԫ\}<dv,j-|Fȸ% .krqAvӢ )g  KZ3a"}:=Y|凲ra >VGfG#tjWɊlUJ 9\~Wqܝb5X6t=n֜Ί(S99J*_kZ5 v15\ P@~ODYٹfUfidK]4PR<-J<X uR.9F ԏ57HȔ'ںsr ڞ|Nɾh-W ll\l'0ݷA*_PYת>Ie{KOCYMܚto]Cc|FW"iBe8pH1mkB|2?p6GQhr }S3CR kgQJe/͟`go8W@2Ey*fNnep Z-,tjpi2$(EWnA^} 1dkvI?V ymTnTBuEODǶ2ZS,CR6>miZIDI#\ պ. 055ue{CBO5,2C}*HSh(+ѪJחҸ[F.$DZ,7e *"M07Ɔ{)+y#++`|(Mee%c +}ŕG7ydy2Q{-$8n Fa8Mu*oi9by;13k7m6ԣS!:!֋GR~D)"MO;DVϛF65Y94 ړ.2Tm>U vto;ȨJ3iRuOɪz'V#}ߐ5IfurZ G%ξ `D?lҵ0X adhU2nUj\*@eeeee$ =Օ煿5eeV&/X+ , ѲT@V Y˄ae u*g)M aq4_g_<} <ӠM(:I|Zz'>Zg\'nsfo;:P HewDR,c qKKzģ. =C\ri6E n qvFΟqo5YY[ +y-YYYYYY[ +e`QY6:kCx?k?\h7XR'!1AQaq ?!*wR.P̫ע{r'=V%d'sh}((ebVIjVOJw&ɾf1Va'O Ga޼ʮ%YsbgUF*wR#\GC+0G2w+UxyVV\GdsZˉ7ǯ1Tсn$Vu̬}R5R1r2J`*SwJϡ's,qp*q;q.51qgsQ;\niK=,Miߣ|J\:U{Cec3*q̬bf?2uQW0'}L/Gv/+N5 M8et%_W:f3y牾!13pjShIosfYK.$AwO˂r-8z[2h [U \Ws~ߧ8s7N}c["&inJ/x,߂P~2 sY2WGCx5/.׺ C1O b:5G|ΝҟL`ذ{-^aɜcl.:]wp\hJ 7 `(EOyN8_17 ʿ ޸?6e sv2 b8c0xY^Gscza~^Ez͖$25{7񻾜ř]Ck^b)i-~gGA@ & +[| t;.CyxXJɰ*NoJk_ n:2e{GGTvU%<'E:8&O@8b6JJρ bO}w5 3 ߘtc@5KJQe{PnE&tLޢ >SxXcu%(ܴ&й%9wĮn 5_{A #uE}R]u)}wG_0T[h4$"XYk'?+{t@ߴ[EBovi*~|J_ED h-dXEPG[?7O_뤮aAE{3΢:}_#?f]R3V{8ѣW:4(Dq~øu?ZC #2a*sg2`C%+<,Sk]O7O1^@6B@Ot ÕuSBڶ=d$Vǹ%}b٘Kg ?.ȣ 9xw7Z3f0%-CdAeyNØ h`uzj!%/Ђf\ʜL:LZǭ4MQ+S}$ROx pOzO&q sDw''>?.CVLA0+V￯2ٖ#({Č׈xAI=x-))3n~q:Ri񬛘cjb(nd)(GW<ʰF2%Y&mmTdxFil";9`t}YhQFVOI;nz3ja}Wܕ+4؛hkd.AqnO/`8"i*'p0uQ#0O#\V<_|@G05QO)o`? VG̾pw7֢6^mLـK%Qj|~j0A?>="Q @fGC*{*.ҫ,lJ|h+e뇩DQc:y'bx#HX69/*1 2͈CS#L uQ*эVw5Đ::z<C1mF}Tss1 5y!"}ܻge5`g%}tzЯD{Mu!3O2j6?0P@eq0\rp "pqv lGg*ࡀv[<D5R'8A1}t-%gLԲ9)ܱ.0WUG [|,ӭF(`em 85Xтx=-+ zi@d~xBJ1-ctf~Ʉ %e SURXe`x`ai\ĭRA̳ ؜-)ML^%ʫ 혵r)v.&F!Sbh <5RK(at!dQzQ(&MK=1weW$:˹VkQQ l"bq82!qo51cZ'*`[9O<b|< w >%:JvM]_Rԣ!$g(LGN%SQB<D*mz' #ض#0@1٢3mh\N=;g 86DTb dD"8ۗͫ6XA%/B7WoCj|f-JRid4l mȵjXP $͑ 8]^SQ ]7/z̫^6J!tL=\#u5C0 ?i+1n'"=`37KKㆇ#&9%щ U2s+L=ƓF{ 01JH-Fe 0f5w0Kxfm8*.KcǟR|@P.WE?' NȸG`s9~T~%d.W3}iQW3T.w^~[o!eF䤶;B \oz҃x~v{}Έk-|al{ԍNCNqaP|C * WJK`y|Lcį7_="x2ق>.單>KP9T06» Te~bqn[Ԩ"AS6U̬3fu5,LۖPr}SOi],-Xh:KV ׈E/Pk =w*u9uwܠV5cS#8l~Kv0U\J"olG9ed%cg{zqr?_1]Ȃ\N4U|y'{V}eƎYy`S!)LKrT‡x#̡MĮ<,/#mskm}DMAC+QEKOy/|LO@jq+zqJK*4klW- rTwv{:&O-҂X?QALcr7%,N@a}r4EKS3/gP6$3/z> MF76H쀌Zy7[07[ܾ)x}05SE1J88e-MN'3=&zw))O1É^@(C-s5 lR|. 3dyKctfY~s X.X %Iqtw+dHof[2KIE.ʳ/SY\\e sz2)ߣ/媚5/4Wn_S~j|BS=z 9m=G0ǴMz`~/G^&'3e6ynVM?s9ENw(3fqKs3*KL%yps&f+rSƥY8霕R hrb|A]zO M`sG:&SPs_p\Vx/&Įȶ|G5g*?0.Sm['X,ᵺUϴ[m!?!F5obv3iiw͐cm5&v> Ξύh`D2²J6R`/~DMX ,౶0o}[ S?DHe%jcy[Ju>\ĉg(y _죬;GBЗViK]Ǭ>`R M8ϵ/ԯ=VqSF`.VrfSK:j =%~6a^`fpGP>Wg] D)%83 Kȹ}i4;~gdH2+,B;zObEQ|vhsL{m&@H@n Ǽ@i"!1AQ a0@Pq?23пC bA!*LHOJ!ZlLy>գCEm=+[P(v$CX!i2Be42y B^q OD!114BpcY%9NH a!q=eЋfH@7QUMk/)c4Ύֽ%L蚣ө9^8=bۉB,&<(ͽ ‰9?by"R(V2OE̠]HP?;zoxbWсVsJ^m3gg(g1mpZC*+AZKW3X1J_(=y)Qxz ~ xoyMۄ4fZ=rݎ Կxu/|;v0<DŽc_yJl.+L]0ďdf /5GKg<`WxY]:_ڿk83`gvwے*Al~b8f渫 YpZļU57%L!Q̫)(bX fPQ`$LAW,Q2RlE]Ѩ-0odxCb4av2E"4k{ g؂̋4ǔpbyGceŽe`e%"H1/c3#* *\Y&aH;Ԡ`bՁFEh7+s PVtsoZ0.WR+K`Kq|BQTQP@%DjPFP! kRJ4is %!1AQaq? 0aFF{e#P*`fP_l2iz`:˨ q[imx @`ǩʗ{W`LC![g,+]f-_MF3:`Դ8' f_Fh;(1*LfgBxT,͎` y* 9`l^9艂+ ysR!T-RU k\p/D.w 7m]Y2Z逧le&#xG08S =Աmí@;EIxNJ[؞.Ӫ7|&6TM9LajPEOG nmnGP 0i7t}`]KJ/obPcHS[72men-52Zs 3ț)`:|&cLVf)uZeUic0YYrZ !GqBy"rT.pu( 3)]%`]偱y 2(9CgFǴCc̤QӅeVN~Xٖ2ަUs`(AGk:4VVde/N1^ Q`AHY;|yju^藑,0R9 R;1QMfr"_4./B&G7ru]V>YOMDhv-g)糉i K$wb^sO ko.`ṃ4lv@vWĤ1kәE䊛72\T 0nZbیv2?n&:[XACfUsX<0J. 4u*qFBgɝ fb*V xטVgsU[%RݸùE"%\^Pn!XlKd9s^.ߨYlfJ -{.sB-ӎ (i穜0'I<ؽb1ApZ-~elq{[jˇnu.b M 0[2 \ccKPS&o+7W9r K3l0AiP]<@s@C z`*Óӧ0,5Jm h]sܥe;bLHfGpDiOPQKdzmXmHsRku=Rݮ((r9T v4mUk~@;Pۡk q[{K6] (E lY2UOPV<0MW1"d}^&.P10MgPz_a{W-\qF.!n< /JE_YbfYtf -_( +RB7w~ XQmԬpBVn NHiK Ue%;]9%3m"5abL77G+CKN-5{ e!6$NhY AA\c1,SR[ "8rzLv(+Q,w+f*շ90lsw:Rx-er&l1͍5aj];]YX0KT)(ZfUlobʱ`]S]A*[E)8WZq8P75L}lxSWvVrm%[Wv'YBt⅌aߘ‰-YcCH-dmpx" *̻0 ^cxuwkq(q+ҌBG0ڴN`McG- 7 L]0h:bX@CV" #윜>n<:e<,RZ+*)ט+^`F. r<9AHP}u ^JNh"Eڐ!QYjpa[g74eZHwn9Ђyj. V .ȋe,ZeSN52A(t!oڕo"VQ4F zN%4:.Ԡ%h1]lvJ=2T~9-6^X)]PP5lYԶLFG o,nTP-,|CQVEa7t'@Qs+ Z0FVsA*w]`%S9kh@ ڔ,/e]mysCv p71Q47TY&bgP@R|Daߦ!UA)XTqn̳B"E%dᅆ./~ͬn"U[9Am$ 1jX0 ލ@gwPB^%dz}͗t˺2 l;6WzP < M?N#fawc;/>Hfij;EJr2T1n{%"9ϯ)5bhx0Տ #O볒G{h#Z6W+?qPcMu]Fo-,[tWV|ۚܦQi9%jp V0TjC׻LGZgFƩʀr P r, W Yp^'C#AcA Ki>b:q;^ ^La')~:[gXF!EVHi|Q|יn8Af:"( ѻզC+p.# Q-ވ^USDCClPb:-phfhއJLG:AW}Dǀ)!<%+Gs ϒ+Q8eB! 9T:`UYc(T!^B]q-  ϩeeB5nZp#`^ic|5} gQ[P-&f8ՠ3_-p^ࢫRB ;𛻕44޶‡2lSW#˽3KW3]h9URE(dyQ@ 6$oE1u-#xg/>朎X:3#:m|T2z)8[bx-`T)-4bOf뚂CXAҎs(6č $NSL/Zĭ0HITWkYzB;[T t_pR+WmZpjX-ua0t/s},*"lf$_0/,APb⤒d]k!V0)ZG>bڵo:4J_o( h~%~6+ז.MwV7 )>v>l39K9>&Zo\EY=G"4Aa|(/ T$j@*x.[P`3Ͳ՗ (w$E(W rk01j&f@ y\ucsl) 6 CI,fP<ߡsn*z|~O2eVז\aw}>! abɘ/..UST,"b iLIwO'6jV(}J]rG(d)`Cw^3f*^W6 !Cr ?,X ԡ~|o ֟7I&,KCD32VcCf??S JE{8G[F[%DƷvʗfMG{ꢽG%4aQ"ZXh&571#H]?5X%3d5hR!%@A6& b99z} %c0bU`R ѧ_+ LAMxLj Aˈ\z00Vε`q ' dIa@t,^L1D^*#u.mp=?9Qr_CP 7x BpQF-|:%)-[.=D#Exh]P`EQxEDsHk[7@@ -h1紣EdV1öj/܍l򎓙y{$eeX 5}ڿ0R?sPIH\]tQތ| OQTZS@rCk'<F6!!E8^5l.Ur+;W-=`;XW7{/n_.4985D8`w) C0v,eL}W|!,~}KUrPq̇- ޵)"t6|gQeNnS}@;XG`!{ab kq(2 Lo* `kUMp(-0Z~V _|Q,lE~ϹyFqc(5< at1fQt9w%Q{Qї4?&Y̡`u+%0}lxJX2LVe~_V''ZGq<[| ; Fvܷ/}r;@\̏;E]@r Pt/a3G ]Y[r:l8%m;Y;eƐmmr˂\nlW#!xTb걖?O[5?Z8WT:3)V^S%j-cjnZ^c.a;+D[Gd!6$VnKsh q}B,qR"q9*+i_1]I28a+g#҇*mX v9[xVE ;au/f@IuUB?*: Bg.j|LtGQZxUW e[D !ZҎÓXi1Y (-k0ƀ1G偣Cno] B7vgdE*9@~c%Z]y IV`g ]?TR:uOWPF"k|ͨ.n ]_E ,J/u Hc<۫R]ՁO,Y ?ނ.xZh"' _%1mNAV_2F]0d,RWk^8N7Ѽؖ}_7L'2Kasv;p#ǴpojS)C]t0V' \&U^G^AueWAlf,MoԵ"/GeU쎟ҍQ1 BmE]c>ff5jxӼɢ%zXcK%|J 鳲isQ;J&/E~%=1o0h1)/,sUq߉LnTX$K"\v94KpQ#Rpǚ§ulkl$WTՄ'WdCڭy`2HWx1}o ([~RaP KZ5VR Xf_1+mZ)w<dĦZtIJ$H4n~G3XȮX*pENnA)z9~'$d@%ͥZPϖR*mW+9@FǔŅU.Xhڅ, Ƃ'`.đ쭜W۟,c.S''i#km_p,P}T\m/_a{%'s[QD8gc)YT-(RB!86 Id cm?R6?*5fUjR౸P*Cl+%>O jX't fo+נ呁7DHUMY!D)7</0R G'߈EQ 0{ `-os&IIdR^CL3j<M*;/;2O6︉Tx#d<-`U2׽~JEIFze ֺD\-8,Wǜ9v0];edW@JO4>b)q2ֈ׼>fnB P&%CVf?{˭es@Cޒ=Ynl)%u]D¨h-@3GjxFF^E~csO(0QE3-J/-]$c9/ eoTqKS8 !oqHVGs cp9C VKґ35U)-uD[ZFqU>/ TQ71a͘G)QlJ^{5 .N/X RhsN%Kl–o0T 灃L =#GC 壘KhO1}Kͪ=`_X&pK4jqspkxk(@DȀX7 +N)LʡQfWUz`O!tcP1py7(jq@^#>s O}[&߈|G6+LmHXatA~HSk, l a<4 %4_RXKr\-+Jn\2b;i6F^NZwC,`!l7]=G(PbZ%+HiBWKghRxi*+"]_1*WӬ7 t~Ⅰ7ĴEep=Ḙ9`3Rv\&*Ṍv|;-,t_Dە 9qt@\QN$5Gwl[U( m4QBVxc}tpZ#_Qa_BXA0m-zmJL*m0LgnHR\SgV-<0z JvZ#\QtG &mYPӂ-q.Fׅ~pwG9vdײ0R~.P.zAAE;h ҡ сeZ q3WY MHiɋjp]jIQ#xRž-G!Qwkn!tfʸ1ڞf ^Zi)A }b݃kga<6﹄kR̙&b;3ލj ۙ\V/)4‹$Қ L@]ѓM2]9|c煀m1M@C.p@`5)iopTb| |NļN+dC9^bՐE,S z U'X9q{i^a0gs"4~ٮhS (bTH x]~M@b=I^5G%A-)*)7zz &sR4 WSA#ɹjQ QݗY7|$+Ś$l<.yU]'嬯_y n[=?8L,\UG~cu7pCqԱ {w>S3{;@V"ʫCl_mj\#+4aL4r4D-^hx8X<͔qv4}- ;X+ۋpB'/wܣ-?rG FU ⥈Eh߃+=R#r5Q.A-L] spyPwLV-|1|k(-Usx Qh=d65ۇ\b[-Po7ݎ0ҜTN eا?j{ %J h[Q4wM&/7 ["`^`WĿ`WʬPMztSVQ" Š֑R{!PQE' M\_+h4(ĺ- =MઝXKnA \#Z 1:*m,ݔD9E+AP plj{p`Ն)OқAIX1QdH6 Kj%6qYn ҙYCAnF7`h$*$fE^+vS_smnKE q;v_7q\2[8K3Z ,w,*XYq#it=&Lr/"`5Ok1%Fo;-urqrgQ4X=<@s~p ]>%yO`/h0RmsBgw"|_)0L/cPsc^:(UTAV ~".J Dc5ù10mYN-QΏ-|lJo#pQ#iAns-L@t6QP0Dt?1c A`ۭ~c 4Xe_\c\Gi폱w,C G7 ċ -Q"d{_/3t#0+<(x|*.m(w 1>X,$Q_s5tqR/X~&c|n,^y׸?(*jZcN#!{jZj&Zp掭D4/cPVe[X.QKCEe cu E9!r4ZuhֳcgG5}-F1EKSL>r_ܠ$He2rP zKb㍼/Ye&!MqY pf/H[<\R( Qf̜*{3X&)N3bDl6@2Pk$lW8q`)=A !Uׁ*_s*+n c2dw 8anW0oWP.,-b mTq):Ԣس9bE}+x?fPsjtnXch€9u] E%}AYS7(њ偠6 'i owW˩Erq"cBj,xkȂCDP ?3 J)5Y`0*L-^..q&$c^*Q 6Q k]dj{-&y*#u\]aTً1- ?hVe _2B!u ljW` =b;TB,L Qse5U1Jiag1*F8?T;`z 4KnUwο5x-M]J l9Tk5VSf\d ѭEiZHnw(5N-k!tP3ܢ u5.-9 f6Ƿ.C}BaB T1l@@Zx%q6H]#*~&:ӔX6>"TV8eH>cINĦo-3V>MiqGW\ ޯH6r!.!`9 ʦf MnԽh>*:rX淙HFlޢ8ŬοN+RK~5kmAT VE@ \/4EXỦ|k̳AшHZզ)VyR%w_W*U֝@89UQ%TwrQ OfIU"{^ kYU{ mxblQ؜,vVlnEu#mM@-r)l7?ljjQfb^6)Ai8Sjgx-j1J(pY@]V>c*21[fcTE. VUclԳ7by.㊰hg p(S/(l#KG9rĬMџU9f´cdsP H^fr^r0]E:Ρ184i|٨\j ƒ>3RN1ph08eW57U±nS# o-=*@ 8Z۴١3ki4s btL (ep. Pz %@Y3;QIDu|$Plc%+s ^sOJ$*WNPⷩa7~(Q[HUh*RԷ m8DuQY14Xk#B,u(TB 4NR/rM0 z7L(lg{Px*z*2F>HY90/9 ܭ%*.}aQ8V׍xJ0p1^Hm͚n+lj g!7p/B,d J:4DlRL>'u]?,jHk/bEcxF-ayf'cchX1jpz8L88"W5ψ3ǨZgaS(&VLm%%7/4 ]Dcodegroup-19981025/codegroup.man0000644000175000017500000001614606615153724016110 0ustar vlmvlm00000000000000 CODEGROUP(1) CODEGROUP(1) NAME codegroup - encode / decode binary file as five letter codegroups SYNOPSIS codegroup -d|-e [ -u ] [ infile [ outfile ] ] DESCRIPTION For decades, spies have written their encoded messages in groups of five letters. codegroup encodes any binary file into this form, allowing it to be transmitted through any medium, and decodes files containing codegroups into the original input. Encoded files contain a 16-bit cyclical redundancy check (CRC) and file size to verify, when decoded, that the message is complete and correct. Files being decoded may contain other information before and after the codegroups, allow- ing in-the-clear annotations to be included. codegroup makes no attempt, on its own, to prevent your message from being read. Cryptographic security should be delegated to a package intended for that purpose, such as pgp. codegroup can then be applied to the encrypted binary output, transforming it into easily transmitted text. Text created by codegroup uses only upper case ASCII letters and spaces. Unlike files encoded with uuen- code or pgp's ``ASCII armour'' facility, the output of codegroup can be easily (albeit tediously) read over the telephone, broadcast on shortwave radio to agents in the field, or sent by telegram, telex, or Morse code. To illustrate the difference, here are the first few lines of a binary file encoded by: base64: H4sICFJ9MzYAA2EudGFyAOxba3faSNKer+lf0SezO3YmgLnY2I6TyQIGgwOGBTtOYjuJEMJo DJJGF1+ys//9rarulpqLHRi/mdk9G84JIKGuqq579eNkNn745q9sNru9tcXhs5gtFPAzm83l xad88WyxmNssbhe3sps8m8ttZ/M/8K1vL9oPP0RBaPggypU1vrad+59zosj0HqAj9xF//pe8 WsaVNbTH1rfkAfoobm7ea//cZn4rtv/mNtq/kM9t/cCz31Io9foftz9nnW77oMdfcdMdWJe+ uuencode: begin 644 data.bin M'XL("&7._R\ VUO;V\ /9U+FN2XSF3G6H5OA1(?HOB<=/<7__X7TNXJ^&PI/\[?7-7U]KU=]SSWQ? pgp: -----BEGIN PGP MESSAGE----- Version: 2.6.2i hIwCCb8iTku3pBUBA/9oSDlfk/On9bwjmTnB98Eejr6agkPSi3n6hd8JkAtJd33f kzFq18Jo0xzRUWZ7Di6Jq/FXpeI1yztVDqispbcYOP0aDv4JZOSF1kRsmJ9xK9Bo Cv4a967IXPkkRsjIAkx0B39dYxCzf8kHUn4THmyV/b2qLUZ0cc+mr8hxFfFpuYSM codegroup: ZZZZZ YBPIL AIAIG FMOPP CPAAA DGNGP GPGPA ADNJN ELJKO ELIMO GEOHF KIFGP IFBCB PKCPI YJMHE PHBHP PPOBH NCOHD AKLLL AGHFP DEGEF LKELC EAIJI ABAGP AHPPO IHHPH OHPDF YNFPB ALEPO KMPKP NGCHI GFPBI CBDML PFGHL LIHPC BOOBB HOLDO FJNHP OLHLL OPNIL Only codegroup conforms to the telegraphic convention of all upper case letters, and passes the ``telephone test'' of being readable without any modifiers such as ``capi- tal'' and ``lower-case''. Avoiding punctuation marks and lower case letters makes the output of codegroup much eas- ier to transmit over a voice or traditional telegraphic link. OPTIONS -decode Decodes the input, previously created by code- group, to recover the original input file, and verifies it to detect truncation or corruption of the contents. -encode Encodes the input into an output text file containing five letter code groups (default). -usage Print how-to-call information. All options may be abbreviated to a single letter. APPLICATION NOTES Encoding a binary file as ASCII characters inevitably increases its size. When used in conjunction with exist- ing compression and encryption tools, the resulting growth in file size is usually acceptable. For example, a random extract of electronic mail 32768 bytes in length was cho- sen as a test sample. Compression with gzip compacted the file to 15062 bytes. It was then encrypted for transmis- sion to a single recipient with pgp, which resulted in a 15233 byte file. (Even though pgp has its own compres- sion, smaller files usually result from initial compres- sion with gzip. In this case, pgp alone would have pro- duced a file of 15420 bytes.) codegroup transforms the encrypted file into a 37296 byte text file. Thus, due to compression, the code groups for the encrypted file are only a little larger than the orig- inal cleartext. Restricting the character set and including spaces between groups results in substantially larger output files than those produced by uuencode and pgp. Files encoded with codegroup are about 2.5 times the size of the input file, while uuencode and pgp expand the file only about 35%. codegroup is thus preferable only for applications where its limited character set is an advantage. FILES If no infile is specified or infile is a single ``-'', codegroup reads from standard input; if no outfile is given, or outfile is a single ``-'', output is sent to standard output. The input and output are processed strictly serially; consequently codegroup may be used in pipelines. BUGS When a CRC error is detected, no indication is given of the location in the file where the error(s) occurred. When sending large files, you may want to break them into pieces with the splits utility (available from the Web page cited below) so, in case of error, only the erroneous pieces have to be re-sent. It might be nice to embed the original file name and modes in the encoded output, but this opens the door to all kinds of system-dependent problems. You can always include this information as text before the first code- group, or send an archive created with tar or zip. SEE ALSO base64(1), gzip(1), pgp(1), splits(1), tar(1), uuen- code(1), zip(1) EXIT STATUS codegroup returns status 0 if processing was completed without errors, 1 if errors were detected in decoding a file which indicate the output is incorrect or incomplete, and 2 if processing could not be performed at all due, for example, to a nonexistent input file or no codegroups found in the input. AUTHOR John Walker This software is in the public domain. Permission to use, copy, modify, and distribute this software and its docu- mentation for any purpose and without fee is hereby granted, without any conditions or restrictions. This software is provided ``as is'' without express or implied warranty.