diff options
author | rsiddharth <s@ricketyspace.net> | 2021-01-25 00:07:08 -0500 |
---|---|---|
committer | rsiddharth <s@ricketyspace.net> | 2021-01-25 00:07:08 -0500 |
commit | e8144de68e247ebc39ae61745907440042f43d71 (patch) | |
tree | a2932f98ccec1c206b4dbf005ffd8038256e7e76 | |
parent | 1e9917c16fa02da5b73a53929a6b8173b2716279 (diff) |
challenge: do challenge 14
-rw-r--r-- | challenge/c14.go | 128 | ||||
-rw-r--r-- | cryptopals.go | 2 | ||||
-rw-r--r-- | lib/oracle.go | 2 |
3 files changed, 131 insertions, 1 deletions
diff --git a/challenge/c14.go b/challenge/c14.go new file mode 100644 index 0000000..9ed4e5f --- /dev/null +++ b/challenge/c14.go @@ -0,0 +1,128 @@ +// Copyright © 2021 rsiddharth <s@ricketyspace.net> +// SPDX-License-Identifier: ISC + +package challenge + +import ( + "fmt" + "ricketyspace.net/cryptopals/lib" +) + +func C14() { + blocksize := findBlockSizeForVarEncryptECB() + rpl, nrpb, rpo := findRandPrefixLen(blocksize) + nbl, us_sz := findUnknownStringNumBlocksLength( + rpl, blocksize) + in := append(freshSheepBlock(rpo), // random prefix offset + freshSheepBlock(blocksize)...) + ds := make([]byte, 0) // deciphered unknown string in bytes + for i := 0; i < nbl; i++ { + nby := blocksize + if i == nbl-1 { + nby = us_sz % blocksize + } + for j := 0; j < nby; j++ { + in, ds = decipherOneByteUS(nrpb, rpo, blocksize, + i+1, j+1, in, ds) + } + s := 16 * i + e := s + 16 + in = append(freshSheepBlock(rpo), ds[s:e]...) + } + fmt.Printf("Unknown String:\n%v", lib.BytesToStr(ds)) +} + +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(freshSheepBlock(blocksize), freshSheepBlock(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!") +} diff --git a/cryptopals.go b/cryptopals.go index 1ae8c8d..179caf0 100644 --- a/cryptopals.go +++ b/cryptopals.go @@ -44,5 +44,7 @@ func main() { challenge.C12() case 13: challenge.C13() + case 14: + challenge.C14() } } diff --git a/lib/oracle.go b/lib/oracle.go index a2e75aa..a8daa12 100644 --- a/lib/oracle.go +++ b/lib/oracle.go @@ -14,7 +14,7 @@ dXN0IHRvIHNheSBoaQpEaWQgeW91IHN0b3A/IE5vLCBJIGp1c3QgZHJvdmUg YnkK` var oracleKey []byte = make([]byte, 16) -var oracleRandom []byte = make([]byte, randomInt(1, 16)) +var oracleRandom []byte = make([]byte, randomInt(1, 4096)) func init() { _, err := rand.Read(oracleKey) |