Featured Post

Có một Biển Đông trên không gian mạng

Có một Biển Đông trên không gian mạng Thái Dương Mùa hè 2014, giữa lúc người Việt trong nước và hải ngoại đang sôi sục vì Trung Quốc đư...

Tuesday, April 19, 2016

Không có gì quý hơn độc lập... tài chính

Độc lập tài chính là gì?

Tôi năm nay 32 tuổi, đi làm được 14 năm, muốn "nghỉ hưu" năm 40 tuổi. Nghỉ hưu trong ngoặc kép vì tôi sẽ không dừng làm việc -- tôi chỉ hi vọng đến lúc đó tôi sẽ có đủ tài sản để không phải lo chuyện kiếm tiền nữa. Tôi không chắc tôi sẽ làm được, nhưng tôi vui vì tôi có kế hoạch và cơ hội đạt được một trong những mục tiêu quan trọng nhất của đời người.

Độc lập tài chính quan trọng vì nó là chìa khóa mở ra nhiều cánh cửa. Có người nói rằng nếu bạn yêu công việc của mình, bạn không phải đi làm một ngày nào cả. Tôi yêu công việc của tôi, nhưng nếu có thể chọn giữa đi làm và ở nhà muốn làm gì thì làm, tôi sẽ chọn ở nhà. Có độc lập tài chính, tôi sẽ đi làm vì tôi muốn đi, chứ không phải vì tôi phải đi. Tôi có thể làm bán thời gian thôi, đi làm tư vấn chẳng hạn, khi nào thích thì làm, không nghỉ ở nhà chơi. Tôi có thể làm startup, đi làm tình nguyện không công, hay tìm hiểu, thử nghiệm những cái mới. Quan trọng hơn hết là có nhiều thời gian hơn với người thân.

Một người có độc lập tài chính khi thu nhập thụ động cao hơn chi phí sinh hoạt. Đọc lướt qua tưởng dễ, nhưng cái khó ở đây là hai từ thụ động, nghĩa là không cần làm gì mà vẫn có đủ tiền để sống theo cách mình muốn. Có nhiều cách để có được độc lập tài chính, nhưng cách đơn giản nhất là để dành và đầu tư. Ý này rất quan trọng, nên tôi muốn nhắc lại một lần nữa: để dành và đầu tư là cách tốt nhất để có độc lập tài chính. Tôi ước chi khi tôi mới bắt đầu đi làm có ai đó chỉ cho tôi biết điều này.

Tại sao phải để dành?

Đừng lầm tưởng muốn giàu, muốn độc lập tài chính, phải làm ra thật nhiều tiền. Tôi biết rất nhiều người thu nhập cao, nhưng vẫn mang một đống nợ và mỗi tháng làm ra được đồng nào xào ngay đồng đó. Những người như vậy sẽ phải làm việc cả đời. Độc lập tài chính không phụ thuộc vào tiền lương, mà phụ thuộc vào tỉ lệ để dành. Người làm ra 100 triệu/tháng đồng, nhưng chỉ để dành 1 triệu sẽ lâu có độc lập tài chính hơn người làm ra 10 triệu, nhưng để dành 5 triệu.

Đừng nghĩ rằng mình còn trẻ, cứ ăn xài thoải mái, không cần phải để dành. Khi còn trẻ, ta thường không có tiền, bù lại ta có sức khỏe, trí tuệ và động lực. Ta làm việc là để chuyển vốn tự có thành tài sản, để khi về già, sức yếu, đầu óc lú lẫn và không còn muốn làm nữa, ta vẫn có đủ tiền để duy trì cuộc sống như mong muốn. Đi làm mà không để dành được gì, tức là đã tiêu phí sức lao động vô ích.

Để dành không có nghĩa là không dám tiêu xài. Ngược lại là đằng khác. Nếu ta biết năm nay cần phải để dành bao nhiêu, khi đạt được mục tiêu rồi, ta có thể thoải mái xài phần tiền dư ra. Người biết để dành thường xài tiền thông minh hơn. Họ không dùng tiền mua sắm những thứ đồ không cần thiết. Thay vì mua iPhone, họ sẽ mua một chiếc điện thoại rẻ tiền, và dùng phần tiền dư ra để đi du lịch.

