Friday, February 7, 2014

Stripe-CTF level1 with golang

Leave a Comment
This year's Stripe-CTF brings some interesting things to the table: Cryptocurrency. I've already known about cryptocurrency and Bitcoin in general, but it's amazing how Bitcoin relates to Git.

The level is here: https://stripe-ctf.com/levels/1

Basically, like Bitcoin, you have to find a block, in this case is a git commit. The commit must have its hash lower than the target difficulty, specified in the file difficulty.txt. You will compete against a bot, and you have to find and submit a block/commit before it does.

As I'm learning Golang, I wrote my miner using it, and managed to bring to 1MHash/s. Some people are going higher, specifically those using OpenCL/GPU to mine.

Basic

The first version of my code is very simple. First it will add myself a Gitcoin to the file "LEDGER.txt", get the difficulty, and get the required parameters to build the commit. Those tasks will only do once per block found, so any code will work.

diff = make([]byte, 0)
diffString := strings.Trim(doExec("cat", "difficulty.txt"), "\n")
for i := 0; i < len(diffString)/2; i++ {
 n, _ := strconv.ParseInt(diffString[i*2:i*2+2], 16, 0)
 diff = append(diff, byte(n))
}
tree = strings.Trim(doExec("git", "write-tree"), "\n")
parent = strings.Trim(doExec("git", "rev-parse", "HEAD"), "\n")
timestamp = strings.Trim(doExec("date", "+%s"), "\n")
I calculate diff as a byte array because SHA1 library returned the hash as an array, so I don't have to convert SHA1 everytime; doExec is just a function to run the command and return console output as a string. The commit hash can be calculate by SHA1 the string "commit [len_commit]\0[commit_string]". The commit string can be built by this code:

baseCommit = fmt.Sprintf("tree %s\nparent %s\nauthor CTF user <%s@stripe-ctf.com> %s +0000\ncommitter CTF user <%s@stripe-ctf.com> %s +0000\n\nFu[4]ny got a Gitcoin\nnonce 1", tree, parent, username, timestamp, username, timestamp)

You should already notice the last "nonce 1" in the commit string, I will replace it with "nonce 2" and so on until I find a commit with hash lower than difficulty. It's surprisingly simple:

func getSHA1(n int) [20]byte {
 return sha1.Sum([]byte(baseCommitHash + "\n"))
}
func isHashValid(hash [20]byte) bool {
 for i, char := range hash {
  if i >= len(diff) {
   return false
  }
  if char > diff[i] {
   return false
  }
  if char < diff[i] {
   return true
  }
 }
 return false
}

After finding a coin, I'll write the commit and push it, I was lazy and just pipe everything to command line. It works but maybe a little slow.

func pushResult(result chan int, done chan bool) {
    var n int
    for {
        n = <-result
        sem <- 1  // Semaphore git command so only one git command at a time
        c1 := exec.Command("echo", getCommit(n, false))
        c2 := exec.Command("git", "hash-object", "-t", "commit", "--stdin", "-w")
        var err error
        c2.Stdin, err = c1.StdoutPipe()
        if err != nil {
            panic(err)
        }
        c2.Stdout = os.Stdout
        _ = c2.Start()
        _ = c1.Run()
        _ = c2.Wait()
        <-sem
        doExec("git", "reset", "--hard", fmt.Sprintf("%x", getCommitSHA(n)))
        res := doExec("git", "push")
        if res != "error" {
            // done <- true
            // do not stop, just wait for a restart
            time.Sleep(10 * time.Second)
        } else {
            log.Println("Error when push, waiting for miner to restart")
            time.Sleep(10 * time.Second)
        }
    }
}


Then I just loop nonce until I found a coin. I use a result channel to communicate between miner thread and pushResult thread, and a done channel to stop when I find a commit. The bot takes about 10 mins to find a block, with just this version I managed to beat it.

Optimize further


After finishing the task, I can join a Gitcoin instance with all players in Stripe-CTF. I knew that I have to optimize it because I can push it only to 200kH/s
Fortunately, Go has profiling built-in, so I can easily point out that, most of the time my program was waiting for fmt.Sprintf, because I used it to build the commit message.
So, because the commit is fixed, just the nonce changes, I was able to prebuilt the commit message and the commit hash, just by giving the commit the fixed length and nonce has 16 number. I thought I can create SHA1 with that prebuilt commit and boost the speed of SHA1 function a lot, but I can't, so removing fmt.Sprintf was good for me.

And by competing with more people, I have to monitor new block, and restart my miner with a new blockchain. I built a channel into the miner, and another gorountine to monitor and send stop signal.

Once in a while, the miner will check for stop signal and get out of the loop.

select {
case msg := <-stop:
    if msg {
        // fmt.Printf("Miner %d stopped! Last i is %d\n", begin, i)
        break jobOuter
    }
default:
}

The monitor function is pretty straightforward, I have two commit hash, last and current, if last commit has different hash than current commit, I do a git hard reset, and send a stop signal.

