--EncryptionKeysImpl.mesa <> <> <> << >> <<>> DIRECTORY Ascii USING [Lower], FS USING [StreamOpen, Error, Copy], IO USING [STREAM, EndOfStream, GetLineRope, PutRope, Close], MessageWindow USING [Append, Blink], BigCardinals USING [BigCARD, BigToDecimalRope, BigFromDecimalRope, BigToRope], EncryptionKeys, Rope USING [ROPE, Concat, Cat, Index, Equal, Substr, FromChar, Fetch, Length], RSA USING [KeyGenerate, Encrypt], UserCredentials USING [Get]; <<>> EncryptionKeysImpl: CEDAR PROGRAM IMPORTS Ascii, FS, IO, RSA, BigCardinals, UserCredentials, Rope, MessageWindow EXPORTS EncryptionKeys = BEGIN KeyFail: PUBLIC ERROR [subclass: ATOM _ $Unspecified] = CODE; CreateKey: PUBLIC PROC[] ~ { length: CARDINAL _ 17; public, private: BigCardinals.BigCARD; PrivateFileName, PublicFileName, UserName: Rope.ROPE; PublicFile, PrivateFile: IO.STREAM; BEGIN [public, private] _ RSA.KeyGenerate[length]; UserName _ UserCredentials.Get[].name; UserName _ Rope.Substr[UserName, 0, Rope.Index[UserName, 0, "."]]; UserName _ ToLowerCase[UserName]; PrivateFileName _ Rope.Cat["///Keys/", UserName, ".PrivateKey"]; PrivateFile _ FS.StreamOpen[PrivateFileName, $create !FS.Error => IF error.group = user THEN GOTO CannotOpenPrivate;]; IO.PutRope[PrivateFile, Rope.Concat[BigCardinals.BigToDecimalRope[private], "\n"]]; PrivateFile.Close[]; PublicFileName _ Rope.Cat["///Keys/", UserName, ".PublicKey"]; PublicFile _ FS.StreamOpen[PublicFileName, $create !FS.Error => IF error.group = user THEN GOTO CannotOpenPublic;]; IO.PutRope[PublicFile, Rope.Concat[BigCardinals.BigToDecimalRope[public], "\n"]]; PublicFile.Close[]; []_FS.Copy[PublicFileName, Rope.Cat["[Indigo]Keys>", UserName, ".PublicKey"] !FS.Error => GOTO CannotCopy]; EXITS CannotOpenPrivate => { MessageWindow.Append[Rope.Concat["Cannot Open ", PrivateFileName], TRUE]; MessageWindow.Blink; ERROR KeyFail[$CannotOpenPrivate]; }; CannotOpenPublic => { MessageWindow.Append[Rope.Concat["Cannot Open ", PublicFileName], TRUE]; MessageWindow.Blink; ERROR KeyFail[$CannotOpenPublic]; }; CannotCopy => { MessageWindow.Append["Cannot copy public key into [Indigo]Keys>", TRUE]; MessageWindow.Blink; ERROR KeyFail[$CannotCopy]; }; END; }; GetPrivateKey: PUBLIC PROC[] RETURNS[PrivateKey: BigCardinals.BigCARD] ~ { private, PrivateFileName, UserName: Rope.ROPE; PrivateFile: IO.STREAM; BEGIN UserName _ UserCredentials.Get[].name; UserName _ Rope.Substr[UserName, 0, Rope.Index[UserName, 0, "."]]; UserName _ ToLowerCase[UserName]; PrivateFileName _ Rope.Cat["///Keys/", UserName, ".PrivateKey"]; PrivateFile _ FS.StreamOpen[PrivateFileName !FS.Error => IF error.group = user THEN GOTO CannotOpenPrivate;]; private _ IO.GetLineRope[PrivateFile !IO.EndOfStream => GOTO NoKey]; PrivateFile.Close[]; PrivateKey _ BigCardinals.BigFromDecimalRope[private]; EXITS CannotOpenPrivate => { MessageWindow.Append[Rope.Concat["Cannot Open ", PrivateFileName], TRUE]; MessageWindow.Blink; ERROR KeyFail[$CannotOpenPrivate]; }; NoKey => { MessageWindow.Append[Rope.Concat[PrivateFileName, " Empty"], TRUE]; MessageWindow.Blink; ERROR KeyFail[$CannotOpenPrivate]; }; END; }; GetPublicKey: PUBLIC PROC[sender: Rope.ROPE, authenticate: BOOLEAN _ FALSE] RETURNS[PublicKey: BigCardinals.BigCARD] ~ { public, PublicFileName, lCaseSender: Rope.ROPE; PublicFile, masterFile: IO.STREAM; masterPublicKey, publicSignedByMaster: BigCardinals.BigCARD; BEGIN lCaseSender _ ToLowerCase[sender]; PublicFileName _ Rope.Cat["[Indigo]Keys>", lCaseSender, ".PublicKey"]; PublicFile _ FS.StreamOpen[PublicFileName !FS.Error => IF error.group = user THEN GOTO KeyNotFound;]; public _ IO.GetLineRope[PublicFile !IO.EndOfStream => GOTO NoPublicKey]; PublicKey _ BigCardinals.BigFromDecimalRope[public]; IF authenticate THEN {publicSignedByMaster _ BigCardinals.BigFromDecimalRope[IO.GetLineRope[PublicFile ! IO.EndOfStream => GOTO Warning]]; masterFile _ FS.StreamOpen["///Keys/MASTER.PublicKey" !FS.Error => IF error.group = user THEN GOTO MasterMissing]; masterPublicKey _ BigCardinals.BigFromDecimalRope[IO.GetLineRope[masterFile ! IO.EndOfStream => GOTO MasterMissing]]; masterFile.Close[]; IF NOT Rope.Equal[ BigCardinals.BigToRope[RSA.Encrypt[publicSignedByMaster, masterPublicKey]], Rope.Concat[lCaseSender, BigCardinals.BigToRope[PublicKey]] ] THEN GOTO Trouble; }; PublicFile.Close[]; EXITS KeyNotFound => { MessageWindow.Append[Rope.Concat["Cannot Open ", PublicFileName], TRUE]; MessageWindow.Blink; ERROR KeyFail[$PublicKeyNotFound]; }; NoPublicKey => { MessageWindow.Append[Rope.Concat[PublicFileName, "Empty"], TRUE]; MessageWindow.Blink; ERROR KeyFail[$PublicKeyNotFound]; }; Trouble => { MessageWindow.Append[Rope.Cat["Either ", PublicFileName, ", or ///Keys/MASTER.PublicKey has been tampered with."], TRUE]; MessageWindow.Blink; ERROR KeyFail[$PublicKeyNotAuthenticated]; }; MasterMissing => { MessageWindow.Append[Rope.Concat["///Keys/MASTER.PublicKey is missing form local disk"], TRUE]; MessageWindow.Blink; ERROR KeyFail[$MasterNotFound]; }; Warning => { MessageWindow.Append[Rope.Concat[sender, " must have his/her public key signed by MASTER for authenication to work"], TRUE]; MessageWindow.Blink; }; END; }; ToLowerCase: PUBLIC PROC[in: Rope.ROPE] RETURNS[out: Rope.ROPE] ~ { out _ NIL; FOR i: INT IN [0 .. Rope.Length[in]) DO IF in.Fetch[i] IN ['A..'Z] THEN out _ Rope.Concat[out, Rope.FromChar[Ascii.Lower[in.Fetch[i]]]] ELSE out _ Rope.Concat[out, Rope.FromChar[in.Fetch[i]]]; ENDLOOP; }; END.