Nhưng bây giờ còn trẻ, có sức khỏe, phải xài tiền, chơi cho đã, chứ để dành làm gì, về già có xài được đâu? Cuộc đời dài hơn ta tưởng nhiều lắm. Y học ngày càng phát triển, tuổi thọ sẽ càng lúc càng cao. Giả sử ta đi làm 30 năm, đến lúc nghỉ hưu cũng chỉ tầm 60 tuổi, vẫn còn khỏe mạnh để hưởng thụ cuộc sống vài chục năm nữa.

Để dành như thế nào?

Bắt đầu để dành bằng cách thống kê chi tiêu. Phải biết mình xài tiền cho việc gì. Có thể sử dụng những công cụ như Quicken, Mint hay Money Lover để ghi lại giao dịch. Ở VN xài tiền mặt là chính, phải nhập thủ công nhiều hơn. Tập thói quen mỗi khi chi tiền lấy điện thoại ra chụp lại hóa đơn hoặc ghi chú lại liền.

Khi đã biết mình xài tiền làm gì, tìm cách thoát ra khỏi tình trạng lương tháng nào xào hết tháng đó. Bắt đầu bằng cách cắt giảm chi tiêu. Ví dụ như thay vì ăn ngoài thường xuyên, tự nấu ăn. Tiền xài hôm nay phải là tiền mà ta đã kiếm được 1 tháng trước đó. Tiếp theo, triệt tiêu thói quen xấu mua sắm đồ linh tinh vô ích. Mỗi khi muốn mua gì, ngủ một giấc. Nếu thức dậy mà vẫn còn muốn mua thì mua cũng chưa muộn.

Tiếp theo, tính xem mỗi tháng chi tiêu bao nhiêu, nhân lên 6, lấy con số đó làm mục tiêu tiết kiệm trong vòng một năm tới. Mở một tài khoản tiết kiệm riêng để giữ số tiền này. Nó sẽ giúp bạn không phải mang nợ, ngay cả khi mất việc, không xin được việc mới trong một thời gian dài. Có mục tiêu để dành rồi, mỗi tháng lãnh lương cứ theo đó mà làm. Nếu cài đặt chuyển khoản tự động được thì tốt, không thì tạo một cái hẹn trên lịch làm việc, mỗi khi lãnh lương vào chuyển tiền ngay, không để tiền dư thừa.

Liệt kê những khoản chi lớn cần phải làm (làm đám cưới, đi du lịch, mua/sửa xe, v.v.) và mở một tài khoản tiết kiệm cho mỗi khoản, tính xem mỗi tháng cần phải gửi vào bao nhiêu tiền và cứ theo đó mà để dành. Cách làm này giúp cho dòng tiền của ta ổn định và dễ dự đoán.

Mỗi khi được tăng lương hay có thêm thu nhập, giữ mức sống như cũ, để dành phần tiền dư ra. Đừng đổi xe mới, đừng đổi điện thoại mới. Thưởng cho mình bằng một chuyến du lịch, một cuốn sách, hay đi học thêm một kỹ năng nào đó mà ta chưa biết (đàn, yoga, nhảy, bơi, lặn, nhảy dù, v.v.). Đừng dùng tiền mua đồ đạc, hãy dùng tiền để có thêm trải nghiệm mới.

Nếu làm được như ở vầy, chẳng mấy chốc ta sẽ để dành được kha khá. Nhưng để dành không chưa đủ. Người ta ước tính, muốn nghỉ hưu, tài sản của ta phải gấp 25 lần thu nhập trung bình mỗi năm. Không có cách chi mà để dành được như vậy. Phải đầu tư.

Tôi sẽ viết tiếp về chuyện đầu tư, trước mắt xem bài http://vnhacker.blogspot.com/2015/06/lam-giau-thu-ong.html.

Wednesday, April 13, 2016

Google mở engineering center ở Singapore

Cơ hội tốt cho kỹ sư Việt Nam: http://googleasiapacific.blogspot.sg/2016/02/building-engineering-team-in-singapore.html. Mặc dù tôi không thích Singapore, nhưng phải thừa nhận đây là một thành phố sạch sẽ, yên bình, được quản lý tốt, thuế thấp, ở trung tâm của châu Á và rất gần Việt Nam. Một nơi tốt để ở và làm việc.