func monitor(stop chan bool) {
    var hash, newHash string
    hash = strings.Trim(doExec("git", "rev-parse", "--short", "origin/master"), "\n")
    for {
        doExec("git", "fetch", "origin")
        newHash = strings.Trim(doExec("git", "rev-parse", "--short", "origin/master"), "\n")
        if hash != newHash {
            doExec("git", "reset", "--hard", "origin/master")
            // log.Println("New block found! Reseting miners!")
            stop <- true
            hash = newHash
            time.Sleep(1 * time.Second)
        }
        time.Sleep(1 * time.Second)
    }
}

That's almost be all, things I can/should do better:

  1. I have to calculate SHA1 again everytime I change nonce. I should calculate a base SHA1, and feed nonce for each loop. I can't find anyway to do this now, so I choose to ignore.
  2. Calling git by command line is bad, maybe use a git library. Sometimes a push does matter, so implement it directly with socket might be good (just the push)
I ended the game with 756 point, with several Gitcoins found. It's very hard to find a coin because I only have 1.5MH/s with all my PCs, so I need a lucky moment to get one.
Read More...

Sunday, January 19, 2014

Bitcoin protocol: the basic

Leave a Comment


Ở bài trước, các bạn đã biết thế nào là cryptocurrency nói chung, và cách hoạt động của nó. Tuy nhiên bài viết chỉ rờ đến một trong những điểm nổi nhất của hệ thống Bitcoin, nếu muốn tìm hiểu một cách chuyên sâu hơn 1 chút, thì Bitcoin hoạt động như thế nào?

Bài viết nhằm phân tích ý nghĩa và phương thích hoạt động của loại tiền mặt này. Trước tiên, nhắc lại một chút về Cryptocurrency

1. Cryptocurrency/Bitcoin?

Cryptocurrency được chỉ một loại tiền mặt thỏa mãn các điều kiện

Peer-to-peer & Decentralized: không phụ thuộc vào bất cứ một cá nhân, máy móc nào làm nhiệm vụ quản lí.
Digital: tồn tại ở dạng số, không có một thể hiện cụ thể về mặt vật lí.
Bởi vì đồng tiền là không phụ thuộc vào bất cứ ai quản lí, vì vậy việc xác nhận/kiểm tra một giao dịch cần được thực hiện bởi các thành viên trong hệ thống (P2P). Quá trình này sử dụng các thuật toán mã hóa, do đó đồng tiền được gọi là cryptocurrency.

Bitcoin là đồng tiền đầu tiên áp dụng cryptocurrency.

2. Bitcoin hoạt động thế nào?

Bitcoin, cũng như cryptocurrency nói chung, sử dụng các thuật toán mã hóa để xác nhận giao dịch, trong quá trình xác nhận giao dịch này, người thực thi thành công việc xác nhận một nhóm giao dịch, được thưởng một số lượng tiền tương ứng, với Bitcoin(BTC) là 25 đồng. Số lượng tiền này được giảm đi 1 nửa sau mỗi 4 năm, nhằm mục đích hạn chế số lượng BTC tối đa là 21 triệu.

Giống như RFC của một protocol, Bitcoin được định nghĩa bởi các thành phần riêng lẻ, và các giao thức để kết nối các thành phần lại với nhau, vì vậy ta sẽ tìm hiểu Bitcoin bằng cách phân tích các thành phần này:

a. Address

Address là một dãy số, dài từ 27-34 kí tự, bắt đầu bằng 1 hoặc 3, ví dụ: 13q1kfWwR56AwTxeJoJV8bgRnQ2WYxWiY5

Address được sinh ra rất đơn giản, enduser tạo ra 1 cặp private-public key, sau đó hash public key này bằng một thuật toán có sẵn tạo ra Address.

b. Transaction

Một transaction chứa các thông tin sau:
  • hash: hash của toàn bộ thông tin transaction này, được sử dụng như là đại diện của transaction
  • version number, number of inputs, number of outputs: tự cái tên nó đã giải thích
  • lock_time: thời gian mà transaction này thực hiện, thường là 0 tức là ngay lập tức
  • size
  • list of inputs and outputs, trong đó mỗi input và output có định dạng riêng biệt
  • inputs:
    • previous tx: hash của transaction trước đó
    • index: vị trí của transaction
    • scriptSig: <sig> <pubKey>: public key, và signature được sign bởi private key và mã hash của transaction trước đó. 
  • outputs:
    • value: số tiền tính bằng satoshi
    • scriptPubKey: đoạn script được dùng để redeem số tiền này
