From 8bb9700533f493f04dcc423f57ca9bb671e6b0b3 Mon Sep 17 00:00:00 2001 From: rsiddharth Date: Wed, 24 Feb 2021 17:29:32 -0500 Subject: challenge/c14.go: refactor Keep everything inside C14 --- challenge/c14.go | 211 +++++++++++++++++++++++++++---------------------------- 1 file changed, 103 insertions(+), 108 deletions(-) (limited to 'challenge') diff --git a/challenge/c14.go b/challenge/c14.go index 4471f44..552c2df 100644 --- a/challenge/c14.go +++ b/challenge/c14.go @@ -9,11 +9,109 @@ import ( "ricketyspace.net/cryptopals/lib" ) -var sheep byte = 65 - func C14() { - blocksize := findBlockSizeForVarEncryptECB() - rpl, nrpb, rpo := findRandPrefixLen(blocksize) + sheep := byte(65) + freshSheepBytes := func(n int) []byte { + in := make([]byte, n) + for i := 0; i < n; i++ { + in[i] = sheep + } + return in + } + findBlockSize := func() int { + in := make([]byte, 0) + + in = append(in, sheep) + is := len(lib.OracleAESVarEncryptECB(in)) // initial size + bs := 0 + for { + in = append(in, sheep) + bs = len(lib.OracleAESVarEncryptECB(in)) + if bs != is { + return (bs - is) + } + } + } + findPrefixLen := func(blocksize int) (int, int, int) { + // Make two sheep blocks. + tsb := append(freshSheepBytes(blocksize), freshSheepBytes(blocksize)...) + + v := []byte{} + index := 0 + found := false + for { + in := append(v, tsb...) + c := lib.OracleAESVarEncryptECB(in) + index, found = lib.HasConsecutiveMatchingBlocks(c, blocksize) + if found { + break + } + // Add another sheep + v = append(v, sheep) + } + l := index - len(v) + nrpb := l / blocksize // number of randbox prefix blocks + rpo := 0 // random prefix offset + if l%blocksize != 0 { + nrpb += 1 + rpo = blocksize - (l % blocksize) + } + return l, nrpb, rpo + } + // Finds the cipher block size and the length of the unknown string + // (target-bytes). + findUnknownStringNumBlocksLength := func(rpl, blocksize int) (int, int) { + padding := blocksize - (rpl % blocksize) + in := make([]byte, padding) + c_sz := len(lib.OracleAESVarEncryptECB(in)) // Cipher size + + nblocks := c_sz / blocksize // total number of blocks + rblocks := (rpl + padding) / blocksize // number of blocks of random prefix + ublocks := nblocks - rblocks // number of blocks of unknown string + // Figure out size of unknown string. + for { + in = append(in, sheep) + bs := len(lib.OracleAESVarEncryptECB(in)) + if bs != c_sz { + return ublocks, (c_sz - len(in) - rpl) + } + } + } + // `nrpb` number of random prefix blocks + // `rpo` random prefix offset + // `blocksize` is the size of a block + // `block` is the nth block that is being deciphered + // `n` is the nth byte of the block `block` that is going to be deciphered. + // `in` (n-1)th block that is known + // `ds` deciphered unknown string + decipherOneByte := func(nrpb, rpo, blocksize, block, n int, in, ds []byte) ([]byte, []byte) { + oo := lib.OracleAESVarEncryptECB(in[0:(len(in) - n)]) + + s := (nrpb * blocksize) + 16*(block-1) + e := s + 16 + nbl := oo[s:e] // nth block of the cipher + + // Shift `in` to the left by one place. + for i := rpo; i < len(in)-1; i++ { + in[i] = in[i+1] + } + + // Try all combinations. + for i := 0; i < 256; i++ { + in[len(in)-1] = byte(i) + oo = lib.OracleAESVarEncryptECB(in) + + if lib.BlocksEqual(nbl, + oo[(nrpb*blocksize):(nrpb*blocksize)+16]) { + ds = append(ds, in[len(in)-1]) + return in, ds + } + } + panic("not found!") + } + + blocksize := findBlockSize() + rpl, nrpb, rpo := findPrefixLen(blocksize) nbl, us_sz := findUnknownStringNumBlocksLength( rpl, blocksize) in := append(freshSheepBytes(rpo), // random prefix offset @@ -25,7 +123,7 @@ func C14() { nby = us_sz % blocksize } for j := 0; j < nby; j++ { - in, ds = decipherOneByteUS(nrpb, rpo, blocksize, + in, ds = decipherOneByte(nrpb, rpo, blocksize, i+1, j+1, in, ds) } s := 16 * i @@ -35,109 +133,6 @@ func C14() { fmt.Printf("Unknown String:\n%v", lib.BytesToStr(ds)) } -func freshSheepBytes(n int) []byte { - in := make([]byte, n) - for i := 0; i < n; i++ { - in[i] = sheep - } - return in -} - -func findBlockSizeForVarEncryptECB() int { - in := make([]byte, 0) - - in = append(in, sheep) - is := len(lib.OracleAESVarEncryptECB(in)) // initial size - bs := 0 - for { - in = append(in, sheep) - bs = len(lib.OracleAESVarEncryptECB(in)) - if bs != is { - return (bs - is) - } - } -} - -func findRandPrefixLen(blocksize int) (int, int, int) { - // Make two sheep blocks. - tsb := append(freshSheepBytes(blocksize), freshSheepBytes(blocksize)...) - - v := []byte{} - index := 0 - found := false - for { - in := append(v, tsb...) - c := lib.OracleAESVarEncryptECB(in) - index, found = lib.HasConsecutiveMatchingBlocks(c, blocksize) - if found { - break - } - // Add another sheep - v = append(v, sheep) - } - l := index - len(v) - nrpb := l / blocksize // number of randbox prefix blocks - rpo := 0 // random prefix offset - if l%blocksize != 0 { - nrpb += 1 - rpo = blocksize - (l % blocksize) - } - return l, nrpb, rpo -} - -// Finds the cipher block size and the length of the unknown string -// (target-bytes). -func findUnknownStringNumBlocksLength(rpl, blocksize int) (int, int) { - padding := blocksize - (rpl % blocksize) - in := make([]byte, padding) - c_sz := len(lib.OracleAESVarEncryptECB(in)) // Cipher size - - nblocks := c_sz / blocksize // total number of blocks - rblocks := (rpl + padding) / blocksize // number of blocks of random prefix - ublocks := nblocks - rblocks // number of blocks of unknown string - // Figure out size of unknown string. - for { - in = append(in, sheep) - bs := len(lib.OracleAESVarEncryptECB(in)) - if bs != c_sz { - return ublocks, (c_sz - len(in) - rpl) - } - } -} - -// `nrpb` number of random prefix blocks -// `rpo` random prefix offset -// `blocksize` is the size of a block -// `block` is the nth block that is being deciphered -// `n` is the nth byte of the block `block` that is going to be deciphered. -// `in` (n-1)th block that is known -// `ds` deciphered unknown string -func decipherOneByteUS(nrpb, rpo, blocksize, block, n int, in, ds []byte) ([]byte, []byte) { - oo := lib.OracleAESVarEncryptECB(in[0:(len(in) - n)]) - - s := (nrpb * blocksize) + 16*(block-1) - e := s + 16 - nbl := oo[s:e] // nth block of the cipher - - // Shift `in` to the left by one place. - for i := rpo; i < len(in)-1; i++ { - in[i] = in[i+1] - } - - // Try all combinations. - for i := 0; i < 256; i++ { - in[len(in)-1] = byte(i) - oo = lib.OracleAESVarEncryptECB(in) - - if lib.BlocksEqual(nbl, - oo[(nrpb*blocksize):(nrpb*blocksize)+16]) { - ds = append(ds, in[len(in)-1]) - return in, ds - } - } - panic("not found!") -} - // Output: // Unknown String: // Rollin' in my 5.0 -- cgit v1.2.3