예제 #1
0
    def test_crypto_secretstream_xchacha20poly1305_pull_incorrect_key(self):
        if not pysodium.sodium_version_check(1, 0, 15): return

        key = pysodium.crypto_secretstream_xchacha20poly1305_keygen()
        state, header = pysodium.crypto_secretstream_xchacha20poly1305_init_push(key)
        ciphertext = pysodium.crypto_secretstream_xchacha20poly1305_push(state, b"howdy", None, pysodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL)

        bad_key = pysodium.crypto_secretstream_xchacha20poly1305_keygen()
        state2 = pysodium.crypto_secretstream_xchacha20poly1305_init_pull(header, bad_key)
        self.assertRaises(ValueError, pysodium.crypto_secretstream_xchacha20poly1305_pull, state2, ciphertext, None)
예제 #2
0
    def test_crypto_secretstream_xchacha20poly1305_pull_incorrect_key(self):
        if not pysodium.sodium_version_check(1, 0, 15): return

        key = pysodium.crypto_secretstream_xchacha20poly1305_keygen()
        state, header = pysodium.crypto_secretstream_xchacha20poly1305_init_push(key)
        ciphertext = pysodium.crypto_secretstream_xchacha20poly1305_push(state, b"howdy", None, pysodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL)

        bad_key = pysodium.crypto_secretstream_xchacha20poly1305_keygen()
        state2 = pysodium.crypto_secretstream_xchacha20poly1305_init_pull(header, bad_key)
        self.assertRaises(ValueError, pysodium.crypto_secretstream_xchacha20poly1305_pull, state2, ciphertext, None)
예제 #3
0
    def test_crypto_secretstream_xchacha20poly1305_rekey(self):
        if not pysodium.sodium_version_check(1, 0, 15): return

        key = pysodium.crypto_secretstream_xchacha20poly1305_keygen()
        state, header = pysodium.crypto_secretstream_xchacha20poly1305_init_push(
            key)

        # Encrypt two messages with intermediate re-key
        ciphertext = pysodium.crypto_secretstream_xchacha20poly1305_push(
            state, b"Correct Horse Battery Staple", None, 0)
        pysodium.crypto_secretstream_xchacha20poly1305_rekey(state)
        ciphertext2 = pysodium.crypto_secretstream_xchacha20poly1305_push(
            state, b"howdy", None,
            pysodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL)

        # Verify by decrypting them
        state2 = pysodium.crypto_secretstream_xchacha20poly1305_init_pull(
            header, key)
        msg, tag = pysodium.crypto_secretstream_xchacha20poly1305_pull(
            state2, ciphertext, None)
        pysodium.crypto_secretstream_xchacha20poly1305_rekey(state2)
        msg2, tag2 = pysodium.crypto_secretstream_xchacha20poly1305_pull(
            state2, ciphertext2, None)

        self.assertEqual(msg, b"Correct Horse Battery Staple")
        self.assertEqual(tag, 0)

        self.assertEqual(msg2, b"howdy")
        self.assertEqual(
            tag2, pysodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL)
예제 #4
0
    def test_streaming_pipeline_org(self):
        return

        crypt_key = pysodium.crypto_secretstream_xchacha20poly1305_keygen()
        print('upload...')
        upload = streaming_upload(client, bucket, key)
        crpt = encrypter(upload, crypt_key)

        upload.begin()

        pl_out = pipeline.build_pipeline_streaming('out', pl_format, config)

        with open('', 'rb') as fle:
            while True:
                chunk = fle.read(chunk_size)
                if chunk == "": break
                crpt.next_chunk(chunk)

        res = upload.finish()

        #---------------
        print('download...')
        download = streaming_download(client, bucket, key, chunk_size)
        dcrpt = decrypter(download, crypt_key)

        with open('', 'wb') as fle:
            while True:
                res = dcrpt.next_chunk()
                if res == None: break
                fle.write(res)