Vậy, để thực hiện 1 transaction, giả sử từ Alice đến Bob, thì 2 bên này phải làm những gì ?
  1. Alice có được address của Bob để gửi tới, đây chính là hash public key của Bob, Alice sinh ra transaction với các thông tin như trên. Trong đó, quan trọng nhất là đoạn scriptCheckSig kia, Alice đặt vào đó hash public key của Bob. Alice là người duy nhất cầm private key của mình, vì vậy <sig> và <pubKey> kia chỉ có Alice mới tạo ra được.
  2. Alice gửi gói tin này cho toàn mạng, toàn mạng biết được và verify Alice đã gửi cho Bob.
  3. Bob phải claim số tiền này tại thời điểm Bob muốn tiêu số tiền này, chính là hình thức Bob tạo ra 1 transaction mới. Tại thời điểm đó, Bob phải chứng minh rằng, Bob chính là Bob trong transaction Alice đã gửi.
  4. Tương tự Alice, Bob tạo transaction mới, đặt vào đó <sig> và <pubKey> của mình, và các miner sẽ verify cho Bob như sau:
Stack
Script
Description
Empty.
<sig> <pubKey> OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
scriptSig và scriptPubKey được ghép lại
<sig> <pubKey>
OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
đẩy 2 biến const vào stack
<sig> <pubKey> <pubKey>
OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
OP_DUP: duplicate top stack
<sig> <pubKey> <pubHashA>
<pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
OP_HASH160: hash top stack
<sig> <pubKey> <pubHashA> <pubKeyHash>
OP_EQUALVERIFY OP_CHECKSIG
đẩy biển const vào stack
<sig> <pubKey>
OP_CHECKSIG
OP_EQUALVERIFY: check bằng nhau giữa <pubHashA> và <pubKeyHash>, chính là check address
true
Empty.
OP_CHECKSIG: check <sig> bằng public_key


Như vậy, chỉ có Alice mới tạo được gói tin tiêu số tiền trong address của mình, và cũng chỉ có Bob mới tạo được gói tin mới tiêu số tiền mà Bob nhận được.

c. Blocks

Block là một tập hợp các transaction, thỏa mãn 1 số điều kiện nhất định. Thông tin trong 1 block gồm có:
  • magic no: luôn là 0xD9B4BEF9
  • blocksize
  • header
    • version
    • hash previous block
    • hash merkle block: hash của tất cả các transaction
    • time: thời gian
    • target: target hiện tại
    • nonce: 1 số nguyên
  • các transactions
Một block thế nào là hợp lệ? Block là hợp lệ khi hash của version + hashPrevBlock + hashMerkleBlock + time + target + nonce nhỏ hơn target. Điều này trái với nhiều bài viết thường nói là các peer sẽ verify block, thực chất ra bất cứ ai cũng có thể verify block đó, và 1 block khi được announce cho toàn mạng thì nó đã hợp lệ.
Để nói về chuyện tìm block, thì cần phải nói đến các miners và mining

d. Mining

Mining là quá trình miner đi tìm block, với 1 lần tìm thấy block, miner sẽ được hưởng 1 số tiền nhất định (hiện tại là 25BTC), và được nhận bởi transaction đầu tiên trong block: transaction không có người gửi và người nhận là miner. Transaction đầu tiên này gọi là coinbase.
Vậy miner tìm ra 1 block như thế nào? Trong 1 block thì các thông tin version + hashPrevBlock + hashMerkleBlock + time + target là cố định (tạm gọi là hashBase) và giá trị nonce là thay đổi. Miner sẽ hash SHA256(SHA256(hashBase+0)), ra 1 giá trị, so sánh giá trị này với target, nếu nhỏ hơn thì dừng lại, thông báo block cho toàn mạng, nếu không, tăng nonce lên 1, tiếp tục hash SHA256(SHA256(hashBase+0))cho đến khi tìm ra block.

Để biết được độ khó của việc này, ta thử một phép tính như sau: giả sử hashBase là "hello" và ta chỉ phải hash 1 lần
  • sha256("hello0")=5a936ee19a0cf3c70d8cb0006111b7a52f45ec01703e0af8cdc8c6d81ac5850c
để có 2 số 0 ở đầu, ta phải duyệt nonce đến 227
  • sha256("hello227")=001b92541ed0a22b0cb89018b561d895503206c0082c0ecf2d0b7e5182191eed
để có 4 số 0 ở đầu, ta phải duyệt nonce đến 60067
  • sha256("hello60067")=0000e49eab06aa7a6b3aef7708991b91a7e01451fd67f520b832b89b18f4e7de
để có 6 số 0 ở đầu, ta phải duyệt đến 33290382
  • sha256("hello33290382")=000000865194de5c0744d72183dcce2eca2b69264b749a1798f1b6996baef7de
Số nonce này tăng lên rất nhanh, hiện tại để nhỏ hơn target ta cần ít nhất 15 chữ số 0 ở đầu
Vậy chốt lại, mining đơn giản là quá trình tính hash sha256, mỗi lần với 1 số nonce khác nhau, cho đến khi tìm ra dãy số hợp lệ. Quá trình tìm nonce này không thể tính toán bằng phương pháp số, mà bắt buộc phải tính sha256 từng lần một, vì vậy nó là proof-of-work.