Có thể nộp hồ sơ trực tiếp ở https://www.google.com/about/careers/search#!t=jo&jid=164755001&, hoặc có thể gửi cho tôi ở địa chỉ thaidn@gmail.com.


Chúc may mắn!

Wednesday, April 6, 2016

Thoát Việt

Một người Mỹ nhiều năm gắn bó với VN từng viết trên thế này trên tờ Tuổi Trẻ (nguồn):

"Bài học lớn nhất của chúng tôi là từ ông Hoàng Tụy. Ông từng viết bài trên Tia Sáng, nói vấn đề ở VN là luôn chỉ tự so sánh với chính mình, từ khoa học, y dược đến mọi ngành khác. VN chỉ tự kết nối với bản thân. Quan điểm của ông Hoàng Tụy là muốn trở thành xuất sắc thì anh phải kết nối với thế giới."

Bất kỳ lĩnh vực nào, trở thành một trong những người giỏi nhất Việt Nam không dễ, nhưng muốn trở thành một trong những người giỏi nhất thế giới khó gắp trăm lần. Chúng ta có rất nhiều ngôi sao cấp xóm, nhưng có quá ít những người thuộc nhóm số một thế giới.

Giải vô địch thế giới năm ngoái, Ánh Viên, 19 tuổi, đứng thứ 10 trong đợt bơi vòng loại 400m hỗn hợp. Trước đó cô thua cách biệt ở nội dung 200m nữ. Trong khi đó, Joseph Schooling, 20 tuổi, đoạt huy chương đồng đầu tiên trong lịch sử cho Singapore. Khủng khiếp hơn, Katie Ledecky, 18 tuổi, người Mỹ, đoạt 5 huy chương vàng, phá ba kỷ lục thế giới.

Tôi ngưỡng mộ Ánh Viên, không phải vì cô ấy đoạt huy chương vàng SEA GAMES, mà vì cô ấy dám đặt mục tiêu đoạt huy chương ở Olympics và giải thế giới. Chỉ khi nào dám bơi ra biển lớn, dám từ bỏ cái tư duy "chỉ so sánh với VN", lúc đó chúng ta mới biết vị trí của mình ở đâu trên thế giới. Có chạy đua cùng thế giới, mới có cơ hội trở nên xuất sắc, không thể nào khác được.

Tôi làm việc trong ngành công nghệ. Tôi thích đọc những bài báo ca ngợi các tài năng công nghệ VN đang làm việc ở các công ty đình đám trên thế giới. Báo chí đã có quá nhiều tin xấu cướp giết hiếp, lâu lâu mới có được một tin người tốt việc tốt, quý lắm. Dẫu vậy tôi nghĩ các nhà báo của chúng ta cũng cần phải kết nối với thế giới.

Các nhà báo thường giới thiệu nhân vật là "người Việt đầu tiên", "người Việt duy nhất", v.v. Hay khi phỏng vấn người có thành tích, các nhà báo thường hay hỏi: anh/chị có thấy tự hào khi là người Việt [đầu tiên] làm được X? Nếu tôi không lầm thì câu hỏi này hàm ý "là người Việt" sẽ khiến cho việc "làm được X" đáng để tự hào thêm, bất kể đã có hàng vạn, hàng trăm ngàn người khác trên thế giới làm được X. Ở đây, chúng ta thấy thái độ "chỉ so sánh với người VN" mà giáo sư Hoàng Tụy đã nhận xét.

Lấy ví dụ như chuyện làm việc cho Google. Trở thành nhân viên của Google không dễ và là một thành tích đáng để mỗi người tự hào về bản thân. So với mặt bằng chung ở VN, "nhân viên Google" có thể nghe rất oách (nếu không, báo chí đã không đăng tin). Nhưng, nếu so với thế giới, "nhân viên Google" không có gì đặc biệt. Tờ New York Times không đăng tin riêng, không phỏng vấn riêng mỗi khi có người Mỹ nào đó được Google nhận vào làm việc.

