ircmaxell / ballandchain
Ball And Chain的PHP实现
Requires
- php: >=5.5
- cilex/cilex: 1.*
- indigophp/hash-compat: ^1.1@dev
- paragonie/random_compat: dev-master
Requires (Dev)
- fabpot/php-cs-fixer: 1.*
- phpunit/phpunit: ^4.7
This package is auto-updated.
Last update: 2024-09-20 01:38:05 UTC
README
这是BallAndChain的PHP实现。
算法中唯一的区别如下
- 由于PHP中可用,使用SHA-2而不是SHA-3
- 使用一个结合的哈希格式,该格式使用版本标识符编码设置
生成种子文件
首先,您需要生成一个"种子文件"。这是一个大型的随机文件,是安全的基础。
理想情况下,您希望尽可能使此文件变得很大(10GB应该是最低限度)。如果能达到1TB则更好。10TB更好!
生成此文件有三个选项。您可以使用dd
自行生成
# Our target is 10 * 2**30 or 10GB. For 100GB change to 100 * 2**30
$ dd if=/dev/urandom of=/path/to/file bs=$((64 * 2**20)) count=$(((10 * 2**30) / (64 * 2**20)))
您可以使用openssl
$ openssl rand -out /path/to/file $((10 * 2**30))
或者您可以使用ballandchain工具生成(最慢的方法)
$ bin/ballandchain build 10G /path/to/file
用法
要使用,通过将文件传递给构造函数来创建一个新的Hash
实例
$hash = new BallAndChain\Hash('/path/to/file');
然后,为了哈希一个新的密码
$hashed = $hash->create($password);
最后,为了验证
if ($hash->verify($password, $hashed)) {
// Success!
}
就这么简单!
输出大小
输出将根据您提供的设置而变化。使用10GB文件,并使用默认设置,输出将为124字节(字符)宽。
输出大小可能会根据文件大小和指定的轮数而变得相当大。
选项
您可以将一些选项传递给->create()
-
轮数
这是在构建哈希时查找的数据指针的数量。它以2的幂表示。最小值是
2
(结果使用4个指针)。任意最大值是62(最大64位有符号整数2的幂)。默认值是3,使用8个指针。实际上,大于10的值将毫无用处,因为生成的哈希大小将急剧增加(每次增加2倍)。
增加此数字将提供暴力破解保护,因为它加倍了哈希密码所需的I/O操作次数。如果种子文件泄露给攻击者,这可以提供额外的保护。
-
指针大小
这是要生成的指针的大小。默认值将检测访问整个文件所需的最小指针(255字节文件将使用1字节的指针大小,10GB文件将使用5字节)。
您可以覆盖默认值,但请注意,设置过短的大小将引发错误。
-
数据大小
这是从每个指针位置提取的2的幂次的数据量。默认值是4(16字节)。增加此值不会增加结果的输出大小。
增加此数字将提供暴力破解保护,因为它增加了哈希操作中消耗的I/O带宽。
工作原理
- 使用SHA-256对密码进行哈希,以创建密钥。
- 每一轮生成一个随机指针
- 在文件中查找每个随机指针,并将其读入数据数组。
- 将收集的所有数据点使用SHA-256进行哈希
- 使用密钥加密指针和哈希后的数据点。
伪代码
function hash(password) {
key = sha256(password)
pointers = ''
data = ''
for (round in rounds) {
pointer = random_pointer()
pointers = pointers + pointer
data = data + read(pointer)
}
iv = random_iv()
return encrypt(key, iv, pointers + sha256(data))
}
为了验证密码,您需要解密密文以获取指针列表。然后您可以通过查找指针来重建数据数组,并最终验证数据的哈希与加密数据的哈希是否匹配。
观看上面的视频。这很值得。
最佳设置
理想情况下,您应该使用尽可能大的文件。10TB是理想的。您希望文件足够大,以至于攻击者无法复制它。
除了使文件很大外,您还可以限制具有文件的服务器的带宽。这会引入更多潜在的安全漏洞,但这可能是一个有效的选项。
如果您的文件非常大,默认设置应该足够。如果我们假设攻击者无法下载文件,那么rounds=3和dataSize=4是足够的。
然而,如果有文件下载的风险,我们可以增加这两个参数以提供额外的暴力破解保护。
增加rounds将增加攻击者对每个哈希所需的I/O操作次数。增加dataSize将增加攻击者对每个哈希所需的I/O吞吐量压力。
为了了解它们之间的关系,让我们选择rounds=8和dataSize=13,看看会发生什么
-
攻击者需要对每个哈希进行256次读取操作。在现代SSD上,这将将其限制在大约每秒400个哈希。这是因为当前最快的SSD可以每秒进行大约100,000次随机的4KB块读取。
-
攻击者需要为每个读取操作读取8192字节。由于8192字节需要2个块读取,我们预计每秒大约有200个哈希。
结合这两者,我们预计攻击者每秒大约有200个哈希。这相当不错。然而,如果我们降低dataSize到12,攻击者可以将每秒的哈希数量翻倍。作为一个经验法则,在12以下的数据大小,大小对哈希率没有影响。在12以上,每增加一步,哈希率将减半。因此,我们预计14将大约是每秒100个哈希。
如果攻击者可以将种子文件放入主内存,事情会有所改变。如果我们只看带宽限制(而不是IOPS限制),那么我们预计每个内存模块大约有10GB/s。这意味着使用我们之前的设置,我们预计大约有130万个哈希每秒(请注意这是一个上限,并假设没有随机多次块读取的开销)。这比简单的SHA-1要少得多,但对于舒适度来说仍然太高。这就是为什么使文件大和保护文件极其重要的原因。