Các miners thường tập hợp lại thành 1 Pool, trong đó pool sẽ phân chia các miner tính, ví dụ miner1 tính nonce từ 0->1 tỉ, miner2 tình từ 1 tỉ->2 tỉ, mỗi block từ 0->1 tỉ gọi là 1 share, khi tìm ra block, các miner sẽ được chia đều dựa trên số share mình submit được (càng nhiều share càng được chia nhiều). Thực tế, share được hình thành phức tạp hơn, dựa trên nguyên tắc sinh block nhưng với target thấp hơn, tuy nhiên về bản chất nó cũng chính là hình thức phân chia việc tính nonce này.

3. FAQ

Thực chất mạng lưới Bitcoin về mặt concept hoạt động rất đơn giản, đó là lí do tại sao các Altcoin ra đời liên tục. Tuy nhiên để hiểu được nó lại cần một số kiến thức về tin học nhất định, đó là lí do tại sao nhiều người còn chưa biết nó là gì. Qua đó nảy sinh 1 số câu hỏi:
a. Bây giờ cắm máy Mining thì có lãi ko?
- Mining đã từ lâu không còn là cuộc chơi của CPU/GPU nữa mà là của các máy chuyên dụng gọi là ASIC. Cắm máy mine Bitcoin thì chắc chắn ko bao giờ có lãi: giả sử bạn có 1 card ATI HD 7850, với độ khó hiện nay thì cần 850 năm để tìm ra 1 block, nếu join vào pool thì mỗi ngày bạn có 0.0001 BTC là khoảng 0.06USD khoảng hơn 1000 không đủ để trả tiền điện.
b. Vậy mua ASIC thì sao?
- Câu trả lời vẫn là không, nếu ASIC là có lãi thì những người sản xuất ASIC họ bán ra làm gì? Sao họ không giữ máy lại và chạy? Đa phần các miner đã đầu tư ASIC từ lâu, và họ chạy ASIC ngoài nhiệm vụ mining kiếm tiền, họ còn góp 1 phần vào mạng lưới mining, để hệ thống Bitcoin ổn định lâu dài với khoản đầu tư từ lâu của họ.
c. Lấy Bitcoin từ đâu?
- Giống như vàng, có 2 cách để có vàng là đi đào và đi mua (hoặc là đi xin, coi như là mua với giá 0 đồng)
d. Vậy sau khi đào hết Bitcoin, có ai đào nữa ko?
- Khi tìm ra 1 block, ngoài tiền thưởng thì người đào còn được hưởng số tiền phí giao dịch (hiện nay phí giao dịch thường là 0.001 BTC mỗi giao dịch), và miner hoàn toàn có thể loại bỏ các transaction không kèm phí trong đó. Vì vậy khi khối lượng giao dịch nhiều lên thì phí này sẽ tăng lên tương ứng.
e. Quá trình tính toán khi tìm ra Block có hữu ích gì ko?
- Không giống như Folding@Home, quá trình tính toán block không có hữu ích gì cho xã hội, nó nhằm nhiệm vụ bảo vệ mạng lưới Bitcoin, vì vậy nó chỉ hữu ích cho Bitcoin mà thôi.
f. Chấp nhận Bitcoin làm thế nào?
- Một số third-party có cung cấp dịch vụ payment, ví dụ như Coinbase. Bạn chỉ cần làm theo hướng dẫn của Coinbase, Coinbase sẽ thực hiện việc thanh toán và trả về cho bạn tiền mặt (USD, EUR) mà không phải đụng đến Bitcoin.


*Kết thúc khoảng 3 tuần đọc và viết lung tung về Bitcoin*














Read More...

Monday, December 9, 2013

Bitcoin - người ta đã làm ra nó như thế nào?

Leave a Comment
Bitcoin không còn là mới, nó đã xuất hiện được vài năm nay. Nhưng chỉ trong thời gian gần đây nó mới bùng nổ thành một hình thức thanh toán cực kì tiện lợi.
Bitcoin là một cryptocurrency, để hiểu được một cách chính xác Bitcoin là gì cần một lượng kiến thức về software, crypto, network nhất định. Tuy nhiên chúng ta có thể tiếp cận Bitcoin để hiểu nó như một người sử dụng "có hiểu biết".
Như vậy, Bitcoin được hình thành trên những concept gì?

1. Mô hình không tập trung

Tiền mặt thông thường được lưu qua các tài khoản. Việc bạn gửi tiền từ tài khoản của mình sang tài khoản người khác được thực hiện thông qua việc gặp trực tiếp, hoặc qua ngân hàng.
Ngân hàng sẽ làm nhiệm vụ kiểm tra tiền của bạn có thật không, có hợp pháp không; đảm bảo việc chuyển tiền giữa bạn và người kia là duy nhất (không có chuyện gửi 2 lần); đảm bảo rằng bạn không thể chuyển tiền cho người kia rồi sau đó lấy lại chuyển cho người khác mà không có lí do. Ngoài ra tiền của bạn cũng không tự nhiên mà có, cũng phải có một ai đó in nó ra, cấp cho bạn qua một hình thức nào đó.