예제 #5
0
    def test_crypto_secretstream_xchacha20poly1305_pull_multiple(self):
        if not pysodium.sodium_version_check(1, 0, 15): return

        key = pysodium.crypto_secretstream_xchacha20poly1305_keygen()
        state, header = pysodium.crypto_secretstream_xchacha20poly1305_init_push(
            key)

        ciphertext = pysodium.crypto_secretstream_xchacha20poly1305_push(
            state, b"Correct Horse Battery Staple", None, 0)
        ciphertext2 = pysodium.crypto_secretstream_xchacha20poly1305_push(
            state, b"howdy", None,
            pysodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL)

        # Verify decryption
        state2 = pysodium.crypto_secretstream_xchacha20poly1305_init_pull(
            header, key)
        msg, tag = pysodium.crypto_secretstream_xchacha20poly1305_pull(
            state2, ciphertext, None)
        msg2, tag2 = pysodium.crypto_secretstream_xchacha20poly1305_pull(
            state2, ciphertext2, None)

        self.assertEqual(msg, b"Correct Horse Battery Staple")
        self.assertEqual(tag, 0)

        self.assertEqual(msg2, b"howdy")
        self.assertEqual(
            tag2, pysodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL)
예제 #6
0
    def test_crypto_secretstream_xchacha20poly1305_pull_corrupted(self):
        if not pysodium.sodium_version_check(1, 0, 15): return

        key = pysodium.crypto_secretstream_xchacha20poly1305_keygen()
        state, header = pysodium.crypto_secretstream_xchacha20poly1305_init_push(
            key)

        ad = 'additional data'
        ciphertext = pysodium.crypto_secretstream_xchacha20poly1305_push(
            state, b"Correct Horse Battery Staple", ad, 0)

        # Verify error is raised if cypher text is changed
        state2 = pysodium.crypto_secretstream_xchacha20poly1305_init_pull(
            header, key)
        self.assertRaises(ValueError,
                          pysodium.crypto_secretstream_xchacha20poly1305_pull,
                          state2, ciphertext + 'this is a corruption'.encode(),
                          ad)

        # Verify error is raised if additional data is changed
        ad2 = 'this is not the same'
        state2 = pysodium.crypto_secretstream_xchacha20poly1305_init_pull(
            header, key)
        self.assertRaises(ValueError,
                          pysodium.crypto_secretstream_xchacha20poly1305_pull,
                          state2, ciphertext, ad2)
예제 #7
0
    def test_simple_pipeline_encrypt(self):
        config = {
            'crypto': {
                'encrypt_opts': {},
                'stream_crypt_key':
                pysodium.crypto_secretstream_xchacha20poly1305_keygen()
            }
        }

        meta_pl_format = pipeline.get_default_pipeline_format()
        meta_pl_format['format'].update(
            {'encrypt': config['crypto']['encrypt_opts']})
        data_in = b'some data input'

        #-------
        pl_out = pipeline.build_pipeline(write_helper, 'out')
        meta = {
            'path': 'test',
            'header': pipeline.serialise_pipeline_format(meta_pl_format)
        }
        meta2 = pl_out(data_in, meta, config)

        self.assertNotEqual(data_in, meta2['data'])

        #-------
        pl_in = pipeline.build_pipeline(read_helper, 'in')
        data_out, meta3 = pl_in(meta2, config)

        self.assertEqual(data_in, data_out)
