# picoCTF Cryptography
# Easy
## hashcrack

https://crackstation.net/

## 13

rot13 online decode
https://cryptii.com/pipes/rot13-decoder

# Medium
## rotation

Hints : Sometimes rotation is right
encrypted.txt

說了 sometimes rotation 會對
那就用 rot13 bruteforce 試試看
https://gchq.github.io/CyberChef

## HideToSee

用`steghide`找出秘密訊息
```
steghide extract -sf atbash.jpg
```

看了一下圖片的檔名
atbash https://blog.csdn.net/weixin_43211186/article/details/123703113
以下破爛的script
```python=
path = 'encrypted.txt'
f = open(path, 'r')
ar_1 = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M','N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X','Y','Z']
ar_2 = ['z','y','x','w','v','u','t','s','r','q','p','o','n','m','l','k','j','i','h','g','f','e','d','c','b','a']
ans = ''
def is_digit(char):
ascii = ord(char)
if ascii >= ord('0') and ascii <= ord('9'):
return True
else :
return False
def convert_char(char):
if(char.isupper()):
return char.lower()
else:
return char.upper()
while 1:
char = f.read(1)
a1_len = len(ar_1)
a2_len = len(ar_2)
if not char:
break
if char == '}' or char == '{' or char == '_' or is_digit(char):
ans = ans + char
if char.isupper():
for i in range(a1_len):
if char == ar_1[i]:
ans = ans + convert_char(ar_2[i])
break
else:
for i in range(a2_len):
if char == ar_2[i]:
ans = ans + convert_char(ar_1[i])
break
print(ans)
f.close()
```
## ReadMyCert

```
echo "<text>" | base64 -d
```
這樣就結束了= =

## Vigenere

Vigenere https://ithelp.ithome.com.tw/articles/10288227?sc=rss.iron
就是假設今天有一個key是DOG
假設明文是MUWL
密文就是PICO