Bitcoin được sinh ra với mục tiêu không có ai là đơn vị quản lí tập trung nó cả, tức là sẽ không có ai kiểm tra tiền đó có thật không, không ai đảm bảo rằng bạn không chuyển tiền 2 lần cả. Vì vậy nó phải sinh ra một số phương pháp để phục vụ mục đích này.

2. Định danh người - Chữ kí điện tử

Việc đầu tiên trong quá trình chuyển một cục tiền điện tử, là xác định xem người gửi và người nhận là ai. Đơn cử như dùng Facebook thì phải login, dùng ngân hàng thì phải xuất thẻ CMND. Giả sử, bạn A muốn gửi cho bạn B một đồng tiền, bạn ấy sẽ viết "Tôi, tên là A, gửi cho B 1 đồng". Làm thế nào để bạn B biết chắc chắn rằng đó là từ bạn A gửi?

Điều này được thực hiện bằng một thuật ngữ gọi là public-key cryptography, tương tự như việc đóng dấu. Bạn có một con dấu và cung cấp cái hình con dấu cho mọi người biết, một khi mọi người nhìn thấy văn bản được đóng dấu, tức là tài liệu đó đã được tin tưởng rằng do bạn viết ra (coi như là con dấu không thể làm giả). Tương tự như vậy, đối với public-key crypto, bạn có một private-key (con dấu) và một public-key (hình). Bạn sẽ kí bằng private-key vào dãy "Tôi, tên là A, gửi cho B 1 đồng" ra một văn bản khác. Người nhận khi nhận được văn bản đó, sẽ dùng public-key để giải mã ra được "Tôi, tên là A, gửi cho B 1 đồng". Như vậy, thông tin giao dịch chắc chắn đã được đảm bảo, bất cứ ai cũng có thể biết A gửi cho B 1 đồng, nhưng không thể có con dấu để giả thông báo đó được.

3. Định danh tiền

Liệu, khi bạn A gửi "Tôi, tên là A, gửi cho B 1 đồng" cho B, sau đó B gửi liên tục thông báo này đi, thì A có bị mất tiền nhiều lần không? Điều này được giải quyết một cách rất đơn giản, mỗi đồng tiền sẽ có một cái tên nhất định: "Tôi, tên là A, gửi cho B 1 đồng với mã số 007". Tất nhiên B có gửi thông báo này đi bao nhiêu lần thì cũng chỉ có đồng 007 này được gửi cho B mà thôi.

Tuy nhiên, làm thế nào để B biết được đồng tiền 007 này là thật? A hoàn toàn có thể gửi cho B một đồng tiền giả, thông thường B có ngân hàng để hỏi, trong trường hợp này thì B phải làm thế nào?

Bitcoin sử dụng một hệ thống cây giao dịch gọi là "block chain", nhìn một cách đơn giản thì việc kiểm tra này được thực hiện bằng cách: B sẽ tra ngược về đầu, giả sử có một bạn X gửi cho A đồng 006, sau đó A đổi là 007 gửi cho B, thì B sẽ kiểm tra xem đồng 006 có phải là thật không. Tương tự thế B check đồng 005 là bố của 006, rồi 004 là bố 005, đến khi nào B tra được đến gốc của nó để đảm bảo nó là thật.

Tuy nhiên điều này không ngăn được việc A từ đồng 006 đặt ra 2 mã số cho đồng tiền đó là 007 và 008, sau đó đồng thời gửi cho B và C. Cả B và C sẽ cùng kiểm tra block chain, và đều tìm về đồng 005 rồi 004 và tưởng nó là thật. Khái niệm này gọi là "double-spending".

Để chắc chắn rằng A không "double-spending", hệ thống cần đảm bảo được cả B và C khi tra định danh đồng tiền đó đều tra từ một điểm chung duy nhất. Việc đảm bảo này được thực hiện thông qua cơ chế "proof-of-work"

4. Proof of work

Proof of work, nôm na gọi là "bằng chứng về công việc", là một mô hình được đặt ra nhằm đảm bảo rằng, để A sinh ra được mã 007 và 008, A hoặc một người nào đó phải bỏ một công sức nhất định mà rất khó làm được 2 lần (ví dụ bắt A chạy 100km rồi mới cho A lấy tiền). Tất nhiên chuyện A chạy 100km là khó, hoặc A cũng có thể chạy 200km rồi sinh ra 2 mã kiếm tiền, đó cũng là một vấn đề mà ta sẽ nhắc đến sau.

