CryptoHack--Dancing Queen

算法都可逆,state生成取决于KEY以及IV,最后的state是msg^msg_enc,前64写一个倒推10轮就可以还原key和IV了。

代码如下:

#!/usr/bin/env python3

from os import urandom
from Crypto.Util.number import *

FLAG = b'crypto{?????????????????????????????}'


def bytes_to_words(b):
    return [int.from_bytes(b[i:i + 4], 'little') for i in range(0, len(b), 4)]


def rotate(x, n):
    return ((x << n) & 0xffffffff) | ((x >> (32 - n)) & 0xffffffff)


def rotate_reverse(x, n):
    return ((x << (32 - n)) & 0xffffffff) | ((x >> n) & 0xffffffff)


def word(x):
    return x % (2 ** 32)


def words_to_bytes(w):
    return b''.join([i.to_bytes(4, 'little') for i in w])


def xor(a, b):
    return b''.join([bytes([x ^ y]) for x, y in zip(a, b)])


class ChaCha20:
    def __init__(self):
        self._state = []

    def _inner_block(self, state):
        self._quarter_round(state, 0, 4, 8, 12)
        self._quarter_round(state, 1, 5, 9, 13)
        self._quarter_round(state, 2, 6, 10, 14)
        self._quarter_round(state, 3, 7, 11, 15)
        self._quarter_round(state, 0, 5, 10, 15)
        self._quarter_round(state, 1, 6, 11, 12)
        self._quarter_round(state, 2, 7, 8, 13)
        self._quarter_round(state, 3, 4, 9, 14)

    def _quarter_round(self, x, a, b, c, d):
        x[a] = word(x[a] + x[b]);
        x[d] ^= x[a];
        x[d] = rotate(x[d], 16)
        x[c] = word(x[c] + x[d]);
        x[b] ^= x[c];
        x[b] = rotate(x[b], 12)
        x[a] = word(x[a] + x[b]);
        x[d] ^= x[a];
        x[d] = rotate(x[d], 8)
        x[c] = word(x[c] + x[d]);
        x[b] ^= x[c];
        x[b] = rotate(x[b], 7)

    def _inner_block_revese(self, state):
        self._quarter_round_revese(state, 3, 4, 9, 14)
        self._quarter_round_revese(state, 2, 7, 8, 13)
        self._quarter_round_revese(state, 1, 6, 11, 12)
        self._quarter_round_revese(state, 0, 5, 10, 15)
        self._quarter_round_revese(state, 3, 7, 11, 15)
        self._quarter_round_revese(state, 2, 6, 10, 14)
        self._quarter_round_revese(state, 1, 5, 9, 13)
        self._quarter_round_revese(state, 0, 4, 8, 12)

    def _quarter_round_revese(self, x, a, b, c, d):
        x[b] = rotate_reverse(x[b], 7)
        x[b] ^= x[c]
        x[c] = word(x[c] - x[d])
        x[d] = rotate_reverse(x[d], 8)
        x[d] ^= x[a]
        x[a] = word(x[a] - x[b])
        x[b] = rotate_reverse(x[b], 12)
        x[b] ^= x[c]
        x[c] = word(x[c] - x[d])
        x[d] = rotate_reverse(x[d], 16)
        x[d] ^= x[a]
        x[a] = word(x[a] - x[b])

    def _setup_state(self, key, iv):
        self._state = [0x61707865, 0x3320646e, 0x79622d32, 0x6b206574]
        self._state.extend(bytes_to_words(key))
        self._state.append(self._counter)
        self._state.extend(bytes_to_words(iv))

    def decrypt(self, c, key, iv):
        return self.encrypt(c, key, iv)

    def encrypt(self, m, key, iv):
        c = b''
        self._counter = 1

        for i in range(0, len(m), 64):
            self._setup_state(key, iv)
            for j in range(10):
                self._inner_block(self._state)
            c += xor(m[i:i + 64], words_to_bytes(self._state))

            self._counter += 1

        return c

    def state_reverse(self, msg, cipher):
        state = []
        for i in range(64):
            state.append(msg[i] ^ cipher[i])
        self._state = []
        self._state.extend(bytes_to_words(state))
        # print(self._state)
        for i in range(10):
            self._inner_block_revese(self._state)
            # self._inner_block(self._state)


        for i in range(16):
            print(hex(self._state[i]) + " ", end="")
        print()
        print(hex(bytes_to_long(words_to_bytes(self._state[4:12]))))
if __name__ == '__main__':
    msg = b'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula.'
    iv1 = 'e42758d6d218013ea63e3c49'
    iv1=bytes.fromhex(iv1)
    iv2 = 'a99f9a7d097daabd2aa2a235'
    iv2=bytes.fromhex(iv2)
    key = '39fd1410fef6485bf3068ea0fb3a8ff6385b4483bc1f321cea4f15cc1c43496c'
    key=bytes.fromhex(key)
    msg_enc = 'f3afbada8237af6e94c7d2065ee0e221a1748b8c7b11105a8cc8a1c74253611c94fe7ea6fa8a9133505772ef619f04b05d2e2b0732cc483df72ccebb09a92c211ef5a52628094f09a30fc692cb25647f'
    flag_enc = 'b6327e9a2253034096344ad5694a2040b114753e24ea9c1af17c10263281fb0fe622b32732'
    c = ChaCha20()
    c.state_reverse(msg[:64],bytes.fromhex(msg_enc)[:64])
    msg_enc = c.decrypt(bytes.fromhex(msg_enc), key, iv1)
    flag_enc = c.decrypt(bytes.fromhex(flag_enc), key, iv2)
    print(f"msg_enc = '{msg_enc}'")
    print(f"flag_enc = '{flag_enc}'")

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值