<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def getSharedSecretActive( self, other_public_bundle, allow_zero_otpks = False ):
 """ Do the key exchange, as the active party. This involves selecting keys from the passive parties' public bundle. :param other_public_bundle: An instance of PublicBundle, filled with the public data of the passive party. :param allow_zero_otpks: A flag indicating whether bundles with no one-time pre keys are allowed or throw an error. False is the recommended default. :returns: A dictionary containing the shared secret, the shared associated data and the data the passive party needs to finalize the key exchange. The returned structure looks like this:: { "to_other": { # The public key of the active parties' identity key pair "ik": bytes, # The public key of the active parties' ephemeral key pair "ek": bytes, # The public key of the used passive parties' one-time pre key or None "otpk": bytes or None, # The public key of the passive parties' signed pre key pair "spk": bytes }, "ad": bytes, # The shared associated data "sk": bytes # The shared secret } :raises KeyExchangeException: If an error occurs during the key exchange. The exception message will contain (human-readable) details. """


        self.__checkSPKTimestamp()

        other_ik = self.__KeyPair(pub = other_public_bundle.ik)

        other_spk = {
            "key": self.__KeyPair(pub = other_public_bundle.spk),
            "signature": other_public_bundle.spk_signature
        }

        other_otpks = [
            self.__KeyPair(pub = otpk) for otpk in other_public_bundle.otpks
        ]

        if len(other_otpks) == 0 and not allow_zero_otpks:
            raise KeyExchangeException(
                "The other public bundle does not contain any OTPKs, which is not " +
                "allowed."
            )

        other_spk_serialized = self.__PublicKeyEncoder.encodePublicKey(
            other_spk["key"].pub,
            self.__curve
        )

        if not self.__XEdDSA(mont_pub = other_ik.pub).verify(
            other_spk_serialized,
            other_spk["signature"]
        ):
            raise KeyExchangeException(
                "The signature of this public bundle's spk could not be verifified."
            )

        ek = self.__KeyPair.generate()

        dh1 = self.__ik.getSharedSecret(other_spk["key"])
        dh2 = ek.getSharedSecret(other_ik)
        dh3 = ek.getSharedSecret(other_spk["key"])
        dh4 = b""

        otpk = None
        if len(other_otpks) > 0:
            otpk_index = ord(os.urandom(1)) % len(other_otpks)
            otpk = other_otpks[otpk_index]

            dh4 = ek.getSharedSecret(otpk)

        sk = self.__kdf(dh1 + dh2 + dh3 + dh4)

        ik_pub_serialized = self.__PublicKeyEncoder.encodePublicKey(
            self.__ik.pub,
            self.__curve
        )

        other_ik_pub_serialized = self.__PublicKeyEncoder.encodePublicKey(
            other_ik.pub,
            self.__curve
        )

        ad = ik_pub_serialized + other_ik_pub_serialized

        return {
            "to_other": {
                "ik": self.__ik.pub,
                "ek": ek.pub,
                "otpk": otpk.pub if otpk else None,
                "spk": other_spk["key"].pub
            },
            "ad": ad,
            "sk": sk
        }