code: def derive(self, peerkey, **kwargs):
          
          if not self.cansign:
              raise ValueError("No private key available")
          ctx = libcrypto.EVP_PKEY_CTX_new(self.key, None)
          if ctx is None:
              raise PKeyError("Initailizing derive context")
          if libcrypto.EVP_PKEY_derive_init(ctx) < 1:
              raise PKeyError("derive_init")
  
          # This is workaround around missing functionality in GOST engine
          # it provides only numeric control command to set UKM, not
          # string one.
          self._configure_context(ctx, kwargs, ["ukm"])
          if libcrypto.EVP_PKEY_derive_set_peer(ctx, peerkey.key) <= 0:
              raise PKeyError("Cannot set peer key")
          if "ukm" in kwargs:
              # We just hardcode numeric command to set UKM here
              if libcrypto.EVP_PKEY_CTX_ctrl(ctx, -1, 1 << 10, 8, 8,
                                             kwargs["ukm"]) <= 0:
                  raise PKeyError("Cannot set UKM")
          keylen = c_long(0)
          if libcrypto.EVP_PKEY_derive(ctx, None, byref(keylen)) <= 0:
              raise PKeyError("computing shared key length")
          buf = create_string_buffer(keylen.value)
          if libcrypto.EVP_PKEY_derive(ctx, buf, byref(keylen)) <= 0:
              raise PKeyError("computing actual shared key")
          libcrypto.EVP_PKEY_CTX_free(ctx)
          return buf.raw[:int(keylen.value)]
docs: Derives shared key (DH,ECDH,VKO 34.10). Requires
          private key available
  
          @param peerkey - other key (may be public only)
  
          Keyword parameters are algorithm-specific