仓库地址:gpg_awesome_keyid
我的 keyid:0x699a698e77777777
原理
根据 rfc4880 的 pgp keyid 的计算方式我们可以得知,修改 key 的创建时间我们即可以达到快速修改 keyid 的目的。
12.2. Key IDs and Fingerprints
...
a.3) low-order length octet of (b)-(e) (1 octet)
b) version number = 4 (1 octet);
c) timestamp of key creation (4 octets);
...
使用如下代码进行快速计算 key
// src/actions.js@do_generate
let prikey = null;
let start = new Date();
for(let index = 0; ; index++) {
if(0 === index % 10000) {
// 每 1 万次之后重新生成 key,防止创建时间过于小
prikey = await gen_basic_key();
// ...
}
// 修改 key 的创建时间并重新计算指纹(时间精度为秒)
// ! 需要注意的是,此时的 key 的 subkey 和 uid 的签名都是需要修正的,是原始指纹的 key 的签名
prikey.keyPacket.created = new Date(prikey.keyPacket.created.getTime() - 1000);
let r = {
// 因为修改了创建时间但是并未重新计算 private key 的指纹,但获取公钥时会重新计算公钥指纹,达到计算指纹的目的
fpr: prikey.toPublic().getFingerprint(),
// key 需要修正,加密子钥和 uid 的签名都是使用的旧 id 进行签名的,import 过程通过 openpgp.reformat 修正
key: prikey.armor()
};
// ...
}
计算速度
测试环境
- os: gentoo linux
- kernel: 5.4.97
- cpu: Intel i5-5200U (4) @ 2.700GHz
- node: v14.16.1
- npm: 6.14.12
计算速度
> node . start
...
[.../gpg_awesome_keyid/dbs/key2.db] 耗时 57.582 秒,已计算 key250000 个,数据库中已保存 6 个 key
[.../gpg_awesome_keyid/dbs/key3.db] 耗时 58.054 秒,已计算 key250000 个,数据库中已保存 6 个 key
[.../gpg_awesome_keyid/dbs/key1.db] 耗时 58.213 秒,已计算 key250000 个,数据库中已保存 8 个 key
[.../gpg_awesome_keyid/dbs/key0.db] 耗时 58.85 秒,已计算 key250000 个,数据库中已保存 5 个 key
预计 8 连 keyid 时间
每分钟 100w 数据
任意 8 连概率大约 0xFFFFFFFF/16 ( 16 种可能)
通过计算:0xFFFFFFFF / 16 / 1000000 / 60 ≈ 4.47 小时
使用
安装
git clone https://github.com/erriy/gpg_awesome_keyid.git \
&& cd gpg_awesome_keyid \
&& npm i
自定义靓号规则
// src/rule.js 文件中
// notify 和 save 函数任意一个返回 true 则保存,否则直接丢弃
/**
* 返回 true 则保存数据库后并发送通知
*/
function notify (fingerprint) {
// 默认提醒后八位相同的 key
return 1 === new Set(fingerprint.slice(32)).size;
}
/**
* 返回 true 则保存到数据库
*/
function save (fingerprint) {
const special_list = [
'01234567',
'76543210',
'abcdef',
'01020304',
'11223344',
];
if(
new Set(fingerprint.slice(35)).size === 1
|| new Set(fingerprint.slice(32)).size <= 2
|| new Set(fingerprint.slice(24)).size <= 3
|| new Set(fingerprint).size <= 4
) {
return true;
}
for(let s of special_list) {
if(fingerprint.endsWith(s)){
return true;
}
}
return false;
}
修改 gpg 使用的算法
// src/action.js@gen_basic_key
// 推荐使用 ecc 算法,生成的公钥更小且计算速度更快
async function gen_basic_key () {
const { privateKeyArmored } = await openpgp.generateKey({
// 如果要修改算法,请自己去 https://github.com/openpgpjs/openpgpjs#performance 里面找
type : 'ecc',
curve : 'curve25519',
userIDs: [{name: 't'}] // userid 在导入时会重新生成,此处修改没有意义
});
return await openpgp.readKey({ armoredKey: privateKeyArmored });
}
开始算号
# 直接开始算号
node . start
# 开始算号,发现帐号后发送 bark 通知
node . start --barkid xxxxxx
查找保存的数据
# 列出所有数据
node . list
# 列出指定后缀的数据
# node . list [suffix]
# 比如列出以 fffff 结尾的 key
node . list fffff
保存结果
注意:导入的 key 并未设置密码,请自行使用命令设置密码,数据库中存在明文 key,记得删除,防止泄漏
# 保存以 fffff 结尾的 key
node . import fffff
# 保存以 fffff 结尾的 key 并指定 uid.name 和 uid.email
node . import fffff -n name -email [email protected]
其他更快速的方法
- scallion : 速度很快,但是只支持 rsa 算法,后 9 位 9 连大概在一分钟以内就能挖出,挖出的 key 无 uid,可以通过 openpgp.reformat 增加 uid 后再给 gpg 使用