OpenSSL

密碼學和 SSL/TLS 工具箱

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 取得副本。