code: purgatorio

ref: 79c64a79a248c31733d4ec0ff9fe1a1e57a58f51
dir: /appl/cmd/auth/factotum/proto/keyreps.b/

View raw version
implement Keyreps;
include "sys.m";
	sys: Sys;
include "keyring.m";
	kr: Keyring;
	IPint: import kr;
include "sexprs.m";
include "spki.m";
include "encoding.m";
	base64: Encoding;
include "keyreps.m";

init()
{
	sys = load Sys Sys->PATH;
	kr = load Keyring Keyring->PATH;
	base64 = load Encoding Encoding->BASE64PATH;
}

keyextract(flds: list of string, names: list of (string, int)): list of (string, ref IPint)
{
	a := array[len flds] of ref IPint;
	for(i := 0; i < len a; i++){
		a[i] = IPint.b64toip(hd flds);
		flds = tl flds;
	}
	rl: list of (string, ref IPint);
	for(; names != nil; names = tl names){
		(n, p) := hd names;
		if(p < len a)
			rl = (n, a[p]) :: rl;
	}
	return revt(rl);
}

Keyrep.pk(pk: ref Keyring->PK): ref Keyrep.PK
{
	s := kr->pktostr(pk);
	(nf, flds) := sys->tokenize(s, "\n");
	if((nf -= 2) < 0)
		return nil;
	case hd flds {
	"rsa" =>
		return ref Keyrep.PK(hd flds, hd tl flds,
			keyextract(tl tl flds, list of {("e",1), ("n",0)}));
	"elgamal" or "dsa" =>
		return ref Keyrep.PK(hd flds, hd tl flds,
			keyextract(tl tl flds, list of {("p",0), ("alpha",1), ("key",2)}));
	* =>
		return nil;
	}
}

Keyrep.sk(pk: ref Keyring->SK): ref Keyrep.SK
{
	s := kr->pktostr(pk);
	(nf, flds) := sys->tokenize(s, "\n");
	if((nf -= 2) < 0)
		return nil;
	case hd flds {
	"rsa" =>
		return ref Keyrep.SK(hd flds, hd tl flds,
			keyextract(tl tl flds,list of {("e",1), ("n",0), ("!dk",2), ("!p",3), ("!q",4), ("!kp",5), ("!kq",6), ("!c2",7)}));
	"elgamal" or "dsa" =>
		return ref Keyrep.SK(hd flds, hd tl flds,
			keyextract(tl tl flds, list of {("p",0), ("alpha",1), ("key",2), ("!secret",3)}));
	* =>
		return nil;
	}
}

Keyrep.get(k: self ref Keyrep, n: string): ref IPint
{
	for(el := k.els; el != nil; el = tl el)
		if((hd el).t0 == n)
			return (hd el).t1;
	return nil;
}

Keyrep.getb(k: self ref Keyrep, n: string): array of byte
{
	v := k.get(n);
	if(v == nil)
		return nil;
	return pre0(v.iptobebytes());
}

pre0(a: array of byte): array of byte
{
	for(i:=0; i<len a-1; i++)
		if(a[i] != a[i+1] && (a[i] != byte 0 || (int a[i+1] & 16r80) != 0))
			break;
	if(i > 0)
		a = a[i:];
	if(len a < 1 || (int a[0] & 16r80) == 0)
		return a;
	b := array[len a + 1] of byte;
	b[0] = byte 0;
	b[1:] = a;
	return b;
}

Keyrep.mkpk(k: self ref Keyrep): (ref Keyring->PK, int)
{
	case k.alg {
	"rsa" =>
		e := k.get("e");
		n := k.get("n");
		return (kr->strtopk(sys->sprint("rsa\n%s\n%s\n%s\n", k.owner, n.iptob64(), e.iptob64())), n.bits());
	* =>
		raise "Keyrep: unknown algorithm" + k.alg;
	}
}

Keyrep.mksk(k: self ref Keyrep): ref Keyring->SK
{
	case k.alg {
	"rsa" =>
		e := k.get("e");
		n := k.get("n");
		dk := k.get("!dk");
		p := k.get("!p");
		q := k.get("!q");
		kp := k.get("!kp");
		kq := k.get("!kq");
		c12 := k.get("!c2");
		return kr->strtosk(sys->sprint("rsa\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
			k.owner, n.iptob64(), e.iptob64(), dk.iptob64(), p.iptob64(), q.iptob64(),
			kp.iptob64(), kq.iptob64(), c12.iptob64()));
	* =>
		raise "Keyrep: unknown algorithm";
	}
}

Keyrep.eq(k1: self ref Keyrep, k2: ref Keyrep): int
{
	# n⁲ but n is small
	for(l1 := k1.els; l1 != nil; l1 = tl l1){
		(n, v1) := hd l1;
		v2 := k2.get(n);
		if(v2 == nil || !v1.eq(v2))
			return 0;
	}
	for(l2 := k2.els; l2 != nil; l2 = tl l2)
		if(k1.get((hd l2).t0) == nil)
			return 0;
	return 1;
}

Keyrep.mkkey(kr: self ref Keyrep): ref SPKI->Key
{
	k := ref SPKI->Key;
	(k.pk, k.nbits) = kr.mkpk();
	k.sk = kr.mksk();
	return k;
}

sig2icert(sig: ref SPKI->Signature, signer: string, exp: int): ref Keyring->Certificate
{
	if(sig.sig == nil)
		return nil;
	s := sys->sprint("%s\n%s\n%s\n%d\n%s\n", "rsa", sig.hash.alg, signer, exp, base64->enc((hd sig.sig).t1));
#sys->print("alg %s *** %s\n", sig.sa, base64->enc((hd sig.sig).t1));
	return kr->strtocert(s);
}

revt[S,T](l: list of (S,T)): list of (S,T)
{
	rl: list of (S,T);
	for(; l != nil; l = tl l)
		rl = hd l :: rl;
	return rl;
}