<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Thinking in Thinking - Hui Zheng's blog</title>
    <link type="application/atom+xml" href="http://en.zhenghui.org/feed/atom.xml" rel="self"/>
    <link href="http://en.zhenghui.org"/>
    <updated>2023-07-14T20:49:15+00:00</updated>
    <id>http://en.zhenghui.org</id>
    <author>
        <name>Hui Zheng</name>
    </author>
    
    <entry>
        <id>http://en.zhenghui.org/2023/07/08/JotSync-Privacy-Policy-zh-Hant</id>
        <link type="text/html" rel="alternate" href="http://en.zhenghui.org/2023/07/08/JotSync-Privacy-Policy-zh-Hant"/>
        <title>JotSync隱私政策</title>
        <updated>2023-07-08T00:00:00+00:00</updated>
        <author>
            <name>Hui Zheng</name>
        </author>
        <content type="html">&lt;h1 id=&quot;jotsync隱私政策&quot;&gt;JotSync隱私政策&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;最後更新：2023年7月8日&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&quot;1-引言&quot;&gt;1. 引言&lt;/h2&gt;

&lt;p&gt;本隱私政策解釋了JotSync（”我們”）如何在您使用JotSync移動應用程式（以下簡稱”應用”）時收集、使用和保護關於您的資訊。&lt;/p&gt;

&lt;p&gt;我們尊重您的隱私，我們承諾通過本政策保護它。&lt;/p&gt;

&lt;h2 id=&quot;2-我們收集的資訊以及收集方式&quot;&gt;2. 我們收集的資訊以及收集方式&lt;/h2&gt;

&lt;p&gt;在提供我們的應用過程中，我們收集並接收以下類型的資訊：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;用戶內容：&lt;/strong&gt; 這包括您保存到我們的應用的鏈接和內容。這些都存儲在我們的安全資料庫中，以便提供應用的核心服務，並確保在您的裝置之間無縫同步。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;裝置和使用資訊：&lt;/strong&gt; 我們可能自動收集關於您正在使用的裝置的某些資訊，包括但不限於您的裝置類型、作業系統版本和應用使用統計資訊。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;請注意，除非您明確向我們提供，否則我們不會收集任何可識別個人身份的資訊。&lt;/p&gt;

&lt;h2 id=&quot;3-我們如何使用您的資訊&quot;&gt;3. 我們如何使用您的資訊&lt;/h2&gt;

&lt;p&gt;我們使用您的資訊來提供、維護和改進我們的應用及其功能。這包括使用您保存的鏈接和內容在您的裝置之間進行同步。&lt;/p&gt;

&lt;p&gt;除非本政策中另有說明，否則我們不會與第三方分享、銷售或披露您的資訊。&lt;/p&gt;

&lt;p&gt;請放心，作爲開發者，我們不會檢查或使用應用中保存的任何數據，除非爲了提供服務。&lt;/p&gt;

&lt;h2 id=&quot;4-您的資訊如何存儲和保護&quot;&gt;4. 您的資訊如何存儲和保護&lt;/h2&gt;

&lt;p&gt;我們使用Firebase這個領先的雲服務提供商來安全地存儲您的資料。Firebase提供了強大的資料保護措施。但是，請注意，通過互聯網傳輸或電子存儲的方法沒有100%的安全性。儘管我們努力採用商業上可接受的方式來保護您的個人資訊，但我們不能保證其絕對的安全性。&lt;/p&gt;

&lt;h2 id=&quot;5-用戶權利和選擇&quot;&gt;5. 用戶權利和選擇&lt;/h2&gt;

&lt;p&gt;您有權訪問我們持有的關於您的個人資訊，並要求對此資訊進行更正、更新或刪除。如果您想行使這些權利，請通過以下聯繫方式聯繫我們。&lt;/p&gt;

&lt;h2 id=&quot;6-隱私政策的變更&quot;&gt;6. 隱私政策的變更&lt;/h2&gt;

&lt;p&gt;我們可能會不時更新我們的隱私政策。如果我們做出變更，我們將通過修訂政策頂部的日期通知您，並在某些情況下，我們可能會提供額外的通知（例如在我們的主頁添加聲明或向您發送通知）。&lt;/p&gt;

&lt;p&gt;您在此類更新後繼續使用應用將構成您對修改的承認和您同意遵守和受修改後的隱私政策的約束。&lt;/p&gt;

&lt;h2 id=&quot;7-聯繫我們&quot;&gt;7. 聯繫我們&lt;/h2&gt;

&lt;p&gt;如果您對本隱私政策有任何問題或疑慮，請通過以下方式聯繫我們：pie01.xyz+jotsync@gmail.com。&lt;/p&gt;

</content>
    </entry>
    
    <entry>
        <id>http://en.zhenghui.org/2023/07/08/JotSync-Privacy-Policy-zh-Hans</id>
        <link type="text/html" rel="alternate" href="http://en.zhenghui.org/2023/07/08/JotSync-Privacy-Policy-zh-Hans"/>
        <title>JotSync隐私政策</title>
        <updated>2023-07-08T00:00:00+00:00</updated>
        <author>
            <name>Hui Zheng</name>
        </author>
        <content type="html">&lt;h1 id=&quot;jotsync隐私政策&quot;&gt;JotSync隐私政策&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;最后更新：2023年7月8日&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&quot;1-引言&quot;&gt;1. 引言&lt;/h2&gt;

&lt;p&gt;本隐私政策解释了JotSync（”我们”）如何在您使用JotSync移动应用程序（以下简称”应用”）时收集、使用和保护关于您的信息。&lt;/p&gt;

&lt;p&gt;我们尊重您的隐私，我们承诺通过本政策保护它。&lt;/p&gt;

&lt;h2 id=&quot;2-我们收集的信息以及收集方式&quot;&gt;2. 我们收集的信息以及收集方式&lt;/h2&gt;

&lt;p&gt;在提供我们的应用过程中，我们收集并接收以下类型的信息：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;用户内容：&lt;/strong&gt; 这包括您保存到我们的应用的链接和内容。这些都存储在我们的安全数据库中，以便提供应用的核心服务，并确保在您的设备之间无缝同步。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;设备和使用信息：&lt;/strong&gt; 我们可能自动收集关于您正在使用的设备的某些信息，包括但不限于您的设备类型、操作系统版本和应用使用统计信息。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;请注意，除非您明确向我们提供，否则我们不会收集任何可识别个人身份的信息。&lt;/p&gt;

&lt;h2 id=&quot;3-我们如何使用您的信息&quot;&gt;3. 我们如何使用您的信息&lt;/h2&gt;

&lt;p&gt;我们使用您的信息来提供、维护和改进我们的应用及其功能。这包括使用您保存的链接和内容在您的设备之间进行同步。&lt;/p&gt;

&lt;p&gt;除非本政策中另有说明，否则我们不会与第三方分享、销售或披露您的信息。&lt;/p&gt;

&lt;p&gt;请放心，作为开发者，我们不会检查或使用应用中保存的任何数据，除非为了提供服务。&lt;/p&gt;

&lt;h2 id=&quot;4-您的信息如何存储和保护&quot;&gt;4. 您的信息如何存储和保护&lt;/h2&gt;