(https://upload.wikimedia.org/wikipedia/commons/thumb/2/25/Vigen%C3%A8re_square.svg/450px-Vigen%C3%A8re_square.svg.png)
我超懶得寫matrix,直接找有沒有online工具

## transposition-trial


仔細觀察可以發現他是三個為一組去選轉的
```python=
f = open("message.txt", "r")
message = f.read()
ans = ""
for i in range(0,len(message),3):
ans = ans + message[i+2] + message[i] + message[i+1]
print(ans)
```

## basic-mod1

number mod 37 = ans
ans 0~25 => 大寫alphabet
ans 26~35 => 數字 `0~9`
ans 36 => 底線 `_`
白癡的暴力破解
```python=
apl = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','0','1','2','3','4','5','6','7','8','9','_']
f = open("message.txt","r")
f = f.read().split()
ans = ""
for num in f:
ans = ans + apl[int(num) % 37]
print(ans)
```

## substitution0

簡單還說就是每個字母被替換成不同的字母
online crack substitution 工具 - https://planetcalc.com/8047/

## Easy1

Hints
1. Submit your answer in our flag format. For example, if your answer was 'hello', you would submit 'picoCTF{HELLO}' as the flag.
2. Please use all caps for the message.
table

https://www.dcode.fr/vigenere-cipher

## la cifra de

Hints:
1. There are tools that make this easy.
2. Perhaps looking at history will help
完全不知道這是什麼
有一個好用的線上工具https://www.dcode.fr/cipher-identifier

選過Jefferson了,沒什麼鳥用
所以才要選Vigenere Cipher


## john_pollard

題目是要我們求出 `p` 和 `q`
這會顯示憑證內的RSA模數 `N(Modulud)` 、指數 `e(Exponent)` 等資訊
```
openssl x509 -in cert -noout -text
```

N = p * q
online tool https://www.alpertron.com.ar/ECM.HTM

## Tapping

很明顯這就是flag,可是不知道是用什麼轉的

老樣子用線上工具https://www.dcode.fr/cipher-identifier


## Flags

真的不知道這是什麼

但好像是什麼International maritime signal flags
https://en.wikipedia.org/wiki/International_maritime_signal_flags
對應的flag的內容得下來是picoCTF{F1AG5AND5TUFF}
## Pixelated

Hint:https://en.wikipedia.org/wiki/Visual_cryptography
第一個hint蠻有用的,直接跟我們說兩張圖片合在一起就會得出答案了
但我不知道則麼寫script
就看了別人的script
參考script https://medium.com/@alireza.ghorbani/pixelated-picoctf-write-up-0b767d322256
方便看flag
```python=
import cv2
import numpy as np
# 讀取圖片
image = cv2.imread("combined_image.png")
# 取得第一個像素的 BGR 顏色 (左上角的像素)
reference_color = image[0, 0] # BGR 格式,例如 [255, 255, 255]
# 建立遮罩,找出所有顏色與 reference_color **不同** 的像素
mask = np.any(image != reference_color, axis=-1)
# 將不同的像素變黑
image[mask] = [0, 0, 0] # 黑色 (BGR 格式)
# 顯示結果
cv2.imshow("Modified Image", image)
cv2.imwrite("modified_image.png", image)
cv2.waitKey(0)
cv2.destroyAllWindows()
```

## No Padding, No Problem

這是RSA,他們給了n、e和密文,然後要求我們給密文

這題是同態乘法https://blog.csdn.net/weixin_45732058/article/details/134701552
`c = encrypt(m1) * encrypt(m2) = (m1 * m2)**e mod n`
```python=
n = 123033154142956375809145321968129110366801132346977429685516857055365915397596831945366373655492805705093442890582623150874354734529231998609747396076661639260509590648708415966479626490250697483239276971780517874543260169762726811017430033268019120839534925004765493087466131706987833562136303083635841505391
e = 65537
c = 113375312785312846498554885116109142235392583719849114629008226030433434049965790829258233844262947846633286824914354955402384367036914126840296848782735806968563472550454519009243161264393670388952321801117132924285348056400610104924336185297866509487150599209416794461334783106289490823038578834478718518630
C = c * pow(2,e,n)
print(C)
```


```python=
m = 580550060391700078946913236734911770139931497702556153513487440893406629034802718534645538074938502890769138695361576199930 // 2
print(bytearray.fromhex(format(m,'x')).decode())
```

### 參考資料
https://github.com/Dvd848/CTFs/blob/master/2021_picoCTF/No_Padding_No_Problem.md
## caesar



隨便找了一個就種了
## Dachshund Attacks (給e,n,c,沒給d)

給你 `e` , `n` , `c` 找出 `d` 求原始 `m` 訊息,然後題目還說 d 很小

Wiener's attack 剛好很符合這種情境[Link](https://en.wikipedia.org/wiki/Wiener%27s_attack)
這是這次會用的工具[Link](https://github.com/orisano/owiener)
```python=
import owiener
e = 24070585963676396836339119266074703631185325935901189976168439494148908568883163639040881970864431071510706853330983669428476562226661829372537697061459642062617336502737377038994047110849464357038658515902223404277927962245162588048036291814862109832747007143611417263619840106713518659058284264465041722951
n = 95246584314953397407160275991257531467183830580341253761818147315002203507825362017580084590210871948611599502817077874354664828546692250382900296034897690562884298340554582412454992941152823190796153149129497355855115547660543312021536216041346041303448157290972055701372662074181708365081208553211022882613
c = 67167396016728997746500326256589576553572112836662193935563088920677217504276174652365331741926389277431344437388449368796787899498526394747629741042218209607396252911411090413367230889577269436192931791260875486687824664397137843532884404551172386541834991123990618786334183009849587435237181262215694200634
d = owiener.attack(e,n)
if d is None:
print("Failed")
else:
print("Hacked d={}".format(d))
m = pow(c,d,n)
print(f"m : {bytearray.fromhex(format(m,'x')).decode()}")
```

## Mini RSA (給n,e,c,但e很小)


這題就是RSA `e` 太小的話,會發生什麼問題?要則麼破解
RSA encrypt公式:


所以只要找到一個整數x,讓C+N*x == M**e,然後就可以開e次根求出M
所以x可以從0~100xx來猜
```python=
from sympy import integer_nthroot
N = 1615765684321463054078226051959887884233678317734892901740763321135213636796075462401950274602405095138589898087428337758445013281488966866073355710771864671726991918706558071231266976427184673800225254531695928541272546385146495736420261815693810544589811104967829354461491178200126099661909654163542661541699404839644035177445092988952614918424317082380174383819025585076206641993479326576180793544321194357018916215113009742654408597083724508169216182008449693917227497813165444372201517541788989925461711067825681947947471001390843774746442699739386923285801022685451221261010798837646928092277556198145662924691803032880040492762442561497760689933601781401617086600593482127465655390841361154025890679757514060456103104199255917164678161972735858939464790960448345988941481499050248673128656508055285037090026439683847266536283160142071643015434813473463469733112182328678706702116054036618277506997666534567846763938692335069955755244438415377933440029498378955355877502743215305768814857864433151287
c = 1220012318588871886132524757898884422174534558055593713309088304910273991073554732659977133980685370899257850121970812405700793710546674062154237544840177616746805668666317481140872605653768484867292138139949076102907399831998827567645230986345455915692863094364797526497302082734955903755050638155202890599808147130204332030239454609548193370732857240300019596815816006860639254992255194738107991811397196500685989396810773222940007523267032630601449381770324467476670441511297695830038371195786166055669921467988355155696963689199852044947912413082022187178952733134865103084455914904057821890898745653261258346107276390058792338949223415878232277034434046142510780902482500716765933896331360282637705554071922268580430157241598567522324772752885039646885713317810775113741411461898837845999905524246804112266440620557624165618470709586812253893125417659761396612984740891016230905299327084673080946823376058367658665796414168107502482827882764000030048859751949099453053128663379477059252309685864790106
e = 3
for x in range(10000):
candidate = c + x * N
m, exact = integer_nthroot(candidate, e)
if exact:
print(f"Found! M = {m}, x = {x}")
break
print(f"m : {bytearray.fromhex(format(m,'x')).decode()}")
```

## basic-mod2

message.txt
```
268 413 438 313 426 337 272 188 392 338 77 332 139 113 92 239 247 120 419 72 295 190 131
```
### modular inverse


### 怎麼求 inverse modulo?
```python=
x = pow(a,-1,m) # 求 a 在 mod m 下的模反元素
```
-----
```cpp=
path = 'message.txt'
with open(path) as f:
content = f.read()
number_list = [int(num) for num in content.strip().split()]
print(number_list)
alpha = '0abcdefghijklmnopqrstuvwxyz0123456789_'
for i in range(len(number_list)):
# print(i)
mod_inverse = pow(int(number_list[i]),-1,41)
print(alpha[mod_inverse],end="")
# print(alpha[number_list[i]%41],end='')
```

## rail-fence

Rail fence cipher [Link](https://en.wikipedia.org/wiki/Rail_fence_cipher)

online decode[Link](https://www.boxentriq.com/code-breaking/rail-fence-cipher)

# Hard
## miniRSA(e很小)

```python=
from sympy import integer_nthroot
N = 29331922499794985782735976045591164936683059380558950386560160105740343201513369939006307531165922708949619162698623675349030430859547825708994708321803705309459438099340427770580064400911431856656901982789948285309956111848686906152664473350940486507451771223435835260168971210087470894448460745593956840586530527915802541450092946574694809584880896601317519794442862977471129319781313161842056501715040555964011899589002863730868679527184420789010551475067862907739054966183120621407246398518098981106431219207697870293412176440482900183550467375190239898455201170831410460483829448603477361305838743852756938687673
c = 2205316413931134031074603746928247799030155221252519872650073010782049179856976080512716237308882294226369300412719995904064931819531456392957957122459640736424089744772221933500860936331459280832211445548332429338572369823704784625368933
e = 3
for x in range(10000):
candidate = c + x * N
m, exact = integer_nthroot(candidate, e)
if exact:
print(f"Found! M = {m}, x = {x}")
break
print(f"m : {bytearray.fromhex(format(m,'x')).decode()}")
```
