สร้าง .ppk ให้ plink/pscp บน Windows โดยไม่ต้องเปิด puttygen
งาน automation ที่ต้องยิง plink/pscp จากสคริปต์ มักติดตรงต้องมี .ppk แต่ puttygen บน Windows แปลงจาก command line ไม่ได้ ทางออกคือเขียนไฟล์ PPK เองซึ่งไม่ยากเมื่อรู้ว่า MAC คำนวณจากอะไร
พอดีผมทำสคริปต์ deploy ที่ต้องยิง plink/pscp ขึ้นเซิร์ฟเวอร์อัตโนมัติจากเครื่อง Windows แล้วติดปัญหาเดิม ๆ คือมันต้องใช้ private key เป็นรูปแบบ .ppk ของ PuTTY ไม่กินไฟล์ OpenSSH ธรรมดา ปกติก็เปิด puttygen แปลงเอา แต่พองานเป็น automation ที่ต้อง generate key ใหม่เองในสคริปต์ เปิด GUI ทีละครั้งไม่ไหว
ลองสั่ง puttygen แบบ batch ดู เจอกำแพงทันที
puttygen id_ed25519 -O private -o out.ppk
# เด้ง dialog: unrecognised option "-O"
puttygen.exe เวอร์ชัน Windows เป็น GUI-only — flag -O/-o ที่มีในฝั่ง Linux ถูกตัดออก สั่งจาก command line ไม่ได้เลย จะ automate การแปลง/สร้าง .ppk ด้วยตัวมันเองไม่ได้
ทางเลือกที่ใช้ได้จริง
มีสองทาง — ทางลัดถ้ามี WSL และทางเขียนเองถ้าไม่อยากพึ่งอะไร
ใช้ putty-tools ฝั่ง Linux
ฝั่ง Ubuntu ใน WSL ตัว puttygen ตัวจริงมี CLI ครบ แปลงได้ในบรรทัดเดียว เหมาะถ้าไม่ซีเรียสเรื่อง dependency
เขียนไฟล์ PPK v3 เอง
ไม่ต้องลงอะไรเพิ่ม รู้สูตร MAC แล้วประกอบไฟล์ได้เลย พกไปเครื่องไหนก็รัน เหมาะกับ automation
ทางลัด WSL:
sudo apt install putty-tools
puttygen id_ed25519 -O private -o out.ppk
เขียนไฟล์ PPK v3 เอง
ไฟล์ PPK เป็น text format ตรงไปตรงมา ส่วนที่หลอนที่สุดคือ MAC ท้ายไฟล์ ที่ต้องคำนวณให้ถูกไม่งั้น plink ปฏิเสธ key
PPK v3 MAC = HMAC-SHA-256 คำนวณจากการต่อ SSH-string ของ 5 อย่างเรียงกัน: ชื่อ algorithm, คำว่า encryption ("none" ถ้าไม่ตั้งรหัส), comment, public blob, private blob โดย SSH-string คือ "ความยาว 4 ไบต์ big-endian + ตัวข้อมูล" และคีย์ของ HMAC เป็น string ว่างเมื่อ key ไม่ได้เข้ารหัส
import base64, hashlib, hmac, struct, sys
def ssh_string(b: bytes) -> bytes:
return struct.pack('>I', len(b)) + b
def ed25519_ppk(openssh_priv_path, out_path, comment='imported'):
# ---- ดึง seed 32 ไบต์ + public 32 ไบต์ จากไฟล์ OpenSSH ที่ decode แล้ว ----
# (ในของจริงผม parse ตัว "-----BEGIN OPENSSH PRIVATE KEY-----" ออกมาเป็น pub/seed)
pub, seed = load_openssh_ed25519(openssh_priv_path) # bytes(32), bytes(32)
alg = b'ssh-ed25519'
public_blob = ssh_string(alg) + ssh_string(pub)
private_blob = ssh_string(seed) # ed25519: seed 32 ไบต์แรก
pub_b64 = base64.b64encode(public_blob).decode()
priv_b64 = base64.b64encode(private_blob).decode()
mac_data = (ssh_string(alg) + ssh_string(b'none') +
ssh_string(comment.encode()) +
ssh_string(public_blob) + ssh_string(private_blob))
mac = hmac.new(b'', mac_data, hashlib.sha256).hexdigest()
def wrap(b64, per=64):
return [b64[i:i+per] for i in range(0, len(b64), per)]
lines = [f'PuTTY-User-Key-File-3: {alg.decode()}',
'Encryption: none', f'Comment: {comment}',
f'Public-Lines: {len(wrap(pub_b64))}', *wrap(pub_b64),
f'Private-Lines: {len(wrap(priv_b64))}', *wrap(priv_b64),
f'Private-MAC: {mac}']
open(out_path, 'w', newline='\r\n').write('\n'.join(lines) + '\n')
print('wrote', out_path)
private blob ของ ed25519 คือ seed 32 ไบต์แรก ของ field 64 ไบต์ในไฟล์ OpenSSH (32 ไบต์หลังเป็น public ซ้ำ) เอามาผิดช่วง key จะใช้ไม่ได้ทั้งที่ไฟล์ดู "ถูก"
เทสว่าใช้ได้จริง
อย่าเชื่อว่าไฟล์ถูกจนกว่า plink จะยอม authenticate จริง:
plink -i out.ppk -batch user@host "echo OK; id"
# ต้องได้ OK + uid ของ user กลับมา ไม่ใช่ prompt ถามรหัส
ถ้า plink เด้ง "Unable to load key file" แปลว่า MAC หรือ blob ผิด — กลับไปเช็คว่าต่อ SSH-string ครบ 5 ท่อนตามลำดับไหม และคีย์ HMAC เป็น string ว่างจริงไหม
สรุปคือปัญหาไม่ได้อยู่ที่ตัว key แต่อยู่ที่ puttygen บน Windows ที่ automate ไม่ได้ พอเข้าใจว่า PPK v3 แค่ต้องการ MAC ที่ถูกสูตร ก็ generate เองในสคริปต์ได้หมด งาน deploy อัตโนมัติที่ต้องพก key เลยไม่ต้องมีขั้นตอนเปิด GUI คั่นอีก ใครทำ automation ฝั่ง Windows→Linux เอาไปปรับใช้ได้ตามสะดวกครับ ตรงไหนผมอธิบายตกหล่นหรือพิมพ์ผิด เดี๋ยวกลับมาแก้เพิ่มให้ภายหลังครับ
อยากให้เราทำให้ไหม?
ให้เราช่วยติดตั้ง ตั้งค่า ย้ายระบบ หรือแก้ปัญหาเซิร์ฟเวอร์ เพื่อให้คุณมีเวลาไปทำงานที่สำคัญกว่า
เคยเจองานแบบนี้ไหม? ติดตรงไหน?
มาแลกวิธีกันต่อในบอร์ด LinuxThai



ความคิดเห็น 0
ยังไม่มีความคิดเห็น — เป็นคนแรกเลย