&lt;p&gt;我们使用Firebase这个领先的云服务提供商来安全地存储您的数据。Firebase提供了强大的数据保护措施。但是，请注意，通过互联网传输或电子存储的方法没有100%的安全性。尽管我们努力采用商业上可接受的方式来保护您的个人信息，但我们不能保证其绝对的安全性。&lt;/p&gt;

&lt;h2 id=&quot;5-用户权利和选择&quot;&gt;5. 用户权利和选择&lt;/h2&gt;

&lt;p&gt;您有权访问我们持有的关于您的个人信息，并要求对此信息进行更正、更新或删除。如果您想行使这些权利，请通过以下联系方式联系我们。&lt;/p&gt;

&lt;h2 id=&quot;6-隐私政策的变更&quot;&gt;6. 隐私政策的变更&lt;/h2&gt;

&lt;p&gt;我们可能会不时更新我们的隐私政策。如果我们做出变更，我们将通过修订政策顶部的日期通知您，并在某些情况下，我们可能会提供额外的通知（例如在我们的主页添加声明或向您发送通知）。&lt;/p&gt;

&lt;p&gt;您在此类更新后继续使用应用将构成您对修改的承认和您同意遵守和受修改后的隐私政策的约束。&lt;/p&gt;

&lt;h2 id=&quot;7-联系我们&quot;&gt;7. 联系我们&lt;/h2&gt;

&lt;p&gt;如果您对本隐私政策有任何问题或疑虑，请通过以下方式联系我们：pie01.xyz+jotsync@gmail.com。&lt;/p&gt;

</content>
    </entry>
    
    <entry>
        <id>http://en.zhenghui.org/2023/07/08/JotSync-Privacy-Policy-en</id>
        <link type="text/html" rel="alternate" href="http://en.zhenghui.org/2023/07/08/JotSync-Privacy-Policy-en"/>
        <title>Privacy Policy for JotSync</title>
        <updated>2023-07-08T00:00:00+00:00</updated>
        <author>
            <name>Hui Zheng</name>
        </author>
        <content type="html">&lt;h1 id=&quot;privacy-policy-for-jotsync&quot;&gt;Privacy Policy for JotSync&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Last Updated: July 8, 2023&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&quot;1-introduction&quot;&gt;1. Introduction&lt;/h2&gt;

&lt;p&gt;This Privacy Policy explains how JotSync (“we,” “us,” or “our”) collects, uses, and protects information from and about you when you use the JotSync mobile and web application (the “App”).&lt;/p&gt;

&lt;p&gt;We respect your privacy and are committed to protecting it through our compliance with this policy.&lt;/p&gt;

&lt;h2 id=&quot;2-information-we-collect-and-how-we-collect-it&quot;&gt;2. Information We Collect and How We Collect It&lt;/h2&gt;

&lt;p&gt;In the course of providing our App, we collect and receive the following types of information:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;User Content:&lt;/strong&gt; This includes the links and content you save to our App. These are stored in our secure databases in order to provide the App’s core services and ensure a seamless sync across your devices.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Device and Usage Information:&lt;/strong&gt; We may automatically collect certain information about the device you are using, including but not limited to your device type, operating system version, and App usage statistics.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Please note that we do not collect any personally identifiable information unless you expressly provide it to us.&lt;/p&gt;

&lt;h2 id=&quot;3-how-we-use-your-information&quot;&gt;3. How We Use Your Information&lt;/h2&gt;

&lt;p&gt;We use your information to provide, maintain, and improve our App and its functionalities. This includes using your saved links and content to sync across your devices.&lt;/p&gt;

&lt;p&gt;We do not share, sell, or disclose your information with third parties, except as described in this policy.&lt;/p&gt;

&lt;p&gt;Please be assured that as the developer, we don’t inspect or use any of the data you save in the App beyond the provision of services.&lt;/p&gt;

&lt;h2 id=&quot;4-how-your-information-is-stored-and-protected&quot;&gt;4. How Your Information is Stored and Protected&lt;/h2&gt;

&lt;p&gt;We use Firebase, a leading cloud service provider, to securely store your data. Firebase provides robust data protection measures. However, please be aware that no method of transmission over the internet or electronic storage is 100% secure. While we strive to use commercially acceptable means to protect your personal information, we cannot guarantee its absolute security.&lt;/p&gt;

&lt;h2 id=&quot;5-user-rights-and-choices&quot;&gt;5. User Rights and Choices&lt;/h2&gt;

&lt;p&gt;You have the right to access the personal information we hold about you and to ask that this information be corrected, updated, or deleted. If you would like to exercise these rights, please contact us through the contact information below.&lt;/p&gt;

&lt;h2 id=&quot;6-changes-to-this-privacy-policy&quot;&gt;6. Changes to This Privacy Policy&lt;/h2&gt;

&lt;p&gt;We may update our Privacy Policy from time to time. If we make changes, we will notify you by revising the date at the top of the policy and, in some cases, we may provide you with additional notice (such as adding a statement to our homepage or sending you a notification).&lt;/p&gt;

&lt;p&gt;Your continued use of the App after such update will constitute your acknowledgment of the modifications and your consent to abide and be bound by the modified Privacy Policy.&lt;/p&gt;

&lt;h2 id=&quot;7-contact-us&quot;&gt;7. Contact Us&lt;/h2&gt;

&lt;p&gt;If you have any questions or concerns about this Privacy Policy, please contact us at: pie01.xyz+jotsync@gmail.com.&lt;/p&gt;

</content>
    </entry>
    
    <entry>
        <id>http://en.zhenghui.org/2013/05/18/magic-of-math_CN</id>
        <link type="text/html" rel="alternate" href="http://en.zhenghui.org/2013/05/18/magic-of-math_CN"/>
        <title>数学魔术——评《具体数学》</title>
        <updated>2013-05-18T00:00:00+00:00</updated>
        <author>
            <name>Hui Zheng</name>
        </author>
        <content type="html">&lt;h2 id=&quot;数学魔术&quot;&gt;数学魔术&lt;/h2&gt;

&lt;p&gt;人民邮电出版社出版的《具体数学——计算机科学基础》译自经典名著
《Concrete Mathematics: A Foundation for Computer Science》。
简单地称赞这是一本好书，虽毫无风险性，却也毫无信息量。
那么《具体数学》（以下简称《具》）具体好在何处呢？
简言之两个词：一曰充分，二曰实在。&lt;/p&gt;

&lt;h2 id=&quot;充分&quot;&gt;充分&lt;/h2&gt;
&lt;p&gt;此所谓充分，系指一本书在深度、广度、高度、细度、角度等各维度上的充分。&lt;/p&gt;

&lt;h3 id=&quot;深度&quot;&gt;深度&lt;/h3&gt;
&lt;p&gt;在不过分为难目标读者的前提下，足够的深度始终是专业书籍的核心价值所在，否则“专业”二字只是枉谈。
哪怕是入门书籍，也不应轻易地点到为止。好书如严师，严师方能出高徒。让人一直轻松的书，通常
也会轻松地被人遗忘。&lt;/p&gt;

