# CRYPTOHACK
## XOR
- Phép toán thao tác bit XOR: lấy hai dãy bit có cùng độ dài và thực hiện phép toán logic bao hàm XOR trên mỗi cặp bit tương ứng. Kết quả ở mỗi vị trí là 1 chỉ khi bit đầu tiên là 1 hoặc nếu chỉ khi bit thứ hai là 1, nhưng sẽ là 0 nếu cả hai là 0 hoặc cả hai là 1
vd: 
- sử dụng thư viện **pwn**
```
from pwn import xor
print(xor(___,____))
```
vd:

input:
```
KEY1=bytes.fromhex('a6c8b6733c9b22de7bc0253266a3867df55acde8635e19c73313')
KEY12=bytes.fromhex('37dcb292030faa90d07eec17e3b1c6d8daf94c35d4c9191a5e1e')
KEY23=bytes.fromhex('c1545756687e7573db23aa1c3452a098b71a7fbf0fddddde5fc1')
KEY=bytes.fromhex('04ee9855208a2cd59091d04767ae47963170d1660df7f56f5faf')
from pwn import xor
KEY2=xor(KEY12, KEY1)
KEY3=xor(KEY2, KEY23)
print("flag:",xor(KEY, KEY1, KEY2, KEY3))
```
output:
```
crypto{x0r_i5_ass0c1at1v3}
```

input:
```
from pwn import xor
flag = bytes.fromhex('0e0b213f26041e480b26217f27342e175d0e070a3c5b103e2526217f27342e175d0e077e263451150104')
print(xor(flag, 'crypto{'.encode()))
print(xor(flag, 'myXORkey'.encode()))
```
output:
```
crypto{1f_y0u_Kn0w_En0uGH_y0u_Kn0w_1t_4ll}
```
## Encoding
- ASCII:

output:
```
crypto{ASCII_pr1nt4bl3}
```
- Base64
- Một lược đồ mã hóa phổ biến khác là Base64, cho phép chúng tôi biểu diễn dữ liệu nhị phân dưới dạng chuỗi ASCII bằng bảng chữ cái gồm 64 ký tự. Một ký tự của chuỗi Base64 mã hóa 6 chữ số nhị phân (bit) và do đó, 4 ký tự của Base64 mã hóa ba byte 8 bit.

input:
```
import base64
given = '72bca9b68fc16ac7beeb8f849dca1d8a783e8acf9679bf9269f7bf'
given_bytes = bytes.fromhex(given)
print(base64.b64encode(given_bytes))
```
output:
```
crypto/Base+64+Encoding+is+Web+Safe/
```
- Bytes and Big Integers

input:
```
from Crypto.Util.number import long_to_bytes
print(long_to_bytes(11515195063862318899931685488813747395775516287289682636499965282714637259206269))
```
input:
```
crypto{3nc0d1n6_4ll_7h3_w4y_d0wn}
```
## Mathematics
*Một số định lí cần biết:
- Định lý nhỏ của Fermat:
- Nếu p là một số nguyên tố , thì với mọi số nguyên a , số  là bội số nguyên của p . Trong ký hiệu của số học mô-đun , điều này được thể hiện dưới dạng

- Nếu a không chia hết cho p , nghĩa là nếu a nguyên tố cùng nhau với p 
- Greatest Common Divisor ( ước chung lớn nhất):

input:
```
def uscln(a, b):
while (a != b):
if (a > b):
a -= b;
else:
b -= a;
uscln = a;
return uscln;
a = int(input("a = "));
b = int(input("b = "));
print(uscln(a, b));
```
output:
```
1512
```
- Extended GCD(GCD mở rộng):
- Modular Arithmetic 1(Số học mô-đun 1)
- Ta nói rằng hai số nguyên đồng dư theo modulo m nếu **a ≡ b mod m.**
- cách khác để nói điều này là khi chúng ta chia số nguyên acho m, phần còn lại là b. Điều này cho bạn biết rằng nếu m chia hết a (điều này có thể được viết là m | a) thì **a ≡ 0 mod m.**
vd:
input:
```
print(min(11 % 6 , 8146798528947 % 17))
```
output:
```
4
```
- Modular Arithmetic 2(Số học mô-đun 2)
vd:
input:
```
from math import gcd
a = 273246787654
p = 65537
if gcd(a,p)==1:
print(1)
```
output:
```
1
```
- Modular Inverting( đảo ngược mô-đun)
- chúng ta có thể làm việc trong một trường hữu hạn Fp, cộng và nhân các phần tử và luôn thu được một phần tử khác của trường. Đối với tất cả g các phần tử trong trường, tồn tại một số nguyên d duy nhất sao cho g * d ≡ 1 mod p. Đây là nghịch đảo nhân của g .
Ví dụ: 7 * 8 = 56 ≡ 1 mod 11

input:
```
print(pow(3,13-2) % 13)
```
output:
```
9
```