b01lers CTF | DES-MMXX

meet-in-the-middle attackってこうやって出すのかなるほどな〜という問題。

import sys
from hashlib import sha256
from Crypto.Cipher import DES


SECRET = 0xa########e          # remember to erase this later..
seed = b'secret_sauce_#9'   


def keygen(s):
   keys = []
   for i in range(2020):
      s = sha256(s).digest()
      keys.append(s)
   return keys

def scramble(s):
   ret = "".join( [format(s & 0xfffff, '020b')]*101 )
   ret += "".join( [format(s >> 20, '020b')]*101 )
   return int(ret, 2)
 
def encrypt(keys, msg):
   dk = scramble(SECRET)
   for v in keys:
      idx = dk & 3
      dk >>= 2
      k = v[idx*8:(idx+1)*8]
      cp = DES.new(k, DES.MODE_CBC, bytes(8))  
      msg = cp.encrypt(msg)
   return msg


keys = keygen(seed)

with open("flag.txt", "rb") as f:
   msg = f.read()

ctxt = encrypt(keys, msg)
sys.stdout.buffer.write(ctxt)
package main

import (
    "crypto/cipher"
    "crypto/des"
    "crypto/sha256"
    "encoding/hex"
    "log"
)

const seed = "secret_sauce_#9"

func keygen(s []byte) [][]byte {
    keys := make([][]byte, 2020)
    for i := 0; i < len(keys); i++ {
        s2 := sha256.Sum256(s)
        keys[i] = s2[:]
        s = s2[:]
    }
    return keys
}

func scramble(src int) []int {
    stream := make([]int, 10)
    for i := 0; i < 10; i++ {
        stream[i] = src & 3
        src = src / 4
    }
    stream2 := make([]int, 0)
    for i := 0; i < 101; i++ {
        for _, j := range stream {
            stream2 = append(stream2, j)
        }
    }
    return stream2
}

func encrypt(keys [][]byte, src int, m []byte) []byte {
    dk := scramble(src)
    encrypted := make([]byte, len(m))
    msg := m[:]
    for i, key := range keys {
        idx := dk[i]
        k := key[idx*8 : (idx+1)*8]
        b, err := des.NewCipher(k)
        if err != nil {
            panic(err)
        }
        encrypter := cipher.NewCBCEncrypter(b, make([]byte, 8))
        encrypter.CryptBlocks(encrypted, msg)
        msg = encrypted[:]
    }
    return msg
}

func decrypt(keys [][]byte, src int, c []byte) []byte {
    dk := scramble(src)
    rev_keys := make([][]byte, 0)
    for i, key := range keys {
        idx := dk[i]
        k := key[idx*8 : (idx+1)*8]
        rev_keys = append(rev_keys, k)
    }

    decrypted := make([]byte, len(c))
    msg := c
    for i := len(rev_keys) - 1; i >= 0; i-- {
        k := rev_keys[i]
        b, err := des.NewCipher(k)
        if err != nil {
            panic(err)
        }
        decrypter := cipher.NewCBCDecrypter(b, make([]byte, 8))
        decrypter.CryptBlocks(decrypted, msg)
        msg = decrypted[:]
    }
    return msg
}

func main() {
    keys := keygen([]byte(seed))

    m := []byte("Attack at DAWN!!")
    c := []byte("\x15\x08\x54\xff\x3c\xf4\xc4\xc0\xd2\x3b\xd6\x8a\x82\x34\x83\xbe")

    table := make(map[string]int)
    for a := 0; a < 65536; a++ {
        s := a*16 + 0xe
        encrypted := encrypt(keys[:len(keys)/2], s, m)
        table[hex.EncodeToString(encrypted)] = s
        if a%256 == 0 {
            log.Printf("Progress1: %d/255\n", a/256)
        }
    }

    for a := 0; a < 65536; a++ {
        s := 0xa*65536 + a
        decrypted := decrypt(keys[len(keys)/2:len(keys)], s, c)
        if s1, exists := table[hex.EncodeToString(decrypted)]; exists {
            log.Printf("Found: %d %d\n", s1, s)
        }
        if a%256 == 0 {
            log.Printf("Progress2: %d/255\n", a/256)
        }
    }
}