&lt;p&gt;《具》书之深，似乎无庸赘述。充斥全书的数学符号，足令大多数非数学专业者望而却步。
此书基于Donald Knuth（第二作者）在斯坦福大学的讲义而成，便是这所全球顶级大学的学生
也倍感不易。虽然不少人推荐该书为The Art of Computer Programming（TAOCP）
的预备书籍，但若仔细比较二者，前者甚至在一些专题上的深入度比后者犹有过之。
好在书中虽不乏抽象的数学理论，但均适可而止，且最终皆为实际问题服务。
这在降低难度的同时，也增加了实用性和亲和力。&lt;/p&gt;

&lt;p&gt;其实，深度并不一定意味着复杂、玄妙或高深，更非概念、理论、公式、数据或代码等单纯的堆砌。
关键是作者能否拨开笼罩在知识周围的迷雾和光晕，引领读者渐入深境，让他们获得头脑
与知识内在的&lt;em&gt;硬核&lt;/em&gt;产生正面撞击的机会（这大概是人们恍然大悟时喜欢摸后脑勺的原因吧？）。&lt;/p&gt;

&lt;p&gt;《具》书的主线是从递归问题到求和问题，再到二项式系数，接着从特殊的数列到一般的生成函数，
内容环环相扣并逐步加深。书中屡见不鲜的情形是：某一问题看似已挖掘至极限，但随着更深刻的
理论或更强大的工具的推出，原问题有了更妙的解法或更强的结论。&lt;/p&gt;

&lt;h3 id=&quot;广度&quot;&gt;广度&lt;/h3&gt;
&lt;p&gt;深度可反映一本书对知识的纵向开采程度，广度则反映它对知识的横向拓展程度。
坦率地说，《具》书的广度不如其深度突出。作为计算机科学基础的数学教材，它未涵盖的内容还有不少，
如图论、自动机理论、博弈论、信息论、可计算性理论等，也没有更基础的集合论或数学逻辑。
另外，数论与离散概率虽有涉及，但篇幅较少。&lt;/p&gt;

&lt;p&gt;当然，这与作者明确的目的有关。正如书中前言所说，“具体”数学是针对“抽象”数学而设的名称。
纯粹数学工作者大都有个通病：醉心理论的抽象而不屑实际的应用。本书试图证明，
兼顾具体性与抽象性、实用性与通用性的数学，同样可以很高级、很优美。
因此它并不打算覆盖全部的离散数学，而是提供一套系统的、有关离散运算的工具和方法。
故仅就其所重视的主线而言，该书的广度也是可观的。&lt;/p&gt;

&lt;h3 id=&quot;高度&quot;&gt;高度&lt;/h3&gt;
&lt;p&gt;一本书应通过深度由表及里，通过广度由此及彼，把局部孤立的知识点编织成整体联系的知识面。
进一步地，它还应上升到一定的高度，让知识图案变得立体而丰满。&lt;/p&gt;

&lt;p&gt;具体数学另有一个&lt;em&gt;双关&lt;/em&gt;的解释：连续与离散数学的混合（&lt;strong&gt;CON&lt;/strong&gt;tinuous与dis&lt;strong&gt;CRETE&lt;/strong&gt;混合
成CONCRETE）。虽说计算机科学主要建立于离散数学之上，而本书又特别强调具体性和实用性，
但仍不可避免地涉及到更具抽象性和理论性的连续数学。原因无他，后者的层次更高。&lt;/p&gt;

&lt;p&gt;人们都有这个体会：一个难解的观点或问题往往在“更上一层楼”之后，立刻一目了然。
以数学为例，在引入代数方程后，算术应用题变得轻而易举；借助高等数学，许多初等数学中的难题
迎刃而解。&lt;/p&gt;

&lt;p&gt;《具》书中这类例子不胜枚举。如：用L’Hospital法则求极限、用导数或积分求和，
用Taylor级数展开生成函数（generating function）、估算近似值，等等。
令人印象最深的是，该书5.2节提出了8个级数问题，一道比一道难，读时目不转睛、屏气凝神，唯恐迷失。
直到后来提升到更一般的超几何级数（hypergeometric series），这才恍然大悟：原来
那些问题不过是些特例罢了。同样有启发性的是9.5节，在证明欧拉求和公式前，提供了一个非正式但
高层次的（high-level）推理。此外，出于严谨，在谈到为何书中经常忽略无穷级数的收敛性
时，用到了域（field）的概念。从抽象代数的高度来解释，自然言简意赅。&lt;/p&gt;

&lt;h3 id=&quot;细度&quot;&gt;细度&lt;/h3&gt;
&lt;p&gt;除了宏观的深度、广度和高度外，微观的细度也是衡量书籍的一个标准。
一本书不应也不可能事无巨细，面面俱到，但一定要有足够的细节，以填补大多数读者的思维盲点。
令人稍感意外的是，《具》书的细度毫不逊色于深度。&lt;/p&gt;

&lt;p&gt;细首先体现在思虑周到、推理严谨。书中不断地在考察：分母是否为零？如何定义退化情形下的函数值？
数列的负下标是否有意义？级数的收敛性如何？等等。程序员若有这份细致，就不会常犯逻辑混乱、
考虑欠周、忽略边界检查等编程错误了。如果说这些只是对数学专业书籍的基本要求，那么
在求得答案后还经常不厌其烦地用特殊值验证就不是那么常见了。这倒不是说数学工作者不如程序员
那么重视测试，而是他们通常不会将此过程写入书中。&lt;/p&gt;

&lt;p&gt;在分析和讲解问题时，本书可谓细致入微。许多细腻的数学小技巧是其他书中鲜有提及的，比如：
如何从特殊情形入手，逐步过渡到一般情形；如何猜测答案，又如何不通过猜测而获取答案；
如何调整级数的下标以利计算；如何通过变换逐步降低求和的难度，等等。不时还夹杂一些
忠告，如：计算效率不等于理解效率（efficiency of computation is not the same as efficiency
of understanding）（译本中将efficiency译为“有效性”似有不妥，易被认为“效果”effectivity之效），
这对那些为微小改进效率而牺牲代码可读性的程序员同样有警示作用。&lt;/p&gt;

&lt;p&gt;最能体现本书之细的是关于数学符号的选取和解释。例如，用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;k&lt;/code&gt;而非常见的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt;做数列下标，以避免
与虚数i混淆；解释用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt; &amp;gt;&lt;/code&gt;代表欧拉数（Eulerian number）、用上下横杠分别代表上下阶乘幂的合理性；
不吝用4个自然段来说明O记号中的等号；为追求表达式的合理性，不惜采用非标准的记法，如
从编程语言APL中引入&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[]&lt;/code&gt;记号、用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\&lt;/code&gt;代替&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;|&lt;/code&gt;作为整除符号、用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;⊥&lt;/code&gt;表示互素、用倒置而非前置的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!&lt;/code&gt;
（即&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;¡&lt;/code&gt;）表示子阶乘（subfactorial，译本干脆译为倒阶乘）、采用简化的超几何函数符号、采用象形
的立方体、硬币、骰子、铺砖符号等。&lt;/p&gt;

