1993-07-08 - Some source code for phone number coding…

Header Data

From: Nickey MacDonald <i6t4@jupiter.sun.csd.unb.ca>
To: cypherpunks list <cypherpunks@toad.com>
Message Hash: 5adbb86e0f454f59d8289905fc464b48e978737c594bc5167b48af5a32b435ad
Message ID: <Pine.3.05.9307071932.B12475-d100000@jupiter>
Reply To: N/A
UTC Datetime: 1993-07-08 05:04:10 UTC
Raw Date: Wed, 7 Jul 93 22:04:10 PDT

Raw message

From: Nickey MacDonald <i6t4@jupiter.sun.csd.unb.ca>
Date: Wed, 7 Jul 93 22:04:10 PDT
To: cypherpunks list <cypherpunks@toad.com>
Subject: Some source code for phone number coding...
Message-ID: <Pine.3.05.9307071932.B12475-d100000@jupiter>
MIME-Version: 1.0
Content-Type: text/plain


Here is a couple of message about my phone encoding format (giving
progressively more info to a person trying to guess the format) followed
by the complete source...  Use it well.  (TABsize was 3.)



Okay, well without giving you the source...  heres the biggest hint I can
think of...

>From /etc/magic:
0	string		\037\235	compressed data

Translating that to decimal and in 4 byte unsigned long we get
  (\037\235\0\0 == 31,157,0,0 == 0,530,382,848
                                 ^^^^^

>From the start of my posted list of phone numbers:
(503) 241-9796  ext: 09
 ^^^                 ^
 ??   ?

If you know the rules for forming (valid looking) phone numbers...

Anyway, to finially give the whole thing away...

The file that is hidden starts with these 4 bytes...

1f 9d 90 54 == 0,530,419,796

Well.. I like puzzles... (as long as the answer is eventually revealed) so
I'll let you think it over for a bit, before I send you the source... ;-)




Okay well... lets assume that all valid phone numbers must be in the form
   [2-9][0-1][0-9]  [2-9][0-9][0-9]  [0-9][0-9][0-9][0-9]

This is the form of my encoding... now if you take a sample number, like
  1,234,567,890
and try encode it into a phone number, you would get
  (123) 456-7890
   ^^
And you notice that the 1 and the two are out of range...
Well.. as it happens, for 32 bit unsigned numbers the range is 0 to
4,294,967,294...  The first digit will always be 0-4, half of which are
illegal in that position, so I decided to swap the first two digits...

That doesn't fix all of the range problems, thus whenever there is an
invalid digit in position 1,2 or 4 I move it to the extension and put a
special indicator value (the higest of the legal range) in its place.

Thats the whole secret...  Code will follow soon...  :-)




/*
	pe.c

	phone encode

	Written by:
		Nickey MacDonald
		July 7, 1993

	Encode a message as a list of phone numbers...  There are some tricks
	used to make the phone numbers appear more realistic, and there is a
	caveate...  If the input file has 4 null bytes aligned of a 4 byte
	boundry, then the program will think its the EOF and stop...  This
	could be fixed easily... I just didn't.
*/


#include <stdio.h>


unsigned long getbytes(FILE *fp);


int main(void)
{
	unsigned short i, ei;					/* i=work counter, ei=ext. counter */
	unsigned char pn[10], ext[4], v=0;	/* Digits of phone num, ext and a */
													/* pseudo random value */
	unsigned long b;							/* 4 bytes compress to a unsigned long */
	char tpnumbuf[11];						/* a sprinft buffer for b */

	/* Read until EOF or 4 properly aligned null bytes */
	while((b=getbytes(stdin)) != 0)
	{
		ei=0;

		/* Convert the unsigned long into a string */
		sprintf(tpnumbuf, "%010lu", b);

		/* Pick up the digits of the unsigned long */

		/* Because of the distribution, swap the first two digits... */
		pn[0]=tpnumbuf[1]-'0';
		pn[1]=tpnumbuf[0]-'0';
		for(i=2; i<10; i++)
		{
			pn[i]=tpnumbuf[i]-'0';
			v+=pn[i];
		}

		/* The first digit of the area code must be [2-9] */
		if (pn[0]<3)
		{
			ext[ei++]=pn[0];
			pn[0]=2;
		}

		/* Currently the middle digit of area code must be 0 or 1 */
		if (pn[1]>0)
		{
			ext[ei++]=pn[1];
			pn[1]=1;
		}

		/* The first digit of prefix must be [2-9] */
		if (pn[3]<3)
		{
			ext[ei++]=pn[3];
			pn[3]=2;
		}

		/* Generate the output phone number */
		fprintf(stdout, "(%d%d%d) %d%d%d-%d%d%d%d", pn[0], pn[1], pn[2],
                                                  pn[3], pn[4], pn[5],
                                                  pn[6], pn[7], pn[8], pn[9]);

		/* Generate the extension if needed */
		if (ei>0)
		{
			ext[ei++]=v%10;
			fprintf(stdout, "  ext: ");
			for (i=0; i<ei; i++)
				fprintf(stdout, "%d", ext[i]);
		}

		fprintf(stdout, "\n");
	}

	return(0);
}