Quá trình này gọi là quá trình kiểm định, qua đó sẽ có một số người kiểm định nhất định (bao gồm cả A và B), những người này sẽ thực hiện việc chạy 100km này, sau đó kí vào và xác nhận việc X gửi cho A, hay A gửi cho B là tin được tại thời điểm đó.
Như vậy, khi ta thấy một đồng tiền, ta đảm bảo rằng bố của nó đã phải bỏ một số công sức có được nó, một cách nào đó ta tin rằng việc chuyển từ 006->007 là tạm tin được.
Quay lại ví dụ trên, giả sử ông sở hữu đồng 006 là ông X có đồng 005 chạy 200km và in ra 2 đồng là 006 gửi cho A và 006' gửi cho Y. Sau đó có 10 người kí rằng tin là X chuyển sang A là hợp lệ, và 3 người kí vào là X gửi cho Y là hợp lệ. Như vậy đồng tiền này đã được tạm tin bởi X và A, và như thế việc gửi cho A là tạm hợp lệ, còn tiền sở hữu của Y là không hợp lệ. Như vậy Y hay B có thể đơn giản tránh việc bị lừa bằng cách đợi một số người kí vào giao dịch đó rồi mới tin là mình được nhận tiền.  Người kiểm định thường ghép nhiều giao dịch vào kiểm định một thể, và sau khi hoàn thành việc kiểm định, người đó được thưởng một số tiền nhất định cùng với phí giao dịch.

Bitcoin sử dụng cơ chế crypto, nhìn một cách đơn giản, thì Bitcoin yêu cầu người muốn kiểm chứng giao dịch phải tìm một dãy sha256: sha256(data+number), trong đó data là thông tin giao dịch: "Tôi, tên là A, gửi cho B 1 đồng với mã số 007" và number là một số bất kì, sao cho sha256(data+number) phải bắt đầu bằng một số lượng số 0 nhất định. Việc này là rất mất công và yêu cầu người kiểm định phải tìm ra số đó, sau khi tìm ra một dãy số thỏa mãn, gọi là một block, thì người này được hưởng 50 đồng Bitcoin (giảm xuống theo thời gian, hiện nay là 25 đồng).

Như vậy, đồng thời với việc kiểm tra giao dịch, ta cũng giải quyết được vấn đề in và cấp tiền

5. Bitcoin

Như vậy, Bitcoin được tổ chức như thế nào?
Mỗi người sẽ có một cái ví điện tử, gọi là wallet,  mỗi ví này sẽ có nhiều địa chỉ (như một ngăn ví), mỗi địa chỉ này chứa 1 số tiền nhất định, gọi là address.
Việc giao dịch tiền từ một address của người này sang address người khác gọi là một transaction.
Các giao dịch này được ghép lại và kiểm định, kết hợp với số tìm được thỏa mãn điều kiện, thành một block.
Những người kiểm định, tìm block với mục tiêu được thưởng tiền, gọi là miners.
Những block được kết nối với nhau thành một cây, block sau chứa dãy serial của block trước, cây này gọi là block chain.

6. Kết luận

Tuy đã giải quyết được phần lớn vấn đề của một đồng tiền điện tử. Bitcoin vẫn có rất nhiều vấn đề còn tồn tại:
  • Nếu như A mua toàn bộ người kiểm định (thực ra chỉ cần mua trên 50%), thì A hoàn toàn có thể sinh ra 2 đồng tiền từ một đồng với số chữ kí là như nhau, người nhận sau đó là B không thể kiểm tra được đó có phải là tiền hợp lệ hay không.
  • Trong quá trình hình thành đồng tiền, sẽ có rất ít người thực hiện việc kiểm định, vì vậy hệ thống cần đặt khả năng tìm được block là dễ dàng, việc này rất dễ gây ra chuyện tìm ra 2 block một lúc và việc chọn 1 trong 2 block sẽ gây ra block còn lại cùng với những người công nhận nó bị mất công sức (đi kèm với việc sẽ không kiểm chứng được giao dịch trong thời gian ngắn)
  • Địa chì là public, toàn bộ giao dịch cũng được theo dõi một cách thỏa mái. Vì vậy việc bị theo dõi đánh cắp là hoàn toàn có thể. Wallet lại chỉ là một dãy số, rất nguy hiểm khi bị đánh mất.
  • Toàn bộ giao dịch đều thông qua Network, rất dễ bị tấn công bởi DDOS, hoặc bị lọc các gói tin khiến thông tin về block bị thiếu sót, dễ bị tấn công double-spending
  • Việc tạo ra tiền: block là do các máy ngang hàng thực hiện, vì vậy hacker có thể dễ dàng thay đổi các thông số khiến cho block tạo ra bởi các máy này là không sử dụng được (ví dụ thay đổi gói tin ntp khiến các node nhận sai giờ, khiến cho block được tạo ra với thời gian chậm hơn thời gian thật)
  • Blockchain chứa thông tin của toàn bộ các block liên kết với nhau, vì vậy client cần phải lưu trữ với dung lượng lơn (đối với Bitcoin hiện nay là khoảng 15GB).
Mong rằng bài viết sau sẽ làm rõ hơn về giao thức của Bitcoin về mặt technical một cách nâng cao hơn.

Thought?
Read More...

Wednesday, October 9, 2013

Silk Road và những điều bạn cần biết