&lt;p&gt;有人或会对本书如此讲究符号不以为然，那他一定低估了简洁直观、自然优美的符号对于数学的重大意义。
数学家兼哲学家怀特海（Whitehead）在《数学导论》中曾说：良好的数学符号能解除大脑多余的工作，
使之集中于更高级的问题，从而有效地提高了心智的力量。本书的作者之一Knuth显然赞同此点，这
从其所著的《Mathematical Writing》中便可看出。无论所编程语言的发明者还是使用者，
均应从中获得启示：良好的语法设计和变量命名有助于提高代码的可读性和编程的效率。&lt;/p&gt;

&lt;p&gt;本书在字体设计上也颇费心思，真正做到了从內在到外表处处展现数学之美。
考虑到Knuth是排版软件TeX的设计者，这也不足为奇。&lt;/p&gt;

&lt;h3 id=&quot;角度&quot;&gt;角度&lt;/h3&gt;
&lt;p&gt;从不同的角度看待同一问题，通常会有不同解释方式和解决方式。一本时常切换角度的书，对读者
融会概念、贯通方法大有裨益。&lt;/p&gt;

&lt;p&gt;例如：《具》书对平方项求和问题，先后共计采用8种方法。在数学书中一题多解并不少见，少见的
是多处一题多解。作者常常在介绍一种新技巧后，并不急于解决新问题，而是用它回头更加漂亮地
解决前面早已解决的老问题，不经意地展现数学的和谐与自洽。宛如一个魔术师，不停地用熟练的、
令人眼花缭乱的手法，变换不同的视角，采用不同的形式，展现同样令人称绝的效果。&lt;/p&gt;

&lt;h2 id=&quot;实在&quot;&gt;实在&lt;/h2&gt;
&lt;p&gt;以上从多个维度分析了《具》书的精彩之处，然其价值远不止此。最理想的专业教材，
应当既能呈现&lt;em&gt;静态&lt;/em&gt;的知识体系和结构，又能重现&lt;em&gt;动态&lt;/em&gt;的知识形成和发展。&lt;/p&gt;

&lt;p&gt;传统数学教材（尤其国内教材）大都按序遵循如下套路：引入概念和定义，提出定理并证明，
列举推论并证明，展示若干例题，布置一堆习题，转入下一章节循环以上过程。
难怪在很多人眼里，数学不过是由一些怪癖的天才们发明的一套冰冷干枯、机械无趣的逻辑系统。&lt;/p&gt;

&lt;p&gt;《具》书最可贵之处在于，它不仅显示数学的当前形态，而且反映其产生和发展的历史过程，
以便让读者感知鲜活真实的知识、掌握切实可行的方法。&lt;/p&gt;

&lt;h3 id=&quot;起源&quot;&gt;起源&lt;/h3&gt;
&lt;p&gt;数学的最终表现通常是高度抽象化和形式化的，但其最初往往起源于具体的实际问题。
本书经常通过一些有趣而实用的问题让数学接上“地气”，既减少了数学的神秘感，也真实
反映了数学的起源。&lt;/p&gt;

&lt;h3 id=&quot;过程&quot;&gt;过程&lt;/h3&gt;
&lt;p&gt;在提出问题后，本书一般并不直截了当地给出解法，而是针对不同问题采用不同策略：
或通过有针对性的变换逐步化繁为简；或从特殊情形入手，通过猜测和归纳来证明一般性结论；
或通过类比从已知结论中获得启示；或通过引进强大的工具解决问题；
或通过反复迭代逐步优化结论（如9.4节中介绍的bootstrapping技巧）。
如同名师做示范表演，既有连贯动作，又有分解动作，各种招式和套路都
交代得一清二楚。&lt;/p&gt;

&lt;h3 id=&quot;积累&quot;&gt;积累&lt;/h3&gt;
&lt;p&gt;本书尤其强调数学知识库的积累和演进。如5.2节8道基本练习题难度递增，但由于读者在拾级而上
的过程中慢慢积累了经验和技巧，故而显得难度曲线并不那么陡峭。
书中一再从简单情形开始，逐步得出越来越强的结论，并尽可能泛化推广，再应用于特殊情形获得
新的结果，由此建立越来越完备的定理仓库和公式列表（类似软件工程中的迭代增量式开发）。
跟随此书一路学来，你会感到心中慢慢堆起了一座数学小山。&lt;/p&gt;

&lt;h3 id=&quot;试错&quot;&gt;试错&lt;/h3&gt;
&lt;p&gt;在实际的数学发现中，单有直觉和洞察力是不够的，更多时候还得靠硬性的计算和反复的试错排除。
可惜绝大多数的教材都是“洁本”——抹去所有的失败痕迹，不见试错的过程或探索的途径，总是每击必中。
《具》书则不然，诸如wrong、fail、embarrassing、impass、lose、loss、mistake、error、deflating等
负面词汇比比皆是，毫不讳言失败，不仅真实再现了数学的探索过程，也告诉读者：不必耻于失败，
也不必因屡次碰壁而怀疑自己。很多时候，失败只是成功路上的一个必要的弯路。
比如，2.5节采用“扰动法”时，从起初的失败中运用类比推理获得正确的解法。
在5.2节的问题6中，作者甚至故卖破绽，给出了一个通过简单验证却仍错误的解法。&lt;/p&gt;

&lt;h3 id=&quot;系统性&quot;&gt;系统性&lt;/h3&gt;
&lt;p&gt;本书宗旨是培养读者的实际数学运算能力，因此虽不乏令人眼花缭乱的&lt;em&gt;技巧（trick）&lt;/em&gt;，
但更着力的却是传授系统成套的&lt;em&gt;技术（technique）&lt;/em&gt;（这从书中高频出现“系统”二字便可看出）。
例如：生成函数法、超几何级数法、Gosper算法、Zeilberger算法，等等。
这些方法不复杂难懂（intricate），不倚重人的洞察力（clairvoyance）或灵光一现
（sudden flash of inspiration），不靠聪明和运气（cleverness and luck）或猜测（guesswork）。
它们是系统的（systematic）和有指导性的（instructive），甚至是机械的
（mechanical）、算法的（algorithmical），乃至可用计算机代劳的。&lt;/p&gt;

&lt;p&gt;搞数学的喜欢聪明的方法，写程序的喜欢聪明的代码，但这种聪明往往缺少可靠性、
可理解性、可重复性和可推广性。有时需抑制这类聪明，谨记大巧若拙。&lt;/p&gt;

&lt;p&gt;无人会低估数学智慧和灵感的作用，那是所有数学知识的来源。
只是智慧多源自先天，灵感也可遇不可求，故本书着重后天通过训练可获得的系统性技术。&lt;/p&gt;

&lt;h3 id=&quot;不定性&quot;&gt;不定性&lt;/h3&gt;
&lt;p&gt;《具》书还原真实数学的另一表现是，让读者充分意识到数学发现的开放性和不定性。
传统的数学教材中往往证明题居多，而实际的数学研究会面对更多的不确定性。
比如，证明或否证一个结论比单纯的证明更困难，因为需要考虑两种不同的可能；
化简表达式也比证明一个等式更费劲，因为方向和目标均不确定。
更为棘手的问题是，找出使某一断言成立的充要条件。
最可怕也最接近真实数学研究的问题则是：给定一个集合，找出其元素所具有的&lt;em&gt;有趣&lt;/em&gt;的性质。
按本书3.2节的标准，这属于最高级（第5级）数学问题，因为其最开放、不定性最大。&lt;/p&gt;

