Derives a key of any length from a password using the PBKDF2 algorithm from PKCS #5.
Public Declare Function PBE_Kdf2 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 nCount As Long, ByVal nOptions As Long) As Long
nRet = PBE_Kdf2(lpDerivedKey(0), nKeyLen, lpPwd(0), nPwdLen, lpSalt(0), nSaltLen, nCount, nOptions) ' Note the "(0)" after the byte array parameters
long __stdcall PBE_Kdf2(unsigned char *lpOutput, long nOutputLen, const unsigned char *lpPwd, long nPwdLen, const unsigned char *lpSalt, long nSaltLen, long nCount, long nOptions);
If successful, the return value is 0; otherwise it returns a non-zero error code.
Public Function pbeKdf2
(dkBytes As Long, lpPwd() As Byte, lpSalt() As Byte, nCount As Long, Optional nOptions As Long = 0) As Byte()
Pbe.Kdf2 Method (Int32, Byte[], Byte[], Int32, HashAlgorithm)
static bvec_t dipki::Pbe::Kdf2 (int dklen, const std::string password, const bvec_t &salt, int count, PrfAlg prfalg=PrfAlg::Hmac_Sha1)
static Pbe.kdf2(dklen, password, salt, count, prfalg=0)
The output buffer for the derived key abDerivedKey()
must have been dimensioned to at least the
required length.
This example uses PBKDF2 as defined in PKCS #5 v2.0 from test vectors provided by Dr. Stephen Henson. The password is "password" (without quotes). This derived key is for the 'des-ede3-cbc' example in the test vectors and therefore needs to be 24 bytes long.
Dim abDerivedKey() As Byte Dim nKeyLen As Long Dim sPassword As String Dim abPwdBytes() As Byte Dim abSalt(7) As Byte Dim nCount As Long Dim nRet As Long ' Convert password String to an array of Bytes sPassword = "password" abPwdBytes = StrConv(sPassword, vbFromUnicode) ' Set 8-byte salt = 78 57 8E 5A 5D 63 CB 06 abSalt(0) = &H78 abSalt(1) = &H57 abSalt(2) = &H8E abSalt(3) = &H5A abSalt(4) = &H5D abSalt(5) = &H63 abSalt(6) = &HCB abSalt(7) = &H6 ' Iteration count is 2048 nCount = 2048 ' Pre-dimension output for derived key to required length of 24 bytes ' (Don't forget to do this) nKeyLen = 24 ReDim abDerivedKey(nKeyLen - 1) ' Derive PBKDF2 key using function from CryptoSys nRet = PBE_Kdf2(abDerivedKey(0), nKeyLen, _ abPwdBytes(0), Len(sPassword), abSalt(0), 8&, nCount, 0&) ' Convert bytes to hex and print Debug.Print "Derived key = " & cnvHexStrFromBytes(abDerivedKey) Debug.Print "Correct key = BFDE6BE94DF7E11DD409BCE20A0255EC327CB936FFE93643"
This should result in output as follows:
Derived key = BFDE6BE94DF7E11DD409BCE20A0255EC327CB936FFE93643 Correct key = BFDE6BE94DF7E11DD409BCE20A0255EC327CB936FFE93643
Had we specified the required key length to be 64 bytes instead of 24, we would have generated this 512-bit key:
BFDE6BE94DF7E11DD409BCE20A0255EC327CB936FFE93643C4B150DEF7751122 4479994567F2E9B4E3BD0DF7AEDA3022B1F26051D81505C794F8940C04DF1144
This second example shows how other SHA-2 hash functions can be used.
Dim abDerivedKey() As Byte Dim nKeyLen As Long Dim sPassword As String Dim abPwdBytes() As Byte Dim abSalt(7) As Byte Dim nSaltBytes As Long Dim nCount As Long Dim nRet As Long ' Convert password String to an array of Bytes sPassword = "password" abPwdBytes = StrConv(sPassword, vbFromUnicode) ' Set 8-byte salt = 78 57 8E 5A 5D 63 CB 06 abSalt(0) = &H78 abSalt(1) = &H57 abSalt(2) = &H8E abSalt(3) = &H5A abSalt(4) = &H5D abSalt(5) = &H63 abSalt(6) = &HCB abSalt(7) = &H6 nSaltBytes = 8 ' Iteration count is 2048 nCount = 2048 ' Pre-dimension output for derived key to required length of 24 bytes ' (Don't forget to do this) nKeyLen = 24 ReDim abDerivedKey(nKeyLen - 1) ' Derive PBKDF2 key using function from CryptoSys API with default HMAC-SHA-1 nRet = PBE_Kdf2(abDerivedKey(0), nKeyLen, _ abPwdBytes(0), Len(sPassword), abSalt(0), nSaltBytes, nCount, PKI_HASH_SHA1) ' Convert bytes to hex and print Debug.Print "Derived key {HMAC-SHA-1} = " & cnvHexStrFromBytes(abDerivedKey) ' Derive PBKDF2 key using function from CryptoSys API with HMAC-SHA-256 nRet = PBE_Kdf2(abDerivedKey(0), nKeyLen, _ abPwdBytes(0), Len(sPassword), abSalt(0), nSaltBytes, nCount, PKI_HASH_SHA256) Debug.Print "Derived key {HMAC-SHA-256} = " & cnvHexStrFromBytes(abDerivedKey) ' Derive PBKDF2 key using function from CryptoSys API with HMAC-SHA-224 nRet = PBE_Kdf2(abDerivedKey(0), nKeyLen, _ abPwdBytes(0), Len(sPassword), abSalt(0), nSaltBytes, nCount, PKI_HASH_SHA224) Debug.Print "Derived key {HMAC-SHA-224} = " & cnvHexStrFromBytes(abDerivedKey)
This should result in output as follows:
Derived key {HMAC-SHA-1} = BFDE6BE94DF7E11DD409BCE20A0255EC327CB936FFE93643 Derived key {HMAC-SHA-256} = 97B5A91D35AF542324881315C4F849E327C4707D1BC9D322 Derived key {HMAC-SHA-224} = 10CFFEDFB13503519969151E466F587028E0720B387F9AEF
Dim lpDK() As Byte Dim strPassword As String Dim lpSalt() As Byte Dim nCount As Long strPassword = "password" lpSalt = cnvBytesFromHexStr("78 57 8E 5A 5D 63 CB 06") nCount = 2048 lpDK = pbeKdf2(24, StrConv(strPassword, vbFromUnicode), lpSalt, nCount) Debug.Print "Derived key = " & cnvHexStrFromBytes(lpDK) Debug.Print "Correct key = BFDE6BE94DF7E11DD409BCE20A0255EC327CB936FFE93643" lpDK = pbeKdf2(24, StrConv(strPassword, vbFromUnicode), lpSalt, nCount, PKI_HASH_SHA256) Debug.Print "Derived key {HMAC-SHA-256} = " & cnvHexStrFromBytes(lpDK) Debug.Print "Correct key {HMAC-SHA-256} = 97B5A91D35AF542324881315C4F849E327C4707D1BC9D322"