예제 #8
0
def prepare_pack_recipient_keys(to_verkeys: Sequence[bytes],
                                from_secret: bytes = None) -> (str, bytes):
    """
    Assemble the recipients block of a packed message.

    Args:
        to_verkeys: Verkeys of recipients
        from_secret: Secret to use for signing keys

    Returns:
        A tuple of (json result, key)

    """
    cek = pysodium.crypto_secretstream_xchacha20poly1305_keygen()
    recips = []

    for target_vk in to_verkeys:
        target_pk = pysodium.crypto_sign_pk_to_box_pk(target_vk)
        if from_secret:
            sender_pk, sender_sk = create_keypair(from_secret)
            sender_vk = bytes_to_b58(sender_pk).encode("ascii")
            enc_sender = pysodium.crypto_box_seal(sender_vk, target_pk)
            sk = pysodium.crypto_sign_sk_to_box_sk(sender_sk)

            nonce = pysodium.randombytes(pysodium.crypto_box_NONCEBYTES)
            enc_cek = pysodium.crypto_box(cek, nonce, target_pk, sk)
        else:
            enc_sender = None
            nonce = None
            enc_cek = pysodium.crypto_box_seal(cek, target_pk)

        recips.append(
            OrderedDict([
                ("encrypted_key", bytes_to_b64(enc_cek, urlsafe=True)),
                (
                    "header",
                    OrderedDict([
                        ("kid", bytes_to_b58(target_vk)),
                        (
                            "sender",
                            bytes_to_b64(enc_sender, urlsafe=True)
                            if enc_sender else None,
                        ),
                        (
                            "iv",
                            bytes_to_b64(nonce, urlsafe=True)
                            if nonce else None,
                        ),
                    ]),
                ),
            ]))

    data = OrderedDict([
        ("enc", "xchacha20poly1305_ietf"),
        ("typ", "JWM/1.0"),
        ("alg", "Authcrypt" if from_secret else "Anoncrypt"),
        ("recipients", recips),
    ])
    return json.dumps(data), cek
예제 #9
0
    def test_crypto_secretstream_xchacha20poly1305_init_pull(self):
        if not pysodium.sodium_version_check(1, 0, 15): return

        key = pysodium.crypto_secretstream_xchacha20poly1305_keygen()
        state, header = pysodium.crypto_secretstream_xchacha20poly1305_init_push(
            key)
        state2 = pysodium.crypto_secretstream_xchacha20poly1305_init_pull(
            header, key)
예제 #10
0
    def test_crypto_secretstream_xchacha20poly1305_push(self):
        if not pysodium.sodium_version_check(1, 0, 15): return

        key = pysodium.crypto_secretstream_xchacha20poly1305_keygen()
        state, header = pysodium.crypto_secretstream_xchacha20poly1305_init_push(
            key)
        ciphertext = pysodium.crypto_secretstream_xchacha20poly1305_push(
            state, b"howdy", None, 0)
예제 #11
0
    def test_crypto_secretstream_xchacha20poly1305_pull_changed_ad(self):
        if not pysodium.sodium_version_check(1, 0, 15): return

        key = pysodium.crypto_secretstream_xchacha20poly1305_keygen()
        state, header = pysodium.crypto_secretstream_xchacha20poly1305_init_push(key)
        ciphertext = pysodium.crypto_secretstream_xchacha20poly1305_push(state, b"howdy", b"some data", pysodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL)

        state2 = pysodium.crypto_secretstream_xchacha20poly1305_init_pull(header, key)
        self.assertRaises(ValueError, pysodium.crypto_secretstream_xchacha20poly1305_pull, state2, ciphertext, b"different data")
예제 #12
0
    def test_crypto_secretstream_xchacha20poly1305_pull_changed_ad(self):
        if not pysodium.sodium_version_check(1, 0, 15): return

        key = pysodium.crypto_secretstream_xchacha20poly1305_keygen()
        state, header = pysodium.crypto_secretstream_xchacha20poly1305_init_push(key)
        ciphertext = pysodium.crypto_secretstream_xchacha20poly1305_push(state, b"howdy", b"some data", pysodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL)

        state2 = pysodium.crypto_secretstream_xchacha20poly1305_init_pull(header, key)
        self.assertRaises(ValueError, pysodium.crypto_secretstream_xchacha20poly1305_pull, state2, ciphertext, b"different data")
예제 #13
0
    def test_crypto_secretstream_xchacha20poly1305_out_of_order_messeges(self):
        if not pysodium.sodium_version_check(1, 0, 15): return

        key = pysodium.crypto_secretstream_xchacha20poly1305_keygen()
        state, header = pysodium.crypto_secretstream_xchacha20poly1305_init_push(key)

        ciphertext = pysodium.crypto_secretstream_xchacha20poly1305_push(state, b"Correct Horse Battery Staple", None, 0)
        ciphertext2 = pysodium.crypto_secretstream_xchacha20poly1305_push(state, b"howdy", None, pysodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL)

        # Decrypting the second message first should fail
        state2 = pysodium.crypto_secretstream_xchacha20poly1305_init_pull(header, key)
        self.assertRaises(ValueError, pysodium.crypto_secretstream_xchacha20poly1305_pull, state2, ciphertext2, None)