&lt;h3 id=&quot;练习&quot;&gt;练习&lt;/h3&gt;
&lt;p&gt;《具》书中精彩绝妙的数学技巧层出不穷，令人叹为观止。但它显然不满足于让读者成为
数学魔术的欣赏者，更希望他们成为数学魔术的表演者。
因此，除了充满知识性和启发性的正文外，本书习题之丰富、解答之详尽也是罕见的。
从相对简单的热身题和基础题，到困难的作业题和考试题，乃至超难的附加题和研究题，
如同逐渐升温的熔炉，为读者淬炼越来越锋利的数学兵器。&lt;/p&gt;

&lt;h2 id=&quot;结语&quot;&gt;结语&lt;/h2&gt;
&lt;p&gt;综上所述，对数学或计算机理论感兴趣者阅读《具》书，如入宝山而不至空返。
至于程序员，他们中的绝大多数在工作中并不涉及高深的数学知识，本书未必会对其编程有直接的帮助。
然而，只考虑工作需求而无自我追求的程序员绝不是好程序员。
研读此书不仅能增长数学知识，更能提高数学修养。要知道，一名程序员最大的价值，
不在于他对某些编程语言和工具的熟练运用，而在于拥有一个
冷静而清晰、 严谨而灵活、抽象而深刻的头脑。&lt;/p&gt;

&lt;p&gt;说到本书的翻译，虽非尽善尽美，但总体忠实原文，甚少生硬之处。
尤为难得的是，译者连原书中最难译的（有些还是德语、法语、拉丁语等非英语文字）非技术
性的幽默双关都给出了恰当的翻译和解释，其认真程度可见一斑。
故此，尽管提倡技术人员多看原版书籍，但至少读此译本是无伤大雅的。&lt;/p&gt;

&lt;p&gt;一直以来，人们只看到数学枯燥无味、艰深晦涩的一面（世上哪门学问又何尝不如此呢？）。
《具》书则揭示了数学生动有趣的另一面，同时也表明：数学不是少数天才们的专属游戏，只要
经过适当的训练，数学魔术人人皆会变。&lt;/p&gt;

&lt;p&gt;（此文发表于《程序员》2013年7月刊，发表时有删节）&lt;/p&gt;
</content>
    </entry>
    
    <entry>
        <id>http://en.zhenghui.org/2012/02/26/one-pass-for-all-intro_CN</id>
        <link type="text/html" rel="alternate" href="http://en.zhenghui.org/2012/02/26/one-pass-for-all-intro_CN"/>
        <title>一条密码走天下 - 1pass4all简介</title>
        <updated>2012-02-26T00:00:00+00:00</updated>
        <author>
            <name>Hui Zheng</name>
        </author>
        <content type="html">&lt;h2 id=&quot;一条密码走天下&quot;&gt;一条密码走天下&lt;/h2&gt;

&lt;p&gt;在这个互联网时代，网络账户大都是以用户名与密码组合的形式来鉴别的。由于
用户名一般是公开的，密码安全就显得至关重要了。设计一个好密码绝非易事，既要
足够强壮又要易记难猜。强密码的一个典型特征是熵（entropy）值高，通俗地说是
随机性强、规律性弱。那些用有规律或广为人知的数字序列或字串组成的密码固然不满足此条件，
一个长度不够、字符取值范围不广的密码在暴力破解面前同样弱不禁风。此外，有些密码
看似强壮，但如果与用户的个人信息紧密相联，也容易被知情人猜出或缩小检测范围。
事实上，绝大多数用户的密码要么不够强壮、要么容易猜测、要么（也是更多的）兼而有之。
去年底爆出的&lt;a href=&quot;http://baike.baidu.com/view/7167245.htm&quot;&gt;“密码门”事件&lt;/a&gt;再次佐证了这一点。
其实情有可原，强壮而难猜的密码通常也难记。有些用户挖空心思地想出强密码，为不增加
设计负担和记忆负担，往往又忍不住在多处网站重复使用，就此埋下安全隐患：
一旦由于某种原因（如此次“密码门事件”）密码被暴露，将殃及多个账户。故而
对密码的另一要求是，不同账户的密码应尽可能不相同、甚至不相关。只不过这样一来，密码
维护的难度更是倍增。正因如此，一些密码管理软件应需而生，它们的核心思想基本上都
很相似， 即以加密的形式为用户保存所有的账户和密码信息，用户仅需记住一条密码
（以下称为“主密码”），便可随时查询内藏的密码库。&lt;/p&gt;

&lt;p&gt;本人使用密码管理工具颇有时日，包括&lt;a href=&quot;http://keepass.info/&quot;&gt;KeePass&lt;/a&gt;、
&lt;a href=&quot;https://agilebits.com/onepassword&quot;&gt;1Password&lt;/a&gt;和&lt;a href=&quot;https://lastpass.com/&quot;&gt;LastPass&lt;/a&gt;，
始终觉得它们各有缺憾。KeePass在功能和界面上不如1Password，但后者价格不菲，且主要
在Mac平台（后虽支持Windows，但界面上远逊，且不支持Linux）。LastPass相比前二者的
优势是支持云同步，但将密码库置于远程服务器也非全无顾虑，比如TechCrunch曾刊载
过&lt;a href=&quot;http://techcrunch.com/2011/05/05/password-manager-last-pass-possibly-hacked&quot;&gt;LastPass被破解的传闻&lt;/a&gt;。另外，虽然这些管理器都能帮用户生成
随机密码，但既难记又难敲。您可能会问：为什么要记呢，这不正是它们的意义所在吗？
话虽如此，然而不可否认，每登陆账户都要额外启动一个程序委实不便。不错，用户可以选择
让浏览器记住密码，或者利用这些管理器在浏览器上的插件来自动填写，但这种便利是以
安全为代价的。我以前的做法是，自定义一些隐秘的变量，然后通过某些规则或函数
进行变换而产生密码。作为一个程序员，我甚至写了一些脚本让此过程自动化。可惜该法
有个弊端：一旦离开自己的电脑，便可能因缺乏脚本或脚本运行环境而失效。
某日细思此事，想到JavaScript当是比一般的脚本更佳的选择，盖因凡有电脑处便有浏览器，
凡有浏览器处便能运行JavaScript。只要把JavaScript代码上传到某个网络空间，即可
予取予求。由于运行的过程与结果既不会在网络中传输，也不会在本地保存，有效保障了
密码的安全性。于是，很自然地开始把焦点集中在
&lt;a href=&quot;http://en.wikipedia.org/wiki/Bookmarklet&quot;&gt;小书签（bookmarklet）&lt;/a&gt;（或译为“书签工具”）上。所谓小书签，
无非是放在浏览器上的一种书签或网页上的一个超链接，与普通书签或超链接不同的是，
其网址（URL）不是某个网页地址，而是一段JavaScript代码。一旦被点击，
不会如普通书签那样进入到新网页，而会在当前网页中执行其内含的JavaScript程序。
此法方便、易安装、跨浏览器、且&lt;a href=&quot;http://en.wikipedia.org/wiki/Unobtrusive_JavaScript&quot;&gt;无干扰（unobtrusive）&lt;/a&gt;
（注：不少人译为“无侵入”，但对应后者更贴切的英文当是unintrusive或non-intrusive）。&lt;/p&gt;

