## CryptoHack Courses
* #### ASCII
1. ASCII is a 7-bit encoding standard which allows the representation of text using the integers 0-127.
1. In Python, the `chr()` function can be used to convert an ASCII ordinal number to a character (the `ord()` function does the opposite).
> **CHALLENGE**
```python=
ascii = [99, 114, 121, 112, 116, 111, 123, 65, 83, 67, 73, 73, 95, 112, 114, 49, 110, 116, 52, 98, 108, 51, 125]
for i in range(len(ascii)):
print(chr(ascii[i]), end="") #chr(),數字轉字符 #end=""用途為讓每次輸出後不換行(預設為end="\n")
# Output: crypto{ASCII_pr1nt4bl3}
```
* #### HEX
1. In Python, the `bytes.fromhex()` function can be used to convert hex to bytes. The `.hex()` instance method can be called on byte strings to get the hex representation.
> **CHALLENGE**
```python=
hex = "63727970746f7b596f755f77696c6c5f62655f776f726b696e675f776974685f6865785f737472696e67735f615f6c6f747d"
result = bytes.fromhex(hex).decode('utf-8')
print(result)
# Output: crypto{You_will_be_working_with_hex_strings_a_lot}
```
* #### Base64
1. Represent binary data as an ASCII string using an alphabet of 64 characters.
2. One character of a Base64 string encodes 6 binary digits (bits), and so 4 characters of Base64 encode three 8-bit bytes.
3. In Python, after importing the base64 module with `import base64`, you can use the `base64.b64encode()` function. Remember to decode the hex first as the challenge description states.
> **CHALLENGE**
```python=
import base64
a = "72bca9b68fc16ac7beeb8f849dca1d8a783e8acf9679bf9269f7bf"
print(base64.b64encode(bytes.fromhex(a)).decode())
# base64.b64encode(),將bytes轉換為base64編碼
# Output: crypto/Base+64+Encoding+is+Web+Safe/
```
* #### Bytes and Big Integers
1. Python's PyCryptodome library implements this with the methods `bytes_to_long()` and `long_to_bytes()`. You will first have to install PyCryptodome and import it with `from Crypto.Util.number import *`
> **CHALLENGE**
```python=
from Crypto.Util.number import *
print(long_to_bytes(11515195063862318899931685488813747395775516287289682636499965282714637259206269).decode())
#long_to_bytes(),將數字轉換為bytes
#Output: crypto{3nc0d1n6_4ll_7h3_w4y_d0wn}
```
* #### XOR
| A | B | Output |
| --- | --- | ------ |
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
```
EX: 0110 ^ 1010 = 1100
```
> **CHALLENGE**
```python=
from pwn import xor
result = xor(b'label', 13)
print(result.decode())
#將label與13做XOR運算
#Output: aloha
```
```
交換律: A ⊕ B = B ⊕ A
結合律: A ⊕ (B ⊕ C) = (A ⊕ B) ⊕ C
恆等律: A ⊕ 0 = A
歸零律: A ⊕ A = 0
```
> **CHALLENGE**
```python=
from pwn import xor
#KEY1 = a6c8b6733c9b22de7bc0253266a3867df55acde8635e19c73313
#KEY2 ^ KEY1 = 37dcb292030faa90d07eec17e3b1c6d8daf94c35d4c9191a5e1e
#KEY2 ^ KEY3 = c1545756687e7573db23aa1c3452a098b71a7fbf0fddddde5fc1
#FLAG ^ KEY1 ^ KEY3 ^ KEY2 = 04ee9855208a2cd59091d04767ae47963170d1660df7f56f5faf
key1 = bytes.fromhex('a6c8b6733c9b22de7bc0253266a3867df55acde8635e19c73313')
key2_1 = bytes.fromhex('37dcb292030faa90d07eec17e3b1c6d8daf94c35d4c9191a5e1e') # key2^key1
key2_3 = bytes.fromhex('c1545756687e7573db23aa1c3452a098b71a7fbf0fddddde5fc1') # key2^key3
flag_132 = bytes.fromhex('04ee9855208a2cd59091d04767ae47963170d1660df7f56f5faf') # flag^key1^key3^key2
print(xor(flag_132, key2_3, key1).decode())
# Output: crypto{x0r_i5_ass0c1at1v3}
```
> **CHALLENGE**
```python=
from pwn import xor
str = bytes.fromhex('73626960647f6b206821204f21254f7d694f7624662065622127234f726927756d')
for i in range(256):
result = xor(str, i).decode()
if 'crypto{' in result:
print(result)
break
#用迴圈去爆破,之後如果xor出來的字串有crypto就輸出
#Output: crypto{0x10_15_my_f4v0ur173_by7e}
```
```python=
from pwn import *
str = bytes.fromhex("0e0b213f26041e480b26217f27342e175d0e070a3c5b103e2526217f27342e175d0e077e263451150104")
keyword = b"crypto{"
for i in range(0, len(keyword)):
print(xor(str[i], keyword[i]).decode(),end="")
print("")
#用"crypto{"推出他secretkey前面的7個字元
#得出"myXORke" 可猜測完整secretkey為"myXORkey"
print(xor(str, b"myXORkey").decode())
#將str與"myXORkey"做XOR運算
#Output: crypto{1f_y0u_Kn0w_En0uGH_y0u_Kn0w_1t_4ll}
```
* 圖片XOR圖片
```python=
from PIL import Image
lemur = Image.open(r'lemur.png')
flag = Image.open(r'flag.png')
pixels_lemur = lemur.load() # create the pixel map
pixels_flag = flag.load()
for i in range(lemur.size[0]): # for every pixel:
for j in range(lemur.size[1]):
# Gather each pixel
l = pixels_lemur[i,j]
f = pixels_flag[i,j]
# XOR each part of the pixel tuple
r = l[0] ^ f[0]
g = l[1] ^ f[1]
b = l[2] ^ f[2]
# Store the resulatant tuple back into an image
pixels_flag[i,j] = (r, g, b)
flag.save("result.png")
```
`flag.png`

`lemur.png`

`result.png`

* #### python找最大公因數
```python=
from math import gcd
a=66528
b=52920
print(gcd(a,b))
# Output: 1512
```
* #### 擴展歐基里德算法 (Extended Euclidean algorithm)
-> https://hackmd.io/@Koios/rJ_lER719
-> https://ithelp.ithome.com.tw/m/articles/10320272
EGCD 除了求出最大公因數外,還能找到一組整數解 x 和 y,滿足:
```
ax + by = gcd(a, b)
```
> **CHALLENGE**
找出當p=26513 和 q=32321 時滿足pu+qv=gcd(p,q)時的u和v
```python=
from egcd import egcd
p=26513
q=32321
print(egcd(p,q))
# Output: (1, 10245, -8404)
```
> **CHALLENGE**
```
11 ≡ x mod 6 #11跟x在除以6的情況下,有相同的餘數
8146798528947 ≡ y mod 17
```
```python=
x = 11 % 6
y = 8146798528947 % 17
print(x, y)
```