Thật tế, mỗi khi có người Việt trở thành "người Việt đầu tiên" làm được một chuyện gì đó, thường đã có hàng chục, hàng trăm, hàng ngàn, thậm chí hàng triệu người Mỹ, người Tàu, người Ấn hay người Âu làm được việc đó trước hoặc hơn như thế rồi. Chỉ khi nào từ bỏ thói quen chỉ so sánh với VN, chúng ta mới thật sự hiểu được mình đang ở đâu. Chỉ khi nào thoát ra khỏi hệ quy chiếu người Việt, lúc đó chúng ta mới có thể bứt phá, đi cùng với thế giới bên ngoài.

Khi tôi chuẩn bị rời VN sang Mỹ, một người bạn của tôi đã nói sao tôi dại thế, có cây kiếm sắt, nên đánh nhau với bọn cầm kiếm gỗ mới dễ ăn, chứ sao lại đi đánh với bọn cầm súng. Ý ảnh là tôi nên ở VN, sẽ có lợi thế cạnh tranh tốt hơn so với sang Mỹ. Tôi cũng suy nghĩ về lời khuyên này, nhưng lúc đó tôi ham đi Mỹ quá, nên đã gạt nó sang một bên. Bây giờ nhìn lại, tôi thấy mình may mắn. Từ lúc ra nước ngoài, nhìn thấy thế giới, tôi mới hiểu xuất sắc là như thế nào và tôi biết muốn trở nên xuất sắc mình phải đo mình bằng thước đo của thế giới.

Người ta nói VN muốn phát triển phải thoát Trung, còn tôi tự nhủ bản thân muốn phát triển phải thoát Việt.

Trivial birthday attacks against HMAC

I ran a poll on Twitter, asking "Is HMAC vulnerable to birthday attacks?". There are 34 votes, 26% said "Yes", 27% "I don't care", and 47% "No". Thomas Pornin, a respected crypto engineer, chose no.

In this post I'll describe two trivial birthday attacks against HMAC. The first one is theoretical, but the second one is more practical and security-relevant.

Existential forgery attack

Suppose we have access to a HMAC-HASH signing oracle. HASH can be MD5, SHA1, SHA256, etc. The oracle has a secret key $K$, and when we send it a message $m$, it'll return $\textit{HMAC}(K, m)$.

If we query the oracle for $2^{n/2}$ messages, where $n$ is the length of the output of the hash function, the birthday paradox says that we will likely get a collision. That means we get $m_1 \neq m_2$ such that $\textit{HMAC-HASH}(K, m_1) = \textit{HMAC-HASH}(K, m_2)$.

When this happens, and suppose that $m_1$ and $m_2$ have the same length, we can query the oracle for the tag of $m_1 \;||\; x$ where $x$ is an arbitrary message, and with high probability the returned value is also the tag of $m_2 \;||\; x$.

In other words, if

$\textit{HMAC-HASH}(K, m_1) = \textit{HMAC-HASH}(K, m_2)$

then it's likely that

$\textit{HMAC-HASH}(K, m_1 \;||\; X) = \textit{HMAC-HASH}(K, m_2  \;||\; X)$.

Thus we have successfully forged a signature for $m_2  \;||\;  X$ with half of the cost of a serialized brute force search.

Of course this attack is purely theoretical. For example, with HMAC-MD5 the attack requires $2^{64}$ oracle queries, and $2^{71}$ bits of memory. Nevertheless, it's still a proof that HMAC is not safe against birthday attacks.

Two important notes before we consider the second attack:

- Truncating HMAC tags doesn't reduce the cost of the birthday attack. The running time of the attack is still O($2^{n/2}$). On the other hand if the tag is truncated too much, just randomly guessing it might have a decent chance of success (if the tag is $n$ bits, each random n-bit string has $2^{-n}$ chance of being correct).

- A collision in HASH doesn't necessarily lead to a forgery in the HMAC-HASH function. With $m_1$ and $m_2$ such that MD5($m_1$) == MD5($m_2$), it's not guaranteed that $\textit{HMAC-MD5}(K, m_1)$ is equal to $\textit{HMAC-MD5}(K, m_2)$. This is because $K$ already changes the initial state of MD5 by the time it starts processing $m_1$ or $m_2$. All known MD5 or SHA1 collision attacks require knowing the initial state, but $k$ is unknown, thus these attacks won't work against HMAC-MD5 or HMAC-SHA1.

