MODULE; IMPORT ASCII, Fmt, IP, MD5, Process, Random, Text, Time; VAR rand: Random.T := NIL; PROCEDURE AuthMD5 CheckResponse (response: TEXT; challenge: TEXT; sharedSecret: TEXT): BOOLEAN = BEGIN RETURN Text.Equal(response, GenResponse(challenge, sharedSecret)); END CheckResponse; PROCEDUREGenChallenge (peerAddr: IP.Address; privateKey: TEXT): TEXT = VAR md5 := MD5.New(); BEGIN IF rand = NIL THEN rand := NEW(Random.Default).init(); END; md5.updateText(Fmt.Int(peerAddr.a[0])); md5.updateText("."); md5.updateText(Fmt.Int(peerAddr.a[1])); md5.updateText("."); md5.updateText(Fmt.Int(peerAddr.a[2])); md5.updateText("."); md5.updateText(Fmt.Int(peerAddr.a[3])); md5.updateText(":"); md5.updateText(Fmt.LongReal(Time.Now(), Fmt.Style.Fix)); md5.updateText(":"); md5.updateText(Fmt.Int(Process.GetMyID())); md5.updateText(":"); md5.updateText(Fmt.Int(rand.integer(0))); md5.updateText(":"); md5.updateText(privateKey); RETURN md5.finish(); END GenChallenge; PROCEDUREGenResponse (challenge: TEXT; sharedSecret: TEXT): TEXT = VAR md5 := MD5.New(); BEGIN md5.updateText(sharedSecret); md5.updateText(":"); md5.updateText(challenge); RETURN md5.finish(); END GenResponse; PROCEDUREMakeSecret (realm: TEXT; user: TEXT; password: TEXT): TEXT = VAR md5 := MD5.New(); BEGIN md5.updateText(ToLower(user)); md5.updateText(":"); md5.updateText(ToLower(realm)); md5.updateText(":"); md5.updateText(password); RETURN "$md5$" & md5.finish(); END MakeSecret; PROCEDUREToLower (t: TEXT): TEXT = VAR len := Text.Length(t); chars := NEW(REF ARRAY OF CHAR, len); BEGIN Text.SetChars(chars^, t); FOR i := 0 TO len-1 DO chars[i] := ASCII.Lower[chars[i]]; END; RETURN Text.FromChars(chars^); END ToLower; BEGIN END AuthMD5.