Implementing libsodium Sealed Box

พอดีมี project ที่จะใช้ Sealed Box เลยได้นั่ง implement ให้กับภาษาที่ใช้งานอยู่ เลยอยากเอามาเล่าให้ฟังครับ

อะไรคือ libsodium

ถ้าเคยเขียนโปรแกรมที่ต้องใช้การเข้ารหัสข้อมูล น่าจะรู้จักกับ OpenSSL ครับ หรือถ้าใช้ PHP อาจจะเคยผ่านตากับ mcrypt ซึ่งสองตัวนี้เป็น library ที่รวบรวม algorithm เข้ารหัสไว้มากมายให้เราเลือกใช้

ปัญหาคือทางเลือกไม่ใช่เรื่องดีครับ เพราะกลายเป็นว่าโปรแกรมเมอร์จะต้องศึกษาดูก่อนว่า Algorithm ตัวไหนปลอดภัยบ้าง และแถมบางที library ก็ไม่ตรงปกซะเอง

นักวิทยาการรหัสลับ นำโดยคุณ Daniel J. Bernstein (djb) ผู้คิดค้น algorithm Ed25519/Poly1305/Salsa20 ที่กำลังมาแรงในช่วงนี้ ก็เลยคิดพัฒนาไลบรารีใหม่เข้ามาที่จะทำให้เข้ารหัสเป็นเรื่องง่าย และเร็ว มีชื่อว่า NaCl (อ่านว่า salt) ย่อมาจาก Networking and Cryptography Library (อ่านที่มาได้ใน Paper นี้ ครับ ไม่มีแมทอะไรมากอ่านสนุกดี)

นอกจากนี้เค้ายังพัฒนา TweetNaCl ซึ่งเป็นไลบรารีที่ใช้งานได้เหมือน NaCl แต่ขนาดเล็กเพียง 140 ตัว * 100 tweets เท่านั้น ทำให้สามารถอ่านโค้ดทั้งหมดเพื่อตรวจสอบได้ง่าย (ปัจจุบันมีการ port ไปหลายๆ ภาษาอีกด้วย เช่น Python, JavaScript) ทั้งนี้ความแตกต่างคือ TweetNaCl อาจจะทำงานช้ากว่า

ปัญหาคือ NaCl นั้นลงยากพอสมควร ทาง OpenDNS ก็เลยเอา NaCl ไปจัดระเบียบใหม่ให้นำไปใช้ได้ง่ายขึ้นอีก โดยเรียกไลบรารีใหม่นี้ว่า Sodium

สำหรับการใช้งานของ NaCl/Sodium นั้นจะเปลี่ยนคำถามใหม่จาก “ต้องการเข้ารหัสด้วย algorithm อะไร” เป็น “ต้องการความปลอดภัยแบบไหน” ตัวอย่างเช่น

  1. ถ้า Alice ต้องการส่งข้อความลับให้เฉพาะ Bob ก็ใช้ Box (authenticated encryption) ซึ่งเมื่อได้รับข้อความแล้ว Bob ยังสามารถยึนยันได้อีกด้วยว่า Alice เป็นผู้เขียนข้อความนี้จริง และข้อความไม่ถูกแก้ไขระหว่างทาง
  2. ถ้าต้องการส่งข้อความที่เข้ารหัสโดยใช้ password ก็ใช้ Secret box (authenticated encryption)
  3. ถ้าไม่ต้องการเข้ารหัสแต่ต้องการยึนยันว่าข้อความนี้เราเขียนจริง โดยใช้ระบบกุญแจสาธารณะ ก็ใช้ Sign (public-key signature)

จะเห็่นว่าเราไม่จำเป็นต้องทราบว่าด้านหลังมันทำงานยังไง ใช้ algorithm อะไรเลยด้วยซ้ำ อ่านรายละเอียดแต่ละ abstraction แล้วถ้าตรงกับโจทย์ก็เลือกใช้ได้ทันที