&lt;p&gt;为避免重复劳动（即所谓的“重新发明轮子”），先在网上查寻是否已有现成产品可用，
结果发现&lt;a href=&quot;http://supergenpass.com&quot;&gt;SuperGenPass&lt;/a&gt;较好地满足了自己的要求。简单地说，SuperGenPass能将
一个主密码按不同的网站域名转换成不同的密码。不出意料，它采用的是&lt;a href=&quot;http://en.wikipedia.org/wiki/MD5&quot;&gt;MD5&lt;/a&gt;
算法。此算法可迅速将主密码与网络域名的组合&lt;strong&gt;单向（one-way）&lt;/strong&gt;映射（计算机术语
是&lt;a href=&quot;http://en.wikipedia.org/wiki/Cryptographic_hash_function&quot;&gt;哈希（hash）&lt;/a&gt;）为一个对输入敏感的、近似随机的字串。“单向”意味着
从输出难以反推输入，从而一条密码泄露不致暴露主密码；“敏感”意味着差异微小的输入
会导致差异极大的输出，从而一条密码泄露不会对其他密码造成危险；“近似随机”则意味
着输出字串可视为强密码。主意是不错，但于我并不新鲜。何况已知有人用&lt;a href=&quot;http://en.wikipedia.org/wiki/SHA-1&quot;&gt;SHA-1&lt;/a&gt;
开发了&lt;a href=&quot;http://angel.net/~nic/passwd.current.html&quot;&gt;密码生成器&lt;/a&gt;，年前还见有国人用
MD5实现了&lt;a href=&quot;http://code.google.com/p/md5-password-creator/wiki/AboutApp&quot;&gt;类似功能&lt;/a&gt;。
SuperGenPass真正令我心动的地方是，它能就地生成密码——在用户于密码项中填入
主密码后，点击小标签便能用新产生的密码直接替换主密码。相比之下，原先在命令行中
运行脚本再将结果拷贝或重敲一遍的做法，既不安全也不方便。&lt;/p&gt;

&lt;p&gt;事情变得简单多了。有了密码小标签，只需牢记一条密钥在心，便能自信地在不同的
网站以不同的强密码登陆，哪怕与这些密码素不谋面。不过传统的密码管理器
仍有用武之地。比如可以记录主密码的提示，以防万一哪天“临时性”失忆；可以
在可信赖的电脑上为非关键性的账户提供自动填单的功能；可以保存其他类型的
敏感信息或文件，等等。&lt;/p&gt;

&lt;p&gt;在准备采用SuperGenPass之前，对其功能和源代码进行了一番考察，很遗憾地发现有些
缺陷令人难以释怀。首先，MD5&lt;a href=&quot;http://www.kb.cert.org/vuls/id/836068&quot;&gt;在理论上不够安全&lt;/a&gt;。作为一个文件校验器
问题还不大，作为密码生成器则有些勉为其难了。更糟的是，SuperGenPass默认的
&lt;a href=&quot;http://en.wikipedia.org/wiki/Salt_(cryptography)&quot;&gt;密码盐（salt）&lt;/a&gt;为空，且除非修改源代码便无法定制。这使其极易受到
&lt;a href=&quot;http://en.wikipedia.org/wiki/Dictionary_attack&quot;&gt;字典攻击&lt;/a&gt;。另一问题是，SuperGenPass基于&lt;a href=&quot;http://en.wikipedia.org/wiki/Base64&quot;&gt;Base64&lt;/a&gt;，
这意味着生成的密码主要有字母与数字组成（此外还有&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt;与&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt;），许多如&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;?&lt;/code&gt;、 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$&lt;/code&gt;
等特殊字符均被排除在外。这便是此前所说字符取值狭窄的问题。以一个8位密码为例，
64种字符的组合数不到94种字符（可打印字符共94个）的组合数的20分之一，相差一个数量级。
若是12位密码，比率更是低于百分之一，整整相差两个数量级。再者，SuperGenPass完全
不考虑用户名也是一大不足。本人在一些网站（如gmail、dropbox）上有多个账户，非常不
希望它们共享密码。诚然，给主密码加上用户名前缀或后缀便能衍生出不同实际密码。但
从名义上看，单个主密码的说法便已然不实；从理论上看，将密钥与数据简单地用字符串
拼接的做法不如&lt;a href=&quot;http://en.wikipedia.org/wiki/HMAC&quot;&gt;HMAC&lt;/a&gt;算法更可靠。此外，在变更密码页中，SuperGenPass似乎
有点问题。不知为何，有时它自动将旧密码、新密码和确认新密码三项均作变换，有时却
只改变其中的一个或两个。权衡再三，最终决定自己从头开发一个密码小书签，这便是
&lt;a href=&quot;http://en.zhenghui.org/1pass4all/&quot;&gt;1pass4all&lt;/a&gt; (意即one pass for all，一码永逸)
的由来。&lt;/p&gt;

&lt;p&gt;1pass4all希望在SuperGenPass之上有如下改进：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;安全性：&lt;/p&gt;

    &lt;p&gt;鉴于&lt;a href=&quot;http://en.wikipedia.org/wiki/SHA-2&quot;&gt;SHA-2&lt;/a&gt;比MD5和SHA-1更安全，HMAC比单纯的字串拼接更合理，
1pass4all基于HMAC-SHA224算法。产生的密码默认可包含任意可打印字符，当然根据
需求也可仅包含Base64字符、数字加字母或纯数字。密码的最大长度也从24位提高到26位。
为防止字典攻击，支持对密码盐的定制。同时为加大破解难度，支持定制hash的迭代次数
（为了&lt;a href=&quot;http://en.wikipedia.org/wiki/Key_stretching&quot;&gt;key stretching&lt;/a&gt;）。进一步地，1pass4all可考虑
用户名，从而只要账户不同，即便主密码和网站均相同，相应的密码也会不同。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;可用性：&lt;/p&gt;

    &lt;p&gt;只要启用“自动登陆”选项，1pass4all在登陆页面生成密码后会自动提交，无需弹出
确认窗口。如果一切顺利，该小书签表现得就像一个登陆按钮，只是暗中施了点“魔法”而已。
正常情况下，点击小书签仅对当前有焦点（如无，则为第一个）的密码项起作用，
这样不会让用户犯晕，也能避免不必要的转换（比如以前手工键入的旧密码）。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;功能：&lt;/p&gt;

    &lt;p&gt;针对高级用户，1pass4all提供了专门的密码语法，可以在不弹出窗口的条件下指定一些
参数，如用户名、域名、密码长度、密码盐、迭代次数、密码字符集以及是否启用用户名
的自动检查、是否自动登陆等。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;和SuperGenPass一样，1pass4all也提供了移动版。有时用户不能或不想安装小书签，比如
在手机上、在他人电脑上、或在可能会盗取主密码的非信任网站上。另外，要想在非浏览器
应用上使用1pass4all，目前也非移动版不可。&lt;/p&gt;

