CopyQ 剪贴板数据加密完全指南:内置密码保护与遗留 GnuPG 插件实战
2026/9/23 13:06:44 网站建设 项目流程
  • 桌面应用

【免费下载链接】CopyQ

Clipboard manager with advanced features

项目地址:https://gitcode.com/gh_mirrors/co/CopyQ
点击查看免费下载

CopyQ 是一款功能强大的剪贴板管理器,会将复制过的内容持久化保存在本地磁盘的标签页中。为了保障这些存储数据的安全,CopyQ 自 14.0.0 版本起内置了基于用户密码的整库加密能力,不再依赖任何外部软件;同时保留了基于 GnuPG 的遗留加密插件,用于按需加密单个条目或兼容旧版本。本文将围绕 docs/password-protection.rst 的完整内容,结合仓库源码(src/common/encryption.cpp、src/gui/encryptionpassword.cpp、plugins/itemencrypted/itemencrypted.cpp)深入讲解两种方案的启用步骤、配置参数、底层密码学原理与实操注意事项,读完即可为你的剪贴板数据加上一道可靠的密码锁。

一、两种加密方案概览

CopyQ 提供两条加密路径,适用场景截然不同:

特性内置加密(Built-in Encryption)遗留加密插件(Encryption Plugin)
引入版本14.0.0 起老版本长期存在,14.0.0 起标记为 deprecated
外部依赖无(依赖 Qt 加密库 QCA 及其 OpenSSL 后端)必须安装 GnuPG(gpg2/gpg
加密范围应用加载的全部标签页,自动覆盖配置中指定的标签页;也可按需加密单个条目
密码输入频率启动时、修改密码时、定时过期时每隔几分钟需重新输入
密钥管理DEK/KEK 信封加密,支持外部密钥库GnuPG 公私钥体系,密钥文件位于配置目录

官方建议是:新版本一律使用内置加密;仅在需要"逐条目加密"或运行 CopyQ 14.0.0 之前旧版本时,才考虑遗留插件。

二、内置加密:启用与配置

2.1 启用步骤

打开Preferences(首选项)对话框,勾选Encrypt Tabs选项(对应界面文件 src/ui/configtabgeneral.ui 中的checkBoxEncryptTabs,配置项定义见 src/common/appconfig.h 的encrypt_tabs,默认值为false)。勾选后 CopyQ 会弹出密码设置对话框:

  • 输入新密码并二次确认(两次不一致会提示重试,最多尝试 3 次,见 src/gui/encryptionpassword.cpp);
  • 密码不允许为空;
  • 设置成功后,CopyQ 会对全部现有标签页数据执行一次性加密(reencryptTabs,调用位置见 src/gui/mainwindow.cpp)。

启用后,所有由应用加载的标签页数据都会被加密——不存在按标签页或按条目逐一勾选的配置,这是与遗留插件最本质的区别。

2.2 何时需要输入密码

根据官方文档与源码,密码在以下场景被要求输入:

  1. CopyQ 启动时:读取加密标签页数据前,需要解锁;
  2. 修改加密密码时:必须提供当前密码;
  3. 定时要求:若在 "History(历史记录)" 配置页中启用Require password after an interval(间隔一段时间后要求输入密码),则到期后应用会周期性请求密码。对应配置项为expire_encrypted_tab_seconds(取值被钳制在 0~999999 秒,见 src/common/appconfig.h)。

此外,禁用加密(取消勾选 Encrypt Tabs)时同样需要输入密码验证身份(见测试用例 src/tests/tests_encryption.cpp)。

2.3 使用外部密钥库(Use external key store)

为避免每次启动都手动输入密码,可勾选Use external key store(使用外部密钥库)。该选项将密码托管给系统级安全存储,对应配置项use_key_store(默认值为true,见 src/common/appconfig.h)。各平台后端如下:

  • Windows— Credential Store(凭据管理器)
  • macOS— Keychain(钥匙串)
  • Linux— GNOME Keyring 或 KWallet

从源码看,密码通过KeychainAccess::writePassword/readPassword读写,服务名为com.github.hluk.copyq;当 CopyQ 以会话(session)方式运行时,键名还会带上会话后缀(PasswordForSession-<session>),避免多会话互相干扰(见 src/gui/encryptionpassword.cpp)。

需要特别提醒:启用外部密钥库并不会绕过定时密码过期——当 "Require password after an interval" 开启时,周期性提示依然生效。

2.4 内置加密与导出数据的边界

官方文档明确了一个容易踩坑的注意点:

  • 内置加密保护的是磁盘上的静态数据(data at rest)
  • exportTabexportData脚本命令始终写出未加密文件,不受加密设置影响;
  • 从 GUI 执行File(文件)— Export(导出)时,CopyQ 会弹出可选导出密码对话框——若填写密码,导出文件中的标签页数据将以该密码加密;不填则明文导出。

详细的备份/导出说明见 docs/backup.rst(其中也强调:GUI 导出可选密码加密,而exportData脚本命令不支持该特性,始终导出未加密数据;若标签页与磁盘目录同步,则文件本身不会被导出)。

三、内置加密的底层原理(源码级)

3.1 DEK/KEK 信封加密架构

内置加密采用标准"信封加密(Envelope Encryption)"设计,核心类为Encryption::EncryptionKey(定义见 src/common/encryption.h):

  • DEK(Data Encryption Key):随机生成的 256 位数据加密密钥,真正用于加密全部标签页数据(generateRandomDEK());
  • KEK(Key Encryption Key):由用户密码经PBKDF2派生而来,用于加密(包裹)DEK;
  • 磁盘上只保存"被 KEK 包裹后的 DEK"(wrapped_dek.dat)与 KEK 派生的随机盐(kek_salt.dat),文件路径由configurationFilePath("wrapped_dek.dat")/configurationFilePath("kek_salt.dat")决定(见 src/common/encryption.cpp)。

这套架构带来两个关键收益(源码注释原话):

  1. 改密码开销极小:修改密码只需用新 KEK 重新包裹 DEK,无需重新加密全部数据(saveKey()只重写两个小文件,见 src/common/encryption.cpp);
  2. 安全性更高:DEK 是密码学随机密钥,强度远高于任何口令派生密钥;且每个用户拥有独立随机盐。

3.2 具体密码学参数

从 src/common/encryption.cpp 的常量定义可以确认完整算法组合:

  • 对称加密:AES-256-CBC,PKCS7 填充(QCA 名称aes256-cbc-pkcs7);
  • 密钥派生:PBKDF2-SHA1,迭代次数100,000,输出 32 字节(256 位);
  • 每条消息随机盐:16 字节,每条消息通过HKDF-SHA256(RFC 5869)从主密钥派生独立的消息密钥(derivePerMessageKey);
  • 完整性校验:对密文负载计算HMAC-SHA256(32 字节标签),解密时用常数时间比较constantTimeEquals)验证,可有效防篡改(见 src/common/encryption.cpp);
  • 文件格式魔数:CPQ1,用于标识新版格式并拒绝旧版遗留格式(decryptAuthenticated会拒绝不以CPQ1开头的负载)。

