--EncryptionKeysImpl.mesa
Last Edited by: Feigenbaum, May 31, 1984 3:46:19 pm PDT PDT PDT
Last Edited by: Greene, June 27, 1984 4:29:11 pm PDT
Swinehart, July 5, 1985 2:06:27 pm PDT
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]<Cryptography>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]<Cryptography>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]<Cryptography>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.