<> <> <> DIRECTORY BasicTime USING[ GetClockPulses ], DESFace, Basics USING[ BITXOR ]; DESDummy: MONITOR IMPORTS Basics, BasicTime EXPORTS DESFace SHARES DESFace = BEGIN OPEN DESFace; Words4: TYPE = MACHINE DEPENDENT RECORD[w1, w2, w3, w4: WORD]; XOR64: PROCEDURE[a, b, out: LONG POINTER] = INLINE BEGIN OPEN aLP: LOOPHOLE[a, LONG POINTER TO Words4], bLP: LOOPHOLE[b, LONG POINTER TO Words4], outP: LOOPHOLE[out, LONG POINTER TO Words4]; outP.w1 _ Basics.BITXOR[aLP.w1, bLP.w1]; outP.w2 _ Basics.BITXOR[aLP.w2, bLP.w2]; outP.w3 _ Basics.BITXOR[aLP.w3, bLP.w3]; outP.w4 _ Basics.BITXOR[aLP.w4, bLP.w4]; END; Words2: TYPE = MACHINE DEPENDENT RECORD[w1, w2: WORD]; XOR32: PROCEDURE[a, b: LONG UNSPECIFIED, out: POINTER] = INLINE BEGIN OPEN aP: LOOPHOLE[a, Words2], bP: LOOPHOLE[b, Words2], outP: LOOPHOLE[out, POINTER TO Words2]; outP.w1 _ Basics.BITXOR[aP.w1, bP.w1]; outP.w2 _ Basics.BITXOR[aP.w2, bP.w2]; END; cachedKey: Key; noKeyCached: BOOLEAN _ TRUE; BadParity: ERROR = CODE; InternalizeKey: ENTRY PROC [keyP: POINTER TO Key] = BEGIN IF noKeyCached OR cachedKey # keyP^ THEN BEGIN FOR i: CARDINAL IN [0..7] DO IF keyP[i].p # parityTable[keyP[i].b] THEN RETURN WITH ERROR BadParity; ENDLOOP; cachedKey _ keyP^; noKeyCached _ FALSE; END; END; --InternalizeKey-- NotImplemented: ERROR = CODE; CryptData: PUBLIC PROCEDURE [keyP: POINTER TO Key, nBlks: CARDINAL, from, to: Blocks, direction: Direction, mode: Mode, seedP: LONG POINTER TO IV _ NIL] = BEGIN newSeed: IV; IF mode = checksum THEN ERROR NotImplemented; IF mode = cbcCheck AND direction = encrypt AND nBlks > 0 THEN BEGIN FOR blk: CARDINAL IN [0..nBlks-1) DO XOR64[@from[nBlks-1], @from[blk], @from[nBlks-1]] ENDLOOP; END; InternalizeKey[keyP]; FOR blk: CARDINAL IN [0 .. nBlks) DO IF mode#ecb THEN IF direction=encrypt THEN XOR64[@from[blk], seedP, @from[blk]] ELSE newSeed _ from[blk]; XOR64[keyP, @from[blk], @to[blk]]; IF mode#ecb THEN IF direction=encrypt THEN seedP _ @to[blk] ELSE {XOR64[@to[blk], seedP, @to[blk]]; seedP^ _ newSeed}; ENDLOOP; IF mode = cbcCheck AND direction = decrypt AND nBlks > 0 THEN BEGIN FOR blk: CARDINAL IN [0..nBlks-1) DO XOR64[@to[nBlks-1], @to[blk], @to[nBlks-1]] ENDLOOP; END END; --CryptData-- randomSeed: Block _ [1,2,3,4]; GetRandomIV: PUBLIC PROCEDURE RETURNS [iv: IV] = BEGIN -- Ideally, this should use a true random number generator -- prevSeed: Block _ randomSeed; pulse1: POINTER TO LONG CARDINAL = LOOPHOLE[@randomSeed[0]]; pulse2: POINTER TO LONG CARDINAL = LOOPHOLE[@randomSeed[2]]; seedKey: POINTER TO Key = LOOPHOLE[@randomSeed]; pulse1^ _ pulse1^ + BasicTime.GetClockPulses[]; XOR32[pulse2^, BasicTime.GetClockPulses[], pulse2]; CorrectParity[seedKey]; CryptData[keyP: seedKey, nBlks: 1, from: LOOPHOLE[LONG[@prevSeed], Blocks], to: LOOPHOLE[LONG[@iv], Blocks], direction: encrypt, mode: ecb, seedP: NIL]; END; --GetRandomIV-- GetRandomKey: PUBLIC PROCEDURE RETURNS [k: Key] = BEGIN k _ LOOPHOLE[GetRandomIV[]]; CorrectParity[@k]; END; --GetRandomKey-- MakeKey: PUBLIC PROCEDURE [source: LONG STRING] RETURNS [key: Key] = BEGIN <> <<"key" is an array that holds the 64 bit key.>> <> key _ nullKey; FOR i: CARDINAL IN [0..source.length) DO j: CARDINAL = i MOD 8; c: CHARACTER = IF source[i] IN ['A..'Z] THEN 'a + (source[i]-'A) ELSE source[i]; key[j].b _ Basics.BITXOR[LOOPHOLE[c, [0 .. 127]], key[j].b]; ENDLOOP; CorrectParity[@key]; END; -- MakeKey parityTable: PACKED ARRAY [0..127] OF [0..1] _ [ 1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1, 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0, 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0, 1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1, 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0, 1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1, 1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1, 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0 ]; CorrectParity: PUBLIC PROC[keyP: LONG POINTER TO Key] = BEGIN FOR i: CARDINAL IN [0 .. 7] DO keyP[i].p _ parityTable[keyP[i].b]; ENDLOOP; END; [] _ GetRandomKey[]; END. --DES--