&lt;p&gt;对高级用户（尤其是程序员），则推荐使用自制（DIY）版，不仅可更随意地定制参数、
设置JavaScript代码的网址、改变界面的风格（以弥补原有界面的简陋），必要时更可修改算法。&lt;/p&gt;

&lt;p&gt;若此文引发了您的些许兴趣，不妨到&lt;a href=&quot;http://en.zhenghui.org/1pass4all/archive/install_zh.html&quot;&gt;安装页面&lt;/a&gt;
一试。更多说明请参见&lt;a href=&quot;https://github.com/hzheng/1pass4all/blob/master/README.rst&quot;&gt;README文件&lt;/a&gt;。如有任何问题或建议，欢迎留言。
需要提醒的是，尽管1pass4all能极大地强化弱密码，但由于其算法是公开的，因此主密码
仍应足够强壮。如是，纵然“一条密码走天下”，亦可高枕无忧矣。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;附：本文的&lt;a href=&quot;http://en.zhenghui.org/2012/02/21/one-pass-for-all-intro/&quot;&gt;英文版&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&quot;参考文献&quot;&gt;参考文献&lt;/h2&gt;

&lt;p&gt;[1] &lt;a href=&quot;http://supergenpass.com&quot;&gt;SuperGenPass&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[2] &lt;a href=&quot;http://en.wikipedia.org/wiki/Bookmarklet&quot;&gt;Wikipedia: bookmarklet&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[3] &lt;a href=&quot;http://en.wikipedia.org/wiki/Unobtrusive_JavaScript&quot;&gt;Wikipedia: Unobtrusive JavaScript&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[4] &lt;a href=&quot;http://en.wikipedia.org/wiki/MD5&quot;&gt;Wikipedia: MD5&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[5] &lt;a href=&quot;http://en.wikipedia.org/wiki/Cryptographic_hash_function&quot;&gt;Wikipedia: Cryptographic_hash_function&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[6] &lt;a href=&quot;http://en.wikipedia.org/wiki/Salt_(cryptography)&quot;&gt;Wikipedia: Salt_(cryptography)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[7] &lt;a href=&quot;http://en.wikipedia.org/wiki/SHA-2&quot;&gt;Wikipedia: SHA-2&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[8] &lt;a href=&quot;http://en.wikipedia.org/wiki/HMAC&quot;&gt;Wikipedia: HMAC&lt;/a&gt;&lt;/p&gt;

</content>
    </entry>
    
    <entry>
        <id>http://en.zhenghui.org/2012/02/21/one-pass-for-all-intro</id>
        <link type="text/html" rel="alternate" href="http://en.zhenghui.org/2012/02/21/one-pass-for-all-intro"/>
        <title>One Pass For All - An introduction to 1pass4all</title>
        <updated>2012-02-21T00:00:00+00:00</updated>
        <author>
            <name>Hui Zheng</name>
        </author>
        <content type="html">&lt;h2 id=&quot;one-pass-for-all&quot;&gt;One Pass For All&lt;/h2&gt;

&lt;p&gt;As an internet user, you probably have a bunch of web accounts.
With few exceptions, all of them are password-protected. 
To keep these accounts as safe as possible, you have to figure out
a set of strong yet easy-to-remember and hard-to-guess passwords. Moreover,
these passwords shouldn’t be the same as or similar to each other, or
more strictly, the relationship among these passwords should be hard to detect.
Otherwise, if one of them is compromised, so are the others. With the 
number of accounts growing, password maintenance tends to be a thorny issue.
That’s where the password management tools come in. The key idea of most of
them is pretty straightforward: they securely keep track of all account
passwords for a user so that he only need remember &lt;strong&gt;one&lt;/strong&gt; single
super-password(called &lt;em&gt;master password&lt;/em&gt;), by which he can access the encrypted
password database whenever in need.&lt;/p&gt;

