Exemple #1
0
    async def verify_message(
        self,
        message: Union[List[bytes], bytes],
        signature: bytes,
        from_verkey: str,
        key_type: KeyType,
    ) -> bool:
        """
        Verify a signature against the public key of the signer.

        Args:
            message: The message to verify
            signature: The signature to verify
            from_verkey: Verkey to use in verification
            key_type: The key type to derive the signature verification algorithm from

        Returns:
            True if verified, else False

        Raises:
            WalletError: If the verkey is not provided
            WalletError: If the signature is not provided
            WalletError: If the message is not provided
            WalletError: If another backend error occurs

        """
        if not from_verkey:
            raise WalletError("Verkey not provided")
        if not signature:
            raise WalletError("Signature not provided")
        if not message:
            raise WalletError("Message not provided")

        verkey = b58_to_bytes(from_verkey)

        if key_type == KeyType.ED25519:
            try:
                pk = Key.from_public_bytes(KeyAlg.ED25519, verkey)
                return pk.verify_signature(message, signature)
            except AskarError as err:
                raise WalletError(
                    "Exception when verifying message signature") from err

        # other key types are currently verified outside of Askar
        return verify_signed_message(
            message=message,
            signature=signature,
            verkey=verkey,
            key_type=key_type,
        )
Exemple #2
0
def _pack_message(to_verkeys: Sequence[str], from_key: Optional[Key],
                  message: bytes) -> bytes:
    """Encode a message using the DIDComm v1 'pack' algorithm."""
    wrapper = JweEnvelope()
    cek = Key.generate(KeyAlg.C20P)
    # avoid converting to bytes object: this way the only copy is zeroed afterward
    cek_b = key_get_secret_bytes(cek._handle)
    sender_vk = (bytes_to_b58(from_key.get_public_bytes()).encode("utf-8")
                 if from_key else None)
    sender_xk = from_key.convert_key(KeyAlg.X25519) if from_key else None

    for target_vk in to_verkeys:
        target_xk = Key.from_public_bytes(KeyAlg.ED25519,
                                          b58_to_bytes(target_vk)).convert_key(
                                              KeyAlg.X25519)
        if sender_vk:
            enc_sender = crypto_box.crypto_box_seal(target_xk, sender_vk)
            nonce = crypto_box.random_nonce()
            enc_cek = crypto_box.crypto_box(target_xk, sender_xk, cek_b, nonce)
            wrapper.add_recipient(
                JweRecipient(
                    encrypted_key=enc_cek,
                    header=OrderedDict([
                        ("kid", target_vk),
                        ("sender", b64url(enc_sender)),
                        ("iv", b64url(nonce)),
                    ]),
                ))
        else:
            enc_sender = None
            nonce = None
            enc_cek = crypto_box.crypto_box_seal(target_xk, cek_b)
            wrapper.add_recipient(
                JweRecipient(encrypted_key=enc_cek, header={"kid": target_vk}))
    wrapper.set_protected(
        OrderedDict([
            ("enc", "xchacha20poly1305_ietf"),
            ("typ", "JWM/1.0"),
            ("alg", "Authcrypt" if from_key else "Anoncrypt"),
        ]),
        auto_flatten=False,
    )
    enc = cek.aead_encrypt(message, aad=wrapper.protected_bytes)
    ciphertext, tag, nonce = enc.parts
    wrapper.set_payload(ciphertext, nonce, tag)
    return wrapper.to_json().encode("utf-8")
Exemple #3
0
def _extract_payload_key(sender_cek: dict,
                         recip_secret: Key) -> Tuple[bytes, str]:
    """
    Extract the payload key from pack recipient details.

    Returns: A tuple of the CEK and sender verkey
    """
    recip_x = recip_secret.convert_key(KeyAlg.X25519)

    if sender_cek["nonce"] and sender_cek["sender"]:
        sender_vk = crypto_box.crypto_box_seal_open(
            recip_x, sender_cek["sender"]).decode("utf-8")
        sender_x = Key.from_public_bytes(
            KeyAlg.ED25519, b58_to_bytes(sender_vk)).convert_key(KeyAlg.X25519)
        cek = crypto_box.crypto_box_open(recip_x, sender_x, sender_cek["key"],
                                         sender_cek["nonce"])
    else:
        sender_vk = None
        cek = crypto_box.crypto_box_seal_open(recip_x, sender_cek["key"])
    return cek, sender_vk