อะไรคือ Sealed Box

ทีนี้สิ่งที่ผมสนใจคือ Sealed box ครับ ซึ่งเป็นหนึ่งใน Security model ที่มีใน libsodium แต่มันพิเศษคือเป็นตัวที่ libsodium สร้างขึ้นมาเอง ไม่มีใน NaCl ปกติ

Sealed box จะเหมือนข้อ 1 ด้านบน คือใช้ส่งข้อความลับหาผู้รับที่เจาะจงและรู้ public key ของเค้า (เช่นส่งหาคุณ Bob) แต่ต่างกันคือเราไม่ต้องการยึนยันตัวผู้ส่งด้วย (ในตัวอย่างด้านบนคือ Alice ไม่ต้องการให้รู้) ซึ่งเราใช้ Box ปกติทำไม่ได้เพราะ Box จะต้องระบุ public key + secret key ของผู้รับและผู้ส่ง

ปัญหาคือพอมันเป็นสิ่งที่มีใน libsodium แล้ว ไลบรารีที่เอา NaCl ไปใช้ก็จะไม่ค่อยมี sealed box ให้ใช้ ซึ่งในหลายๆ ไลบรารีก็จะมี feature request เรื่องนี้อยู่

แกะ Sealed Box

วิธีแก้ปัญหาก็ไม่ยากครับ ไม่มีก็เขียนใช้เองซะสิ! แต่เราคงต้องแกะซอร์สซะก่อน

ซอร์ส libsodium จัดไว้ค่อนข้างง่ายครับ หาเจอไม่ยาก ไฟล์ที่เราต้องการคือ libsodium/src/libsodium/crypto_box/crypto_box_seal.c

พออ่านโค้ดใน crypto_box_seal แล้วก็จะพบว่าจริงๆ แล้ว Sealed box ก็คือ box ประเภทหนึ่งครับ ซึ่งจะสร้าง public และ private ของผู้ส่งขึ้นมาใหม่ทุกครั้ง แล้วก็ใช้ Box ปกติเข้ารหัสได้เลย จากนั้นเวลาส่งข้อมูลก็ให้ส่ง public key นำไปก่อน แล้วตามด้วย Box

ที่น่าสนใจคือ Nonce ครับ ใน docs ของ Box จะบอกว่าการส่งข้อความจะต้องมี Nonce ทุกครั้ง (ถ้าใครอ่านตำรา crypto มา อาจจะรู้จักกับ IV เจ้า Nonce นี่ก็คือ IV ล่ะครับ แต่ต่างกันคือ NaCl อนุญาตให้ใช้ string ใดๆ เป็น Nonce ได้ ขอแค่ห้ามใช้ซ้ำกัน ต่างกับ IV ตรงที่ IV จะต้องคาดเดาไม่ได้ด้วย) แต่การสร้าง Nonce ของ Sealed box น่าสนใจมากครับ คือแทนที่จะสุ่ม Nonce มา เราก็พบว่า Public key เราสุ่มใหม่ทุกรอบอยู่แล้ว ก็เลยเอา public key นั้น ต่อกับ public key ผู้รับ เข้า Hash function ก็จะได้ Nonce เลยที่ไม่ซ้ำแน่นอน และไม่จำเป็นต้องส่งไปด้วยเพราะผู้รับก็ทราบ public key ทั้งหมดอยู่แล้ว

อีกจุดนึงของ Nonce generation ที่น่าสนใจคือมันใช้ Hash function ใหม่ล่าสุดอย่าง BLAKE2 ครับ ข้อดีของเค้าคือสามารถกำหนดความยาวของแฮชเองได้ ไม่เหมือน SHA-256/512 ที่กำหนดความยาวไว้ชัดเจน แน่นอนว่าในเคสนี้เราก็กำหนดให้ยาวเท่ากับ Nonce ที่ Box ต้องการได้เลย