3.3 数据落盘的健壮性设计

  • 写入采用QSaveFile原子提交,避免写一半损坏;
  • Unix 系平台上,密钥文件权限被收紧为仅属主可读写(ReadOwner | WriteOwner,见 src/common/encryption.cpp);
  • saveKey()在改写前会先备份wrapped_dek.dat/kek_salt.dat.backup后缀),写完后用新密码反向解包校验 DEK 一致,任何一步失败都会自动回滚备份(见 src/common/encryption.cpp)。

3.4 密码输入途径与测试验证

源码支持多种密码来源(PasswordSource):

  • 交互式密码对话框(QInputDialog,密码模式输入);
  • 环境变量COPYQ_PASSWORD(适合自动化/无头场景,见 src/gui/encryptionpassword.cpp);
  • 系统密钥库(上文所述)。

仓库测试 src/tests/tests_encryption.cpp 与 src/tests/tests_encryption_expire.cpp 覆盖了:启用加密、写入/重载/重启后解密读取、禁用加密时要求密码、密码过期周期等场景。命令行层面可用copyq config encrypt_tabs true/false直接开关该配置(测试代码RUN("config" << "encrypt_tabs" << "true", ...)即此用法)。

四、遗留加密插件(Legacy Encryption Plugin)

自 14.0.0 起该插件已被官方标记为deprecated(已弃用)。仅推荐两类用户使用:需要逐条目加密,或运行 CopyQ14.0.0 之前旧版本