Leave a Comment
Nhân tiện một buổi họp công nghệ và bắt gặp 1 dòng chữ "Silk road bảo mật website như thế nào?", mình phát hiện ra 1 điều là mọi người đọc báo và biết về Silk Road, chứ ko hề hiểu nó là cái gì. Và vì thế, lại 1 bài chém gió ra đời.
Vậy, câu hỏi đầu tiên, Silk Road là cái gì?
- Silk Road là một chợ đen hoạt động trên mạng Tor.
Đến đây đủ để giải đáp cho câu hỏi "Silk road bảo mật website như thế nào?": câu trả lời là "Silk Road không hề bảo mật website"

Nếu vậy thì lí do gì để có Silk Road? Silk Road được sinh ra nhằm mục đích bảo vệ thông tin người sử dụng, vì vậy Silk Road đã sử dụng những thành phần sau:

  • Tor network: nói 1 cách đơn giản thì Tor giúp người sử dụng giấu đi tất cả mọi thứ: location, usage...nhằm mục đích ngăn chặn việc điều tra ra người dùng bằng hành vi trên mạng. Đây là bước thứ nhất: liên hệ
  • PGP: Mỗi dealer trên BitCoin đều sử dụng PGP để giao dịch mua bán, qua đó dealer sẽ cấp 1 public key, những người liên hệ với dealer sẽ encrypt địa chỉ, thông tin và message bằng public key đó, và chỉ dealer có private key mới giải mã để đọc được. Đây là bước thứ 2: giao dịch
  • BitCoin: BitCoin là một loại tiền được cho là pseudo-anonymous, các giao dịch trên BitCoin được mã hóa và không thông qua một máy chủ tập trung nào. Ngoài ra SilkRoad còn cung cấp 1 tumbler, được sử dụng như một trung gian thứ 3 nhận tiền và gửi tiền. Đây là bước thứ 3: trả tiền.
Như vậy, một giao dịch hoàn toàn được bảo mật và dealer lẫn buyer đều anonymous. Đó chính là lí do Silk Road tồn tại: tạo lập một sân chơi, chứ không phải là một shop buôn bán drug.
Vậy, lí do tại sao tôi dám chém gió là Silk Road không hề bảo mật website?
Nếu bạn lắm thời gian và thừa dở hơi như tôi thì có thể đọc cái này. Một số điểm quan trọng:
  • 23/07/2013, FBI đã có một bản hoàn thiện website Silk Road, trong đó có user account và thông tin giao dịch
  • FBI đã nắm được 1,217,218 message trao đổi trên mạng lưới Silk Road từ 24/5->23/7/2013.
Đa phần thông tin trong này không có ý nghĩa, vì những điều được nhắc tới ở trên: bảo mật giao dịch, không bảo mật website ở mức cao cấp (chỉ có dở hơi mới tin là nó không làm gì để bảo mật website cả). Tất nhiên một số người stupid không dùng PGP thì sẽ bị bắt.
Lí do tại sao admin trang này, DPR bị bắt
  1. Người đầu tiên quảng bá Silk Road vào năm 2011, được biết đến qua điều tra tên là "altoid" 
  2. 11/2011, một người tên altoid post trên Bit Coin Talk, đăng tìm người và dẫn đến email tại gmail "rossulbricht"
Từ đây, FBI rất dễ dàng điều tra ra Ross William Ulbricht, người sáng lập trang web, bằng rất nhiều nguồn khác nhau:
  1. LinkedIn, Google+, Youtube đều từ cái tên mà bị truy ra
  2. Dùng VPN log-in vào server Silk Road, từ đó bị truy ra địa chỉ nhà
  3. Bị điều tra ra sử dụng rất nhiều ID giả
  4. Post trên Stack Overflow với tên thật và hỏi về Tor, sau đó sửa tên thành frosty, trùng tên với SSH public key được lưu trên server Silk Road (stupid)
  5. Cùng với nhiều biện pháp nghiệp vụ khác.
Vì vậy, sử dụng VPN chỉ là một trong những điều khiến cho DPR bị bắt, chứ không phải là nguyên nhân, bởi vì một khi đã bị bắt tên và cái ảnh, thì chắc chắn là không có lí do gì để thoát cả.

Kết luận

  1. Silk Road là mạng lưới chợ đen, thành công của nó nằm ở chỗ bảo vệ thông tin người mua bán, chứ không phải là bảo mật website
  2. DPR bị bắt vì những sai lầm rất căn bản và từ rất lâu, tất cả đều liên quan đến anonymity.
Bài học được rút ra là: đừng phạm tội, nếu có phạm tội thì cũng đừng ngu như thằng này.

Thông tin được tổng hợp bởi một redditor thỉnh thoảng vào /r/Bitcoin và /r/SilkRoad (tất nhiên là không hề có tham gia mua bán gì)







Read More...

Monday, January 21, 2013

Phiếm bàn chuyện...đặt tên