สุดท้ายแล้วผมก็พบว่าไม่ต้องอ่านโค้ดก็ได้ ใน docs เค้าก็เขียนไว้ชัดเจนแล้วว่ามันคือ ephemeral_pk ‖ box(m, recipient_pk, ephemeral_sk, nonce=blake2b(ephemeral_pk ‖ recipient_pk)) *facepalm* (‖ แปลว่าต่อ string)

Implement ใน JavaScript

ทีนี้ก็ได้เวลา implement ครับ ใน project ที่ผมจะทำ client side จะเข้ารหัสข้อความไปให้ server ซึ่งก็แน่นอนว่าฝั่ง client เราจะต้องใช้ JavaScript

ใน JavaScript ก็มีหลาย library ที่ใช้ libsodium ครับ แม้แต่ libsodium เองก็ยังมี official release ที่ใช้ Emscripten compile เป็น JavaScript ให้เลย แต่ปัญหาคือมันจะใหญ่มากและเปลือง memory ก็เลยตัดสินใจใช้ pure JavaScript implementation อย่าง TweetNaCl.js ซึ่งตัวนี้โดน Security audit มาแล้วด้วยซ้ำ และผลการ Audit คือ “ยอดเยี่ยม ไม่เจออะไรไม่ดีเลย” เป็นเรื่องที่หายากมากๆ

เวลาเขียนตัวนี้ก็ไม่ยากครับ JavaScript ยุคใหม่มี Fixed size array อย่าง Uint8Array แล้ว ก็ map จาก C ลงไปได้เลย แต่เขียนไปสักพักก็จะเจอปัญหาว่าไม่มี BLAKE2!

คือ NaCl ของแท้ๆ เนี่ยครับ hash function ที่เค้าเลือกใช้จะเป็น SHA-512 แต่ใน NaCl จะเปลี่ยนเป็น BLAKE2 ฉะนั้นก็ไม่มีทางเลือก เราต้องลง library ที่ทำ BLAKE2 ได้

ก็ปรากฏว่า BLAKE2 มีสองแบบครับ คือ BLAKE2s ที่มี library BLAKE2s.js และ BLAKE2b ที่มี library BLAKE.js ทำไว้ ตอนแรกก็เลือกผิดตัวไป เสียเวลาเขียนใหม่เล็กน้อย

(สำหรับความแตกต่างคือ BLAKE2s จะ optimize สำหรับ 32 bit ครับ และ BLAKE2b optimize สำหรับ 64 bit ผลลัพท์ไม่เหมือนกันใช้สลับกันไม่ได้นะครับ)

สุดท้ายก็ได้ Library ออกมาครับอย่าง tweetnacl-sealed-box ไปจิ้มจาก npm ได้เลย

Implement ใน Python

สำหรับฝั่ง server ผมใช้ Django ซึ่งสำหรับภาษา Python นั้นก็มี libsodium binding หลายตัวครับ เดิมทีผมใช้ PyNaCl อยู่ แต่อยากจะย้ายเป็นตัวอื่นที่มี wheel จะได้ build ไวๆ (มันเป็น Docker ครับ build นานเสียเวลา)

ตัวที่เลือกใช้ก็คือ libnacl ซึ่งเลือกจากว่ามันใช้ใน Salt ที่เป็น Server automation tool เจ้าดังตัวนึง (แต่เอาเข้าจริงเหมือนเค้าจะไม่ค่อย maintain libnacl เท่าไรนะ)

สำหรับ Implementation อันนี้ไม่ยากครับ เพราะ libnacl นั้นจะไปเรียก sodium.so ของแท้ๆ อยู่แล้ว เราก็แค่เขียน ctypes definition ให้มัน ก็จบ แต่ครั้นจะส่งแพทช์ไปแบบนี้เลยก็คงจะไม่ดีเท่าไร เลยต้องเขียน Abstraction ให้เค้าด้วย และ documentation ซึ่งก็ไม่รู้จะเขียนอะไรดี เลยก๊อปอีกหน้านึงมาแก้ซะเลย 555