예제 #14
0
    def test_crypto_secretstream_xchacha20poly1305_pull(self):
        if not pysodium.sodium_version_check(1, 0, 15): return

        key = pysodium.crypto_secretstream_xchacha20poly1305_keygen()
        state, header = pysodium.crypto_secretstream_xchacha20poly1305_init_push(key)
        ciphertext = pysodium.crypto_secretstream_xchacha20poly1305_push(state, b"howdy", None, pysodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL)

        state2 = pysodium.crypto_secretstream_xchacha20poly1305_init_pull(header, key)
        msg, tag = pysodium.crypto_secretstream_xchacha20poly1305_pull(state2, ciphertext, None)

        self.assertEqual(msg, b"howdy")
        self.assertEqual(tag, pysodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL)
예제 #15
0
    def test_crypto_secretstream_xchacha20poly1305_out_of_order_messeges(self):
        if not pysodium.sodium_version_check(1, 0, 15): return

        key = pysodium.crypto_secretstream_xchacha20poly1305_keygen()
        state, header = pysodium.crypto_secretstream_xchacha20poly1305_init_push(key)

        ciphertext = pysodium.crypto_secretstream_xchacha20poly1305_push(state, b"Correct Horse Battery Staple", None, 0)
        ciphertext2 = pysodium.crypto_secretstream_xchacha20poly1305_push(state, b"howdy", None, pysodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL)

        # Decrypting the second message first should fail
        state2 = pysodium.crypto_secretstream_xchacha20poly1305_init_pull(header, key)
        self.assertRaises(ValueError, pysodium.crypto_secretstream_xchacha20poly1305_pull, state2, ciphertext2, None)
예제 #16
0
    def test_crypto_secretstream_xchacha20poly1305_pull(self):
        if not pysodium.sodium_version_check(1, 0, 15): return

        key = pysodium.crypto_secretstream_xchacha20poly1305_keygen()
        state, header = pysodium.crypto_secretstream_xchacha20poly1305_init_push(key)
        ciphertext = pysodium.crypto_secretstream_xchacha20poly1305_push(state, b"howdy", None, pysodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL)

        state2 = pysodium.crypto_secretstream_xchacha20poly1305_init_pull(header, key)
        msg, tag = pysodium.crypto_secretstream_xchacha20poly1305_pull(state2, ciphertext, None)

        self.assertEqual(msg, b"howdy")
        self.assertEqual(tag, pysodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL)
예제 #17
0
    def test_crypto_secretstream_xchacha20poly1305_missing_rekey(self):
        if not pysodium.sodium_version_check(1, 0, 15): return

        key = pysodium.crypto_secretstream_xchacha20poly1305_keygen()
        state, header = pysodium.crypto_secretstream_xchacha20poly1305_init_push(key)

        # Encrypt two messages with intermediate re-key
        ciphertext = pysodium.crypto_secretstream_xchacha20poly1305_push(state, b"Correct Horse Battery Staple", None, 0)
        pysodium.crypto_secretstream_xchacha20poly1305_rekey(state)
        ciphertext2 = pysodium.crypto_secretstream_xchacha20poly1305_push(state, b"howdy", None, pysodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL)

        state2 = pysodium.crypto_secretstream_xchacha20poly1305_init_pull(header, key)
        msg, tag = pysodium.crypto_secretstream_xchacha20poly1305_pull(state2, ciphertext, None)
        # re-key should be here, so following call should fail
        self.assertRaises(ValueError, pysodium.crypto_secretstream_xchacha20poly1305_pull, state2, ciphertext2, None)