1 comment
Code mình viết ra cũng như con đẻ của mình vậy, chuyện đặt cho nó cái tên để gọi là chuyện vô cùng quan trọng. Đặt tên sao để cho tên nó hay, có ý nghĩa, lại còn phải để người khác dễ gọi, chưa kể là còn phải tránh tên dễ suy luận không là bạn bè của con nó chửi xéo.
Chắc 100% người đụng vào code đều biết mấy kiểu đặt tên họ:

  • viết_thường_kèm_gạch_dưới
  • ViếtHoaChữCáiĐầu
  • VIẾT_HOA_KÈM_GẠCH
  • một vài loại biến thể khác
Ngoài ra một số quy tắc khác như tên biến int thì bắt đầu bằng chữ i, class bắt đầu bằng cls, rồi thì là const thì viết hoa tất, quy tắc thì có lẽ chỉ dành cho project manager ngồi bịa ra viết tài liệu rồi cho các bạn đọc, đọc xong rồi nhớ áp dụng là xong.
Đã phiếm bàn thì bàn cái gì cho nó hay tí, gọi là "đặt tên một cách thông minh".
Đầu tiên có lẽ cần trích đến nguyên tắc đặt tên của Golang: short, concise, evocative; tạm dịch là ngắn gọn, súc tích và tạo ấn tượng.
Ngắn gọn nhưng súc tích là một điểm đến rất khó khi đặt tên, một vài ví dụ như:
1. setup_and_run(new_work, job) : ngắn gọn, đầy đủ, rõ nghĩa
do_setup_and_run: ai chả biết là làm ?
setup_new_and_run: đã setup...(new_work) rồi lại còn có new ở tên.
2. io.NewIO(), Device.NewDevice(): trong package A có hàm NewA là một lỗi khá phổ biến, cách đặt thừa tên này dẫn đến việc đọc code rất là căng thẳng.
Tránh điều này rất đơn giản, ta có thể dùng io.New() nếu cần làm 1 số việc và trả về object IO, hoặc sử dụng trực tiếp io.IO()
3. god.Do(action) và god.DoOrWaitTilDone(action): cách gọi thứ 2 tuy giải thích được việc hàm này sẽ thực hiện hoặc chờ nếu action đã đang thực hiện, tuy nhiên việc này nên đặt trong comment thì hơn là đặt vào tên. Nên nhớ nói dài là nói dại.
4. from what import what_exception: hay thường được biết đến với dòng from what.what_exception import WhatNotFound. Tại sao lại là what.what_exception ? Bỏ cái đoạn what_ có làm nó khó hiểu hơn ko ? Có lẽ tự ai cũng hiểu: from what.exception import WhatNotFound
5. from what.exception import WhatNotFoundException: tại sao ??? WhatNotFound tốt, WhatError tốt, WhatYeahException tốt, NotFoundException vừa trùng lặp lại khó nhớ.
6. User.username, User.user_email: khỏi nói chắc ai cũng biết là thừa, User.name, User.email là 2 cái tên ngắn gọn và tốt hơn rất nhiều
7. from devices.device import Device: move Device import qua __init__ là cách tránh tình trạng này rất dễ dàng, nên để nó là from devices import Device

Vậy, tránh việc đặt tên xấu như thế nào?
Thực ra, tên xấu ngay bản thân nó đã thể hiện được cách tránh, đã là cái tên thì phải đọc, đọc lên thấy...xấu thì phải suy nghĩ ngay:
1. Tên quá dài: đặt 1 cái tên xong thấy nó quá dài, hãy đọc lại thử 1 lần nữa xem nó có vấn đề gì không. Đừng quá ham nhét nhiều thông tin vào tên biến, tên hàm. Súc tích không có nghĩa là đầy đủ thông tin. Dành thời gian thừa khi nghĩ tên vào việc viết document hoặc comment cho rõ ràng.
2. Tên lặp lại quá nhiều: khi gọi vào biến đó hoặc hàm đó, bạn thấy rằng có 1 từ đang lặp lại 2 lần hay thậm chí 3 lần, dừng lại và nghĩ xem tại sao nó lặp lại, và việc lặp lại đó có ý nghĩa gì không. Điều này đúng với cả từ trùng nghĩa lặp lại như NotFoundException.
3. Tên đọc thấy...trẹo lưỡi: tên xấu, ví dụ như earth.create_a_new_god(), chưa đọc đã thấy nó trẹo cả lưỡi rồi, earth.new_god() có lẽ sẽ tốt hơn rất nhiều, chỉ cần chú ý một chút để sửa.

Cuối cùng, code mình code ra, tên mình đặt, con mình mình nuôi, thế nên chú ý cho nó cái tên hay một chút, sau này có chuyển cho ai nuôi thì người ta cũng thích. Tất nhiên cũng đừng có nghĩ nhiều quá, đôi khi cũng cần một "ngoại lệ" nho nhỏ, bởi vì dù sao, mình đặt tên ra thì mình là người gọi nhiều nhất, đặt theo ý người khác cũng chả vui gì.

*Bài viết bậy viết bạ đánh dấu 2 năm không blog* 
Read More...