forsyth20121205-174063a80cc13 years agoHistory
344 lines · 7.2 KB · Brainfuck
RawDownload
implement Oldauth; ## TO DO#	- more error checking?#	- details of auth error handling# include "sys.m";	sys: Sys; include "ipints.m";	ipints: IPints;	IPint: import ipints; include "crypt.m";	crypt: Crypt;	PK, SK, PKsig: import crypt; include "msgio.m";	msgio: Msgio; include "oldauth.m"; init(){	sys = load Sys Sys->PATH;	ipints = load IPints IPints->PATH;	crypt = load Crypt Crypt->PATH;	msgio = load Msgio Msgio->PATH;	msgio->init();} efmt(){	sys->werrstr("input or format error");} readauthinfo(filename: string): ref Authinfo{	fd := sys->open(filename, Sys->OREAD);	if(fd == nil)		return nil;	a := array[5] of string;	for(i := 0; i < len a; i++){		(s, err) := getstr(fd);		if(err != nil){			sys->werrstr(sys->sprint("%q: input or format error", filename));			return nil;		}		a[i] = s;	}	info := ref Authinfo;	(info.spk, nil) = strtopk(a[0]);	info.cert = strtocert(a[1]);	(info.mysk, info.owner) = strtosk(a[2]);	if(info.spk == nil || info.cert == nil || info.mysk == nil){		efmt();		return nil;	}	info.mypk = crypt->sktopk(info.mysk);	info.alpha = IPint.strtoip(a[3], 64);	info.p = IPint.strtoip(a[4], 64);	if(info.alpha == nil || info.p == nil){		efmt();		return nil;	}	return info;} writeauthinfo(filename: string, info: ref Authinfo): int{	if(info.alpha == nil || info.p == nil ||	   info.spk == nil || info.mysk == nil || info.cert == nil){		sys->werrstr("invalid authinfo");		return -1;	}	a := array[5] of string;	a[0] = pktostr(info.spk, info.cert.signer);	# signer's public key	a[1] = certtostr(info.cert);	# certificate for my public key	a[2] = sktostr(info.mysk, info.owner);	# my secret/public key	a[3] = b64(info.alpha);	# diffie hellman base	a[4] = b64(info.p);	# diffie hellman modulus	fd := sys->open(filename, Sys->OWRITE|Sys->OTRUNC);	if(fd == nil){		fd = sys->create(filename, Sys->OWRITE, 8r600);		if(fd == nil){			fd = sys->open(filename, Sys->OWRITE);			if(fd == nil)				return -1;		}	}	for(i := 0; i < len a; i++)		if(sendstr(fd, a[i]) <= 0)			return -1;	return 0;} sendstr(fd: ref Sys->FD, s: string): int{	a := array of byte s;	return msgio->sendmsg(fd, a, len a);} getstr(fd: ref Sys->FD): (string, string){	b := msgio->getmsg(fd);	if(b == nil)		return (nil, sys->sprint("%r"));	return (string b, nil);} certtostr(c: ref Certificate): string{	s := sys->sprint("%s\n%s\n%s\n%ud\n", c.sa, c.ha, c.signer, c.exp);	pick r := c.sig {	RSA =>		s += b64(r.n)+"\n";	Elgamal =>		s += b64(r.r)+"\n"+b64(r.s)+"\n";	DSA =>		s += b64(r.r)+"\n"+b64(r.s)+"\n";	* =>		raise "unknown key type";	}	return s;} pktostr(pk: ref PK, owner: string): string{	pick k := pk {	RSA =>		s := sys->sprint("rsa\n%s\n", owner);		s += b64(k.n)+"\n"+b64(k.ek)+"\n";		return s;	Elgamal =>		s := sys->sprint("elgamal\n%s\n", owner);		s += b64(k.p)+"\n"+b64(k.alpha)+"\n"+b64(k.key)+"\n";		return s;	DSA =>		s := sys->sprint("dsa\n%s\n", owner);		s += b64(k.p)+"\n"+b64(k.q)+"\n"+b64(k.alpha)+"\n"+b64(k.key)+"\n";		return s;	* =>		raise "unknown key type";	}} sktostr(sk: ref SK, owner: string): string{	pick k := sk {	RSA =>		s := sys->sprint("rsa\n%s\n", owner);		s += b64(k.pk.n)+"\n"+b64(k.pk.ek)+"\n"+b64(k.dk)+"\n"+			b64(k.p)+"\n"+b64(k.q)+"\n"+			b64(k.kp)+"\n"+b64(k.kq)+"\n"+			k.c2.iptob64()+"\n";		return s;	Elgamal =>		pk := k.pk;		s := sys->sprint("elgamal\n%s\n", owner);		s += b64(pk.p)+"\n"+b64(pk.alpha)+"\n"+b64(pk.key)+"\n"+b64(k.secret)+"\n";		return s;	DSA =>		pk := k.pk;		s := sys->sprint("dsa\n%s\n", owner);		s += b64(pk.p)+"\n"+b64(pk.q)+"\n"+b64(pk.alpha)+"\n"+b64(k.secret)+"\n";		return s;	* =>		raise "unknown key type";	}} fields(s: string): array of string{	(nf, flds) := sys->tokenize(s, "\n^");	a := array[nf] of string;	for(i := 0; i < len a; i++){		a[i] = hd flds;		flds = tl flds;	}	return a;} bigs(a: array of string): array of ref IPint{	b := array[len a] of ref IPint;	for(i := 0; i < len b; i++){		b[i] = IPint.strtoip(a[i], 64);		if(b[i] == nil)			return nil;	}	return b;} need[T](a: array of T, min: int): int{	if(len a < min){		efmt();		return 1;	}	return 0;} strtocert(s: string): ref Certificate{	f := fields(s);	if(need(f, 4))		return nil;	sa := f[0];	ha := f[1];	signer := f[2];	exp := int big f[3];	# unsigned	b := bigs(f[4:]);	case f[0] {	"rsa" =>		if(need(b, 1))			return nil;		return ref Certificate(sa, ha, signer, exp, ref PKsig.RSA(b[0]));	"elgamal" =>		if(need(b, 2))			return nil;		return ref Certificate(sa, ha, signer, exp, ref PKsig.Elgamal(b[0], b[1]));	"dsa" =>		if(need(b, 2))			return nil;		return ref Certificate(sa, ha, signer, exp, ref PKsig.DSA(b[0], b[1]));	* =>		sys->werrstr("unknown algorithm: "+f[0]);		return nil;	}} strtopk(s: string): (ref PK, string){	f := fields(s);	if(need(f, 3))		return (nil, "format error");	sa := f[0];	owner := f[1];	b := bigs(f[2:]);	case sa {	"rsa" =>		if(need(b, 2))			return (nil, "format error");		return (ref PK.RSA(b[0], b[1]), owner);	"elgamal" =>		if(need(b, 3))			return (nil, "format error");		return (ref PK.Elgamal(b[0], b[1], b[2]), owner);	"dsa" =>		if(need(b, 4))			return (nil, "format error");		return (ref PK.DSA(b[0], b[1], b[2], b[3]), owner);	* =>		return (nil, "unknown algorithm: "+f[0]);	}} strtosk(s: string): (ref SK, string){	f := fields(s);	if(need(f, 3))		return (nil, "format error");	sa := f[0];	owner := f[1];	b := bigs(f[2:]);	case sa {	"rsa" =>		if(need(b, 8))			return (nil, "format error");		return (ref SK.RSA(ref PK.RSA(b[0], b[1]), b[2], b[3], b[4], b[5], b[6], b[7]), owner);	"elgamal" =>		if(need(b, 4))			return (nil, "format error");		return (ref SK.Elgamal(ref PK.Elgamal(b[0], b[1], b[2]), b[3]), owner);	"dsa" =>		if(need(b, 5))			return (nil, "format error");		return (ref SK.DSA(ref PK.DSA(b[0], b[1], b[2], b[3]), b[4]), owner);	* =>		return (nil, "unknown algorithm: "+f[0]);	}} skalg(sk: ref SK): string{	if(sk == nil)		return "nil";	case tagof sk {	tagof SK.RSA =>	return "rsa";	tagof SK.Elgamal =>	return "elgamal";	tagof SK.DSA =>	return "dsa";	* =>	return "gok";	}} sign(sk: ref SK, signer: string, exp: int, state: ref Crypt->DigestState, ha: string): ref Certificate{	# add signer name and expiration time to hash	if(state == nil)		return nil;	a := sys->aprint("%s %d", signer, exp);	digest := hash(ha, a, state);	if(digest == nil)		return nil;	b := IPint.bebytestoip(digest);	return ref Certificate(skalg(sk), ha, signer, exp, crypt->sign(sk, b));} verify(pk: ref PK, cert: ref Certificate, state: ref Crypt->DigestState): int{	if(state == nil)		return 0;	a := sys->aprint("%s %d", cert.signer, cert.exp);	digest := hash(cert.ha, a, state);	if(digest == nil)		return 0;	b := IPint.bebytestoip(digest);	return crypt->verify(pk, cert.sig, b);} hash(ha: string, a: array of byte, state: ref Crypt->DigestState): array of byte{	digest: array of byte;	case ha {	"sha" or "sha1" =>		digest = array[Crypt->SHA1dlen] of byte;		crypt->sha1(a, len a, digest, state);	"md5" =>		digest = array[Crypt->MD5dlen] of byte;		crypt->md5(a, len a, digest, state);	* =>		# don't bother with md4		sys->werrstr("unimplemented algorithm: "+ha);		return nil;	}	return digest;} b64(ip: ref IPint): string{	return ip.iptob64z();}