-- File: Passworder.mesa, Last Edit: HGM December 7, 1980 12:23 PM DIRECTORY Inline USING [BITAND, BITNOT, BITSHIFT, COPY, LowHalf, HighHalf], System USING [GetGreenwichMeanTime], Password USING []; Passworder: PROGRAM IMPORTS Inline, System EXPORTS Password = BEGIN Encrypted: PUBLIC TYPE = RECORD [ a: ARRAY [0..2) OF WORD, b: ARRAY [0..2) OF WORD, c: ARRAY [0..4) OF WORD]; Encrypt: PUBLIC PROCEDURE [name, password: STRING] RETURNS [e: Encrypted] = BEGIN e.a ← [0, 0]; FOR i: CARDINAL IN [0..name.length) DO c: WORD ← LOOPHOLE[name[i]]; RightShift6[LOOPHOLE[@e.a], 2]; e.a[0] ← e.a[0] + LeftShift9[c]; ENDLOOP; e.b ← LOOPHOLE[System.GetGreenwichMeanTime[]]; e.c ← ComputePassword[e.a, e.b, password]; END; Check: PUBLIC PROCEDURE [password: STRING, old: Encrypted] RETURNS [BOOLEAN] = BEGIN RETURN[old.c = ComputePassword[old.a, old.b, password]]; END; -- Computation is: -- x ← 16-bit number extracted from password -- x ← 16-bit number extracted from password -- c ← -a*x*x + b*y ComputePassword: PROCEDURE [a, b: ARRAY [0..2) OF WORD, password: STRING] RETURNS [c: ARRAY [0..4) OF WORD] = BEGIN x, y: ARRAY [0..2) OF WORD ← ALL[0]; p: POINTER TO ARRAY [0..2) OF WORD; t, s: ARRAY [0..4) OF WORD; one: ARRAY [0..4) OF WORD ← [0, 0, 0, 1]; FOR i: CARDINAL IN [0..password.length) DO c: WORD ← LOOPHOLE[UpperCase[password[i]]]; p ← IF ((c MOD 3) = 1) THEN @x ELSE @y; RightShift6[LOOPHOLE[p], 2]; p[0] ← p[0] + (c*512); -- Left Shift 9 ENDLOOP; -- Now we have a,b,x,y Mult[LOOPHOLE[@t], LOOPHOLE[@x], LOOPHOLE[@x], 1]; -- t ← x*x Mult[LOOPHOLE[@t], LOOPHOLE[@t], LOOPHOLE[@a], 2]; -- t ← a*x*x -- negate t FOR i: CARDINAL IN [0..4) DO t[i] ← Inline.BITNOT[t[i]]; ENDLOOP; Add[LOOPHOLE[@t], LOOPHOLE[@t], LOOPHOLE[@one], 4]; Mult[LOOPHOLE[@s], LOOPHOLE[@b], LOOPHOLE[@y], 2]; -- s ← b*y Add[LOOPHOLE[@c], LOOPHOLE[@t], LOOPHOLE[@s], 4]; END; UpperCase: PROCEDURE [c: CHARACTER] RETURNS [CHARACTER] = -- Copy over from StringsB to avoid not-in-memory problems from interrupt routine on the Alto BEGIN IF c IN ['a..'z] THEN c ← c + ('A - 'a); RETURN[c]; END; RightShift6: PROCEDURE [a: POINTER TO ARRAY OF WORD, n: CARDINAL] = BEGIN THROUGH [0..6) DO RightShift[a, n]; ENDLOOP; END; LeftShift9: PROCEDURE [w: WORD] RETURNS [WORD] = INLINE {RETURN[w*512]; }; RightShift: PROCEDURE [a: POINTER TO ARRAY OF WORD, n: CARDINAL] = BEGIN ci: WORD ← 0; FOR i: CARDINAL IN [0..n) DO new: WORD ← Inline.BITSHIFT[a[i], -1] + ci; ci ← IF (Inline.BITAND[a[i], 1]) = 0 THEN 0 ELSE 100000B; a[i] ← new; ENDLOOP; END; Add: PROCEDURE [a, b, c: POINTER TO ARRAY OF WORD, n: CARDINAL] = BEGIN carry: BOOLEAN ← FALSE; FOR i: CARDINAL DECREASING IN [0..n) DO temp: LONG CARDINAL ← LONG[b[i]] + LONG[c[i]]; IF carry THEN temp ← temp + 1; carry ← Inline.HighHalf[temp] # 0; a[i] ← Inline.LowHalf[temp]; ENDLOOP; END; Mult: PROCEDURE [a, b, c: POINTER TO ARRAY OF WORD, n: CARDINAL] = BEGIN n2: CARDINAL ← 2*n; bb: ARRAY [0..10B) OF WORD ← ALL[0]; Inline.COPY[to: @bb, nwords: n, from: b]; RightShift[LOOPHOLE[@bb], n2]; FOR i: CARDINAL IN [0..n2) DO a[i] ← 0; ENDLOOP; FOR i: CARDINAL IN [0..n*16 - 1) DO w: WORD ← c[i/16]; IF INTEGER[Inline.BITSHIFT[w, i MOD 16]] < 0 THEN Add[a, a, LOOPHOLE[@bb], n2]; RightShift[LOOPHOLE[@bb], n2]; ENDLOOP; END; END.