สรุป

Sealed box เป็น design ที่น่าสนใจครับ คือเค้าพยายาม design ของใหม่ โดยใช้ของเดิมที่มีอยู่แล้ว เนื่องจากว่าของเดิมถูกพัฒนาโดยนักวิทยาการรหัสลับจึงมั่นใจได้ว่าปลอดภัย พอเป็นแบบนี้แล้วการจะ port ไปให้ภาษาอื่นๆ เลยค่อนข้างง่าย แต่ถ้า port ไป TweetNaCl ก็จะยุ่งยากนิดนึง

อ่านมาถึงตรงนี้ไม่รู้ว่าเจอศัพท์เทคนิคกันจนปิดไปหรือยัง แต่จะบอกว่า “ชนะโดยไม่ต้องรบจึงว่าเลิศ” นะครับ ถึง NaCl จะทำให้เราเข้ารหัสข้อมูลแบบปลอดภัยได้ง่ายๆ แต่ถ้าเราสามารถออกแบบโปรแกรมที่ไม่จำเป็นต้องเข้ารหัสเลยก็จะปลอดภัยกว่าแน่นอน

JSEXP or: How I Learned to Coding and Love the JavaScript

*(ชื่อบทความมาจาก [Dr. Strangelove](https://en.wikipedia.org/wiki/Dr._Strangelove)*

@[winwanwon](https://twitter.com/winwanwon) จะเรียน JavaScript เราเลยว่าประสบการณ์เรียน JavaScript เรามันแปลกกว่าการเรียนภาษาอื่นๆ เลยมาเขียนไว้หน่อย

ตอนป. 6 มีอยู่ project ตัวนึง (source ผมหายไปจากการฟอร์แมตโง่ๆ ครั้งนั้น แล้วก็เพื่อนไม่ได้เก็บไว้) ซึ่งผมพูดถึงบ่อยแล้ว มันคือ DarkWorld ซึ่งเป็น megaproject ตัวแรกของผม มันเกิดจากว่าผมเห็นเพื่อนในห้องมันเอาหนังสือแฮกกิ้งมาอ่านเลยเข้าไปคุยด้วย หลังจากนั้นไปเดือนนึงเราก็ชวนกันทำ project และผมก็เลือก project เกม ซึ่งเกมเนี่ยผมพยายามเขียนมาแต่ขี้เกียจมาตั้งแต่ป. 4-5 แล้วมั้ง (มีอันนึงเคยทำเกมจุดขายคือหน้า login สวยใน IE เพราะมันใช้ HTTP Authorization ซึ่งใน IE จะเหมือน login network drive)

ทีนี้ทำเกมมันก็ต้องมีจุดขาย ผมให้เพื่อนในห้องเล่นได้ง่ายๆ แค่ชวนว่าเอออันนี้พวกเราในห้องทำกันก็ได้กลุ่ม user มาเป็นสิบแล้ว (คาบคอมผมเห็นหลายคนเล่น เป็นอะไรที่ดีใจมาก) แต่จุดขายที่ผมเลือกคือ “เกมแรกของไทยที่ใช้ AJAX” ซึ่งสมัยนั้น AJAX มันเป็นอะไรที่เท่มากและเพิ่งมี เกมออนไลน์บนเว็บไทยก็พอมีอยู่บ้าง เจ้าใหญ่สุดคือ oceanica (เข้าไปล่าสุดเมื่อหลายปีก่อนมันยังคล้ายๆ สมัยก่อนโน้นอยู่เลย) ก็มีแต่ ajax chat ตัวเกมคลิกแล้วก็รอโหลดอยู่ดี

(ที่จริงไอ้คำโฆษณาแบบนี้ผมว่ามันขาย user ได้จริงหรอฟะ แต่ตอนนั้นเป็นเด็กน้อยก็คิดได้แค่ว่ามันเท่อะนะ แล้วไอ้คุณเพื่อนในกลุ่มก็รู้จักคำนี้ดีก็เลยเห็นดีเห็นงามไปด้วยไม่ได้คัดค้านอะไร – -!)

ฟีเจอร์แรกสุดในเกมที่ควรรีบมีและเป็น AJAX คือ Chat ผมเลยหาข้อมูลว่าจะเขียนยังไงดีด้วย PHP และผมไม่รู้เรื่อง JavaScript บังเอิญไปเจอ [xajax](http://xajaxproject.org/) ซึ่งมันเป็นอะไรที่เจ๋งมากเพราะสามารถแก้ไข DOM ฝั่ง client ได้โดยไม่ต้องรู้ JS สักนิด

ทีนี้ต่อมาผมก็บอกไปแล้วว่า ajax chat มันไม่ใช่ฟีเจอร์เกม ฉะนั้นเกมต้องมี ajax ต่อมาเลยมีฟีเจอร์ ajax แรก มันคือร้านขายของ แต่เกมนี้ผมคิดร้านขายของไปได้ไงไม่รู้ ให้เอาเงินไปซื้อ exp ในแต่ละสกิลได้ – – !! (เข้าใจว่าลอกเลียนแบบมาจากอีกเกมของสนพ. ไทยชื่อดังซึ่งโดนผมยิงจนปิดไปแล้ว ยิงในที่นี้ไม่ใช่ยิงให้ล่ม แต่ยิงเข้าไปหน้าตีมอนรัวๆๆๆ จนไอดีผมขึ้นที่ 1 ในเกมแล้วเหมือนจะโดนลบ เลยครีใหม่แล้วทำอีก อิอิ) เวลากดซื้อปุ๊บมันก็จะยิง xajax เข้าไปที่ server ให้เซฟแล้วก็ส่งกลับมา

มาถึง beta 3 ผมบอกว่าเวอร์ชั่นนี้เกมจะเริ่มเป็นเกมจริงๆ ใน beta 4 ซึ่งผมเขียนรุ่นนี้อยู่สามวัน (beta 2 2 วัน) โดยใช้ code DHTML หมดเลยจาก dynamic drive เรียกได้ว่าเกมหน้าเดียวมีทุกเมนู กดไปก็เป็น iframe แต่จะมี AJAX Polling ไปเรื่อยๆ ที่ server สำหรับ notify เวลามีคน PK เพราะuser บ่นมาว่าโดน PK ไม่เห็นมีอะไรเตือน

สุดท้ายจบ project นี้ไปด้วยว่าทีมงานทะเลาะกันแยกกัน…อ้าว แล้วไหนว่าเรียน JavaScript

ทีนี้มาตอนม. 1 มันมี script.acuolo.us ออกมา เป็น animation library ทำวู๊บๆ ได้ ผมละแบบว่าเหยดเข้พระเจ้าจอร์ช xajax มันไม่มีแบบนี้ ก็เลยลองโหลดมาดู *โดยที่ไม่ได้ลง prototype* แน่นอนว่าใช้ไม่ได้เพราะไม่มี prototype แต่เด็กม. 1 ไม่รู้เรื่อง ก็เลยไปหาตัวอื่นหลายตัว รวมถึง… [เขียน animation library เอง!](http://whs.whs.in.th/archive/whsjs.html) (setTimeout + height++ เอา) เพราะตัวไหนก็อ่านไม่รู้เรื่อง ส่วนไอ้พวกคำสั่ง setTimeout document.getElementById นี่ก็คือไป view source ชาวบ้านเขา เห็นเค้าใช้กันก็เลยเออเอามั่ง `function $(i){return document.getElementById(i);}` นี่จำขึ้นใจ (สมัยนี้ใช้ jQuery หมดแล้วแหละ จะไปเรียนแบบผมไม่ได้แล้ว)

*(ส่วน project สุดท้ายที่ใช้ xajax คิดว่าเป็น [ตัวนี้](http://whs.whs.in.th/archive/songkran/) ที่ยังหาเจอ ก๊อปโค้ดมาจาก exteen เติม ajax+save)*

จนมาเจอตัวนึง คือ moo.fx ของ prototype นี่แหละ ดูไปดูมาไปเจอ MooTools เจ้าของเดียวกัน เป็นแบบครบจบในตัว ผมเลยเอามาลอง แล้วก็ใช้ไอ้นี่ทำมาหลายงาน ไม่ว่าจะเป็น [Clickr](http://whs-clickr.appspot.com/clickr.html) (ม. 2) [แข่งคอมภายนอกโรงเรียน](http://whs.whs.in.th/archive/htm32/) (กรรมการชมว่า accordion สวยเนอะ) [Ubuntuclub Headline](http://whs.whs.in.th/archive/headline/) (โหลดช้าหน่อย อันนี้ทำไว้ว่าจะเป็น homepage ตัวเอง สุดท้ายไม่ได้ใช้หรอก) [Get Ubuntu](http://whs.whs.in.th/archive/ubuntu/) (ถ้าจำไม่ผิดหน้านี้น่าจะได้ใช้)

แต่งานเลี้ยงมีวันเลิกรา MooTools 1.2 เปลี่ยน API คำสั่ง Animation ไม่ใช่ Fx.Styles แล้ว ผมก็เลยว่าไม่ใช้มันแล้ว บังเอิญตอนนั้นเจอ jQuery ด้วย เลยเห็นหน้าแรกแล้วแบบว่าเฮ้ยเจ๋ง MooTools ต้องมานั่ง new Fx.Styles ไรเยอะแยะ นี่ $(“..”).animate แถม MooTools มันทำได้ทีละอันใน $() นี่ $ พี่ท่านเล่นใส่ CSS Selector เข้าไปได้เลย (ใน MooTools มี ผมก็เคยต้องใช้ มันใช้คำสั่ง $$ คืนเป็น Array ให้ไปลูปเอาเอง แต่ jQuery จะ match ล้านอันท่านก็สั่งเหมือนอันเดียว ลูปมันจัดการให้) ก็เลยว่าเออ เอาวะ ลอง

ผมจำไม่ได้ว่า jQuery ตัวแรกที่เขียนคืออะไร แต่ผมจำได้ตอนเลือก​ MooTools ตอนนั้น jQuery ผมก็เห็น แต่ผมเห็นตัวอย่างอันเดียวกันนี่แหละที่มันเทพๆ แล้วผมบอกว่ามันเทพไปว่ะ ล้ำลึกจนงง

สิ่งที่พบจาก jQuery คือมันทำงานเกี่ยวกับ DOM ได้สะดวกรวดเร็วมาก แต่นอก DOM แล้วจะทำอะไรไม่สะดวก เพราะ MooTools มัน extend native object ไปเลย (พูดง่ายๆ ว่า [‘1′,’2′,’3’].unique() อะไรแบบนี้ได้เลย jQuery ไม่มีแม้แต่คำสั่ง unique) อันนี้ไม่ใช่ปัญหา ผมหา library มาใส่ได้ ซึ่งตัวนึงที่ใช้บ่อยช่วงนั้นคือ [phpjs](http://phpjs.org/) อันนี้ตัดเฉพาะคำสั่งที่ใช้ไปได้ ไม่ต้องเอาไปหมด

ต่อมา project นึงที่ทำให้ผมรู้เรื่อง JavaScript เยอะมากคือ Twitica Desktop นี่แหละ ตอนนั้นผมเขียน JS เป็นอยู่แล้วแต่ทำไอ้นี่มันเป็น project ใหญ่ที่จะได้เรียนอะไรเยอะ และยิ่งเป็นแบบไม่มีเซิร์ฟเวอร์ด้วย เขียนอะไรไม่เป็นหาทางหลบไม่ได้ต้องชนกับปัญหาตรงๆ (ถึงตอนนี้ผมว่าโค้ด Twitica บางจุดมันเกินอ่านได้แล้วอะ โดยเฉพาะตรงวาดทวิตนี่แบบว่า engineering mistake)

ถัดมาอีกอันที่ผมรู้สึกว่าเรียน JS ไปมากขึ้นเยอะ มันคือ Twitica for webOS ถึงมันจะไม่ออกแต่มันเสร็จ ผมเขียนสองวันเสร็จได้ด้วยพลังอะไรไม่รู้ แต่กลับไปอ่านพบว่าบางอย่างเขียนไปด้วยวิธีที่ผิดแต่ผลลัพท์ถูก ข้างตัวมีตำรา webOS หนาเท่าหนังสือสรุปฟิสิกส์ ที่เรียนได้เพราะ webOS ใช้ Prototype และนั่นแปลว่าคุณต้องใช้ Prototype ไม่ใช่ jQuery (ถึงจะใช้พร้อมกันได้ในทางปฎิบัติ แต่เราว่ามันไม่ควรทำบนมือถือนะ) ทำให้เราเจอกับคอนเซปต์แปลกๆ เช่น bound function ซึ่งพบว่าบั๊กบางตัวใน Twitica ที่เราหาคำตอบไม่ได้ก็ต้องแก้ด้วย bound function นี่แหละ

*(bound function คือ function ที่เวลาเรียกแล้วจะมี argument, this คงที่ เช่น (ถ้าใช้ prototype.js) `var x = “5”; var y = (function(x){alert(x);}).bind(null, x); x=”30″;` เวลาเราเรียก y() จะพบว่าขึ้นว่า 5 เพราะค่าของ x = “5” ตั้งแต่ตอน bind function นั้นแล้ว (สังเกตว่าเรียก y() เฉยๆ ไม่มีการระบุ argument เพราะ argument x มาจากการ bind) แต่ถ้าไม่มีการ bind แล้วเรา y() จะขึ้นว่า 30 ส่วน null ข้างหน้าใน bind มันเป็นการกำหนดค่าของ this ใน function y ถ้าไม่ได้สนใจก็ใส่อะไรมั่วๆ ไปเหอ)*

ตอนนี้ผมเขียน menome และตอนผมเขียน menome forum ได้ลอง underscore + backbone และพบว่ามันคืออะไรที่เจ๋งมาก underscore คือ prototype นั่นแหละ แต่ว่าไม่ผูกกะ native function ซึ่งส่วนตัวผมอยากให้ผูกมากกว่าเพราะเขียนสะดวกกว่า แต่ว่ามันออกแบบมาไม่ให้ชนกับ jQuery หรืออื่นๆ เลยทำให้ต้องใช้ตัวนี้แทนที่จะใช้ prototype เวลา bind ก็เช่น `_.bind(function(){}, null, x)`

ส่วน backbone เป็นอะไรที่อยากแนะนำนะถ้าบรรลุ JS พื้นฐานไปแล้ว อธิบายง่ายๆ คือเหมือนมี Object เก็บข้อมูลอยู่ พอ object นี้มีการเปลี่ยนแปลงจะส่งสัญญาณออกมา แล้วเราจะเขียน view อีกตัวไปต่อสัญญาณพวกนี้ อาจจะให้ทำการ render html ใหม่ หรือทำอะไรก็แล้วแต่ และสุดท้ายสามารถ sync ข้อมูลขึ้นลงกับฝั่ง server ได้อีกด้วย

จบห้วนๆ อีกแล้ว ไม่รู้ทำไมชอบเขียนอะไรจบแบบนี้