Duplicate signature attack

(Dan Kaminsky wrote about this attack last year: http://dankaminsky.com/2015/05/07/the-little-mac-attack/. See also this thread on Hacker News: https://news.ycombinator.com/item?id=9533984)

Let's take a look at how HMAC is defined:
$\textit{HMAC-HASH}(K, m) = \textit{HASH} \Bigl( (K \oplus opad) \;||\; \textit{HASH} \bigl( (K \oplus ipad) \;||\; m \bigr) \Bigr)$,

where opad and ipad are padding constants. If we have a collision in the inner hash $\textit{HASH} \bigl( (K \oplus ipad) \;||\; m \bigr)$, we are guaranteed to have a collision in the outer hash and the whole HMAC-HASH function. That means if we know $K$, and we can find $m_1$ and $m_2$ such that $\textit{HASH} \bigl( (K \oplus ipad) \;||\; m_1 \bigr) = \textit{HASH} \bigl( (K \oplus ipad) \;||\; m_2 \bigr)$, we will obtain $\textit{HMAC-HASH}(K, m_1) = \textit{HMAC-HASH}(K, m_2)$.

This is not a forgery attack, because the attacker must know the key. It is called duplicate signature attack in the literature, as it produces two messages having the same tag. It is more security-relevant that the first attack.

I once looked at a server that:
- accepts a signed command from the requester
- verifies the signature
- validates the command
- finally executes it.

Because command validation is expensive, once the command is validated, its signature is added to a cache. For every new command the system just needs to verify the signature, and checks if it is in the cache, and if so, runs it, without having to validate it again. This system is thus vulnerable to the duplicate signature attack. An adversary can generate two commands having the same signature, one of them is benign, and the other malicious. They send the benign command first so that its signature is added to the cache. Then they send the malicious command, which bypasses the validation because its signature is already in the cache. The root cause of this bug is that HMAC is a pseudorandom function (PRF), it should not be used as a pseudorandom permutation (PRP) (more on PRP vs PRF).

This second attack is much easier to exploit than the first one. We just need to generate a collision in the hash function, and we can do that offline (without having to query any oracle). Again the birthday paradox tells us that we need to generate only $2^{n/2}$ messages before hitting a collision. The problem is the memory cost. Storing $2^{n/2}$ messages is a big deal. Fortunately there is an algorithm that reduces not only the memory cost, but also the running time. This algorithm is described in the classic paper "Parallel collision search with cryptanalytic applications" by van Oorschot and Wiener.

The core idea is similar to the mining process in Bitcoin. Each CPU independently searches for a "distinguished point", e.g., the first 32 bits are all zero, by iterating a function $f$ and producing a trail. When a distinguished point is found, the CPU reports a triple consisting of the starting point, the number of iterations, and the distinguished point to a centralized server. The CPU then picks another starting point, and searches for the next distinguished point. As there is no communication or synchronization between the CPUs, the algorithm is perfectly parallelized, which in turn vastly reduces the running time. After the CPUs have run for a while, the central server will sort the distinguished points and find collisions. If it founds a collision, that means two trails produced by two CPUs collided and merged with each other at some point. Right before the trail collision, we will find two values $a$ and $b$ such that $f(a) = f(b)$.

$f(x_2) = f(x_{1'})$. Picture stolen from "Parallel collision search with cryptanalytic applications".
Suppose that we are attacking HMAC-SHA1.

Suppose that we have a machine with $2^{40}$ SHA1 circuits, and we feed each of them a random starting point, and let them work in parallel to find distinguished points which start with 40 zero bits. The machine can compute $2^{80}$ hashes in time of only $2^{40}$ SHA1 computations. See "Understanding brute force" by Dan Bernstein for how such a machine can be built.

The central server has to store the distinguished points, thus it needs some memory. Let's say that it has 128 GB of memory. It has to store many aforementioned triples. Because we're going to produce $2^{40}$ trails, the starting point can be represented with 5 bytes. The distinguished point can be represented with 16 bytes because a SHA1 hash value is 20 bytes long, and distinguished points have at least 4 leading zero bytes which need not be stored. The number of steps can be represented with 6 bytes, because $2^{48}$ is the maximum number of iterations before we abandon a trail (e.g., it has a cycle). Overall, a triple requires 27 bytes. Thus with 128 GB of memory we can store around $4,74 * 10^9$ said triples.

Since it takes on average $2^{40}$ iterations before a trail reaches a distinguished point, by the time the memory on the central server is nearly full, we have computed on average $2^{40} * 4,92 * 10^9 \approx 2^{72}$ SHA1 hashes. This should give us (approximately) a $2^{-17}$ chance of having a collision. If we run the machine again and again, each run takes slightly more time than $2^{40}$ SHA1 computations, we'll increase the chance of hitting a collision to pretty close to 1.

As noted by van Oorschot and Wiener, the run time of this attack is proportional to the square root of the hash result space. Thus if this attack were applied to SHA256, it would be $2^{48}$ times slower.

Three conclusions:
- There are birthday attacks that work well against HMAC.
- Birthday attacks can usually be parallelized.
- Use HMAC-SHA256 when you can.

Monday, April 4, 2016

Lương 6 chữ số

Mấy bữa trước một người bạn gửi tin có mấy bạn sinh viên từ Việt Nam được các hãng công nghệ lớn nhận làm nhân viên chính thức, lương 6 chữ số, tức là từ 100 ngàn đô la/năm, khoảng hơn 2 tỉ đồng/năm (nói 200 chai nghe hay, nhưng sao nói 2.000 chai nghe kỳ quá, giống như là giá nước ngọt!).

Đây là mức lương hợp lý và xứng đáng với khả năng của một sinh viên mới ra trường [1]. Tôi không biết con số cụ thể, nhưng tôi đoán tổng thu nhập, kể cả thưởng và cổ phiếu, sẽ ở mức 120-160 ngàn/năm. Một người có vài năm kinh nghiệm, có vài offer cùng một lúc từ hai ba công ty, có thể được nhận gấp đôi, thậm chí gấp ba gấp bốn. Lưu ý đây là thu nhập trước thuế, tùy hoàn cảnh mỗi người, thuế sẽ dao động từ 15%-35%.

Đi làm chừng 10 năm, ăn xài bình thường, còn dư nhiêu tiền bỏ tiết kiệm, mua index fund, trở thành triệu phú đô la là điều không thể tránh khỏi. Nếu làm tốt, có thể rút ngắn một vài năm. Thử tưởng tượng, tốt nghiệp đại học năm 22 tuổi, đi làm 8 năm, 30 tuổi ôm 1 triệu đô la về Việt Nam, nghỉ hưu luôn, sướng không?

Tôi nói về những chuyện này vì tôi thấy kỹ sư máy tính ở Việt Nam có thu nhập quá bèo, trung bình tầm 30 ngàn/năm, tức khoảng 700 chai/năm. Lưu ý con số 700 chai/năm chỉ ngang với đi thực tập 3 tháng ở Google, nhưng vẫn cao hơn thu nhập tối thiểu 500 chai/năm mà FPT trả cho chuyên gia công nghệ cấp tập đoàn.

Nếu bạn đang làm lập trình viên, tiếng Anh khá, tại sao không tìm cơ hội ở các tập đoàn công nghệ lớn trên thế giới? Quên Viettel, FPT, VNG đi. Nhắm vô Uber, Airbnb, Facebook, Google, Apple, Microsoft. Có rất rất nhiều lựa chọn, nếu muốn làm công ty nhỏ cũng không thiếu! Quên Sài Gòn hay Hà Nội đi. Quên luôn Singapore, Nhật Bản hay Hàn Quốc. Hãy nghĩ về Silicon Valley và San Francisco.

Đã có người đi trước rồi, chứng tỏ là làm được, chỉ cần cố gắng và một chút máy mắn. Chúc thành công!

[1] Ý tôi đây là mức lương mà các công ty ở Silicon Valley trả cho sinh viên mới ra trường. Mức này rất cao so với mặt bằng chung của xã hội, kể cả ở Mỹ. Bất bình đẳng thu nhập là một vấn đề lớn, nằm ngoài chủ đề của bài này.