# crypto hack
## Great Snakes
Run python code -> get flag:
```python
#!/usr/bin/env python3
import sys
# import this
if sys.version_info.major == 2:
print("You are running Python 2, which is no longer supported. Please update to Python 3.")
ords = [81, 64, 75, 66, 70, 93, 73, 72, 1, 92, 109, 2, 84, 109, 66, 75, 70, 90, 2, 92, 79]
print("Here is your flag:")
print("".join(chr(o ^ 0x32) for o in ords))
```
flag: `crypto{z3n_0f_pyth0n}`
## ASCII
ASCII là mã chuẩn hóa 7bits cho phép biểu diễn văn bản bằng số nguyên -> có thể dùng chr() để convert từ số thứ tự sang char và ord là ngược lại.
[99, 114, 121, 112, 116, 111, 123, 65, 83, 67, 73, 73, 95, 112, 114, 49, 110, 116, 52, 98, 108, 51, 125] -> chuyển thành flag:
```python
ints = [99, 114, 121, 112, 116, 111, 123, 65, 83, 67, 73, 73, 95, 112, 114, 49, 110, 116, 52, 98, 108, 51, 125]
print("".join([chr(i) for i in ints]))```
flag: `crypto{ASCII_pr1nt4bl3}`
## Hex
Thông thường trong những chall này, thì kết quả khi được mã hóa(hay còn gọi là ciphertext sẽ thường có các bytes không thể in được các kí tự ASCII) -> do đó những output được gửi cho ta thành một cái gì đó thân thiện và di động hơn trên các hệ thống khác nhau là cần thiết.
Và hexadecimal(hệ 16) có thể sử dụng như vậy để biểu diễn chúng: đầu tiên từng ký tự sẽ chuyển bằng ord() sang số thứ tự -> tiếp đó hệ decimal được chuyển thành hệ hexadecimal -> các số nối lại tạo thành chuỗi dài.
Python có thể dùng `bytes.fromhex()` để chuyển đổi hex thành byte và `.hex()` để chuyển byte thành hex.
```python
hex = "63727970746f7b596f755f77696c6c5f62655f776f726b696e675f776974685f6865785f737472696e67735f615f6c6f747d"
print(bytes.fromhex(hex))
```
flag: `crypto{You_will_be_working_with_hex_strings_a_lot}`
## Base64
base64 biểu diễn mã hóa bằng bảng chữ cái 64 kí tự
`import base64`, `base64.b64encode()`
```python
import base64
hex = "72bca9b68fc16ac7beeb8f849dca1d8a783e8acf9679bf9269f7bf"
bytes = bytes.fromhex(hex)
print(base64.b64encode(bytes))
```
flag: `b'crypto/Base+64+Encoding+is+Web+Safe/'`
## Bytes and Big Integers
các hệ thống mã hóa trên rsa hoạt động trên các số, nhưng các thông điệp được tạo thành từ các ký tự, để chuyển đổi các thông điệp của mình thành các số để các phép toán có thể được áp dụng.
Cách phổ biến là lất từng byte của tin nhắn -> chuyển đổi chúng thành hex.
Ví dụ:
```
message: HELLO
ascii bytes: [72, 69, 76, 76, 79]
hex bytes: [0x48, 0x45, 0x4c, 0x4c, 0x4f]
base-16: 0x48454c4c4f
base-10: 310400273487
```
Trong python có PyCryptodome thực hiện nó với các phương thức`bytes_to_long()` và `long_to_bytes()` -> cài đặt PyCryptodome và import bằng `from Crypto.Util.number import *`
```
from Crypto.Util.number import *
print(long_to_bytes(11515195063862318899931685488813747395775516287289682636499965282714637259206269))
crypto{3nc0d1n6_4ll_7h3_w4y_d0wn}
```
## XOR Starter
là một toán tử bitwise trả về 0 nếu các bit same nhau và 1 nếu không. kí hiệu `^`
```
------------
|A|B|output|
------------
|0|0|0|
-------
|0|1|1|
-------
|1|0|1|
-------
|1|1|0|
-------
```
trong python có `pwntools` tiện lợi để `xor()`
Để XOR hai chuỗi:
Chuyển từng ký tự sang mã Unicode (ord())
XOR từng cặp ký tự tương ứng
Sau đó có thể chuyển kết quả về ký tự (chr()), nếu muốn kết quả là chuỗi
XOR giữa các số nguyên (decimal):
```
a = 6 # 0110
b = 10 # 1010
c = a ^ b # 1100 = 12
print(c) # Output: 12
```
```
from pwn import xor
label = b"label"
key = 13
result = xor(label, key)
print(f"crypto{{{result.decode()}}}")
label = "label"
new_str = ""
for c in label:
new_str += chr(ord(c) ^ 13)
print(f"crypto{{{new_str}}}")
```
flag: `crypto{aloha}`
## XOR attribute
Commutative: A ⊕ B = B ⊕ A
Associative: A ⊕ (B ⊕ C) = (A ⊕ B) ⊕ C
Identity: A ⊕ 0 = A
Self-Inverse: A ⊕ A = 0
```
KEY1 = a6c8b6733c9b22de7bc0253266a3867df55acde8635e19c73313
KEY2 ^ KEY1 = 37dcb292030faa90d07eec17e3b1c6d8daf94c35d4c9191a5e1e
KEY2 ^ KEY3 = c1545756687e7573db23aa1c3452a098b71a7fbf0fddddde5fc1
FLAG ^ KEY1 ^ KEY3 ^ KEY2 = 04ee9855208a2cd59091d04767ae47963170d1660df7f56f5faf
```
Tư duy đơn giản, kiểu giải toán thôi:
k1 xor k2 xor k1 = (k1 xor k1) xor k1 = 0 xor k2 = k2 -> tìm ra k2
tương tự k2 xor k2 xor k3 -> tìm được k3
FLAG xor k1 xor k2 xor k3 xor k1 xor k2 xor k3 = FLAG XOR 0 XOR 0 XOR 0 = FLAG
```python
from pwn import xor
KEY1 = bytes.fromhex("a6c8b6733c9b22de7bc0253266a3867df55acde8635e19c73313")
XOR_KEY2_KEY1 = bytes.fromhex("37dcb292030faa90d07eec17e3b1c6d8daf94c35d4c9191a5e1e")
XOR_KEY2_KEY3 = bytes.fromhex("c1545756687e7573db23aa1c3452a098b71a7fbf0fddddde5fc1")
XOR_ALL_KEYS_FLAG = bytes.fromhex("04ee9855208a2cd59091d04767ae47963170d1660df7f56f5faf")
#KEY2: XOR_KEY2_KEY1 ^ KEY1
KEY2 = xor(XOR_KEY2_KEY1, KEY1)
#KEY3: XOR_KEY2_KEY3 ^ KEY2
KEY3 = xor(XOR_KEY2_KEY3, KEY2)
#FLAG: XOR_ALL_KEYS_FLAG ^ KEY1 ^ KEY2 ^ KEY3
FLAG = xor(xor(xor(XOR_ALL_KEYS_FLAG, KEY1), KEY2), KEY3)
print(f"{FLAG.decode()}")
```
flag: `crypto{x0r_i5_ass0c1at1v3}`
## Favourite byte
I've hidden some data using XOR with a single byte, but that byte is a secret. Don't forget to decode from hex first.
`73626960647f6b206821204f21254f7d694f7624662065622127234f726927756d`
```python
from pwn import xor
flagBytes = bytes.fromhex("73626960647f6b206821204f21254f7d694f7624662065622127234f726927756d")
byte=0x00
for i in range(256):
flag=xor(flagBytes, byte).decode("utf-8")
if("crypto" in flag):
print(flag)
break
byte=byte + 0x01
```
flag: `crypto{0x10_15_my_f4v0ur173_by7e}`
# Modular Arithmetic
## Greatest Common Divisor (GCD)
ước chung lớn nhất của 2 số - số lớn nhất trong giao của 2 tập hợp ước chung của từng số.
có nhiều thuật toán tìm như sàng, euclid, millerabin. -> ở đây sẽ dùng euclid để tính gcd(66528, 52920).
```python
def gcd(a,b):
if a<b:
a,b = b,a
while b!=0:
a,b = b,a%b
return a
print(gcd(66528,52920))
```
answer: 1512
## Extended GCD(euclid mở rộng)
cho a và b là số nguyên dương -> Extend Euclide là cách hiệu quả tìm u,v sao cho: `u.a+b.v = gcd(a,b)`
-> này hay được dùng trong RSA.
```python
def extended_gcd(a, b):
if b == 0:
return (a, 1, 0)
else:
g, x1, y1 = extended_gcd(b, a % b)
x = y1
y = x1 - (a // b) * y1
return (g, x, y)
g, x, y = extended_gcd(26513, 32321)
print(g ,x, y)
1, 10245, -8404
```
## Modular Arithmetic 1
giống toán chuyên đề thôi:

```python
x = 11 % 6
y = 8146798528947 % 17
print(x if (x < y) else y)
4
```
## Modular Arithmetic 2
giống toán chuyên đề, fermat thôi:

```python
print(pow(273246787654, 65536, 65537))
1
```
## Modular Inverting (Nghịch đảo modulo)