1 # cipher-core on its own: a block's hex and byte forms, XOR, tables, the 2 # word helpers on bits against their native forms, Feistel rounds over a toy 3 # round function, and the 64-bit modes over a toy cipher (XOR with the key 4 # block: not a cipher, but enough to show the modes chain and undo 5 # themselves), with their refusals. The ciphers' own packages test the 6 # modes over real ciphers (des: against Python's cryptography). 7 import Base 8 import bend-osdev-bytes@0.1.1.0/bytes.bend as B 9 import ./cipher_core.bend as L 10 import ./modes64.bend as X 11 12 def err(e: L.LcError) -> String: 13 match e: 14 case L.LcBadKeyLength{n}: 15 "bad key " ++ Nat.show(n) 16 case L.LcBadIvLength{n}: 17 "bad iv " ++ Nat.show(n) 18 case L.LcNotBlockMultiple{n}: 19 "not whole blocks " ++ Nat.show(n) 20 21 def show(r: Result<&2, &2, L.LcError, B.Octets>) -> String: 22 match r: 23 case Fail{e}: 24 err(e) 25 case Done{o}: 26 B.Octets.hex(o) 27 28 def show_blocks(r: Result<&2, &2, L.LcError, List<&2, L.LcBlock64>>) -> String: 29 match r: 30 case Fail{e}: 31 err(e) 32 case Done{bs}: 33 B.Octets.hex(X.Lc64.octets_of(bs)) 34 35 def show_some(m: Maybe<&2, L.LcBlock64>) -> String: 36 match m: 37 case None{}: 38 "none" 39 case Some{b}: 40 L.LcBlock64.hex(b) 41 42 # a word as hex, through the block's hex form 43 def word(x: U32) -> String: 44 L.LcBlock64.hex(L.LcBlock64{0, x}) 45 46 # the toy cipher: XOR with the key block, its own inverse 47 def toy(k: L.LcBlock64, b: L.LcBlock64) -> L.LcBlock64: 48 L.LcBlock64.xor(k, b) 49 50 def toy_key() -> L.LcBlock64: 51 L.LcBlock64{19088743, 2309737967} 52 53 # a toy round function for the Feistel rounds: x + k, then rotated by 7 54 def toy_f(k: U32, x: U32) -> U32: 55 L.lc.rotl(U32.add(x, k), 7n) 56 57 def msg() -> B.Octets: 58 B.Octets.of_list([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]) 59 60 def iv() -> B.Octets: 61 B.Octets.of_list([240, 241, 242, 243, 244, 245, 246, 247]) 62 63 def ecb(m: B.Octets) -> String: 64 +c = X.Lc64.ecb_encrypt(~L.LcBlock64, ~toy, toy_key(), m) 65 show(c) ++ " " ++ show(Result.bind(&2, &2, L.LcError, B.Octets, B.Octets, c, x => X.Lc64.ecb_decrypt(~L.LcBlock64, ~toy, toy_key(), x))) 66 67 def cbc(+v: B.Octets, m: B.Octets) -> String: 68 +c = X.Lc64.cbc_encrypt(~L.LcBlock64, ~toy, toy_key(), v, m) 69 show(c) ++ " " ++ show(Result.bind(&2, &2, L.LcError, B.Octets, B.Octets, c, x => X.Lc64.cbc_decrypt(~L.LcBlock64, ~toy, toy_key(), v, x))) 70 71 def feistel(+b: L.LcBlock64) -> String: 72 +ks = {[1, 2, 3, 4, 5, 6, 7, 8] : List<&2, U32>} 73 +c = L.lc.fe.run(~U32, ~toy_f, ks, b) 74 L.LcBlock64.hex(c) ++ " " ++ L.LcBlock64.hex(L.lc.fe.unrun(~U32, ~toy_f, ks, c)) 75 76 def tab() -> String: 77 +t = L.lc.tab(2n, [10, 20, 30, 40]) 78 word(L.lc.tab.get(2n, t, 2)) ++ " " ++ word(L.lc.tab.get(2n, L.lc.tab.set(2n, t, 1, 99), 1)) ++ " " ++ word(L.lc.tab.get(2n, t, 1)) 79 80 def main() -> IO(Unit): 81 do IO: 82 IO.print(L.LcBlock64.hex(toy_key())) 83 IO.print(B.Octets.hex(L.LcBlock64.to_octets(toy_key()))) 84 IO.print(show_some(L.LcBlock64.of_octets(L.LcBlock64.to_octets(toy_key())))) 85 IO.print(show_some(L.LcBlock64.of_octets(B.Octets.zeros(7n)))) 86 IO.print(L.LcBlock64.hex(L.LcBlock64.xor(toy_key(), L.LcBlock64{4294967295, 0}))) 87 IO.print(word(L.lc.bswap.bits(16909060)) ++ " " ++ word(L.lc.rotl1.bits(2147483649)) ++ " " ++ word(L.lc.rotl(2147483649, 1n)) ++ " " ++ word(L.lc.rotl31.bits(3))) 88 IO.print(word(L.lc.be(1, 2, 3, 4)) ++ " " ++ word(L.lc.le(1, 2, 3, 4)) ++ " " ++ word(L.lc.byte(16909060, 3n))) 89 IO.print(tab()) 90 IO.print(feistel(L.LcBlock64{305419896, 2596069104})) 91 IO.print(show_blocks(X.Lc64.blocks_of(msg()))) 92 IO.print(ecb(msg())) 93 IO.print(cbc(iv(), msg())) 94 IO.print(cbc(B.Octets.zeros(7n), msg())) 95 IO.print(ecb(B.Octets.zeros(9n))) 96 97 #|0123456789abcdef 98 #|0123456789abcdef 99 #|0123456789abcdef 100 #|none 101 #|fedcba9889abcdef 102 #|0000000004030201 0000000000000003 0000000000000003 0000000080000001 103 #|0000000001020304 0000000004030201 0000000000000001 104 #|000000000000001e 0000000000000063 0000000000000014 105 #|3eefc45f6fc66333 123456789abcdef0 106 #|000102030405060708090a0b0c0d0e0f1011121314151617 107 #|012247648daecbe8092a4f6c85a6c3e0113257749dbedbf8 000102030405060708090a0b0c0d0e0f1011121314151617 108 #|f1d3b597795b3d1ff8f9fafbfcfdfeffe9cbad8f61432507 000102030405060708090a0b0c0d0e0f1011121314151617 109 #|bad iv 7 bad iv 7 110 #|not whole blocks 9 not whole blocks 9