密钥环
简单加密并带有Node.js的密钥旋转支持.

注: 密钥环 实值 没有 用于加密密码,请使用 类似的东西 微声它的本意为 在纯文本中加密您需要访问的敏感数据( 例如存储) 用户的OAuth令牌). 密码不属于这一类别.
此软件包完全独立于任何存储机制;目标是 提供几种易于与任何ORM相融合的功能. 与 但是,这个软件包会捆绑一个与 排序。 。 。 .
安装
在您的软件包中添加 package.json 使用雅恩语.
yarn add -E @fnando/keyring
使用量
加密
默认情况下,AES-128-CBC是用于加密的算法. 此算法 使用 16 字节键,但需要使用比大小多一倍的键 因为其中一半的密钥将被用于生成 HMAC 。 前16个字节 将用作加密密钥,最后16个字节将用于 生成 HMAC.
使用随机数据库64-编码是推荐的方法. 很容易生成 使用下列命令键:
$ dd if=/dev/urandom bs=32 count=1 2>/dev/null | openssl base64 -A
qUjOJFgZsZbTICsN0TMkKqUvSgObYxnkHDsazTqE5tM=
在 value 关键说明的章节
在键盘。 一半用于加密,一半用于HMAC.
密钥大小
密钥大小取决于使用的算法. 键大小应该双倍 用于 HMAC 计算.
aes-128-cbc: 16字节(加密)+16字节(HMAC).aes-192-cbc: 24字节(加密)+24字节(HMAC).aes-256-cbc: 32 字节(加密)+ 32 字节(HMAC).
关于加密信件
初始化矢量(IV)应当是不可预测的和独特的;理想的情况是: 将按密码随机排列。 它们不必是秘密的:IV是 通常只是添加到未加密的密码文本中。 可能听起来 矛盾的是,有些东西必须是不可预料和独特的,但并不 必须保密;必须记住攻击者必须不能 提前预测给定的IV是什么.
考虑到这一点, 密钥环 用途
base64(hmac(unencrypted iv + encrypted message) + unencrypted iv + encrypted message)
作为最后的信息。 如果你打算从其他加密中迁移出去
不使用 密钥环, (中文(简体) ),
确保你对此负责。 HMAC长32字节,IV长16字节
长.
密钥环
密钥是通过一个 keyring - a short JSON 文件来管理 加密密钥. 密钥环必须是 JSON 对象映射 键入键值。 密钥环必须至少有一把钥匙. 例如:
{
"1": "uDiMcWVNTuz//naQ88sOcN+E40CyBRGzGTT7OkoBS6M=",
"2": "VN8UXRVMNbIh9FWEFVde0q7GUA1SGOie1+FgAKlNYHc="
}
这个 id 用于跟踪哪个密钥加密了哪个数据; 带有
更大的id被认为是更新的。 值为
加密密钥.
密钥旋转
与 密钥环 您可以同时拥有多个加密密钥和密钥旋转 相当直截了当:如果您在 密钥环 具有较高编号 相对于任何其他密钥,当 对象或创建或更新。 不再使用的密钥可以是 安全离开 密钥环。 。 。 .
你一定要把钥匙环的ID保存下来 encrypt()· ;
否则,您可能无法解密值( 您总是可以解密值)
如果你仍然拥有 全部 加密密钥).
如果你在用的话 密钥环 要加密数据库列,建议使用 分离 密钥环 您计划加密的每个表格: 在您需要时(例如密钥泄漏),可以更容易地旋转密钥.
注意:这些例子上的密钥是硬编码的,但是你不应该用你的密码 基础。 你可以拿回来 密钥环 从环境变量,如果你正在部署 改为 赫鲁库 或部署一个JSON文件 配置管理软件(如Ansible,Pupet,Chef等).
键盘的基本使用
import { keyring } from "@fnando/keyring";
const keys = { 1: "uDiMcWVNTuz//naQ88sOcN+E40CyBRGzGTT7OkoBS6M=" };
const encryptor = keyring(keys, { digestSalt: "<custom salt>" });
// STEP 1: Encrypt message using latest encryption key.
const [encrypted, keyringId, digest] = encryptor.encrypt("super secret");
console.log(`🔒 ${encrypted}`);
console.log(`🔑 ${keyringId}`);
console.log(`🔎 ${digest}`);
//=> 🔒 Vco48O95YC4jqj44MheY8zFO2NLMPp/KILiUGbKxHvAwLd2/AN+zUG650CJzogttqnF1cGMFb//Idg4+bXoRMQ==
//=> 🔑 1
//=> 🔎 e24fe0dea7f9abe8cbb192702578715079689a3e
// STEP 2: Decrypted message using encryption key defined by keyring id.
const decrypted = encryptor.decrypt(encrypted, keyringId);
console.log(`✉️ ${decrypted}`);
//=> ✉️ super secret
更改加密算法
您可以在 AES-128-CBC, (中文(简体) ), AES-192-CBC 财务报告和审定财务报表 AES-256-CBC。通过
默认, AES-128-CBC 将被使用.
要指定加密算法,请设置 encryption 选项。 以下内容:
示例使用 AES-256-CBC。 。 。 .
import { keyring } from "@fnando/keyring";
const keys = { 1: "uDiMcWVNTuz//naQ88sOcN+E40CyBRGzGTT7OkoBS6M=" };
const encryptor = keyring(keys, {
encryption: "aes-256-cbc",
digestSalt: "<custom salt>",
});
使用序列
如果你使用序列, 你可能不想手动处理
加密如上. 考虑到这一点, keyring 带有小插件的船舶
减轻手动处理属性加密/解密的所有痛苦,因为
还有钥匙旋转和消化.
首先,你必须装入一个设置模型的不同文件.
const Sequelize = require("sequelize");
const sequelize = new Sequelize("postgres:///test", { logging: false });
const Keyring = require("@fnando/keyring/sequelize");
const User = await sequelize.define(
"users",
{
id: {
type: Sequelize.UUIDV4,
primaryKey: true,
allowNull: false,
defaultValue: Sequelize.UUIDV4,
},
// This column is required and will store the
// keyring id (which encryption key was used).
keyring_id: Sequelize.INTEGER,
// All encrypted columns must be prefixed with `encrypted_`.
// Optionally, you may have a `<attribute>_digest` column,
// will store a SHA1 digest from the value, making
// unique indexing and searching easier.
// Finally, notice that you're responsible for defining
// a VIRTUAL property for all columns you're encrypting.
encrypted_email: Sequelize.TEXT,
email_digest: Sequelize.TEXT,
email: Sequelize.VIRTUAL,
},
{ timestamps: false },
);
// Retrieve encryption keys from `USER_KEYRING` environment variable.
// It's recommended that you use one keyring for each model, to make
// a rollout easier (e.g. an encryption key leaked).
//
// ```js
// const keys = JSON.parse(process.env.USER_KEYRING);
// ```
//
// Alternatively, you can load a JSON file deployed by some config management software like Ansible, Chef or Puppet.
//
// ```js
// const fs = require("fs");
// const keys = JSON.parse(fs.readFileSync("user_keyring.json"));
// ```
//
// For the purposes of this example, we're going to set keys manually.
// WARNING: DON'T EVER DO THAT FOR REAL APPS.
const keys = { 1: "uDiMcWVNTuz//naQ88sOcN+E40CyBRGzGTT7OkoBS6M=" };
// This is the step you set up your model with hooks to encrypt/decrypt
// columns. You can specify the encryption keys, which columns are going
// to be encrypted, how the column will be encrypted and the name of the
// keyring id column. You can see below the default values for `encryption`
// and keyring id column.
Keyring(User, {
keys, // [required]
columns: ["email"], // [required]
digestSalt: "<custom salt>", // [required]
keyringIdColumn: "keyring_id", // [optional]
encryption: "aes-128-cbc", // [optional]
});
(async () => {
// Now you can create records, like you usually do.
const user = await User.create({ email: "[email protected]" });
console.log(JSON.stringify(user, null, 2));
// Let's update the email address.
await user.update({ email: "[email protected]" });
console.log(JSON.stringify(user, null, 2));
// Now let's pretend that you set USER_KEYRING env var to a
// {1: old_key, 2: new_key} or rollout a new JSON file via your
// config management software, and restarted the app.
keys[2] = "VN8UXRVMNbIh9FWEFVde0q7GUA1SGOie1+FgAKlNYHc=";
// To simply roll out a new encryption, just call `.save()`.
// This will trigger a `beforeSave` hook, which will re-encrypt
// all properties again.
await user.save();
console.log(JSON.stringify(user, null, 2));
// Attributes are also re-encrypted when you call `.update()`.
await user.update({ email: "[email protected]" });
console.log(JSON.stringify(user, null, 2));
})();
查询
加密的一个棘手方面是 查查已知的秘密记录 要解决 您可以为加密的字符串生成 SHA1 摘要 保存到数据库中.
keyring 检测是否存在 <attribute>_digest 列并更新
因此,SHA1摘要可用于独特的索引编制或
寻找。 你不必用散热盐,但很受推荐;
这样可以避免用户信息通过彩虹表被泄露.
// A utility function to generate SHA1s out of strings.
const { sha1 } = require("@fnando/keyring");
await User.create({ email: "[email protected]" });
const user = await User.findOne({
where: {
email_digest: sha1("[email protected]", { digestSalt: "<custom salt>" }),
},
});
与Ruby交换数据
如果你用鲁比,你可能会有兴趣 https://github.com/fnando/atr keyring 互联网档案馆的存檔,存档日期2013-12-21,它能够读写 使用相同的格式发送信件.
发展
检查后,运行 yarn install 以安装依赖。 接下来,
运行 yarn test 进行测试.
捐款
GitHub 上欢迎错误报告和拉取请求 https://github.com/fnando/ keyring-node 互联网档案馆的存檔,存档日期2014-12-02这个项目旨在成为一个安全, 欢迎合作空间,预计捐助方将遵守 页:1 《促进者公约》 行为守则.
许可证
该宝石作为公开源码,按照以下规定提供: MIT 许可证。 。 。 .
图标
行为守则
每个人都在互动 密钥环 项目的代码库, 问题跟踪器, 聊天室和邮件列表 行为守则。 。 。 .