sodium_crypto_pwhash

(PHP 7 >= 7.2.0, PHP 8)

sodium_crypto_pwhash使用 Argon2 从密码派生密钥

描述

sodium_crypto_pwhash(
    int $length,
    string $password,
    string $salt,
    int $opslimit,
    int $memlimit,
    int $algo = SODIUM_CRYPTO_PWHASH_ALG_DEFAULT
): string

此函数提供对 libsodium 的 crypto_pwhash 密钥派生函数的低级访问。除非你有特定原因使用此函数,否则你应该使用 sodium_crypto_pwhash_str()password_hash() 函数。

使用此特定函数的一个常见原因是从密码和盐派生加密密钥的种子,然后使用这些种子生成某些用途所需的实际密钥(例如,sodium_crypto_sign_detached())。

参数

length

int; 要生成的密码散列的长度,以字节为单位。

password

string; 要生成散列的密码。

salt

在散列之前添加到密码的盐。盐应该是不可预测的,理想情况下应该从良好的随机数源(例如 random_bytes())生成,并且长度正好为 SODIUM_CRYPTO_PWHASH_SALTBYTES 字节。

opslimit

表示要执行的最大计算量。增加此数字将使函数需要更多 CPU 周期来计算密钥。有一些常量可用于根据预期用途将操作限制设置为适当的值,按强度排序:SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVESODIUM_CRYPTO_PWHASH_OPSLIMIT_MODERATESODIUM_CRYPTO_PWHASH_OPSLIMIT_SENSITIVE

memlimit

函数将使用的最大 RAM 量,以字节为单位。有一些常量可以帮助你选择适当的值,按大小排序:SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVESODIUM_CRYPTO_PWHASH_MEMLIMIT_MODERATESODIUM_CRYPTO_PWHASH_MEMLIMIT_SENSITIVE。通常这些应该与匹配的 opslimit 值配对。

algo

int 表示要使用的哈希算法的数字。默认情况下为 SODIUM_CRYPTO_PWHASH_ALG_DEFAULT(当前推荐的算法,可能会在 libsodium 的不同版本之间发生变化),或者明确使用 SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13,表示 Argon2id 算法版本 1.3。

返回值

返回派生的密钥。返回值是散列的二进制字符串,而不是 ASCII 编码的表示形式,并且不包含有关用于创建散列的参数的额外信息,因此如果你将来要验证密码,则需要保留这些信息。使用 sodium_crypto_pwhash_str() 以避免需要执行所有这些操作。

示例

示例 #1 sodium_crypto_pwhash() 示例

<?php
//需要保留盐,如果我们将来要检查此密码
$salt = random_bytes(SODIUM_CRYPTO_PWHASH_SALTBYTES);
//使用 bin2hex 使输出可读
echo bin2hex(
sodium_crypto_pwhash(
16, // == 128 位
'password',
$salt,
SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE,
SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE,
SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13
)
);
?>

上面的示例将输出类似于以下内容

a18f346ba57992eb7e4ae6abf3fd30ee

添加说明

用户贡献说明 1 说明

-10
craig at craigfrancis dot co dot uk
4 年前
在加密时,你理想情况下应该使用随机生成的密钥,因为这要难猜得多。

例如,sodium_crypto_aead_chacha20poly1305_ietf_keygen()

但如果你需要使用密码来加密/解密,则可以使用 sodium_crypto_pwhash()

<?php

function secrets_encrypt($password, $secret) {

$config = [
'size' => SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_KEYBYTES,
'salt' => random_bytes(SODIUM_CRYPTO_PWHASH_SALTBYTES),
'limit_ops' => SODIUM_CRYPTO_PWHASH_OPSLIMIT_SENSITIVE,
'limit_mem' => SODIUM_CRYPTO_PWHASH_MEMLIMIT_SENSITIVE,
'alg' => SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13,
'nonce' => random_bytes(SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_NPUBBYTES),
];

// $config['limit_ops'] = SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE;
// $config['limit_mem'] = SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE;

$key = sodium_crypto_pwhash(
$config['size'],
$password,
$config['salt'],
$config['limit_ops'],
$config['limit_mem'],
$config['alg'],
);

$encrypted = sodium_crypto_aead_chacha20poly1305_ietf_encrypt(
$secret,
$config['nonce'], // Associated Data
$config['nonce'],
$key
);

return [
'config' => array_map('base64_encode', $config),
'encrypted' => base64_encode($encrypted),
];

}

$password = 'YoxPR4QLeZ';
$secret = 'This-is-my-secret';

$data = secrets_encrypt($password, $secret);

?>

使用相同限制,使用该密码解密

<?php

function secrets_decrypt($password, $data) {

$config = array_map('base64_decode', $data['config']);
$encrypted = base64_decode($data['encrypted']);

$key = sodium_crypto_pwhash(
$config['size'],
$password,
$config['salt'],
$config['limit_ops'],
$config['limit_mem'],
$config['alg'],
);

return
sodium_crypto_aead_chacha20poly1305_ietf_decrypt(
$encrypted,
$config['nonce'], // Associated Data
$config['nonce'],
$key
);

}

$secret = secrets_decrypt($password, $data);

?>
To Top