官方同时给出两条明确警告:

  • 插件依赖GnuPG(gpg2,引入外部密钥管理复杂性与版本兼容问题;
  • 密码必须每隔几分钟重新输入一次,使用体验较差。

4.1 安装插件与 GnuPG

Configuration 对话框的 "Items" 配置页中启用Encryptionitem 插件(仓库实现见 plugins/itemencrypted/itemencrypted.cpp,插件 ID 为itemencrypted,名称 "Encryption")。

若系统未安装 GnuPG,插件配置页会提示先安装:

  • Windows:可用 Chocolatey 安装 Gpg4win:

    choco install gpg4win
  • Linux:安装gpg命令行工具,一般由gnupg软件包提供(个别发行版包名不同)。

从源码看,插件会依次探测gpg2gpg可执行文件,并要求主版本号 ≥ 2(GpgExecutable构造与findGpgExecutable(),见 plugins/itemencrypted/itemencrypted.cpp);若检测不到 GnuPG,插件状态为GpgNotInstalled,加密标签页将无法加载(loadItems中会提示 "GnuPG must be installed to view encrypted tabs.")。

4.2 生成密钥与设置密码

加密标签页与条目前,必须先生成 GnuPG 公私钥文件。在插件配置页点击"Generate New Keys..."按钮并等待——源码中该操作通过gpg --batch --gen-key生成RSA 4096 位、仅用于加密(Key-Usage: encrypt)的密钥,真实姓名固定为copyq(见startGenerateKeysProcess,plugins/itemencrypted/itemencrypted.cpp),密钥环文件存放在 CopyQ 配置目录下。

密钥生成后,若尚未设置密码,点击"Change Password..."按钮完成设置:

最后一步在插件配置中填入要加密的标签页名列表(每行一个,与标签页名精确匹配;支持&助记键与/路径写法,匹配逻辑见canSaveItems(),plugins/itemencrypted/itemencrypted.cpp)。若只想逐条目加密,可跳过此步。

点击"OK"确认关闭 Configuration 对话框即可生效。

4.3 保护整个标签页

  1. Ctrl+T新建标签页;
  2. 标签页名称必须与插件配置中填写的名称之一完全一致
  3. 该标签页的数据在保存时会经gpg --encrypt加密(文件头为CopyQ_encrypted_tab v2,见ItemEncryptedSaver::saveItems(),plugins/itemencrypted/itemencrypted.cpp)。

此后打开该标签页会提示输入密码(无需每次都输,间隔一段时间才要求一次)。若输错密码或取消了密码提示,可点击标签页上的"Reload(重新加载)"按钮再次输入密码:

4.4 保护单个条目

在不加密的标签页中,可添加带快捷键的菜单/工具栏动作实现单条目加密:

  1. 打开Command 对话框(F6)
  2. 点击"Add(添加)",从列表中选择Encryption类命令,用"OK"确认关闭对话框。

插件向命令系统注册了 4 个内置命令(见commands(),plugins/itemencrypted/itemencrypted.cpp):

命令菜单路径快捷键底层脚本
Encrypt(需要 GnuPG)Items — Encryption — EncryptCtrl+Lplugins.itemencrypted.encryptItems()
DecryptItems — Encryption — DecryptCtrl+Lplugins.itemencrypted.decryptItems()
Decrypt and CopyItems — Encryption — Decrypt and CopyCtrl+Shift+Lplugins.itemencrypted.copyEncryptedItems()
Decrypt and PasteItems — Encryption — Decrypt and PasteEnterplugins.itemencrypted.pasteEncryptedItems()

加密时,选中条目中所有非 CopyQ 内部格式(不以application/x-copyq-前缀开头)的数据被pack序列化后经 GnuPG 加密,以application/x-copyq-encrypted格式(源码常量mimeEncryptedData)存储;解密时反向unpack还原(见encryptItem/decryptItem/encryptItems/decryptItems,plugins/itemencrypted/itemencrypted.cpp)。加密条目在界面上以挂锁图标标识(ItemEncrypted控件显示IconLock)。

4.5 密钥文件与跨机器共享

插件配置页会提示:若要在其他电脑或会话中共享加密条目,需要保留密钥环文件(存放于 CopyQ 配置目录)。gpg 2.1 以下版本需要同时保存公钥环与私钥环(.pub/.sec);gpg 2.1 及以上仅需公钥环文件。源码通过--export-secret-key导出私钥并以属主可读写权限落盘(见exportGpgKey(),plugins/itemencrypted/itemencrypted.cpp)。请务必妥善保管这些文件。

五、常见问题与最佳实践

  1. 新旧方案如何选?运行 14.0.0 及以上版本、加密目标是"全部剪贴板历史"时,一律使用内置加密;只有需要"单条目选择性加密"才考虑遗留插件。
  2. 密码忘记了怎么办?内置加密的密钥文件(wrapped_dek.dat/kek_salt.dat)被 KEK 包裹,丢失密码即丢失 DEK,加密数据无法恢复——请务必保管好密码,或依赖外部密钥库(use_key_store)。
  3. 导出的数据默认是明文:脚本exportTab/exportData永远输出未加密文件;GUI 导出可自愿设置导出密码,请根据数据敏感度自行决定。
  4. 自动化场景:可通过环境变量COPYQ_PASSWORD在无人值守环境下提供密码(内置加密),或用命令行copyq config encrypt_tabs true/false管理开关。
  5. 备份加密数据:直接复制数据/配置目录即可完成备份,但备份与恢复前务必完全退出 CopyQ(见 docs/backup.rst)。

六、参考资源

  • 官方文档原文:docs/password-protection.rst
  • 备份与导出说明:docs/backup.rst
  • 内置加密核心实现:src/common/encryption.cpp、src/common/encryption.h
  • 密码提示与密钥库逻辑:src/gui/encryptionpassword.cpp、src/common/keychainaccess.cpp
  • 配置项定义:src/common/appconfig.h
  • 遗留加密插件:plugins/itemencrypted/itemencrypted.cpp、plugins/itemencrypted/itemencrypted.h
  • 加密相关测试:src/tests/tests_encryption.cpp、src/tests/tests_encryption_expire.cpp
  • 桌面应用

【免费下载链接】CopyQ

Clipboard manager with advanced features

项目地址:https://gitcode.com/gh_mirrors/co/CopyQ
点击查看免费下载

相关推荐

上一篇:EspoCRM企业级开源CRM系统架构深度解析与实战部署指南
下一篇:攻克React认证难题:Redux-Auth-Wrapper 3.x全攻略

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询