Rating:
Block3.dig
```
63 |
.------------|-------.
| 1~63 0~62 0~63 |
____ .------|----| |
Clock |>--|S ~Q| | 0~63 0 |
|--|R__Q|--. I | .----------------------------------.
RS | Clock |>--v | | |
| | ______ | | ____ ______ |
Plain [o]--------|>-----------.----|D | | .-\\ \ .------------|D | |
___ | | | ||xor|----. ___ | | |
Clock |>-|_H_|-|>C Q|---------------.---//___/ Clock |>-|_H_|-|>C Q|--.----(o) Enc
| | | |
>-----|en____| >-----|en____|
Reg Reg
Clock [_n_r]---<| Clock
```
Encryption is done by the following pseudocode:
```python
def enc(x):
result = 0
while x > 0:
result ^= x
x = (x << 1) & 0xFFFFFFFFFFFFFFFF
return result
```
enc(x) = (x ^ (x << 1) ^ (x << 2) ^ ...) & 0xFFFFFFFFFFFFFFFF
Decryption is actually simply
dec(x) = (x ^ (x << 1)) & 0xFFFFFFFFFFFFFFFF
```
Background knowledge:
For 64-bit integer,
If enc(x) = (x ^ (x << n)) & 0xFFFFFFFFFFFFFFFF where n >= 32, then dec(x) = enc(x) because the part that was used to xor with the upper part has not been changed.
However, if n < 32, then the part that was used to xor with the upper part has also been changed when it is xor-ed with the lower part.
For example, if n = 16, for a 64-bit integer denoted by L1 L2 L3 L4, each of L* is 16-bit in size,
Then enc(x) = (L1^L2) (L2^L3) (L3^L4) L4.
By using dec(x) = (x ^ (x << 16)) & 0xFFFFFFFFFFFFFFFF, the result is actually just
(L1^L2)^(L2^L3) (L2^L3)^(L3^L4) (L3^L4)^L4 L4 = (L1^L3) (L2^L4) L3 L4, L1 and L2 are not yet recovered.
By using dec(x) = (x ^ (x << 16) ^ (x << 32)) & 0xFFFFFFFFFFFFFFFF, the result is
(L1^L3)^(L3^L4) (L2^L4)^L4 L3 L4 = (L1^L4) L2 L3 L4, L1 is not yet recovered.
Therefore, we have to use dec(x) = (x ^ (x << 16) ^ (x << 32) ^ (x << 48)) & 0xFFFFFFFFFFFFFFFF, then
(L1^L4)^L4 L2 L3 L4 = L1 L2 L3 L4
Generally for enc(x) = (x ^ (x << n)) & 0xFFFFFFFFFFFFFFFF,
dec(x) = (x ^ (x << n) ^ (x << 2n) ^ (x << 3n) ^ (x << 4n) ^ ... ^ (x << mn)) & 0xFFFFFFFFFFFFFFFF, where (m + 1)n >= 64.
From the challenge we can see that enc(x) is actually the dec(x) case for n = 1,
Therefore dec(x) is simply (x ^ (x << 1)) & 0xFFFFFFFFFFFFFFFF
```
Solving Script:
```python
c = [0xDE2120DED3DDD6EC, 0xD1EEDA2C3531EEDD, 0xEF2ECC232E2ECAEC, 0xC5DC35132C2CDDC2, 0x3521251010CAEE2B]
print(b"".join(bytes.fromhex(hex((ct ^(ct << 1)) & ((1 << 64) - 1))[2:]) for ct in c))
```
Output:
```
b'bcactf{4r3nt_R3g1sTers_4Nd_5tufF_co01_2}'
```