Derives a key of any length from a password using the SCRYPT algorithm.
Public Declare Function PBE_Scrypt Lib "diCrPKI.dll" (ByRef lpDerivedKey As Byte, ByVal nKeyLen As Long, ByRef lpPwd As Byte, ByVal nPwdLen As Long, ByRef lpSalt As Byte, ByVal nSaltLen As Long, ByVal nParamN As Long, ByVal nParamR As Long, ByVal nParamP As Long, ByVal nOptions As Long) As Long
nRet = PBE_Scrypt(abDerivedKey(0), nKeyLen, abPwd(0), nPwdLen, abSalt(0), nSaltLen, nParamN, nParamR, nParamP, nOptions)
' Note the "(0)" after the byte array parameters
long __stdcall PBE_Scrypt(unsigned char *lpDerivedKey, long nKeyLen, const unsigned char *lpPwd, long nPwdLen, const unsigned char *lpSalt, long nSaltLen, long nParamN, long nParamR, long nParamP, long nOptions);
"costParameter"
) a number greater than one and a power of 2."blockSize"
)"parallelizationParameter"
)If successful, the return value is 0; otherwise it returns a non-zero error code.
Public Function pbeScrypt
(dkBytes As Long, lpPwd() As Byte, lpSalt() As Byte, nParamN As Long, nParamR As Long, nParamP As Long, Optional nOptions As Long = 0) As Byte()
Pbe.Scrypt Method (Int32, Byte[], Byte[], Int32, Int32, Int32)
static bvec_t dipki::Pbe::Scrypt (int dklen, const std::string password, const bvec_t &salt, int N, int r, int p)
static Pbe.scrypt(dklen, pwdbytes, salt, N, r, p)
This uses the SCRYPT algorithm from [RFC7914]. There are restrictions on the values of the parameters N, r and p. In particular, N must be larger than 1 and a power of 2. The output buffer for the derived key abDerivedKey must have been dimensioned to at least the required length nKeyLen in bytes.
Two examples from [RFC7914].
Dim abPwd() As Byte Dim abSalt() As Byte Dim abDK() As Byte Dim nKeyLen As Long Dim nPwdlen As Long Dim nSaltLen As Long Dim nRet As Long nKeyLen = 64 ' Dimension key byte array ReDim abDK(nKeyLen - 1) ' Convert strings to byte array form abPwd = StrConv("password", vbFromUnicode) abSalt = StrConv("NaCl", vbFromUnicode) ' Get lengths in bytes nPwdlen = UBound(abPwd) + 1 nSaltLen = UBound(abSalt) + 1 ' Call the SCRYPT function to derive a 64-byte key with parameters N=1024, r=8, p=16 nRet = PBE_Scrypt(abDK(0), nKeyLen, abPwd(0), nPwdlen, abSalt(0), nSaltLen, 1024, 8, 16, 0) Debug.Print "PBE_Scrypt() returns " & nRet & " (expecting 0)" Debug.Print "KEY=" & cnvHexStrFromBytes(abDK)
PBE_Scrypt() returns 0 (expecting 0) KEY=FDBABE1C9D3472007856E7190D01E9FE7C6AD7CBC8237830E77376634B373162 2EAF30D92E22A3886FF109279D9830DAC727AFB94A83EE6D8360CBDFA2CC0640
In this second example, we need to pass zero-length byte arrays (representing the empty string) for the password and salt.
' INPUT: (N=16, r=1, p=1) ' P="", S="" => empty strings => byte arrays of length zero ' VBA ISSUE: we cannot pass an empty byte array in the usual way `abPwd(0)` ' because it gives a "Subscript out of range" error. ' FIX: pass `0` for the array parameters and zero for the lengths nRet = PBE_Scrypt(abDK(0), nKeyLen, 0, 0, 0, 0, 16, 1, 1, 0) Debug.Print "PBE_Scrypt() returns " & nRet & " (expecting 0)" Debug.Print "KEY=" & cnvHexStrFromBytes(abDK)
PBE_Scrypt() returns 0 (expecting 0) KEY=77D6576238657B203B19CA42C18A0497F16B4844E3074AE8DFDFFA3FEDE21442 FCD0069DED0948F8326A753A0FC81F17E8D3E0FB2E0D3628CF35E20C38D18906
Dim lpPwd() As Byte Dim lpSalt() As Byte Dim lpDK() As Byte lpPwd = StrConv("password", vbFromUnicode) lpSalt = StrConv("NaCl", vbFromUnicode) lpDK = pbeScrypt(64, lpPwd, lpSalt, 1024, 8, 16, 0) Debug.Print "DK=" & cnvHexStrFromBytes(lpDK) Debug.Print "OK=FDBABE1C9D3472007856E7190D01E9FE7C6AD7CBC8237830E77376634B3731622EAF30D92E22A3886FF109279D9830DAC727AFB94A83EE6D8360CBDFA2CC0640" ' INPUT: (N=16, r=1, p=1) ' P="", S="" => empty strings => byte arrays of length zero ' IMPORTANT: dummy variables *must* be independent Dim lpDummy1() As Byte Dim lpDummy2() As Byte lpDK = pbeScrypt(64, lpDummy1, lpDummy2, 16, 1, 1, 0) Debug.Print "DK=" & cnvHexStrFromBytes(lpDK) Debug.Print "OK=77D6576238657B203B19CA42C18A0497F16B4844E3074AE8DFDFFA3FEDE21442FCD0069DED0948F8326A753A0FC81F17E8D3E0FB2E0D3628CF35E20C38D18906"
Dim strDerivedKey As String
strDerivedKey = pbeScryptHex(64, "pleaseletmein", cnvHexStrFromString("SodiumChloride"), 16384, 8, 1, 0)
Debug.Print "Derived key = " & strDerivedKey
Debug.Print "OK = " & "7023BDCB3AFD7348461C06CD81FD38EBFDA8FBBA904F8E3EA9B543F6545DA1F2D5432955613F0FCF62D49705242A9AF9E61E85DC0D651E40DFCF017B45575887"