EVP_KDF-SCRYPT
名稱
EVP_KDF-SCRYPT - scrypt EVP_KDF 實作
說明
透過 EVP_KDF API 支援計算 scrypt 基於密碼的 KDF。
EVP_KDF-SCRYPT 演算法實作 scrypt 基於密碼的密鑰衍生函數,如 RFC 7914 所述。它在記憶體方面很耗費,因為它刻意需要大量的 RAM 才能有效運算。這樣做的目的是讓缺乏大量主記憶體(例如 GPU 或 ASIC)的系統無法暴力破解密碼。
scrypt 提供三個可自訂的工作因子:N、r 和 p。N 必須是 2 的正次方,是通用的工作因子,並以近似線性方式調整 CPU 時間。r 是內部使用的雜湊函數的區塊大小,而 p 是並行化因子。r 和 p 都必須大於 0。scrypt 運算所需的 RAM 量大約是 (128 * N * r * p) 位元組。
在 Colin Percival 的原始論文(「透過順序記憶體耗費函數強化密鑰衍生」,2009 年)中,建議的值在 2.5 GHz Intel Core 2 Duo 上的運算時間不到 5 秒,為 N = 2^20 = 1048576、r = 8、p = 1。因此,此運算所需的記憶體量大約是 1 GiB。在較新的 CPU(3.5 GHz 的 Intel i7-5930K)上,此運算大約需要 3 秒。如果未指定 N、r 或 p,它們的預設值分別為 1048576、8 和 1。scrypt 可能使用的最大 RAM 量預設為 1025 MiB。
識別
「SCRYPT」是此實作的名稱;它可用於 EVP_KDF_fetch() 函數。
支援的參數
支援的參數為
- 「pass」 (OSSL_KDF_PARAM_PASSWORD) <八位元組字串>
- 「salt」 (OSSL_KDF_PARAM_SALT) <八位元組字串>
-
這些參數的運作方式如 EVP_KDF(3) 中的「參數」 所述。
- "n" (OSSL_KDF_PARAM_SCRYPT_N) <未簽署整數>
- "r" (OSSL_KDF_PARAM_SCRYPT_R) <未簽署整數>
- "p" (OSSL_KDF_PARAM_SCRYPT_P) <未簽署整數>
- "maxmem_bytes" (OSSL_KDF_PARAM_SCRYPT_MAXMEM) <未簽署整數>
-
這些參數設定 scrypt 工作因子 N、r、maxmem 和 p。N 和 maxmem_bytes 都是類型為 uint64_t 的參數。r 和 p 都是類型為 uint32_t 的參數。
- "properties" (OSSL_KDF_PARAM_PROPERTIES) <UTF8 字串>
-
在內部擷取固定摘要時,這可設定屬性查詢字串。如果未設定此值,則使用 NULL。
備註
可透過呼叫取得 scrypt 的內容
EVP_KDF *kdf = EVP_KDF_fetch(NULL, "SCRYPT", NULL);
EVP_KDF_CTX *kctx = EVP_KDF_CTX_new(kdf);
scrypt 金鑰衍生的輸出長度是透過 EVP_KDF_derive(3) 函式的 "keylen" 參數指定的。
範例
此範例使用 scrypt 衍生 64 位元組長的測試向量,密碼為 "password",鹽為 "NaCl",且 N = 1024、r = 8、p = 16。
EVP_KDF *kdf;
EVP_KDF_CTX *kctx;
unsigned char out[64];
OSSL_PARAM params[6], *p = params;
kdf = EVP_KDF_fetch(NULL, "SCRYPT", NULL);
kctx = EVP_KDF_CTX_new(kdf);
EVP_KDF_free(kdf);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PASSWORD,
"password", (size_t)8);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
"NaCl", (size_t)4);
*p++ = OSSL_PARAM_construct_uint64(OSSL_KDF_PARAM_SCRYPT_N, (uint64_t)1024);
*p++ = OSSL_PARAM_construct_uint32(OSSL_KDF_PARAM_SCRYPT_R, (uint32_t)8);
*p++ = OSSL_PARAM_construct_uint32(OSSL_KDF_PARAM_SCRYPT_P, (uint32_t)16);
*p = OSSL_PARAM_construct_end();
if (EVP_KDF_derive(kctx, out, sizeof(out), params) <= 0) {
error("EVP_KDF_derive");
}
{
const unsigned char expected[sizeof(out)] = {
0xfd, 0xba, 0xbe, 0x1c, 0x9d, 0x34, 0x72, 0x00,
0x78, 0x56, 0xe7, 0x19, 0x0d, 0x01, 0xe9, 0xfe,
0x7c, 0x6a, 0xd7, 0xcb, 0xc8, 0x23, 0x78, 0x30,
0xe7, 0x73, 0x76, 0x63, 0x4b, 0x37, 0x31, 0x62,
0x2e, 0xaf, 0x30, 0xd9, 0x2e, 0x22, 0xa3, 0x88,
0x6f, 0xf1, 0x09, 0x27, 0x9d, 0x98, 0x30, 0xda,
0xc7, 0x27, 0xaf, 0xb9, 0x4a, 0x83, 0xee, 0x6d,
0x83, 0x60, 0xcb, 0xdf, 0xa2, 0xcc, 0x06, 0x40
};
assert(!memcmp(out, expected, sizeof(out)));
}
EVP_KDF_CTX_free(kctx);
符合
RFC 7914
另請參閱
EVP_KDF(3)、EVP_KDF_CTX_new(3)、EVP_KDF_CTX_free(3)、EVP_KDF_CTX_set_params(3)、EVP_KDF_derive(3)、EVP_KDF(3) 中的 "PARAMETERS"
歷程
此功能於 OpenSSL 3.0 中新增。
版權
Copyright 2017-2021 The OpenSSL Project Authors。保留所有權利。
根據 Apache 授權條款 2.0 版(「授權條款」)授權。您不得使用此檔案,除非符合授權條款。您可以在原始程式碼散佈中的 LICENSE 檔案或 https://www.openssl.org/source/license.html 取得副本。