예제 #18
0
    def test_crypto_secretstream_xchacha20poly1305_missing_rekey(self):
        if not pysodium.sodium_version_check(1, 0, 15): return

        key = pysodium.crypto_secretstream_xchacha20poly1305_keygen()
        state, header = pysodium.crypto_secretstream_xchacha20poly1305_init_push(key)

        # Encrypt two messages with intermediate re-key
        ciphertext = pysodium.crypto_secretstream_xchacha20poly1305_push(state, b"Correct Horse Battery Staple", None, 0)
        pysodium.crypto_secretstream_xchacha20poly1305_rekey(state)
        ciphertext2 = pysodium.crypto_secretstream_xchacha20poly1305_push(state, b"howdy", None, pysodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL)

        state2 = pysodium.crypto_secretstream_xchacha20poly1305_init_pull(header, key)
        msg, tag = pysodium.crypto_secretstream_xchacha20poly1305_pull(state2, ciphertext, None)
        # re-key should be here, so following call should fail
        self.assertRaises(ValueError, pysodium.crypto_secretstream_xchacha20poly1305_pull, state2, ciphertext2, None)
예제 #19
0
    def test_crypto_secretstream_xchacha20poly1305_pull_corrupted(self):
        if not pysodium.sodium_version_check(1, 0, 15): return

        key = pysodium.crypto_secretstream_xchacha20poly1305_keygen()
        state, header = pysodium.crypto_secretstream_xchacha20poly1305_init_push(key)

        ad = 'additional data'
        ciphertext = pysodium.crypto_secretstream_xchacha20poly1305_push(state, b"Correct Horse Battery Staple", ad, 0)

        # Verify error is raised if cypher text is changed
        state2 = pysodium.crypto_secretstream_xchacha20poly1305_init_pull(header, key)
        self.assertRaises(ValueError, pysodium.crypto_secretstream_xchacha20poly1305_pull, state2, ciphertext + 'this is a corruption'.encode(), ad)

        # Verify error is raised if additional data is changed
        ad2 = 'this is not the same'
        state2 = pysodium.crypto_secretstream_xchacha20poly1305_init_pull(header, key)
        self.assertRaises(ValueError, pysodium.crypto_secretstream_xchacha20poly1305_pull, state2, ciphertext, ad2)
예제 #20
0
    def test_crypto_secretstream_xchacha20poly1305_pull_multiple(self):
        if not pysodium.sodium_version_check(1, 0, 15): return

        key = pysodium.crypto_secretstream_xchacha20poly1305_keygen()
        state, header = pysodium.crypto_secretstream_xchacha20poly1305_init_push(key)

        ciphertext = pysodium.crypto_secretstream_xchacha20poly1305_push(state, b"Correct Horse Battery Staple", None, 0)
        ciphertext2 = pysodium.crypto_secretstream_xchacha20poly1305_push(state, b"howdy", None, pysodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL)

        # Verify decryption
        state2 = pysodium.crypto_secretstream_xchacha20poly1305_init_pull(header, key)
        msg, tag = pysodium.crypto_secretstream_xchacha20poly1305_pull(state2, ciphertext, None)
        msg2, tag2 = pysodium.crypto_secretstream_xchacha20poly1305_pull(state2, ciphertext2, None)

        self.assertEqual(msg, b"Correct Horse Battery Staple")
        self.assertEqual(tag, 0)

        self.assertEqual(msg2, b"howdy")
        self.assertEqual(tag2, pysodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL)
예제 #21
0
    def test_crypto_secretstream_xchacha20poly1305_rekey(self):
        if not pysodium.sodium_version_check(1, 0, 15): return

        key = pysodium.crypto_secretstream_xchacha20poly1305_keygen()
        state, header = pysodium.crypto_secretstream_xchacha20poly1305_init_push(key)

        # Encrypt two messages with intermediate re-key
        ciphertext = pysodium.crypto_secretstream_xchacha20poly1305_push(state, b"Correct Horse Battery Staple", None, 0)
        pysodium.crypto_secretstream_xchacha20poly1305_rekey(state)
        ciphertext2 = pysodium.crypto_secretstream_xchacha20poly1305_push(state, b"howdy", None, pysodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL)

        # Verify by decrypting them
        state2 = pysodium.crypto_secretstream_xchacha20poly1305_init_pull(header, key)
        msg, tag = pysodium.crypto_secretstream_xchacha20poly1305_pull(state2, ciphertext, None)
        pysodium.crypto_secretstream_xchacha20poly1305_rekey(state2)
        msg2, tag2 = pysodium.crypto_secretstream_xchacha20poly1305_pull(state2, ciphertext2, None)

        self.assertEqual(msg, b"Correct Horse Battery Staple")
        self.assertEqual(tag, 0)

        self.assertEqual(msg2, b"howdy")
        self.assertEqual(tag2, pysodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL)
