Compute EC Diffie-Hellman (ECDH) shared secret.
Public Declare Function ECC_DHSharedSecret Lib "diCrPKI.dll" (ByRef lpZZ As Byte, ByVal nOutBytes As Long, ByVal strIntPrivateKey As String, ByVal strIntPublicKey As String, ByVal nOptions As Long) As Long
nRet = ECC_DHSharedSecret(lpZZ(0), nOutBytes, strIntPrivateKey, strIntPublicKey, nOptions)
long __stdcall ECC_DHSharedSecret(unsigned char *lpZZ, long nOutBytes, const char *szIntPrivateKey, const char *szIntPublicKey, long nOptions);
If successful, the return value is the number of bytes in or required in the output; otherwise it returns a negative error code.
Public Function eccDHSharedSecret
(szIntPrivateKey As String, szIntPublicKey As String, Optional nOptions As Long = 0) As Byte()
static bvec_t dipki::Ecc::DHSharedSecret (std::string ourIntPrivateKey, std::string theirIntPublicKey)
static Ecc.dh_shared_secret(intprikeystr, intpubkeystr)
The output is the Diffie-Hellman shared secret. This may require further processing to be used in an application; for example, as input to a key derivation function.
The keys are expected in ephemeral "internal" format read into a string using
ECC_ReadPrivateKey
,
ECC_ReadPublicKey
or
ECC_ReadKeyByCurve
.
All supported NIST/SEC curves can be used as well as the safe curve X25519 (but not Ed25519 or Ed448, which are for signatures only).
Dim strOurPriKeyHex As String Dim strTheirPubKeyHex As String Dim strOurPrivateKey As String Dim strTheirPublicKey As String Dim strCurveName As String Dim strCorrectHex As String Dim lpZZ() As Byte Dim nChars As Long Dim nBytes As Long Dim nBits As Long ' Ref: CAVS 14.1 ECC CDH Primitive (SP800 - 56A Section 5.7.1.2) ' Test Information for "testecccdh" ecccdhtestvectors.zip '[P-256] strCurveName = "P-256" ' Our private key is dUIT: strOurPriKeyHex = "7d7dc5f71eb29ddaf80d6214632eeae03d9058af1fb6d22ed80badb62bc1a534" ' Their public key as hex is "04" || QCAVSx || QCAVSy strTheirPubKeyHex = "04" & "700c48f77f56584c5cc632ca65640db91b6bacce3a4df6b42ce7cc838833d287" _ + "db71e509e3fd9b060ddb20ba5c51dcc5948d46fbf640dfe0441782cab85fa4ac" ' Correct result is ZIUT strCorrectHex = "46fc62106420ff012e54a434fbdd2d25ccc5852060561e68040dd7778997bd7b" Debug.Print "Test for curve " & strCurveName & " ..." ' Read in keys to internal key strings ' Our private key... nChars = ECC_ReadKeyByCurve("", 0, strOurPriKeyHex, strCurveName, 0) Debug.Assert nChars > 0 strOurPrivateKey = String(nChars, " ") nChars = ECC_ReadKeyByCurve(strOurPrivateKey, nChars, strOurPriKeyHex, strCurveName, 0) Debug.Assert nChars > 0 ' Check the key we read in nBits = ECC_QueryKey("", 0, strOurPrivateKey, "keyBits", 0) Debug.Print "Our private key has " & nBits & " bits" ' Their public key... nChars = ECC_ReadKeyByCurve("", 0, strTheirPubKeyHex, strCurveName, 0) Debug.Assert nChars > 0 strTheirPublicKey = String(nChars, " ") nChars = ECC_ReadKeyByCurve(strTheirPublicKey, nChars, strTheirPubKeyHex, strCurveName, 0) Debug.Assert nChars > 0 ' Check the key we read in nBits = ECC_QueryKey("", 0, strTheirPublicKey, "keyBits", 0) Debug.Print "Their public key has " & nBits & " bits" ' Compute shared secret ' - find required length nBytes = ECC_DHSharedSecret(ByVal 0&, 0, strOurPrivateKey, strTheirPublicKey, 0) Debug.Print "ECC_DHSharedSecret returns " & nBytes & " (expecting +ve)" Debug.Assert nBytes > 0 ' - allocate memory ReDim lpZZ(nBytes - 1) ' - do the business nBytes = ECC_DHSharedSecret(lpZZ(0), nBytes, strOurPrivateKey, strTheirPublicKey, 0) Debug.Assert nBytes > 0 Debug.Print "ZZ=" & cnvHexStrFromBytes(lpZZ) ' Check the result Debug.Print "OK=" & strCorrectHex Debug.Assert UCase(cnvHexStrFromBytes(lpZZ)) = UCase(strCorrectHex)
Test for curve P-256 ... Our private key has 256 bits Their public key has 256 bits ECC_DHSharedSecret returns 32 (expecting +ve) ZZ=46FC62106420FF012E54A434FBDD2D25CCC5852060561E68040DD7778997BD7B OK=46fc62106420ff012e54a434fbdd2d25ccc5852060561e68040dd7778997bd7b
Dim strCurveName As String Dim ourPrivateKey As String Dim theirPublicKey As String Dim lpZZ() As Byte ' Ref: RFC7748 Section 6.1 Const alicePrivateKeyHex As String = "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a" Const alicePublicKeyHex As String = "8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a" Const bobPrivateKeyHex As String = "5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb" Const bobPublicKeyHex As String = "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f" strCurveName = "X25519" ' 1. Alice's private + Bob's public ourPrivateKey = eccReadKeyByCurve(alicePrivateKeyHex, strCurveName, PKI_ECC_PRIVATE_KEY) Debug.Print "Our key has " & eccQueryKey(ourPrivateKey, "keyBits") & " bits and is a " & _ IIf(eccQueryKey(ourPrivateKey, "isPrivate") = "1", "Private", "Public") & " key" theirPublicKey = eccReadKeyByCurve(bobPublicKeyHex, strCurveName, PKI_ECC_PUBLIC_KEY) Debug.Print "Their key has " & eccQueryKey(theirPublicKey, "keyBits") & " bits and is a " & _ IIf(eccQueryKey(theirPublicKey, "isPrivate") = "1", "Private", "Public") & " key" ' Compute shared secret lpZZ = eccDHSharedSecret(ourPrivateKey, theirPublicKey) Debug.Print "ZZ=" & cnvHexStrFromBytes(lpZZ) Debug.Print "OK=4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742" ' 2. Bob's private + Alice's public ourPrivateKey = eccReadKeyByCurve(bobPrivateKeyHex, strCurveName, PKI_ECC_PRIVATE_KEY) Debug.Print "Our key has " & eccQueryKey(ourPrivateKey, "keyBits") & " bits and is a " & _ IIf(eccQueryKey(ourPrivateKey, "isPrivate") = "1", "Private", "Public") & " key" theirPublicKey = eccReadKeyByCurve(alicePublicKeyHex, strCurveName, PKI_ECC_PUBLIC_KEY) Debug.Print "Their key has " & eccQueryKey(theirPublicKey, "keyBits") & " bits and is a " & _ IIf(eccQueryKey(theirPublicKey, "isPrivate") = "1", "Private", "Public") & " key" ' Compute shared secret lpZZ = eccDHSharedSecret(ourPrivateKey, theirPublicKey) Debug.Print "ZZ=" & cnvHexStrFromBytes(lpZZ) Debug.Print "OK=4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742"