/* Input 4 bytes, convert EOF to null and encode as an unsigned long */
unsigned long getbytes(FILE *fp)
{
	int b[4];
	unsigned short i;

	for(i=0; i<4; i++)
	{
		b[i]=fgetc(fp);
		if (b[i]==EOF)  b[i]=0;
	}

	return(((unsigned long)b[0])<<24 |
          ((unsigned long)b[1])<<16 |
          ((unsigned long)b[2])<< 8 |
          ((unsigned long)b[3]));
}




/*
	pd.c

	phone decode

	Written by:
		Nickey MacDonald
		July 7, 1993

	Decodes a message hidden in a list of phone numbers.
*/


#include <stdio.h>


void putbytes(FILE *fp, unsigned long val);


int main(void)
{
	unsigned short i, ei;	/* i=work counter, ei=extention work counter */
	unsigned char pn[10];	/* The digits of the phone number */
	unsigned long b;			/* The finally decoded value from the phone num */
	char pnline[30];			/* Input line buffer */
	int flg=0;					/* The error message is only output once */

	/* Read lines until end of file */
	while((fgets(pnline, 30, stdin)) != NULL)
	{
		/* error checking */
		if ((pnline[0] != '(')  ||
          (pnline[4] != ')')  ||
          (pnline[9] != '-'))
		{
			if (flg==0)
			{
				fprintf(stderr, "Input not in correct format, output will be garbage!\n");
				flg=1;
			}
		}

		/* Extract the digits of the phone number, and convert from ASCII */
		pn[0]=pnline[1]-'0';
		pn[1]=pnline[2]-'0';
		pn[2]=pnline[3]-'0';

		pn[3]=pnline[6]-'0';
		pn[4]=pnline[7]-'0';
		pn[5]=pnline[8]-'0';

		pn[6]=pnline[10]-'0';
		pn[7]=pnline[11]-'0';
		pn[8]=pnline[12]-'0';
		pn[9]=pnline[13]-'0';

		/* The first digit of the extension should be the 21st loc of input buf */
		ei=21;

		/* The first digit of an area code is always [2-9] */
		if (pn[0]==2)
		{
			pn[0]=pnline[ei++]-'0';
		}

		/* Currently, the middle digit of area code is always 0 or 1 */
		if (pn[1]==1)
		{
			pn[1]=pnline[ei++]-'0';
		}

		/* The first digit of a prefix is always [2-9] */
		if (pn[3]==2)
		{
			pn[3]=pnline[ei++]-'0';
		}

		/* Swap first two digits */
		i=pn[0];
		pn[0]=pn[1];
		pn[1]=i;

		/* Encode the individualt digits into a unsigned long */
		b=0;
		for(i=0; i<10; i++)
			b=b*10+pn[i];

		/* output the decoded bytes */
		putbytes(stdout, b);
	}

	return(0);
}


/* Simple encoding... 4 bytes to the longword...  seperate them here */
void putbytes(FILE *fp, unsigned long val)
{
	int b[4];

	b[0]=(int)(val>>24 & 255);
	b[1]=(int)(val>>16 & 255);
	b[2]=(int)(val>> 8 & 255);
	b[3]=(int)(val     & 255);

	fprintf(fp, "%c%c%c%c", b[0], b[1], b[2], b[3]);
}

--
Nick MacDonald               | NMD on IRC
i6t4@jupiter.sun.csd.unb.ca  | PGP 2.1 Public key available via finger
i6t4@unb.ca                  | (506) 457-1931    ^{1024/746EBB 1993/02/23}







Thread