예제 #22
0
    def test_crypto_secretstream_xchacha20poly1305_push(self):
        if not pysodium.sodium_version_check(1, 0, 15): return

        key = pysodium.crypto_secretstream_xchacha20poly1305_keygen()
        state, header = pysodium.crypto_secretstream_xchacha20poly1305_init_push(key)
        ciphertext = pysodium.crypto_secretstream_xchacha20poly1305_push(state, b"howdy", None, 0)
예제 #23
0
    def test_crypto_secretstream_xchacha20poly1305_init_pull(self):
        if not pysodium.sodium_version_check(1, 0, 15): return

        key = pysodium.crypto_secretstream_xchacha20poly1305_keygen()
        state, header = pysodium.crypto_secretstream_xchacha20poly1305_init_push(key)
        state2 = pysodium.crypto_secretstream_xchacha20poly1305_init_pull(header, key)
예제 #24
0
    def test_crypto_secretstream_xchacha20poly1305_keygen(self):
        if not pysodium.sodium_version_check(1, 0, 15): return

        key = pysodium.crypto_secretstream_xchacha20poly1305_keygen()
        self.assertEqual(len(key), 32)
예제 #25
0
    def test_crypto_secretstream_xchacha20poly1305_keygen(self):
        if not pysodium.sodium_version_check(1, 0, 15): return

        key = pysodium.crypto_secretstream_xchacha20poly1305_keygen()
        self.assertEqual(len(key), 32)
def prepare_pack_recipient_keys(to_verkeys: Sequence[bytes],
                                from_verkey: bytes = None,
                                from_sigkey: bytes = None) -> (str, bytes):
    """
    Assemble the recipients block of a packed message.

    Args:
        to_verkeys: Verkeys of recipients
        from_verkey: Sender Verkey needed to authcrypt package
        from_sigkey: Sender Sigkey needed to authcrypt package

    Returns:
        A tuple of (json result, key)

    """
    if from_verkey is not None and from_sigkey is None or \
            from_sigkey is not None and from_verkey is None:
        raise CryptoError(
            'Both verkey and sigkey needed to authenticated encrypt message')

    cek = pysodium.crypto_secretstream_xchacha20poly1305_keygen()
    recips = []

    for target_vk in to_verkeys:
        target_pk = pysodium.crypto_sign_pk_to_box_pk(target_vk)
        if from_verkey:
            sender_vk = bytes_to_b58(from_verkey).encode("ascii")
            enc_sender = pysodium.crypto_box_seal(sender_vk, target_pk)
            sk = pysodium.crypto_sign_sk_to_box_sk(from_sigkey)

            nonce = pysodium.randombytes(pysodium.crypto_box_NONCEBYTES)
            enc_cek = pysodium.crypto_box(cek, nonce, target_pk, sk)
        else:
            enc_sender = None
            nonce = None
            enc_cek = pysodium.crypto_box_seal(cek, target_pk)

        recips.append(
            OrderedDict([
                ("encrypted_key", bytes_to_b64(enc_cek, urlsafe=True)),
                (
                    "header",
                    OrderedDict([
                        ("kid", bytes_to_b58(target_vk)),
                        (
                            "sender",
                            bytes_to_b64(enc_sender, urlsafe=True)
                            if enc_sender else None,
                        ),
                        (
                            "iv",
                            bytes_to_b64(nonce, urlsafe=True)
                            if nonce else None,
                        ),
                    ]),
                ),
            ]))

    data = OrderedDict([
        ("enc", "xchacha20poly1305_ietf"),
        ("typ", "JWM/1.0"),
        ("alg", "Authcrypt" if from_verkey else "Anoncrypt"),
        ("recipients", recips),
    ])
    return json.dumps(data), cek