&lt;p&gt;Having used password management tools(e.g. &lt;a href=&quot;http://keepass.info/&quot;&gt;KeePass&lt;/a&gt;, 
&lt;a href=&quot;https://agilebits.com/onepassword&quot;&gt;1Password&lt;/a&gt;, &lt;a href=&quot;https://lastpass.com/&quot;&gt;LastPass&lt;/a&gt;)
for a fairly long time, I still feel they are not perfectly desirable.
1Password looks nicer than KeePass, but it’s expensive and is not available in
Linux. The advantage of LastPass is it supports cloud sync, but storing
confidential data in the internet is not worry-free, and 
&lt;a href=&quot;http://techcrunch.com/2011/05/05/password-manager-last-pass-possibly-hacked&quot;&gt;LastPass is not exception&lt;/a&gt;.
Although all of them can generate random passwords, they are inherently
unfriendly to my memory. Surely, I don’t have to remember them, and that is
exactly the whole point of these managers, isn’t it? But it’s kind of a pain
to launch an additional application each time to log in an account.
Having them or browsers autofill passwords is possible, but less secure.
My personal solution used to be applying some rules or functions to some
predefined private variables to produce passwords.
Being a programmer, I’ve even written some scripts to help reproduce them.
The catch of this approach is I’ll be out of luck when away from my own
computer. Finally, it occurs to me that JavaScript is a better choice than
shell scripts in such situation, for the former is more related to browsers
and its runtime environment is more available. Besides, the process and
result of JavaScript execution is neither transmitted in network nor saved
in local disk, which guarantees the safety of passwords.
Therefore, I begin to focus on &lt;a href=&quot;http://en.wikipedia.org/wiki/Bookmarklet&quot;&gt;bookmarklet&lt;/a&gt; way.
Technically, a bookmarklet is a piece of JavaScript saved as the URL of a 
bookmark in a browser or as a hyperlink on a web page. Unlike a normal
bookmark, once clicked a bookmarklet won’t take you to another web page.
Instead, the stored JavaScript code will be executed in the current web page.
It’s &lt;a href=&quot;http://en.wikipedia.org/wiki/Unobtrusive_JavaScript&quot;&gt;unobtrusive&lt;/a&gt;, cross-browser, handy, and easy-to-install.&lt;/p&gt;

&lt;p&gt;To avoid reinventing the wheel, I look up the web to see if anyone else has
the same idea. It turns out &lt;a href=&quot;http://supergenpass.com&quot;&gt;SuperGenPass&lt;/a&gt;
meets my requirement quite well. Basically, SuperGenPass is able to transform a
master password into strong and different passwords for the different web sites.
Not surprisingly, it uses &lt;a href=&quot;http://en.wikipedia.org/wiki/MD5&quot;&gt;MD5&lt;/a&gt; algorithm to achieve the goal. As a one-way
&lt;a href=&quot;http://en.wikipedia.org/wiki/Cryptographic_hash_function&quot;&gt;cryptographic hash function&lt;/a&gt;, MD5 can quickly convert the
combination of a master password and an internet domain
to an input-sensitive, pseudo-random string, which implies that even if the
password for some specific website is compromised, it is infeasible to reversely
compute the original master password or passwords for other websites.
Great as the idea is, it’s not new to me. The actual sweet spot to me is that it 
populates the password just in-place; namely, after a user fills out a master
password in a password field and clicks the SuperGenPass bookmarklet,
the hashed password will directly replace the master password.
By contrast, running a script under a shell and copying or retyping the output
into password field is somewhat unsafe and cumbersome.&lt;/p&gt;

&lt;p&gt;Life becomes easier now. With the aid of a password bookmarklet, I only have to
keep one secret key in mind, yet confidently sign on various websites with
unique and strong passwords, without even knowing what they actually look like.
That said, traditional password managers still have their places, they may
save the hints of some(one or very few) master passwords just in case,
or autofill login form for non-crucial accounts on trusted machines,
or record some other sensitive information.&lt;/p&gt;

&lt;p&gt;Before adopting SuperGenPass, I take a closer look at its features and source
code. In my opinion, there are some defects that cannot be ignored.
For one thing, MD5 is &lt;a href=&quot;http://www.kb.cert.org/vuls/id/836068&quot;&gt;considered cryptographically broken&lt;/a&gt;.
It’s OK to serve as file integrity checker, but not that competent as a password
generator. What is worse, SuperGenPass’s default 
&lt;a href=&quot;http://en.wikipedia.org/wiki/Salt_(cryptography)&quot;&gt;salt&lt;/a&gt; is empty and cannot
be customized unless you modify the source code. This makes it more vulnerable
to &lt;a href=&quot;http://en.wikipedia.org/wiki/Dictionary_attack&quot;&gt;dictionary attack&lt;/a&gt;. Another problem is SuperGenPass is
solely based on &lt;a href=&quot;http://en.wikipedia.org/wiki/Base64&quot;&gt;Base64&lt;/a&gt;, which means the generated
password are mainly composed of letters and digits, excluding many special
characters like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;?&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$&lt;/code&gt;, etc. This may dilute the strength of the 
passwords, especially considering the default password length is only 10.
One more thing that concerns me is it totally neglects the login name(username).
I have multiple accounts on the same websites(e.g. gmail, dropbox), and
definitely don’t wish all of them share passwords. Appending or prepending
a master password with a username may be barely enough, but nominally 
this make ONE master password not really true, and theoretically,
simple concatenation of a key and data is less reliable than
&lt;a href=&quot;http://en.wikipedia.org/wiki/HMAC&quot;&gt;HMAC&lt;/a&gt; algorithm. In addition, it seems that SuperGenPass doesn’t work
well on password-change page(let me know if I am wrong here). I have no clue
why sometimes it autofills all passwords including old password, new password
and confirmed new password, sometimes it only fill just one or two of them.
Eventually, I decide to develop one by myself from scratch. As a result, a
gadget named &lt;a href=&quot;http://en.zhenghui.org/1pass4all/&quot;&gt;1pass4all&lt;/a&gt; (i.e. one pass for all)
comes out.&lt;/p&gt;

&lt;p&gt;Hopefully, 1pass4all provides some improvements over SuperGenPass as follows:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;security:&lt;/p&gt;

    &lt;p&gt;1pass4all is based on algorithm HMAC-SHA224, seeing that &lt;a href=&quot;http://en.wikipedia.org/wiki/SHA-2&quot;&gt;SHA-2&lt;/a&gt; is
more secure than MD5, and HMAC is more suitable than plain concatenation. 
By default, the generated password may contain any printable characters(Base94)
instead of Base64 characters, and password’s maximal length extends from 24
to 26. Besides, it supports customizable salt and hash iteration(for
&lt;a href=&quot;http://en.wikipedia.org/wiki/Key_stretching&quot;&gt;key stretching&lt;/a&gt;).
Furthermore, 1pass4all can take username into account, which means the same
master password on the same website will result in different passwords
as long as logins differ.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;usability:&lt;/p&gt;

    &lt;p&gt;When possible, 1pass4all will auto-login after populating password
without popping up a confirmation form. If everything goes smoothly,
the bookmarklet just acts as a login button, except doing something magic underneath.
Normally, clicking the bookmarklet will only change the value of the focused
password field(or the first one if none is focused). This is less confusing, 
and can avoid unwanted password transformation(e.g. those manually typed
old-password).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;functionality:&lt;/p&gt;

    &lt;p&gt;Aiming at advanced users, 1pass4all supports a specialized password syntax,
so that they can specify username, domain, password-length, salt, hash
iteration, password character set, username auto-detection, auto-login etc.
in the password field(instead of a pop-up form) on-the-fly.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Like SuperGenPass, 1pass4all also has mobile version in case you cannot 
or don’t want to install bookmarklet for some reason. For example, when you are
on a mobile or on other’s computer, or you are visiting an untrusted website
that may steal your master password. It’s useful as well when you are logging
on a non-browser application.&lt;/p&gt;

&lt;p&gt;Advanced users(esp. programmers) are recommended to choose DIY version, where
they could more readily define parameters, relocate JavaScript code’s hosting
address, change the style of interface(to improve the crude UI), 
and modify the algorithm when necessary.&lt;/p&gt;

&lt;p&gt;I will be gratified if your interest has been aroused so far. Please don’t
hesitate to &lt;a href=&quot;http://en.zhenghui.org/1pass4all/archive/install.html&quot;&gt;give it a try&lt;/a&gt; now.
For further instructions, you may read &lt;a href=&quot;https://github.com/hzheng/1pass4all/blob/master/README.rst&quot;&gt;README file&lt;/a&gt;.
Any problems and suggestions are welcome in the comments below.
As a reminder, despite the fact that 1pass4all can largely strengthen your
password, you still need design a very strong master password, since 1pass4all’s
algorithm is open. Fortunately, that’s the only password you have to memorize
at any time.&lt;/p&gt;

&lt;p&gt;Lastly,  I’d like to acknowledge SuperGenPass for inspiring me to develop
this project.&lt;/p&gt;

&lt;p&gt;P.S. The &lt;a href=&quot;http://en.zhenghui.org/2012/02/26/one-pass-for-all-intro_CN/&quot;&gt;Chinese version&lt;/a&gt;
of this article is also available.&lt;/p&gt;

&lt;h2 id=&quot;reference&quot;&gt;Reference&lt;/h2&gt;

&lt;p&gt;[1] &lt;a href=&quot;http://supergenpass.com&quot;&gt;SuperGenPass&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[2] &lt;a href=&quot;http://en.wikipedia.org/wiki/Bookmarklet&quot;&gt;Wikipedia: bookmarklet&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[3] &lt;a href=&quot;http://en.wikipedia.org/wiki/Unobtrusive_JavaScript&quot;&gt;Wikipedia: Unobtrusive JavaScript&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[4] &lt;a href=&quot;http://en.wikipedia.org/wiki/MD5&quot;&gt;Wikipedia: MD5&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[5] &lt;a href=&quot;http://en.wikipedia.org/wiki/Cryptographic_hash_function&quot;&gt;Wikipedia: Cryptographic_hash_function&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[6] &lt;a href=&quot;http://en.wikipedia.org/wiki/Salt_(cryptography)&quot;&gt;Wikipedia: Salt_(cryptography)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[7] &lt;a href=&quot;http://en.wikipedia.org/wiki/SHA-2&quot;&gt;Wikipedia: SHA-2&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[8] &lt;a href=&quot;http://en.wikipedia.org/wiki/HMAC&quot;&gt;Wikipedia: HMAC&lt;/a&gt;&lt;/p&gt;

</content>
    </entry>
    
</feed>


