summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--challenge/c14.go128
-rw-r--r--cryptopals.go2
-rw-r--r--lib/oracle.go2
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)