<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>加密 on 豆子技术站</title><link>https://blog.91demo.top/tags/%E5%8A%A0%E5%AF%86/</link><description>Recent content in 加密 on 豆子技术站</description><generator>Hugo -- 0.155.1</generator><language>zh-cn</language><lastBuildDate>Thu, 11 Jan 2018 12:40:16 +0800</lastBuildDate><atom:link href="https://blog.91demo.top/tags/%E5%8A%A0%E5%AF%86/index.xml" rel="self" type="application/rss+xml"/><item><title>实战笔记：为了管好那堆记不住的密码，我给自己写了个全加密密码本</title><link>https://blog.91demo.top/tool-pwbook/</link><pubDate>Thu, 11 Jan 2018 12:40:16 +0800</pubDate><guid>https://blog.91demo.top/tool-pwbook/</guid><description>&lt;p&gt;虽然现在的 App 普遍支持手机号或微信一键登录，但对于开发者来说，GitHub、服务器、各类海外服务的登录依然离不开“邮箱+密码”的传统模式。&lt;/p&gt;
&lt;p&gt;我曾经历过一段漫长的“密码管理进化史”：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Excel 时代&lt;/strong&gt;：最早用一个加密的 Excel 表格记录，在电脑端还凑合。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Flutter App 时代&lt;/strong&gt;：为了手机查看方便，我曾写过一个简单的 Flutter App，支持指纹查看，但功能简陋，只有新增功能，连“修改”功能都没有。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;直到有一次，GitHub 要求我重新登录，由于我频繁重置密码且新旧密码不能重复，导致我彻底记混了。在另一台电脑前尝试了无数次失败后，我意识到：&lt;strong&gt;我需要一个足够安全、随时可用、功能完整的个人密码管理工具。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;于是，“豆子工具”里的&lt;strong&gt;小程序版密码本&lt;/strong&gt;诞生了。&lt;/p&gt;
&lt;p&gt;&lt;img alt="我的密码本" loading="lazy" src="https://blog.91demo.top/images/wander/tool-pwbook.webp"&gt;&lt;/p&gt;
&lt;h3 id="1-设计核心绝对的隐私与自由"&gt;1. 设计核心：绝对的隐私与自由&lt;/h3&gt;
&lt;p&gt;在设计之初，我就定下了两个原则：&lt;strong&gt;不联网、重加密。&lt;/strong&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;：这是我花费心血最多的地方。主密码（Master Password）不存储在设备上。
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;第一步&lt;/strong&gt;：用主密码解密 &lt;strong&gt;RSA 私钥&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;第二步&lt;/strong&gt;：用私钥解密 &lt;strong&gt;AES 密钥&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;第三步&lt;/strong&gt;：用 AES 密钥解密具体的 &lt;strong&gt;JSON 序列化记录&lt;/strong&gt;。&lt;br&gt;
这种混合加密机制确保了即使手机丢失，只要主密码不泄露，数据依然是安全的。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="2-攻克开发中的大山"&gt;2. 攻克开发中的“大山”&lt;/h3&gt;
&lt;p&gt;这个功能的开发过程远比我想象中痛苦。尤其是在小程序环境下处理&lt;strong&gt;文件缓存、二进制流转换和加解密逻辑&lt;/strong&gt;，经常一个 Bug 就要调试好几天。&lt;/p&gt;
&lt;p&gt;中途我好几次想过放弃，觉得用 Excel 也可以凑合。但每次想到反复重置密码的痛苦，还是咬牙坚持了下来。为了稳定性，我将原本不稳定的二进制存储改为了 UTF-8 编码的 JSON 序列化，最终实现了丝滑的操作体验，这都是心血的教训。&lt;/p&gt;
&lt;h3 id="3-功能完善不仅仅是存一下"&gt;3. 功能完善：不仅仅是“存一下”&lt;/h3&gt;
&lt;p&gt;相比之前的 Flutter 版本，这次我补全了所有短板：&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;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;h3 id="4-字段灵活满足多样需求"&gt;4. 字段灵活，满足多样需求&lt;/h3&gt;
&lt;p&gt;每一条记录都包含了：&lt;strong&gt;标题、URL、用户名、密码、备注&lt;/strong&gt;。&lt;br&gt;
无论是一个服务器的 SSH 密码，还是一个冷门网站的登录信息，都能井井有条地分类存放。&lt;/p&gt;
&lt;h3 id="5-核心代码展示"&gt;5. 核心代码展示&lt;/h3&gt;
&lt;p&gt;纯小程序本地原生实现，首先是密码本初始化，它会根据用户输入的主密码，生成密码本文件。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;// 第一次使用设置方法
async setupFirstTime(masterPassword, passwordHint) {
try {
// 1. 检查是否已有密码本
if (!passwordManager.hasPasswordBook()) {
console.log(&amp;#39;1. 创建空密码本...&amp;#39;);
const createResult = await passwordManager.createEmptyPasswordBook(masterPassword, passwordHint);
if (createResult.success) {
console.log(&amp;#39;✓&amp;#39;, createResult.message);
} else {
console.log(&amp;#39;创建失败:&amp;#39;, createResult.error);
wx.showToast({
title: createResult.error,
icon: &amp;#39;none&amp;#39;
});
return;
}
}
} catch (err) {
console.log(&amp;#39;创建密码本错误，&amp;#39;, err)
}
// 保存主密码安装和提示
wx.setStorageSync(&amp;#39;pwbookInstall&amp;#39;, new Date().toLocaleString());
wx.setStorageSync(&amp;#39;passwordHint&amp;#39;, passwordHint || &amp;#39;&amp;#39;);
wx.setStorageSync(&amp;#39;pwbookBakTime&amp;#39;, getSecTs());
this.setData({
isFirstTime: false,
isUnlocked: true,
showPasswordDialog: false
});
wx.showToast({
title: &amp;#39;初始化成功&amp;#39;,
icon: &amp;#39;success&amp;#39;
});
this.loadPasswordList();
},
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;创建密码本文件核心代码：&lt;/p&gt;</description></item></channel></rss>